Files
lda-wf/docs/historical/superpowers/plans/2026-07-26-capability-step-update.md
T

28 KiB

Capability Step Update Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Add one atomic, presence-aware capability-step update across Python, JSON-RPC, MCP, and CLI, and let capability-step creation set the same metadata and canonical literal inputs directly.

Architecture: Define a transport-safe CapabilityStepUpdate model in wf_api, then keep all semantic mutation in WorkflowDraftAuthoringApi. Extract the existing capability-aware input-binding preflight into one private implementation reused by set-input, update, and creation. RPC, MCP, and CLI are adapters that preserve omitted fields, explicit metadata nulls, and canonical binding order.

Tech Stack: Python 3.14, Pydantic 2, Typer, FastAPI JSON-RPC, FastMCP, pytest, Ruff, basedpyright.

Global Constraints

  • Never change an existing step's use capability.
  • Preserve routes, output bindings, and unrelated step fields.
  • Omitted update fields preserve stored values.
  • Explicit metadata null clears; explicit input: null is invalid.
  • Supplied input replaces the complete ordered canonical list; [] clears.
  • Reuse one capability-aware input preflight for set-input, update, and add.
  • Stale revision wins over semantic step, capability, path, and schema errors.
  • Metadata-only updates must not resolve the capability source.
  • Exact no-ops do not increment revision.
  • Input clearing does not delete previously projected workflow schemas.
  • Keep compatibility input_map for real callers, but reject simultaneous compatibility and canonical input forms.
  • Keep routes and output bindings under their existing focused operations.
  • Python baseline is 3.14. Add comments/docstrings around field-presence and schema-projection behavior that is not obvious.
  • Use scoped tests in each task and the complete focused matrix only in Task 5.

Task 1: Presence-Aware Model And Canonical Authoring

Files:

  • Create: src/wf_api/draft_updates.py
  • Modify: src/wf_api/__init__.py
  • Modify: src/wf_api/draft_authoring.py
  • Modify: tests/wf_api/test_drafts_service.py

Interfaces:

  • Produces: CapabilityStepUpdate(desc, retry, timeout_seconds, input).

  • Produces: WorkflowDraftAuthoringApi.update_capability_step(*, workspace_id: str, revision: int, step_id: str, update: CapabilityStepUpdate).

  • Extends: WorkflowDraftAuthoringApi.add_step_from_capability(..., desc=None, retry=None, timeout_seconds=None, input_bindings=None).

  • Preserves: WorkflowDraftAuthoringApi.set_step_input_bindings(...).

  • Step 1: Write failing update-model tests

Add focused tests in tests/wf_api/test_drafts_service.py:

def test_capability_step_update_preserves_field_presence() -> None:
    update = CapabilityStepUpdate.model_validate(
        {"desc": None, "retry": 0, "input": []}
    )

    assert update.model_fields_set == {"desc", "retry", "input"}
    assert update.desc is None
    assert update.retry == 0
    assert update.input == []


@pytest.mark.parametrize(
    "payload",
    [
        {},
        {"input": None},
        {"desc": ""},
        {"retry": -1},
        {"timeout_seconds": 0},
    ],
)
def test_capability_step_update_rejects_invalid_patch(payload: object) -> None:
    with pytest.raises(ValidationError):
        CapabilityStepUpdate.model_validate(payload)
  • Step 2: Run the model tests red

Run:

