Skip to content

Fix static compilation for capabilities using preflight: hydrate_invoke_target - #35

Merged
ryan-s-roberts merged 2 commits into
PlasmTools:mainfrom
neithanmo:fix/hydrate_invoke
Aug 15, 2026
Merged

Fix static compilation for capabilities using preflight: hydrate_invoke_target#35
ryan-s-roberts merged 2 commits into
PlasmTools:mainfrom
neithanmo:fix/hydrate_invoke

Conversation

@neithanmo

Copy link
Copy Markdown
Contributor

Live runtime hydration was already implemented, but the network-free compile path left this preflight variant as a no-op. As a result, valid mappings could fail with unknown-variable errors before live hydration had a chance to provide the required target fields.

Problem

Capabilities can hydrate their invoke target before dispatch:

  preflight:
    - kind: hydrate_invoke_target
      get: datasource_get
      prefix: ds

At runtime, this fetches the target and exposes fields such as:

  Datasource.type → ds_type
  Datasource.uid  → ds_uid

APIs such as Grafana require this metadata in their request mappings:

  [type, { type: var, name: ds_type }]

The actual value is available during live execution, but static compilation runs first and intentionally performs no network requests. Because hydrate_invoke_target did not declare compile-time placeholders, compilation rejected ds_type before runtime hydration executed.

Other preflight variants already modeled their explicit merge fields during compilation. hydrate_invoke_target was the remaining schema-derived case.

Changes

  • Resolve the configured Get capability and target entity during static compilation.
  • Add type-correct placeholders for declared, prefixed target fields.
  • Keep compilation deterministic and network-free.
  • Continue using real hydrated values during live execution.
  • Validate the Get capability, entity relationship, and prefix.
  • Preserve unknown-variable errors for undeclared fields and typos.
  • Add focused static and live hydration coverage.

Compile-time placeholders are never sent to the remote API:

  static compilation: ds_type = "preflight-stub"
  live execution:     ds_type = "prometheus"

This is a generic runtime fix required by catalogs that reference hydrated target fields, including Grafana, Discord, Gmail, Google Drive, and Linear. It is independent of semantic discovery and capability
effect classification.

@ryan-s-roberts ryan-s-roberts left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The bug is real: compile-only preflight left HydrateInvokeTarget as a no-op, so mappings that reference {prefix}_{field} (Grafana ds_type, Gmail parent_*, etc.) fail with unknown-variable before live hydration runs. The fixture tests for prefix, typo rejection, and provides not stripping decoded fields are the right coverage. Keep those.

The implementation is much larger than the missing match arm. Requested change: reframe this so the extra concepts disappear.

Do this instead

Extend the existing compile-stub match arm with the existing wire-key heuristic. Motivating mappings are string vars (ds_type). The compile path only needs the env key to exist; unused stub values are not transport values and CML does not type-check them.

PreflightStep::HydrateInvokeTarget { get, prefix } => {
    let Some(get_cap) = cgs.get_capability(get) else { continue };
    let Some(entity) = cgs.get_entity(get_cap.domain.as_str()) else { continue };
    for field_name in entity.fields.keys() {
        let key = format!("{prefix}_{field_name}");
        env.insert(key.clone(), preflight_wire_key_compile_stub_value(&key));
    }
}

That keeps apply_preflight_compile_stubs infallible, leaves live hydrate_invoke_target untouched, and deletes compile_stub_value.rs, HydrateInvokeTargetContract, the Result signature change, the extra capability argument on the live hydrator, and the view_stub_rows lock-in comment/test.

If typed stubs are actually required, show a mapping that fails compilation when the stub is "preflight-stub" (date formatter, compound entity-ref descent, etc.). Then delete preflight_wire_key_compile_stub_value and route HydrateEntityRefParam / QueryPick through the same helper. One dialect. Right now there are three (wire-key heuristic, schema-derived typed stubs, view placeholder_value).

Also

  • Do not reimplement validate_capability_preflight / validate_get_on_domain in the runtime for an “unvalidated CGS” defensive boundary.
  • Do not add a second Create-skip predicate (capability.kind != Create vs live is_create). Schema load already rejects this step on Create.
  • Drop the apis/grafana compile test. plasm-runtime tests must not take new apis/ dependencies for compile/runtime shape; the new fixture already is Grafana-shaped.

Approval is blocked on the structural cut, not on behavior.

Comment thread crates/plasm-runtime/src/preflight.rs
Comment thread crates/plasm-runtime/src/preflight.rs Outdated
Comment thread crates/plasm-runtime/src/compile_stub_value.rs Outdated
Comment thread crates/plasm-runtime/src/preflight.rs Outdated
Comment thread crates/plasm-runtime/tests/hydrate_invoke_target.rs Outdated
Comment thread crates/plasm-runtime/src/view_stub_rows.rs Outdated
@ryan-s-roberts

Copy link
Copy Markdown
Collaborator

💯

@ryan-s-roberts
ryan-s-roberts merged commit 1600333 into PlasmTools:main Aug 15, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants