27 KiB
Run List API/RPC/CLI 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: Expose persisted stopped workflow runs through a compact, paged list_runs API, JSON-RPC method, RPC client method, and wf run list CLI command.
Architecture: RunStore.list_runs() already stores durable run records for completed, failed, and interrupted runs. Add a summary-only read surface in wf_api, delegate it through WorkflowApiSurface, expose it over JSON-RPC, and add a CLI command that emits JSON like the rest of wf run. Do not expose checkpoints, trace entries, deletion, retention, or retry policy in this slice.
Tech Stack: Python 3.14, Pydantic v2, Typer, fastapi-jsonrpc, pytest/pytest-asyncio, ruff, basedpyright.
Desired Behavior
wf run list should answer “what durable runs exist in this target store?” without requiring a run id.
Output shape:
{
"runs": [
{
"run_id": "run_abc",
"deployment_id": "echo.personal",
"artifact_id": "echo",
"artifact_version": 1,
"status": "completed",
"resume_readiness": "not_applicable",
"diagnostic_count": 0,
"created_at": "2026-06-11T00:00:00Z",
"updated_at": "2026-06-11T00:00:01Z"
}
],
"total": 1,
"cursor": null,
"next_cursor": null,
"limit": 50
}
Rules:
- Sort newest first by
updated_at, thenrun_id. - Support
statusfilter values:completed,failed,interrupted. - Use offset cursor strings:
cursor="0",cursor="50", etc. - Reject invalid
cursor,limit, andstatuswithValueErrorinwf_api. - Do not include trace entries, checkpoint state,
output,error, or pinned artifact/deployment bodies in list rows. - Keep
inspect_runas the detail surface andread_run_traceas the bounded trace surface.
File Structure
- Modify
src/wf_api/runs.py- Add
WorkflowRunApi.list_runs(...). - Add
_run_summary(record)and_cursor_offset(cursor)helpers.
- Add
- Modify
src/wf_api/surface.py- Add
list_runs(...)toWorkflowRunSurface.
- Add
- Modify
src/wf_api/service.py- Add
WorkflowApi.list_runs(...)delegate.
- Add
- Modify
src/wf_transport_rpc_http/models.py- Add
ListRunsParams.
- Add
- Modify
src/wf_transport_rpc_http/methods/runs.py- Register
workflow.runs.list.
- Register
- Modify
src/wf_transport_rpc_http/client/runs.py- Add
RpcRunClientMixin.list_runs(...).
- Add
- Modify
src/wf_cli/commands/runs.py- Add
wf run list.
- Add
- Modify tests:
tests/wf_api/test_run_api.pytests/wf_transport_rpc_http/test_app.pytests/wf_transport_rpc_http/test_client.pytests/wf_cli/test_run_deploy.pyortests/wf_cli/test_remote_target.py, whichever already owns run CLI routing assertions.
- Modify docs:
docs/wf_cli.mddocs/current_roadmap.mddocs/superpowers/specs/2026-06-03-persisted-run-resume-contract.md
Task 1: Add WorkflowRunApi.list_runs
Files:
-
Modify:
src/wf_api/runs.py -
Modify:
tests/wf_api/test_run_api.py -
Step 1: Add failing API tests
Append these tests to tests/wf_api/test_run_api.py. Prefer async def for the new tests; existing older tests can remain unchanged.
async def test_run_api_lists_runs_newest_first_with_summary(tmp_path: Path) -> None:
root = tmp_path / "run_api_list"
service, _ = _service_with_echo(root)
context = context_from_service(service)
api = WorkflowRunApi(context)
first = await api.run_deployment(
deployment_id="echo.personal",
workflow_input={"text": "first"},
)
second = await api.run_deployment(
deployment_id="echo.personal",
workflow_input={"text": "second"},
)
payload = await api.list_runs()
assert payload["total"] == 2
assert payload["cursor"] is None
assert payload["next_cursor"] is None
assert payload["limit"] == 50
assert [row["run_id"] for row in payload["runs"]] == [
second["run_id"],
first["run_id"],
]
first_row = payload["runs"][0]
assert first_row["deployment_id"] == "echo.personal"
assert first_row["artifact_id"] == "echo"
assert first_row["artifact_version"] == 1
assert first_row["status"] == "completed"
assert first_row["resume_readiness"] == "not_applicable"
assert first_row["diagnostic_count"] == 0
assert "trace" not in first_row
assert "output" not in first_row
assert "environment" not in first_row
async def test_run_api_lists_runs_with_status_filter_and_offset_cursor(
tmp_path: Path,
) -> None:
root = tmp_path / "run_api_list_filter"
service, _ = _service_with_echo(root)
context = context_from_service(service)
api = WorkflowRunApi(context)
await api.run_deployment(
deployment_id="echo.personal",
workflow_input={"text": "first"},
)
await api.run_deployment(
deployment_id="echo.personal",
workflow_input={"text": "second"},
)
first_page = await api.list_runs(status="completed", limit=1)
second_page = await api.list_runs(
status="completed",
cursor=first_page["next_cursor"],
limit=1,
)
assert first_page["total"] == 2
assert first_page["next_cursor"] == "1"
assert len(first_page["runs"]) == 1
assert second_page["total"] == 2
assert second_page["cursor"] == "1"
assert second_page["next_cursor"] is None
assert len(second_page["runs"]) == 1
assert first_page["runs"][0]["run_id"] != second_page["runs"][0]["run_id"]
@pytest.mark.parametrize(
("kwargs", "message"),
[
({"status": "running"}, "status must be one of"),
({"cursor": "not-int"}, "cursor must be a non-negative integer offset"),
({"cursor": "-1"}, "cursor must be a non-negative integer offset"),
({"limit": 0}, "limit must be between 1 and 100"),
({"limit": 101}, "limit must be between 1 and 100"),
],
)
async def test_run_api_list_runs_rejects_invalid_query(
tmp_path: Path,
kwargs: dict[str, object],
message: str,
) -> None:
root = tmp_path / "run_api_list_invalid"
service, _ = _service_with_echo(root)
context = context_from_service(service)
api = WorkflowRunApi(context)
with pytest.raises(ValueError, match=message):
await api.list_runs(**kwargs)
- Step 2: Run the failing tests
Run:
uv run pytest tests/wf_api/test_run_api.py -q
Expected: fail because WorkflowRunApi has no list_runs.
- Step 3: Implement
list_runsinsrc/wf_api/runs.py
Add StoredRunStatus and WorkflowRunRecord to the existing wf_artifacts import:
from wf_artifacts import (
DependencyDiagnostic,
RunStore,
StoredRunStatus,
WorkflowArtifact,
WorkflowDeployment,
WorkflowRunRecord,
)
Add this method to WorkflowRunApi, after resume_run and before inspect_run:
async def list_runs(
self,
*,
status: str | None = None,
cursor: str | None = None,
limit: int = 50,
) -> dict[str, Any]:
"""Return compact persisted run summaries without trace or checkpoint state."""
if limit < 1 or limit > 100:
raise ValueError("limit must be between 1 and 100")
start = _cursor_offset(cursor)
status_filter: StoredRunStatus | None = None
if status is not None:
try:
status_filter = StoredRunStatus(status)
except ValueError as exc:
allowed = ", ".join(item.value for item in StoredRunStatus)
raise ValueError(f"status must be one of: {allowed}") from exc
records = self._run_store().list_runs()
if status_filter is not None:
records = [record for record in records if record.status == status_filter]
records.sort(key=lambda record: (record.updated_at, record.id), reverse=True)
total = len(records)
end = start + limit
page = records[start:end]
return {
"runs": [_run_summary(record) for record in page],
"total": total,
"cursor": cursor,
"next_cursor": str(end) if end < total else None,
"limit": limit,
}
Add these helpers near _trace_range_values:
def _cursor_offset(cursor: str | None) -> int:
"""Parse the simple offset cursor used by run listing."""
if cursor is None:
return 0
try:
offset = int(cursor)
except ValueError as exc:
raise ValueError("cursor must be a non-negative integer offset") from exc
if offset < 0:
raise ValueError("cursor must be a non-negative integer offset")
return offset
def _run_summary(record: WorkflowRunRecord) -> dict[str, Any]:
"""Return an operator-facing run row without heavy runtime state."""
environment = record.environment
return {
"run_id": record.id,
"deployment_id": environment.deployment.id,
"artifact_id": environment.root_artifact.id,
"artifact_version": environment.root_artifact.version,
"status": record.status.value,
"resume_readiness": record.resume_readiness.value,
"diagnostic_count": len(record.diagnostics),
"created_at": record.created_at.isoformat(),
"updated_at": record.updated_at.isoformat(),
}
- Step 4: Run API tests
Run:
uv run pytest tests/wf_api/test_run_api.py -q
Expected: all tests pass.
- Step 5: Commit API slice
Run:
git add src/wf_api/runs.py tests/wf_api/test_run_api.py
git commit -m "feat: add workflow run listing API"
Task 2: Add Surface And Facade Delegation
Files:
-
Modify:
src/wf_api/surface.py -
Modify:
src/wf_api/service.py -
Test:
tests/wf_api/test_run_api.py -
Step 1: Add delegation assertion to existing handler delegation test
In tests/wf_api/test_run_api.py, extend test_run_api_handler_delegation_matches after the existing inspect assertions:
handler_list = asyncio.run(handlers.list_runs())
api_list = asyncio.run(api.list_runs())
assert handler_list["total"] == api_list["total"]
assert handler_list["runs"][0]["run_id"] == api_list["runs"][0]["run_id"]
Expected: fail because WorkflowSurfaceHandlers may not expose list_runs yet. If it already delegates through WorkflowApi, add a new WorkflowApi facade test instead:
from wf_api import WorkflowApi
async def test_workflow_api_facade_lists_runs(tmp_path: Path) -> None:
root = tmp_path / "workflow_api_list_runs"
service, _ = _service_with_echo(root)
context = context_from_service(service)
api = WorkflowApi(context)
await api.run_deployment(
deployment_id="echo.personal",
workflow_input={"text": "hello"},
)
payload = await api.list_runs()
assert payload["total"] == 1
assert payload["runs"][0]["deployment_id"] == "echo.personal"
- Step 2: Add
list_runstoWorkflowRunSurface
In src/wf_api/surface.py, add this method at the top of WorkflowRunSurface, before run_deployment:
async def list_runs(
self,
*,
status: str | None = None,
cursor: str | None = None,
limit: int = 50,
) -> dict[str, Any]: ...
- Step 3: Add
WorkflowApi.list_runsdelegate
In src/wf_api/service.py, add this under # -- runs --, before run_deployment:
async def list_runs(
self,
*,
status: str | None = None,
cursor: str | None = None,
limit: int = 50,
) -> dict[str, Any]:
return await self.runs.list_runs(
status=status,
cursor=cursor,
limit=limit,
)
- Step 4: Add MCP workflow surface handler delegation if needed
If Step 1 fails because WorkflowSurfaceHandlers lacks list_runs, update src/wf_mcp/workflow_surface/handlers.py or the current handler module that owns run methods with:
async def list_runs(
self,
*,
status: str | None = None,
cursor: str | None = None,
limit: int = 50,
) -> dict[str, Any]:
return await self._api.list_runs(status=status, cursor=cursor, limit=limit)
Use the existing handler construction pattern in that file. Do not expose an MCP tool in this task unless the existing run tools are generated from this handler automatically.
- Step 5: Run tests
Run:
uv run pytest tests/wf_api/test_run_api.py -q
Expected: pass.
- Step 6: Commit surface slice
Run:
git add src/wf_api/surface.py src/wf_api/service.py src/wf_mcp/workflow_surface tests/wf_api/test_run_api.py
git commit -m "feat: expose run listing on workflow surface"
If no wf_mcp/workflow_surface file changed, omit that path from git add.
Task 3: Add JSON-RPC Method And Client
Files:
-
Modify:
src/wf_transport_rpc_http/models.py -
Modify:
src/wf_transport_rpc_http/methods/runs.py -
Modify:
src/wf_transport_rpc_http/client/runs.py -
Modify:
tests/wf_transport_rpc_http/test_app.py -
Modify:
tests/wf_transport_rpc_http/test_client.py -
Step 1: Add failing RPC app test
Append to tests/wf_transport_rpc_http/test_app.py:
async def test_rpc_run_list_method(tmp_path) -> None:
server = build_local_static_workflow_server(tmp_path / "store")
await server.api.create_artifact_from_plan(
artifact_id="list_runs_rpc",
version=1,
title="List Runs RPC",
plan=_constant_plan(),
outcomes=["ok"],
source_bindings={"wf.std": "wf.std"},
)
await server.api.save_deployment(
{
"id": "list_runs_rpc.default",
"artifact_id": "list_runs_rpc",
"artifact_version": 1,
"bindings": [{"logical_source": "wf.std", "concrete_source": "wf.std"}],
}
)
started = await server.api.run_deployment(
deployment_id="list_runs_rpc.default",
workflow_input={},
)
app = create_rpc_app(server)
transport = httpx.ASGITransport(app=app)
async with httpx.AsyncClient(transport=transport, base_url="http://test") as client:
payload = await _rpc(
client,
"workflow.runs.list",
{"status": "completed", "limit": 10},
)
assert payload["result"]["total"] == 1
assert payload["result"]["runs"][0]["run_id"] == started["run_id"]
assert payload["result"]["runs"][0]["deployment_id"] == "list_runs_rpc.default"
assert "trace" not in payload["result"]["runs"][0]
- Step 2: Add failing RPC client test
In tests/wf_transport_rpc_http/test_client.py, add a test near existing run client tests:
async def test_rpc_client_lists_runs(tmp_path) -> None:
server = build_local_static_workflow_server(tmp_path / "store")
await server.api.create_artifact_from_plan(
artifact_id="client_list_runs",
version=1,
title="Client List Runs",
plan=_constant_plan(),
outcomes=["ok"],
source_bindings={"wf.std": "wf.std"},
)
await server.api.save_deployment(
{
"id": "client_list_runs.default",
"artifact_id": "client_list_runs",
"artifact_version": 1,
"bindings": [{"logical_source": "wf.std", "concrete_source": "wf.std"}],
}
)
started = await server.api.run_deployment(
deployment_id="client_list_runs.default",
workflow_input={},
)
app = create_rpc_app(server)
transport = httpx.ASGITransport(app=app)
async with httpx.AsyncClient(transport=transport, base_url="http://test") as http:
client = RpcWorkflowApiClient(base_url="http://test/rpc", http_client=http)
listed = await client.list_runs(status="completed", limit=5)
assert listed["total"] == 1
assert listed["runs"][0]["run_id"] == started["run_id"]
If _constant_plan, create_rpc_app, or RpcWorkflowApiClient are already imported under different names, follow the existing file convention.
- Step 3: Run tests to verify failure
Run:
uv run pytest tests/wf_transport_rpc_http/test_app.py::test_rpc_run_list_method tests/wf_transport_rpc_http/test_client.py::test_rpc_client_lists_runs -q
Expected: fail because workflow.runs.list and client method are missing.
- Step 4: Add RPC params model
In src/wf_transport_rpc_http/models.py, add after TraceRangeParams or before StartRunParams:
class ListRunsParams(RpcParamsModel):
status: Literal["completed", "failed", "interrupted"] | None = None
cursor: str | None = None
limit: int = Field(default=50, ge=1, le=100)
- Step 5: Register JSON-RPC method
In src/wf_transport_rpc_http/methods/runs.py, import ListRunsParams:
from ..models import (
InspectRunParams,
ListRunsParams,
ReadRunTraceParams,
ResumeRunParams,
StartRunParams,
)
Add this method before workflow.runs.start:
@entrypoint.method(name="workflow.runs.list", errors=[WorkflowRpcError])
async def workflow_runs_list(
params: ListRunsParams = RpcParams(),
) -> dict[str, Any]:
try:
return await server.api.list_runs(
status=params.status,
cursor=params.cursor,
limit=params.limit,
)
except (ValueError, KeyError, LookupError, FileNotFoundError) as exc:
raise_workflow_rpc_error(exc)
- Step 6: Add RPC client method
In src/wf_transport_rpc_http/client/runs.py, add this method at the top of RpcRunClientMixin:
async def list_runs(
self: RpcCaller,
*,
status: str | None = None,
cursor: str | None = None,
limit: int = 50,
) -> dict[str, Any]:
return await self._call(
"workflow.runs.list",
{
"status": status,
"cursor": cursor,
"limit": limit,
},
)
- Step 7: Run RPC tests
Run:
uv run pytest tests/wf_transport_rpc_http/test_app.py::test_rpc_run_list_method tests/wf_transport_rpc_http/test_client.py::test_rpc_client_lists_runs -q
Expected: pass.
- Step 8: Commit RPC slice
Run:
git add src/wf_transport_rpc_http/models.py src/wf_transport_rpc_http/methods/runs.py src/wf_transport_rpc_http/client/runs.py tests/wf_transport_rpc_http/test_app.py tests/wf_transport_rpc_http/test_client.py
git commit -m "feat: expose run listing over json rpc"
Task 4: Add wf run list
Files:
-
Modify:
src/wf_cli/commands/runs.py -
Modify:
tests/wf_cli/test_run_deploy.pyortests/wf_cli/test_remote_target.py -
Step 1: Add CLI tests
If tests/wf_cli/test_run_deploy.py owns fake run handlers, add:
def test_wf_run_list_emits_json(monkeypatch) -> None:
captured: dict[str, object] = {}
class FakeHandlers:
async def list_runs(self, *, status=None, cursor=None, limit=50):
captured["status"] = status
captured["cursor"] = cursor
captured["limit"] = limit
return {
"runs": [
{
"run_id": "run_1",
"deployment_id": "demo.default",
"artifact_id": "demo",
"artifact_version": 1,
"status": "completed",
"resume_readiness": "not_applicable",
"diagnostic_count": 0,
"created_at": "2026-06-11T00:00:00",
"updated_at": "2026-06-11T00:00:01",
}
],
"total": 1,
"cursor": None,
"next_cursor": None,
"limit": 25,
}
monkeypatch.setattr(
"wf_cli.commands.runs.load_cli_context_from_typer",
lambda ctx: type("Ctx", (), {"handlers": FakeHandlers(), "verbose": False})(),
)
result = CliRunner().invoke(
app,
["list", "--status", "completed", "--limit", "25"],
)
assert result.exit_code == 0, result.output
payload = json.loads(result.output)
assert payload["total"] == 1
assert payload["runs"][0]["run_id"] == "run_1"
assert captured == {"status": "completed", "cursor": None, "limit": 25}
If that file does not import the run Typer app directly, follow the existing pattern in tests/wf_cli/test_remote_target.py and assert the command routes through the RPC client.
- Step 2: Run failing CLI test
Run the selected CLI test:
uv run pytest tests/wf_cli/test_run_deploy.py -q
Expected: fail because wf run list is missing.
- Step 3: Add command to
src/wf_cli/commands/runs.py
Add this command before start_run:
@app.command("list")
def list_runs(
ctx: typer.Context,
status: Annotated[
str | None,
typer.Option(
"--status",
help="Filter by stopped status: completed, failed, or interrupted.",
),
] = None,
cursor: Annotated[
str | None,
typer.Option("--cursor", help="Offset cursor returned by a previous page."),
] = None,
limit: Annotated[
int,
typer.Option("--limit", min=1, max=100, help="Maximum run summaries."),
] = 50,
) -> None:
"""List durable stopped workflow runs without trace entries."""
context = load_cli_context_from_typer(ctx)
payload = run_cli_operation(
context,
context.handlers.list_runs(status=status, cursor=cursor, limit=limit),
)
emit_json(payload)
- Step 4: Run CLI tests
Run:
uv run pytest tests/wf_cli/test_run_deploy.py tests/wf_cli/test_remote_target.py -q
Expected: pass.
- Step 5: Commit CLI slice
Run:
git add src/wf_cli/commands/runs.py tests/wf_cli/test_run_deploy.py tests/wf_cli/test_remote_target.py
git commit -m "feat: add wf run list command"
Only include the test files that changed.
Task 5: Docs And Verification
Files:
-
Modify:
docs/wf_cli.md -
Modify:
docs/current_roadmap.md -
Modify:
docs/superpowers/specs/2026-06-03-persisted-run-resume-contract.md -
Move:
docs/superpowers/plans/2026-06-11-run-list-api-rpc-cli.mdtodocs/historical/superpowers/plans/2026-06-11-run-list-api-rpc-cli.md -
Step 1: Update
docs/wf_cli.md
Add under the run commands section:
### List durable runs
```bash
wf run list --limit 20
wf run list --status interrupted
wf --url http://127.0.0.1:8765/rpc run list --status failed
wf run list returns compact stopped-run summaries from the target store. It
does not include trace entries or checkpoint state. Use wf run inspect <run_id>
for one run summary and wf run trace <run_id> --from 0 --limit 25 for bounded
debug detail.
- [ ] **Step 2: Update roadmap**
In `docs/current_roadmap.md`, under “Priority 2: Durable Run/Resume Hardening”, add:
```markdown
- Completed: paged `wf run list` exposes compact persisted stopped-run
summaries without trace or checkpoint state. Implementation:
[`run list API/RPC/CLI`](historical/superpowers/plans/2026-06-11-run-list-api-rpc-cli.md).
- Step 3: Update persisted run/resume spec
In docs/superpowers/specs/2026-06-03-persisted-run-resume-contract.md, update the section that says public listing is missing. Replace it with:
- `RunStore` can list runs, and the public workflow API exposes compact paged
run listing. Checkpoint listing remains intentionally private for now.
Also add a short operation note near the inspect_run/read_run_trace sections:
### `list_runs`
Returns paged compact summaries for stopped durable runs. The list payload
contains run id, deployment id, artifact id/version, status, resume readiness,
diagnostic count, and timestamps. It never returns trace entries, checkpoint
state, runtime output, or pinned environment bodies.
- Step 4: Move completed plan
Run:
git mv docs/superpowers/plans/2026-06-11-run-list-api-rpc-cli.md docs/historical/superpowers/plans/2026-06-11-run-list-api-rpc-cli.md
- Step 5: Run focused verification
Run:
uv run pytest tests/wf_api/test_run_api.py tests/wf_transport_rpc_http/test_app.py tests/wf_transport_rpc_http/test_client.py tests/wf_cli/test_run_deploy.py tests/wf_cli/test_remote_target.py -q
uv run ruff check src/wf_api/runs.py src/wf_api/surface.py src/wf_api/service.py src/wf_transport_rpc_http/models.py src/wf_transport_rpc_http/methods/runs.py src/wf_transport_rpc_http/client/runs.py src/wf_cli/commands/runs.py tests/wf_api/test_run_api.py tests/wf_transport_rpc_http/test_app.py tests/wf_transport_rpc_http/test_client.py tests/wf_cli/test_run_deploy.py tests/wf_cli/test_remote_target.py
uv run ruff format --check src/wf_api/runs.py src/wf_api/surface.py src/wf_api/service.py src/wf_transport_rpc_http/models.py src/wf_transport_rpc_http/methods/runs.py src/wf_transport_rpc_http/client/runs.py src/wf_cli/commands/runs.py tests/wf_api/test_run_api.py tests/wf_transport_rpc_http/test_app.py tests/wf_transport_rpc_http/test_client.py tests/wf_cli/test_run_deploy.py tests/wf_cli/test_remote_target.py
uv run basedpyright --level error src/wf_api src/wf_transport_rpc_http src/wf_cli tests/wf_api/test_run_api.py tests/wf_transport_rpc_http/test_app.py tests/wf_transport_rpc_http/test_client.py tests/wf_cli/test_run_deploy.py tests/wf_cli/test_remote_target.py
git diff --check
Expected:
-
Focused tests pass.
-
Ruff check passes.
-
Ruff format check passes.
-
Basedpyright reports 0 errors for changed files, or only explicitly documented unrelated pre-existing errors.
-
git diff --checkreports no whitespace errors; CRLF warnings on Windows are acceptable. -
Step 6: Final commit
Run:
git add docs/wf_cli.md docs/current_roadmap.md docs/superpowers/specs/2026-06-03-persisted-run-resume-contract.md docs/historical/superpowers/plans/2026-06-11-run-list-api-rpc-cli.md
git commit -m "docs: record run listing surface"
If code files remain uncommitted because earlier task commits were skipped, include all changed files in one final commit:
git add src tests docs
git commit -m "feat: add durable run listing"
Acceptance Criteria
WorkflowRunApi.list_runs()returns compact summaries, sorted newest first.WorkflowApiSurfaceincludeslist_runs.- JSON-RPC method
workflow.runs.listworks. RpcWorkflowApiClient.list_runs()works.wf run listworks for local and remote targets.- Listing never includes trace entries, checkpoint state, output payloads, or pinned environment bodies.
- Invalid
status,cursor, andlimitare rejected. - Docs state that
inspectand boundedtraceremain the detail surfaces.