.venv\Scripts\python.exe -m pytest -n 0 `
  tests/wf_api/test_drafts_service.py `
  -q -k "capability_step_update_preserves or capability_step_update_rejects" `
  --basetemp=.pytest-capability-update-model-red

Expected: collection fails because CapabilityStepUpdate does not exist.

  • Step 3: Implement the update model

Create src/wf_api/draft_updates.py:

from __future__ import annotations

from typing import Self

from pydantic import BaseModel, ConfigDict, Field, model_validator

from wf_core.models.steps import InputBinding


class CapabilityStepUpdate(BaseModel):
    """Presence-aware patch for one existing capability-backed draft step."""

    model_config = ConfigDict(extra="forbid")

    desc: str | None = Field(default=None, min_length=1)
    retry: int | None = Field(default=None, ge=0)
    timeout_seconds: int | None = Field(default=None, gt=0)
    input: list[InputBinding] | None = None

    @model_validator(mode="after")
    def validate_patch_shape(self) -> Self:
        if not self.model_fields_set:
            raise ValueError("capability step update requires at least one field")
        if "input" in self.model_fields_set and self.input is None:
            raise ValueError("capability step update input must be a list")
        return self

Export it from src/wf_api/__init__.py. Run the model tests green.

  • Step 4: Write failing semantic update tests

Add a helper that creates a capability-backed draft step containing:

  • use;
  • path and literal input bindings;
  • output bindings;
  • desc;
  • retry;
  • timeout_seconds;
  • routes.

Add tests with field-level assertions:

@pytest.mark.asyncio
async def test_update_capability_step_changes_metadata_and_inputs_atomically(
    tmp_path: Path,
) -> None:
    draft_api, _, authoring = _draft_api(
        FileWorkflowArtifactStore(tmp_path / "update_capability"),
        register_echo=True,
    )
    draft = _echo_draft()
    draft["steps"]["echo"].update(
        {
            "desc": "Old description",
            "retry": 1,
            "timeout_seconds": 10,
        }
    )
    await draft_api.create_draft_workspace(workspace_id="echo", draft=draft)

    result = await authoring.update_capability_step(
        workspace_id="echo",
        revision=1,
        step_id="echo",
        update=CapabilityStepUpdate.model_validate(
            {
                "desc": "New description",
                "retry": 0,
                "timeout_seconds": None,
                "input": [
                    {"path": "input.text", "target": "text"},
                ],
            }
        ),
    )
    inspected = await draft_api.get_draft_workspace(
        workspace_id="echo",
        include_draft=True,
    )

    step = inspected["draft"]["steps"]["echo"]
    assert result["revision"] == 2
    assert step["use"] == "demo.personal.echo_tool"
    assert step["desc"] == "New description"
    assert step["retry"] == 0
    assert "timeout_seconds" not in step
    assert step["input"] == [{"path": "input.text", "target": "text"}]
    assert step["output"] == draft["steps"]["echo"]["output"]
    assert inspected["draft"]["routes"]["echo"] == {"ok": "__end__"}

Add separate tests for:

  • omitted fields preserved;

  • each metadata field set and cleared;

  • exact no-op keeps revision;

  • input=[] clears bindings but preserves projected schemas;

  • metadata-only update succeeds when capability lookup is monkeypatched to fail;

  • missing step and non-DraftUseStep rejection;

  • stale revision wins over missing step, wrong kind, and unavailable capability;

  • malformed input leaves the complete inspected workspace unchanged;

  • path/literal input replacement projects schemas and preserves order;

  • compile/run succeeds after one combined metadata/input update.

  • Step 5: Run semantic tests red

Run:

.venv\Scripts\python.exe -m pytest -n 0 `
  tests/wf_api/test_drafts_service.py `
  -q -k "update_capability_step" `
  --basetemp=.pytest-capability-update-authoring-red

Expected: failures because the authoring method does not exist.

  • Step 6: Extract one shared input-binding preflight

In src/wf_api/draft_authoring.py, add a private result model:

@dataclass(frozen=True)
class _ProjectedStepInputBindings:
    payload: list[dict[str, Any]]
    input_schema: dict[str, Any]
    state_schema: dict[str, Any]

Extract the current semantic body of set_step_input_bindings into a private method:

def _project_step_input_bindings(
    self,
    *,
    workspace: WorkflowDraftWorkspace,
    capability_name: str,
    bindings: Sequence[InputBinding],
) -> _ProjectedStepInputBindings:
    """Validate canonical inputs and project missing workflow source schemas."""

This method must:

  1. resolve the capability;
  2. reject overlapping local targets;
  3. require every target in the capability input schema;
  4. validate literal values, including root-object behavior;
  5. preserve context.* without schema projection;
  6. project missing input.* and state.* source schemas;
  7. return canonical binding payload and projected schemas.

Rewrite set_step_input_bindings to call this method, preserving its no-op and patch behavior. Run all existing set_step_input_bindings tests before adding the update method:

