Files
lda-wf/docs/superpowers/specs/2026-06-27-draft-bind-from-to.md
T

5.6 KiB

Draft Bind From/To Design

Status

Implemented. This design replaces bind-output-to-state with the general bind --from ... --to ... operation. bind-output-to-state was introduced recently as an incomplete narrow helper and should be removed rather than preserved as compatibility.

Problem

Agents authoring drafts repeatedly hit the same boundary: step input/output bindings are not just path edits. They often require workflow-level schema declarations too.

Today:

  • wf draft set-input edits a step input map, but it does not declare input_schema.properties.<field>.
  • wf draft bind-output-to-state declares one root state field and writes a step output binding, but only covers local.output -> state.field. It is too narrow now that input-side schema projection is needed too.
  • Agents interpret this split inconsistently, then fall back to raw JSON Patch.

The product needs one capability-aware operation with the mental model:

bind <destination> from <source>

User-Facing Shape

Primary CLI:

wf draft bind <workspace_id> `
  --revision <n> `
  --step <step_id> `
  --from <path> `
  --to <path>

Examples:

# Workflow input into a capability input.
wf draft bind browser_ws --revision 2 --step click `
  --from input.simulate `
  --to local.simulate
# Capability output into workflow state.
wf draft bind browser_ws --revision 3 --step click `
  --from local.after `
  --to state.after
# Capability output into final workflow output.
wf draft bind report_ws --revision 7 --step render `
  --from local.markdown `
  --to output.markdown

Semantics

bind is capability-aware and step-scoped. The step must be a capability-backed draft step with a use field.

Supported directions:

From To Draft edit Schema projection
input.* local.* add/merge step input binding copy capability input schema for local.* into workflow input_schema at input.*
state.* local.* add/merge step input binding copy capability input schema for local.* into workflow state_schema at state.*
local.* state.* add/merge step output binding copy capability output schema for local.* into workflow state_schema at state.*
local.* output.* add/merge step output binding copy capability output schema for local.* into workflow output_schema at output.*

Unsupported directions should fail clearly:

  • local.* -> local.*
  • input.* -> state.*
  • state.* -> output.*
  • output.* -> local.*
  • Any path root outside input, state, output, or local

Schema Projection

The schema projection helper should be generalized from the current output-to-state helper.

Requirements:

  • Use jsonschema.Draft202012Validator.check_schema to validate input schemas and projected schemas. Do not hand-roll JSON Schema validation.
  • Copy the selected local field schema from the capability input/output schema.
  • Preserve $defs and definitions, rejecting conflicting definitions.
  • Insert the copied field schema at the target workflow path.
  • Support nested target paths such as state.options.timeout_seconds.
  • Create missing ancestor object schemas only when the ancestor does not exist.
  • Reject inserting through an existing non-object ancestor.
  • Reject overwriting an existing target property by default.

Nested insertion example:

{
  "type": "object",
  "properties": {
    "options": {
      "type": "object",
      "properties": {
        "timeout_seconds": { "type": "number" }
      }
    }
  }
}

This is a schema projection operation, not a general JSON Schema editor. It only copies one capability local input/output field schema to one workflow graph path.

API Shape

Add the general method:

async def bind_draft(
    self,
    *,
    workspace_id: str,
    revision: int,
    step_id: str,
    source_path: str,
    target_path: str,
) -> dict[str, Any]:
    ...

Name notes:

  • User-facing CLI says bind --from ... --to ....
  • Python/RPC names should avoid reserved words and use source_path / target_path.
  • Remove bind_output_to_state end-to-end. It has no long-lived compatibility contract and is replaced by bind_draft.

RPC And MCP

New JSON-RPC method:

workflow.draft_workspaces.bind

Params:

{
  "workspace_id": "browser_ws",
  "revision": 3,
  "step_id": "click",
  "source_path": "local.after",
  "target_path": "state.after"
}

New MCP tool:

wf.workflow.bind

Remove existing RPC/MCP bind_output_to_state surfaces during this slice.

Repair Hints

Existing invalid-destination hints currently recommend:

wf draft bind-output-to-state ...

They should instead recommend:

wf draft bind <workspace_id> --revision <n> --step <step_id> --from local.<field> --to state.<field>

Future missing-input-schema diagnostics can also point to:

wf draft bind <workspace_id> --revision <n> --step <step_id> --from input.<field> --to local.<field>

Non-Goals

  • Do not preserve bind-output-to-state as a compatibility alias.
  • Do not add arbitrary schema editing commands.
  • Do not support array item schema projection.
  • Do not infer routes.
  • Do not mutate bindings without revision checks.

Acceptance Criteria

  • Agents can fix browser-click input schema issues with wf draft bind --from input.simulate --to local.simulate instead of raw JSON Patch.
  • Agents can bind outputs with wf draft bind --from local.after --to state.after; the old bind-output-to-state command/method/tool is gone.
  • Nested target paths are handled safely or rejected with clear errors.