.venv\Scripts\python.exe -m pytest -n 0 `
  tests/wf_api/test_drafts_service.py `
  -q -k "step_input_bindings" `
  --basetemp=.pytest-capability-update-shared-preflight

Expected: PASS.

  • Step 7: Implement atomic capability-step update

Implement:

async def update_capability_step(
    self,
    *,
    workspace_id: str,
    revision: int,
    step_id: str,
    update: CapabilityStepUpdate,
) -> dict[str, Any]:
    """Patch capability metadata and optional canonical inputs atomically."""

Required implementation shape:

checked = self._workspace_if_revision_matches(
    workspace_id=workspace_id,
    revision=revision,
)
if isinstance(checked, dict):
    return checked
workspace = checked
step = draft_step(workspace.draft, step_id)
if step.get("kind") != "use":
    raise ValueError(f"step {step_id!r} is not capability-backed")
current = DraftUseStep.model_validate(step)

changes: dict[str, object] = {}
for field in ("desc", "retry", "timeout_seconds"):
    if field in update.model_fields_set:
        changes[field] = getattr(update, field)

projected = None
if "input" in update.model_fields_set:
    assert update.input is not None
    projected = self._project_step_input_bindings(
        workspace=workspace,
        capability_name=current.use,
        bindings=update.input,
    )
    changes["input"] = update.input

changed = current.model_copy(update=changes)
step_payload = changed.model_dump(
    mode="json",
    by_alias=True,
    exclude_none=True,
)

Do not use model_copy(update=...) with unvalidated external values; all values here come from CapabilityStepUpdate. Build one patch for changed schemas plus replacement of /steps/<step_id>. If the step payload and schemas are unchanged, return summarize_draft_workspace(workspace).

  • Step 8: Write failing creation-parity tests

Add tests proving:

result = await authoring.add_step_from_capability(
    workspace_id="report",
    revision=1,
    step_id="publish",
    capability_name="demo.personal.structured_report",
    routes={"ok": "__end__"},
    desc="Publish report",
    retry=2,
    timeout_seconds=30,
    input_bindings=[
        InputPathBinding(
            path=GraphSourcePath.state("report", "title"),
            target=LocalPath.of("request", "title"),
        ),
        InputValueBinding(
            target=LocalPath.of("request", "format"),
            value="markdown",
        ),
    ],
)

Assert metadata, ordered canonical bindings, and projected schemas. Add tests rejecting input_map and input_bindings whenever both arguments are supplied, including an explicit empty compatibility map, and proving existing map-only callers retain behavior.

  • Step 9: Extend creation through the shared preflight

Extend the method signature:

async def add_step_from_capability(
    ...,
    input_map: dict[str, str] | None = None,
    input_bindings: Sequence[InputBinding] | None = None,
    bind_outputs: dict[str, str] | None = None,
    desc: str | None = None,
    retry: int | None = None,
    timeout_seconds: int | None = None,
) -> dict[str, Any]:

If both canonical bindings and a compatibility map are supplied, even when either collection is explicitly empty, raise:

input_map and input_bindings are mutually exclusive

Lower compatibility input_map with input_bindings_payload(input_map, {}) and validate the resulting typed list, or accept input_bindings directly. Use _project_step_input_bindings for both. Persist metadata only when not None; retry=0 must survive.

  • Step 10: Verify and commit Task 1

Run:

.venv\Scripts\python.exe -m pytest -n 0 `
  tests/wf_api/test_drafts_service.py -q `
  --basetemp=.pytest-capability-update-task1
.venv\Scripts\ruff.exe check `
  src/wf_api/draft_updates.py `
  src/wf_api/draft_authoring.py `
  tests/wf_api/test_drafts_service.py
.venv\Scripts\basedpyright.exe --level error `
  src/wf_api/draft_updates.py `
  src/wf_api/draft_authoring.py

Then:

git add src/wf_api/__init__.py src/wf_api/draft_updates.py \
  src/wf_api/draft_authoring.py tests/wf_api/test_drafts_service.py
git commit -m "feat: update capability-backed draft steps"

Task 2: Public Interface And JSON-RPC

Files:

  • Modify: src/wf_api/surface.py
  • Modify: src/wf_api/service.py
  • Modify: src/wf_transport_rpc_http/models.py
  • Modify: src/wf_transport_rpc_http/methods/drafts.py
  • Modify: src/wf_transport_rpc_http/client/drafts.py
  • Modify: src/wf_transport_rpc_http/__init__.py
  • Modify: tests/wf_transport_rpc_http/test_app.py
  • Modify: tests/wf_transport_rpc_http/test_client.py

Interfaces:

  • Consumes: Task 1's CapabilityStepUpdate, update_capability_step(...), and extended add_step_from_capability(...).

  • Produces: workflow.draft_workspaces.update_capability_step.

  • Extends the existing add-capability RPC with metadata and canonical input_bindings.

  • Step 1: Write failing RPC model tests

Add tests for:

params = UpdateCapabilityStepParams.model_validate(
    {
        "workspace_id": "report",
        "revision": 4,
        "step_id": "publish",
        "update": {"desc": None, "retry": 0},
    }
)

assert params.update.model_fields_set == {"desc", "retry"}
assert params.update.desc is None
assert params.update.retry == 0

Add malformed cases for empty update, input:null, negative retry, zero timeout, and unknown fields. Extend AddStepFromCapabilityParams tests for metadata, canonical path/value order, and simultaneous input_map plus input_bindings.

  • Step 2: Run RPC model tests red

Run the focused new tests. Expected: import/model failures.

  • Step 3: Add RPC models

Add:

class UpdateCapabilityStepParams(RpcParamsModel):
    workspace_id: str = Field(min_length=1)
    revision: int = Field(ge=1)
    step_id: str = Field(min_length=1)
    update: CapabilityStepUpdate

Extend AddStepFromCapabilityParams:

input_map: dict[str, str] | None = None
input_bindings: list[InputBinding] | None = None
desc: str | None = Field(default=None, min_length=1)
retry: int | None = Field(default=None, ge=0)
timeout_seconds: int | None = Field(default=None, gt=0)

Add a model validator rejecting both input forms when both were supplied.

  • Step 4: Write failing endpoint and client tests

Add a real ASGI test that creates a capability step, updates metadata and a literal input through:

workflow.draft_workspaces.update_capability_step

Inspect the draft and assert preservation of use, routes, and outputs.

Add a client serialization test that passes:

CapabilityStepUpdate.model_validate({"desc": None, "retry": 0})

and asserts the emitted nested object is exactly:

{"desc": None, "retry": 0}

No default timeout_seconds or input keys may appear. Extend add-capability client tests for canonical input order and metadata.

  • Step 5: Implement public and RPC adapters

Add the update method to WorkflowDraftSurface and WorkflowApi, delegating to draft_authoring.

Register the RPC method and client. The client must serialize:

update.model_dump(mode="json", exclude_unset=True)

Extend every add-capability seam with the Task 1 fields. Compatibility map-only calls remain valid.

  • Step 6: Verify and commit Task 2

Run:

.venv\Scripts\python.exe -m pytest -n 0 `
  tests/wf_transport_rpc_http/test_app.py `
  tests/wf_transport_rpc_http/test_client.py `
  -q --basetemp=.pytest-capability-update-task2
.venv\Scripts\ruff.exe check src/wf_api src/wf_transport_rpc_http `
  tests/wf_transport_rpc_http
.venv\Scripts\basedpyright.exe --level error

Commit:

git add src/wf_api/surface.py src/wf_api/service.py \
  src/wf_transport_rpc_http tests/wf_transport_rpc_http
git commit -m "feat: expose capability step updates over rpc"

Task 3: MCP Update Tool And Creation Parity

Files:

  • Modify: src/wf_mcp/workflow_surface/models.py
  • Modify: src/wf_mcp/workflow_surface/tools.py
  • Modify: src/wf_mcp/proxy/runtime.py
  • Modify: tests/wf_mcp/workflow_surface/test_drafts.py
  • Modify: tests/wf_mcp/server/test_tools.py
  • Modify: tests/wf_mcp/server/test_config.py

Interfaces:

  • Consumes: Task 2's public update method and Task 1's model.

  • Produces: wf.workflow.update_capability_step.

  • Extends: wf.workflow.add_step_from_capability.

  • Step 1: Write failing MCP request tests

Add:

request = UpdateCapabilityStepRequest.model_validate(
    {
        "workspace_id": "report",
        "revision": 4,
        "step_id": "publish",
        "update": {
            "desc": None,
            "input": [
                {"value": "markdown", "target": "request.format"},
            ],
        },
    }
)

assert request.update.model_fields_set == {"desc", "input"}
assert isinstance(request.update.input[0], InputValueBinding)

Add malformed update cases and add-capability request parity tests.

  • Step 2: Write failing discovery and real invocation tests

Require the tool in normal and search-mode inventories. Call it through an in-memory FastMCP client and assert:

  • one delegation;
  • typed CapabilityStepUpdate;
  • exact model_fields_set;
  • exact canonical binding order.

Extend the add-capability invocation test with metadata and a literal binding.

  • Step 3: Implement MCP request and tools

Add:

class UpdateCapabilityStepRequest(BaseModel):
    workspace_id: WorkspaceId
    revision: int = Field(ge=1)
    step_id: NonEmptyString
    update: CapabilityStepUpdate

Register:

@server.tool(
    name="wf.workflow.update_capability_step",
    title="Update Capability Step",
    description=(
        "Update capability-step metadata and optionally replace its complete "
        "canonical input bindings. Preserves use, routes, and outputs."
    ),
)
async def update_capability_step(
    request: UpdateCapabilityStepRequest,
) -> DraftWorkspaceResult:
    return DraftWorkspaceResult.model_validate(
        await handlers.update_capability_step(
            workspace_id=request.workspace_id,
            revision=request.revision,
            step_id=request.step_id,
            update=request.update,
        )
    )

Add the name to _SEARCH_ALWAYS_VISIBLE_TOOL_NAMES. Extend AddStepFromCapabilityRequest and its tool delegation with the creation-parity fields.

  • Step 4: Verify and commit Task 3

Run:

.venv\Scripts\python.exe -m pytest -n 0 `
  tests/wf_mcp/workflow_surface/test_drafts.py `
  tests/wf_mcp/server/test_tools.py `
  tests/wf_mcp/server/test_config.py `
  -q --basetemp=.pytest-capability-update-task3
.venv\Scripts\ruff.exe check src/wf_mcp tests/wf_mcp
.venv\Scripts\basedpyright.exe --level error

Commit:

git add src/wf_mcp tests/wf_mcp
git commit -m "feat: expose capability step updates to mcp"

Task 4: Add And Update CLI

Files:

  • Create: src/wf_cli/commands/draft_update.py
  • Modify: src/wf_cli/commands/draft_add.py
  • Modify: src/wf_cli/commands/draft_options.py
  • Modify: src/wf_cli/commands/drafts.py
  • Modify: tests/wf_cli/test_app.py
  • Modify: tests/wf_cli/test_remote_target.py

Interfaces:

  • Consumes: Task 2's local/remote update and extended add methods.

  • Produces: wf draft update capability.

  • Extends: wf draft add capability.

  • Step 1: Write failing parser tests

Refactor the private input-shaped path parser so the option name and target audience are parameters:

def _parse_input_path_binding_flags(
    values: list[str] | None,
    *,
    option_name: str,
    target_label: str,
) -> list[InputPathBinding]:

Keep parse_step_input_binding_flags behavior unchanged. Add:

def parse_capability_input_binding_flags(
    values: list[str] | None,
) -> list[InputPathBinding]:
    return _parse_input_path_binding_flags(
        values,
        option_name="--input",
        target_label="node-local",
    )

Reuse parse_step_input_value_flags and parse_step_input_bindings_file. Write tests for --input-specific diagnostics and canonical order.

  • Step 2: Write failing update command tests

Add local CLI tests for:

wf draft update capability report --revision 4 --step publish \
  --description "Publish report" \
  --retry 0 \
  --clear-timeout \
  --input state.report.title=request.title \
  --value request.format='"markdown"'

Assert the fake handler receives a CapabilityStepUpdate whose model_fields_set is exactly:

{"desc", "retry", "timeout_seconds", "input"}

and whose input bindings preserve path-then-literal order.

Add tests for every set/clear conflict, bindings-file conflict, clear-input conflict, empty update, and validation before load_cli_context.

  • Step 3: Implement the update command group

Create draft_update.py with a Typer group and capability command. Build a plain payload dictionary only from selected flags:

payload: dict[str, object] = {}
if description is not None:
    payload["desc"] = description
elif clear_description:
    payload["desc"] = None

if retry is not None:
    payload["retry"] = retry
elif clear_retry:
    payload["retry"] = None

if timeout_seconds is not None:
    payload["timeout_seconds"] = timeout_seconds
elif clear_timeout:
    payload["timeout_seconds"] = None

if input_mode_selected:
    payload["input"] = bindings

update = CapabilityStepUpdate.model_validate(payload)

Parse all exclusivity and validation errors before loading context. Register:

app.add_typer(draft_update.app, name="update")

in drafts.py.

  • Step 4: Write failing add-command parity tests

Test wf draft add capability with metadata, --input, --value, and --bindings-file. Pin:

  • canonical path/value order;

  • retry=0;

  • bindings-file exact interleaving;

  • file/convenience exclusivity before context;

  • existing path-only invocation unchanged.

  • Step 5: Extend add capability

Add the approved flags and call canonical input_bindings. Do not pass both the compatibility map and canonical list. The CLI should use canonical bindings for every new invocation; input_map remains only for non-CLI compatibility callers.

  • Step 6: Add remote parity tests

Use the real ASGI RPC target to assert exact methods and payloads:

workflow.draft_workspaces.update_capability_step
workflow.draft_workspaces.add_step_from_capability

For update, assert omitted metadata keys do not appear and explicit clears do. For add, assert ordered path/value input bindings and metadata.

  • Step 7: Verify and commit Task 4

Run:

.venv\Scripts\python.exe -m pytest -n 0 `
  tests/wf_cli/test_app.py `
  tests/wf_cli/test_remote_target.py `
  -q --basetemp=.pytest-capability-update-task4
.venv\Scripts\ruff.exe check src/wf_cli tests/wf_cli
.venv\Scripts\basedpyright.exe --level error

Commit:

git add src/wf_cli tests/wf_cli
git commit -m "feat: add capability step update cli"

Task 5: Documentation, Verification, And Review

Files:

  • Modify: ISSUES.md
  • Modify: docs/wf_cli.md
  • Modify: docs/workflow_drafts.md
  • Modify: docs/workflow_capabilities.md
  • Modify: docs/wf_mcp_operator_manual.md
  • Modify: skills/wf-cli/SKILL.md
  • Modify: skills/wf-workflow/references/draft-workspaces.md
  • Modify: skills/wf-workflow/references/workflow-lifecycle.md
  • Modify: docs/current_roadmap.md
  • Move: docs/superpowers/plans/2026-07-26-capability-step-update.md to docs/historical/superpowers/plans/2026-07-26-capability-step-update.md

Interfaces:

  • Consumes: verified Tasks 1-4.

  • Produces: accurate current docs, closed issue state, archived checked plan, and final review evidence.

  • Step 1: Update issue and roadmap state

Mark the focused capability-step update issue complete. State that:

  • creation accepts metadata and canonical literal inputs;
  • update preserves use, routes, and outputs;
  • update can atomically replace canonical input bindings;
  • changing capability remains remove/add;
  • TypeScript parity remains open.

Add a completed roadmap entry linked to the historical plan.

  • Step 2: Update user and agent docs

Document:

wf draft add capability report --revision 3 --step publish \
  --capability local.report.publish \
  --description "Publish report" \
  --retry 2 \
  --timeout-seconds 30 \
  --input state.report.title=request.title \
  --value request.format='"markdown"' \
  --route ok=__end__

wf draft update capability report --revision 4 --step publish \
  --clear-description \
  --retry 0 \
  --clear-timeout

Explain omission versus clearing, complete input replacement, bindings-file interleaving, and separate route/output operations. Add JSON-RPC and MCP operation names to live inventories.

  • Step 3: Archive the checked plan

Mark every checkbox complete, move the plan to the historical path, and update all live links:

rg -n '2026-07-26-capability-step-update' docs skills README.md
  • Step 4: Run the full focused matrix

Run:

.venv\Scripts\python.exe -m pytest -n 0 `
  tests/wf_api/test_drafts_service.py `
  tests/wf_transport_rpc_http/test_app.py `
  tests/wf_transport_rpc_http/test_client.py `
  tests/wf_mcp/workflow_surface/test_drafts.py `
  tests/wf_mcp/server/test_tools.py `
  tests/wf_mcp/server/test_config.py `
  tests/wf_cli/test_app.py `
  tests/wf_cli/test_remote_target.py `
  -q --basetemp=.pytest-capability-update-final

Expected: PASS with only already-known dependency deprecation warnings.

  • Step 5: Run static verification

Run:

.venv\Scripts\ruff.exe check
.venv\Scripts\ruff.exe format --check
.venv\Scripts\basedpyright.exe --level error
git diff --check

Expected: all clean.

  • Step 6: Run independent two-axis review

Review from commit 05afc2e1 through the current worktree against:

docs/superpowers/specs/2026-07-26-capability-step-update-design.md

Require findings first with severity and file/line references. The spec reviewer must inspect:

  • omission versus explicit null;
  • explicit input:null rejection;
  • stale-revision precedence;
  • metadata-only operation without capability resolution;
  • no-op revision behavior;
  • preservation of use, outputs, and routes;
  • shared input preflight rather than duplicated semantics;
  • add/update canonical input parity;
  • RPC exclude_unset=True;
  • CLI pre-context exclusivity;
  • MCP discovery and real invocation;
  • docs and issue truthfulness.

Fix every Critical and Important finding and rerun affected checks.

  • Step 7: Commit documentation and review fixes

Commit documentation:

git add ISSUES.md docs skills
git commit -m "docs: complete capability step updates"

Commit production/test review fixes separately after verification. Finish:

git status --short --branch
git log --oneline -10

Expected: clean worktree and task-level commits.