Skip to content

fix(runtime-api): cancel mirrored human requirements - #5741

Merged
keweichen merged 2 commits into
mainfrom
factory/kc/base-a824ff022dd2c8a24ee7102e-03c45f61e20f
Oct 20, 2026
Merged

keweichen merged 2 commits into
mainfrom
factory/kc/base-a824ff022dd2c8a24ee7102e-03c45f61e20f

Conversation

@keweichen

Copy link
Copy Markdown
Collaborator

Priority

Level: medium
Reason: Owner-approved reliability improvement.

Closes

N/A — owner-approved work; no public issue is claimed as closed.

Summary

fix(runtime-api): cancel mirrored human requirements

Review first: src/runtime-api/dispatcher.py, src/runtime-api/ha_adapter.py, tests/runtime-api-dispatcher.test.py, tests/runtime-api-human-action.test.py, tests/runtime-api-request-cancellation.test.py.

Checklist

  • Confirmed no other open PR closes the same issue (gh pr list --repo sonichi/sutando --search "closes #N")
  • Git author email matches my CLA-signed email (git log -1 --format='%ae' shows a GH-mapped email, not *.local or noreply@anthropic.com)
  • Single concern per PR — no bundled refactors / drive-by feature additions
  • Confirmed bug exists on upstream/main (or feature isn't already covered)
  • Test added (or N/A explained below)
  • Before/after evidence pasted below — the actual command output for both states, not a description of it (this is the Add demo video to README #1 reason PRs bounce)
  • Every claim in this PR body is verifiable from the diff or the pasted output — no statement the reviewer can't check
  • Live path? If this touches a bridge, network path, delivery loop, or startup, I included a real post-restart round-trip — unit tests / harnesses alone are not accepted for these
  • Stacked PR? I named the parent + merge order and will rebase/update + rerun full checks after the parent lands (or N/A)
  • Scanned added lines for host-specific hardcoded paths and inline home/workspace fallbacks; fixtures are narrowly scoped
  • If this PR adds or edits a CI workflow, I confirmed it actually runs on this PR (see the Checks tab — a branches: filter can silently exclude a stacked PR)
  • Doesn't reinvent workspace / home-path resolution — uses the resolve_workspace / resolveWorkspace / claude_home_path helpers (see CLAUDE.md "Workspace contract"; enforced by the lint-workspace-resolution, lint-claude-home-path, and workspace-leak-check CI checks)

Contribution observations (unchecked items remain reviewer decisions):

  • Duplicate search: Searched PRs (all states) and open issues using fix(runtime-api): cancel mirrored human requirements, "request.cancel", "task.cancel". Related results for reviewer comparison: docs(scp): v0 is not local-only — describe the shipped network surface accurately #3565, fix(runtime-api): emit recognized cancellation instructions #5535, feat(runtime-api): Sutando Server v0 — local runtime daemon, canonical CLI, instance registry, base views #3303 Returned PRs were compared against current files and overlapping diffs: docs(scp): v0 is not local-only — describe the shipped network surface accurately #3565: Different changed files.; fix(runtime-api): emit recognized cancellation instructions #5535: Different changed files.; feat(runtime-api): Sutando Server v0 — local runtime daemon, canonical CLI, instance registry, base views #3303: Related files, different patch; current-source reproduction and independent review remain required.. Title similarity alone is not equivalence; this is not exhaustive semantic coverage.

  • Upstream observed during evidence preparation: 8e6ebd5f857a99044f0a0b2d1b3dd4cc95b2a8fe. Main matched the tested source base at preparation; PR checks and review remain required.

  • Diff review: - review-correctness: Inspected the full change against original base 8e6ebd5 and traced dispatcher, adapter, stores, task status, projection and RPC error handling. Cancellation re-reads durable status, reconciles previously cancelled human requests and uses the deterministic mirror ID after restart. Existing terminal guards preserve outcomes. Mirror-write errors propagate instead of returning success.

  • review-scope: Only the five allowed paths changed. Regenerated patch SHA-256 matches 672286b833a55a7412b3556a8eecb5e96378c5e510240d84501fbdef49f60212. The repair relative to HEAD's parent adds one blank line between imports. Task cancellation, worker recovery, capability execution semantics, historical cleanup, transport, card wording and desktop changes remain excluded.

  • review-maintainability: Dispatcher orchestration delegates through HumanActionAdapter.cancel to HitlManager.cancel. Locking, terminal-state protection and atomic persistence remain in the existing shared writer. No duplicate persistence policy, schema migration or new configuration was introduced. Tests cover behavior and delegation.

  • Documentation: No standalone documentation files changed. The reviewer should assess the code and contract comments for documentation completeness.

  • Live-path verification: - monitor-user-journey: Executed python3 [local path] at 2026-10-19T21:47:19Z–21:47:26Z: 60 real bin/sutando calls against this checkout's server.py on the supplied private socket. Initial daemon PID 60309 reached CLI readiness in 0.381 seconds. Commands included approval request, elicitation request, human-action request and request cancel. For example, bin/sutando request cancel approval-dfe1c4cd74e6 returned status cancelled; both durable records were cancelled at mirror revision 2, the old action was rejected, the local projection edited the existing card to cancelled, and its task returned to pending. All three types passed. Transcript: monitor-journey.jsonl.

  • monitor-repeatability: Repeated bin/sutando request cancel for all three cancelled requests before and after daemon restart; snapshots, revisions and record inventory remained unchanged, and another projection drive emitted nothing. A controlled write failure made bin/sutando request cancel human_action-e6fa5293eb9a exit 1 with -32000 and Permission denied. Restart alone preserved the cancelled runtime row and pending mirror. Retrying the same command cancelled that mirror, advancing revision 1 to 2 exactly once; another retry changed nothing. Four journey daemons exited 0 and were reaped. Commands, outputs and timestamps: monitor-journey.jsonl.

These observations used the isolated candidate; no production deployment was performed.

  • Risks / rollback: Change scope: Synchronize request.cancel with its matching approval, elicitation or human-action requirement through HumanActionAdapter and the existing HitlManager cancellation primitive. Preserve terminal outcomes and unrelated requirements. Repeated cancellation must reconcile a cancelled request whose mirror write previously failed, including after restart; surface write failures instead of reporting complete success. Add focused socket and lifecycle regressions. Exclude task.cancel, worker recovery, capability execution cancellation semantics, automatic historical cleanup, transport changes, card wording and desktop changes.
    Rollback: revert this PR. Production behavior after deployment remains to be observed.
  • Stacking: N/A; one concern against main.
  • Author maps to keweichen; CLA status must be observed on the PR.

Before / after evidence

Before

  • triage-evidence: Loaded the supplied environment and ran python3 [local path] preflight successfully. Ran python3 [local path] at 2026-10-19T21:15:56Z–21:16:01Z: 42 real bin/sutando calls against python3 src/runtime-api/server.py on the private runtime.sock, including restart. Commands, responses, readiness and timestamps are in diagnostics/triage-request-cancel.json; bounded daemon logs and capability-preflight.json are alongside it. All started daemons were stopped and reaped. Answers and projection delivery used local synthetic fixtures.

Recorded command/output on the pinned source:

/bin/zsh -c "python3 - <<'PY'
import json, os, subprocess, sys
from pathlib import Path
root=Path('[local path]')
env=os.environ.copy(); env.update(json.loads((root/'environment.json').read_text())); env['PYTHONDONTWRITEBYTECODE']='1'
p=subprocess.run([sys.executable,str(root/'process-tools.py'),'preflight'],env=env,text=True,capture_output=True,timeout=60)
print(p.stdout); print(p.stderr); print('exit',p.returncode)
PY"
{"schema": "ag2-runtime-preflight/v1", "product_ready": "not observed", "tmux": {"available": true, "detail": "tmux 3.8\n"}, "process_inspection": {"available": true, "detail": "82966\n"}, "private_socket": {"available": true}}


exit 0

Exit: 0

/bin/zsh -c "python3 - <<'PY'
import datetime, json, os, subprocess
from pathlib import Path
root=Path('[local path]'); diag=root/'diagnostics'; diag.mkdir(exist_ok=True)
env=os.environ.copy(); env.update(json.loads((root/'environment.json').read_text())); env['PYTHONDONTWRITEBYTECODE']='1'; env['SUTANDO_TELEMETRY']='0'
cmd=['python3','tests/runtime-api-human-action.test.py']; start=datetime.datetime.now(datetime.timezone.utc).isoformat()
p=subprocess.run(cmd,env=env,capture_output=True,text=True,timeout=60)
(diag/'adapter-baseline.log').write_text(p.stdout+p.stderr)
print(json.dumps({'command':cmd,'started':start,'exit':p.returncode,'output':(p.stdout+p.stderr)[-5000:]}))
PY"
{"command": ["python3", "tests/runtime-api-human-action.test.py"], "started": "2026-10-19T21:14:08.419040+00:00", "exit": 0, "output": "test_a_duplicate_answer_is_swallowed_not_raised (__main__.AdapterEdgeTests.test_a_duplicate_answer_is_swallowed_not_raised) ... ok\ntest_an_expired_requirement_reports_expired_on_every_poll (__main__.AdapterEdgeTests.test_an_expired_requirement_reports_expired_on_every_poll) ... ok\ntest_answer_shape_fallbacks (__main__.AdapterEdgeTests.test_answer_shape_fallbacks) ... ok\ntest_free_text_decision_round_trips_the_typed_answer (__main__.AdapterEdgeTests.test_free_text_decision_round_trips_the_typed_answer) ... ok\ntest_resolve_refuses_an_unknown_requirement_and_a_bad_index (__main__.AdapterEdgeTests.test_resolve_refuses_an_unknown_requirement_and_a_bad_index) ... ok\ntest_api_complete_resolves_request_and_closes_card (__main__.HumanActionTests.test_api_complete_resolves_request_and_closes_card) ... ok\ntest_api_decline_and_terminal_is_idempotent_safe (__main__.HumanActionTests.test_api_decline_and_terminal_is_idempotent_safe) ... ok\ntest_card_done_completes_and_decline_declines (__main__.HumanActionTests.test_card_done_completes_and_decline_declines) ... ok\ntest_complete_rejects_wrong_type_and_unknown (__main__.HumanActionTests.test_complete_rejects_wrong_type_and_unknown) ... ok\ntest_request_mirrors_card_with_act_and_outcome_options (__main__.HumanActionTests.test_request_mirrors_card_with_act_and_outcome_options) ... ok\ntest_status_returns_request_state (__main__.HumanActionTests.test_status_returns_request_state) ... ok\ntest_ungranted_caller_cannot_settle_and_leaves_the_row_pending (__main__.HumanActionTests.test_ungranted_caller_cannot_settle_and_leaves_the_row_pending) ... ok\ntest_ungranted_unix_client_cannot_settle_its_own_request (__main__.ProductionComposedSettleTests.test_ungranted_unix_client_cannot_settle_its_own_request) ... ok\ntest_unix_transport_grants_nothing (__main__.ProductionComposedSettleTests.test_unix_transport_grants_nothing) ... ok\n\n----------------------------------------------------------------------\nRan 14 tests in 0.096s\n\nOK\n"}

Exit: 0

After

  • acceptance-1: Real server.py and bin/sutando journeys passed for approval, elicitation and human_action. Both durable records became cancelled; requirements left active(); previous actions were rejected as stale; local projections edited existing cards to cancelled. Associated tasks returned to pending with unchanged task files and no duplicates.

  • acceptance-2: Unrelated requirements remained actionable and resolved normally. Approved, denied, resolved, completed and declined outcomes and answers remained unchanged. Unknown IDs returned exit 1 with -32602. Unmirrored cancellation created no requirement. An independent socket witness confirmed another pending request keeps its shared task waiting.

  • acceptance-3: Repeated cancellation and restart preserved record inventories, snapshots and revisions. Explicit retry after restart repaired a cancelled runtime row with an active mirror; restart alone did not reconcile it. An independent witness also confirmed retry preserved an archived cancelled requirement without recreating its live file.

  • acceptance-4: Directory-permission failures exercised the production mirror writer and returned CLI exit 1 with -32000 and Permission denied. Restoring permissions and retrying reconciled the same records, including after restart. A mirror resolved before retry retained its terminal outcome and answer. The independent approval witness confirmed exactly one mirror revision increment.

  • acceptance-5: The new integration suite and both extended focused suites passed using the supplied scratch environment and private sockets. Startup, CLI and shutdown waits were bounded; fixtures were synthetic and local. All 17 daemon launches across frozen, coverage and independent boundary runs reached readiness and were reaped. Scoped ps was unavailable during the boundary run; direct Popen PID, CLI readiness and wait receipts established lifecycle.

  • check-request-cancel-integration: python3 tests/runtime-api-request-cancellation.test.py exited 0: four tests passed, 64 CLI calls and seven successfully reaped daemons. Ran 2026-10-19T21:40:10.949Z–21:40:18.891Z in 7.942 seconds, within 120 seconds.

  • check-request-cancel-dispatcher: python3 tests/runtime-api-dispatcher.test.py exited 0 in 1.275 seconds, within 60 seconds. Delegation, terminal preservation, durable-state race and restart reconciliation assertions passed.

  • check-request-cancel-adapter: python3 tests/runtime-api-human-action.test.py exited 0: 17 tests passed in 0.215 seconds, within 60 seconds.

  • repair-review-comment-cap: git diff 8e6ebd5 HEAD | bash scripts/review-checks.sh exited 0. The unchanged scanner reported hardcoded-paths, root-artifacts and prose-cap clean.

  • coverage: Reran all three suites with python3 -m coverage run --rcfile=.coveragerc, combined results and exported XML. diff-cover against original base 8e6ebd5 with --fail-under=95 exited 0: six changed executable lines, zero missing, 100% coverage. Dispatcher coverage was 71%; adapter coverage was 91%. Commands and measurements are in coverage/commands.json.

  • checkout-integrity: Final HEAD matches the pinned candidate; git status --porcelain=v1 --untracked-files=all is empty. Working-tree and base-to-candidate diff checks passed. Only the five approved paths changed. Regenerated patch SHA-256 matches 672286b833a55a7412b3556a8eecb5e96378c5e510240d84501fbdef49f60212. Scanners, coverage configuration and CI workflow remain unchanged.

Test plan

python3 tests/runtime-api-request-cancellation.test.py

Observed: PASS; exit 0.

test_all_types_cancel_stale_actions_project_and_survive_restart (__main__.RequestCancellationTests.test_all_types_cancel_stale_actions_project_and_survive_restart) ... {"event": "daemon-start", "at": "2026-10-19T21:39:22.371041+00:00", "argv": ["/opt/homebrew/opt/python@3.13/bin/python3.13", "[local path]"], "pid": 35060, "socket": "[local path]"}
{"event": "cli", "at": "2026-10-19T21:39:22.970766+00:00", "argv": ["[local path]", "request", "list"], "exit_code": 0, "stdout": "{\n \"requests\": []\n}\n", "stderr": ""}
{"event": "ready", "at": "2026-10-19T21:39:22.970964+00:00", "pid": 35060, "response": {"requests": []}}
{"event": "cli", "at": "2026-10-19T21:39:23.072642+00:00", "argv": ["[local path]", "task", "submit", "Synthetic approval cancellation"], "exit_code": 0, "stdout": "{\n \"taskId\": \"task-rtapi-7b0a067183b6\",\n \"state\": \"pending\"\n}\n", "stderr": ""}
{"event": "cli", "at": "2026-10-19T21:39:23.168767+00:00", "argv": ["[local path]", "approval", "request", "--action", "synthetic.approval", "--task-id", "task-rtapi-7b0a067183b6"], "exit_code": 0, "stdout": "{\n \"requestId\": \"approval-0aa0d9f2d7b4\",\n \"status\": \"pending\"\n}\n", "stderr": ""}
{"event": "cli", "at": "2026-10-19T21:39:23.268347+
[Excerpt: middle omitted; full recorded output SHA256 4cb207b7a371352014de6ac9c661c2eb3d491366713f9a7e1d6919eec828fef6]
dout": "{\n \"requestId\": \"human_action-56af22e216e5\",\n \"status\": \"completed\",\n \"resolvedBy\": \"synthetic-owner\"\n}\n", "stderr": ""}
{"event": "cli", "at": "2026-10-19T21:39:29.753879+00:00", "argv": ["[local path]", "request", "cancel", "human_action-56af22e216e5"], "exit_code": 0, "stdout": "{\n \"requestId\": \"human_action-56af22e216e5\",\n \"status\": \"completed\",\n \"resolvedBy\": \"synthetic-owner\"\n}\n", "stderr": ""}
{"event": "cli", "at": "2026-10-19T21:39:29.854398+00:00", "argv": ["[local path]", "human-action", "request", "--action", "Synthetic local act"], "exit_code": 0, "stdout": "{\n \"requestId\": \"human_action-32ad8f8d1447\",\n \"status\": \"pending\"\n}\n", "stderr": ""}
{"event": "cli", "at": "2026-10-19T21:39:29.950593+00:00", "argv": ["[local path]", "request", "wait", "human_action-32ad8f8d1447", "--timeout", "2"], "exit_code": 0, "stdout": "{\n \"requestId\": \"human_action-32ad8f8d1447\",\n \"status\": \"declined\",\n \"resolvedBy\": \"synthetic-owner\"\n}\n", "stderr": ""}
{"event": "cli", "at": "2026-10-19T21:39:30.035656+00:00", "argv": ["[local path]", "request", "cancel", "human_action-32ad8f8d1447"], "exit_code": 0, "stdout": "{\n \"requestId\": \"human_action-32ad8f8d1447\",\n \"status\": \"declined\",\n \"resolvedBy\": \"synthetic-owner\"\n}\n", "stderr": ""}
{"event": "cli", "at": "2026-10-19T21:39:30.128380+00:00", "argv": ["[local path]", "request", "cancel", "unknown-fixture"], "exit_code": 1, "stdout": "", "stderr": "{\"error\": \"-32602: unknown requestId: 'unknown-fixture'\"}\n"}
{"event": "cli", "at": "2026-10-19T21:39:30.238184+00:00", "argv": ["[local path]", "request", "cancel", "approval-0cd76834dc02"], "exit_code": 0, "stdout": "{\n \"requestId\": \"approval-0cd76834dc02\",\n \"status\": \"cancelled\",\n \"resolvedBy\": \"synthetic-cancellation-test\"\n}\n", "stderr": ""}
{"event": "cli", "at": "2026-10-19T21:39:30.340509+00:00", "argv": ["[local path]", "request", "cancel", "capability-612f838e83d7"], "exit_code": 0, "stdout": "{\n \"requestId\": \"capability-612f838e83d7\",\n \"status\": \"cancelled\",\n \"resolvedBy\": \"synthetic-cancellation-test\"\n}\n", "stderr": ""}
{"event": "daemon-stop", "at": "2026-10-19T21:39:30.355367+00:00", "pid": 35524, "exit_code": 0, "reaped": true, "log": "[runtime-api] listening on [local path] (actor=synthetic-cancellation-test)\n"}
ok

----------------------------------------------------------------------
Ran 4 tests in 7.991s

OK
python3 tests/runtime-api-dispatcher.test.py

Observed: PASS; exit 0.

── dispatch table ──
  ok   unknown method → -32601
  ok   ungranted human_action.complete → -32601 before any param check
  ok   granted human_action.complete still requires requestId
  ok   approval.request requires action
  ok   elicitation.request requires question
  ok   approval.request returns pending + requestId
  ok   issued row is durable and pending
  ok   actor persisted from CONSTRUCTOR, not params
  ok   a client-supplied actor cannot override the daemon actor
── elicitation types ──
  ok   free_text rejected in v0
  ok   unknown type rejected
  ok   single_select requires options
  ok   multi_select requires options
  ok   valid single_select issues
  ok   confirmation needs no options
── human-action mirror failure ──
  ok   mirror failure raises -32603
  ok   a failed mirror leaves NO pending row behind
── get / wait / cancel ──
  ok   get unknown requestId → -32602
  ok   cancel unknown requestId → -32602
  ok   get with no requestId → -32602
  ok   public shape: requestId + status only while pending
  ok   cancel transitions to cancelled
  ok   cancellation is durable
  ok   public shape includes resolvedBy once set
── cancellation reconciles only its human requirement ──
  ok   approval: dispatcher
[Excerpt: middle omitted; full recorded output SHA256 08ed7a4ea44d573b55626433d8b65850ef3b2900a75c1def23dbdf07229f5430]
irror is not created
  ok   approval: only human requests delegate cancellation
  ok   wait times out and reports timedOut
  ok   a timed-out request stays pending
  ok   wait honoured the short timeout
── governed capability gating ──
  ok   message.send is governed
  ok   governed action with NO approval fails closed
  ok   no executor ran for the ungated attempt
  ok   unknown approvalRequestId fails closed
  ok   a non-approved approval fails closed
  ok   still no executor ran
── fingerprint binding ──
  ok   fingerprint changes with input
  ok   fingerprint changes with resource
  ok   fingerprint changes with action
  ok   fingerprint is stable for identical params
  ok   fingerprint ignores key order
── executor results ──
  ok   unknown executor returns a failed result (does not raise)
  ok   unknown executor's failure is durable
  ok   the failure names the missing executor
  ok   ungoverned action executes without an approval
  ok   its executor actually ran
  ok   the completed result is durable
  ok   a blocking executor is offloaded (loop stayed responsive)
── resolver loop isolation ──
[runtime-api] resolver error (isolated): transient store error
  ok   resolver survives a polling exception (did not die on first error)
── crash recovery ──
[runtime-api] recovered 2 pending request(s)
  ok   recovery relinks a pending approval to its card
  ok   recovery relinks a pending elicitation to its card
  ok   recovered approval is still pending
── approval.respond (device-plane; needs a daemon-resolved grant) ──
  ok   respond WITHOUT a grant is not callable (fails closed)
  ok   ungranted respond leaves the approval pending
  ok   respond requires requestId
  ok   respond requires a valid decision
  ok   respond on unknown request
  ok   respond approves and reports the transition
  ok   approved is durable
  ok   second respond reports alreadyTerminal, never flips the row
  ok   respond refuses a non-approval request type
  ok   respond reject denies
── schedule / task param edges ──
  ok   schedule.list without a schedules surface
  ok   task.* without a task pipeline is a clean -32601
  ok   request.get without requestId
── configured-surface branches ──
  ok   schedule.list serves configured rows through the dispatcher
  ok   task.status with a pipeline but no taskId
  ok   task.details unknown id
  ok   task.submit empty text is a ValueError -> -32602
  ok   request.wait without requestId

PASS — runtime-api dispatcher
python3 tests/runtime-api-human-action.test.py

Observed: PASS; exit 0.

test_a_duplicate_answer_is_swallowed_not_raised (__main__.AdapterEdgeTests.test_a_duplicate_answer_is_swallowed_not_raised) ... ok
test_an_expired_requirement_reports_expired_on_every_poll (__main__.AdapterEdgeTests.test_an_expired_requirement_reports_expired_on_every_poll) ... ok
test_answer_shape_fallbacks (__main__.AdapterEdgeTests.test_answer_shape_fallbacks) ... ok
test_cancel_delegates_to_manager_and_rejects_old_actions (__main__.AdapterEdgeTests.test_cancel_delegates_to_manager_and_rejects_old_actions) ... ok
test_cancel_preserves_terminal_answers_and_missing_records (__main__.AdapterEdgeTests.test_cancel_preserves_terminal_answers_and_missing_records) ... ok
test_cancel_write_failure_propagates_and_retry_uses_production_writer (__main__.AdapterEdgeTests.test_cancel_write_failure_propagates_and_retry_uses_production_writer) ... ok
test_free_text_decision_round_trips_the_typed_answer (__main__.AdapterEdgeTests.test_free_text_decision_round_trips_the_typed_answer) ... ok
test_resolve_refuses_an_unknown_requirement_and_a_bad_index (__main__.AdapterEdgeTests.test_resolve_refuses_an_unknown_requirement_and_a_bad_index) ... ok
test_api_complete_resolves_request_and_closes_card (__main__.HumanActionTests.test_api_complete_resolves_request_and_closes_card) ... ok
test_api_decline_and_terminal_is_idempotent_safe (__main__.HumanActionTests.test_api_decline_and_terminal_is_idempotent_safe) ... ok
test_card_done_completes_and_decline_declines (__main__.HumanActionTests.test_card_done_completes_and_decline_declines) ... ok
test_complete_rejects_wrong_type_and_unknown (__main__.HumanActionTests.test_complete_rejects_wrong_type_and_unknown) ... ok
test_request_mirrors_card_with_act_and_outcome_options (__main__.HumanActionTests.test_request_mirrors_card_with_act_and_outcome_options) ... ok
test_status_returns_request_state (__main__.HumanActionTests.test_status_returns_request_state) ... ok
test_ungranted_caller_cannot_settle_and_leaves_the_row_pending (__main__.HumanActionTests.test_ungranted_caller_cannot_settle_and_leaves_the_row_pending) ... ok
test_ungranted_unix_client_cannot_settle_its_own_request (__main__.ProductionComposedSettleTests.test_ungranted_unix_client_cannot_settle_its_own_request) ... ok
test_unix_transport_grants_nothing (__main__.ProductionComposedSettleTests.test_unix_transport_grants_nothing) ... ok

----------------------------------------------------------------------
Ran 17 tests in 0.098s

OK

Canonical review scanner:

review-checks: PASS (hardcoded-paths + root-artifacts + prose-cap clean)
prose-cap: PASS (comment blocks within cap 2, exts .py)

Verified candidate: a4a2a4581cf0285ba9d8e0e78c0ef4e3dcb84c6d. Publication commit: 0da838c81b615f1cbdf65f51af5d52da01b61f79. Both have tree 14d82d215be195362dda2a1c6f890b33ba318653; only factory-authored commit metadata changed. Acceptance evidence refers to the verified candidate; the scanner ran on the publication tree.

@github-actions

github-actions Bot commented Oct 19, 2026 •

Copy link
Copy Markdown
Contributor

Coverage Gate

✅ Diff coverage PASSES the 95% bar. Whole-tree (informational): 92%.

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • src/runtime-api/dispatcher.py (100%)
  • src/runtime-api/ha_adapter.py (100%)

Summary

  • Total: 8 lines
  • Missing: 0 lines
  • Coverage: 100%

@keweichen keweichen left a comment

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Reviewed head 0da838c against base 8e6ebd5.

This is a COMMENT review because the authenticated GitHub login, keweichen, is also the PR author; it cannot count as an approval or a formal change request.

Changes requested before merge:

  • Blocking (src/runtime-api/dispatcher.py:573-574): this adds a second production copy of the mirrored human-request type set already used by recover at line 156. Repository architecture explicitly treats duplicated policy as a defect because a later request type can drift between recovery and cancellation. Please define one named constant or helper for the mirrored request types and use it in both branches.

Verification:

  • Base reproduction: request.cancel left approval, elicitation, and human_action mirrors pending and active while their runtime rows became cancelled. The same probe at this head cancelled both records for all three types.
  • Independent exact-head QA passed 313 focused tests and assertions. The two changed behavioral suites failed against base production code as expected: the integration suite had six failures and the adapter suite had nine errors.
  • The real daemon, Unix socket, CLI, SQLite store, HITL writer, restart, stale-action rejection, projection edit, permission failure, and explicit retry paths passed. Terminal winners and unrelated requirements remained unchanged.
  • review-checks and git diff --check passed. CI run 39330519245 completed successfully, and license/cla is green.

Worst-case disruption: the runtime DB and HITL file store cannot commit atomically. A mirror-write failure can leave a cancelled runtime row with an active card until request.cancel is retried. The command returns an error instead of false success, and retry repair is verified both before and after restart.

Merge readiness: not ready at this head. The behavior is otherwise sound, but the duplicated policy should be centralized, then the PR still needs two independent maintainer approvals. I did not merge.

@github-actions

Copy link
Copy Markdown
Contributor

@cla-assistant check

@keweichen

Copy link
Copy Markdown
Collaborator Author

Addressed review feedback in 949505dc46d36fc7078df93a8b8891c869d23c6c.

  • feedback-1: Direct AST inspection confirmed one MIRRORED_REQUEST_TYPES definition at dispatcher.py:87 containing approval, elicitation and human_action, used by recover() at line 157 and _cancel() at line 574. No duplicate literal set remains in that file. Evidence: verify-feedback-1.json.

  • acceptance-1: The real daemon and bin/sutando cancelled approval-617113e1d58f, elicitation-55ed55fb77e7 and human_action-b929e3c52b2c. SQLite rows and matching HITL records became cancelled; requirements left active(), and previous actions raised StaleRequirementError. The production projector emitted cancellation edits to the synthetic local projection fixture. Each associated task returned from its request-waiting state to pending, preserving original task files without duplicates. Evidence: verify-request-cancel-integration.log and verify-integration-events.json.

  • acceptance-2: An unrelated pending elicitation remained unchanged and actionable, then resolved normally to B. Cancellation preserved approved, denied, resolved, completed and declined records and answers. An unknown ID returned CLI exit 1 with -32602. Cancelling unmirrored approval and capability rows created no requirements. These controls ran through the real socket, with synthetic answers supplied through the production adapter.

  • acceptance-3: Repeated cancellation before and after daemon restart preserved both records, requirement revisions and record inventory. A failed-write request retained its cancelled runtime row and active mirror across restart; explicit request.cancel then reconciled the same requirement once, and subsequent cancellation made no further change. Evidence: the restart and snapshot assertions in verify-request-cancel-integration.log.

  • acceptance-4: Removing write permission from the private HITL directory exercised the production writer. Cancellation returned CLI exit 1, empty stdout and -32000 Permission denied instead of success. Restoring permission and retrying repaired the same records, both immediately and after restart. A separate mirror resolved to B before reconciliation retained its terminal outcome and answer after restart and retry.

  • acceptance-5: The requested CLI/socket test exists, and dispatcher/adapter regressions cover delegation, terminal preservation and retry behavior. All three suites passed. Subprocesses inherited the supplied scratch environment, preserving PATH and PYTHONPATH; sockets and state stayed beneath the private runtime directory. Readiness, CLI calls and shutdown waits were bounded, and all seven daemon processes were reaped.

Running-product observations:

  • monitor-user-journey: Ran python3 [local path] exit 0, 57 real bin/sutando calls and 47 assertions. Started this checkout's src/runtime-api/server.py on the private runtime.sock. Issued approval, elicitation and human-action requests linked to submitted tasks. Commands bin/sutando request cancel approval-d7cbe4b52a16, elicitation-02564489d06f and human_action-76c1716cc9bc returned status=cancelled. SQLite and HITL records both persisted cancellation; active() excluded them; previous actions raised StaleRequirementError. The production projector emitted cancellation edits to a synthetic local receiver. Original tasks returned to pending. Commands, responses and persisted snapshots: monitor-journey.jsonl.

  • monitor-repeatability: Repeated bin/sutando request cancel for all three cancelled requests before and after daemon restart: responses remained cancelled and complete record snapshots, revisions and inventory remained identical. For human_action-01d8d9c2dc21, the first cancellation returned exit 1 with -32000 Permission denied. After restoring directory permissions and restarting, bin/sutando request cancel human_action-01d8d9c2dc21 repaired the existing mirror to cancelled at revision 2; another cancellation changed nothing. Repeated production projection emitted no payloads. Evidence: monitor-journey.jsonl and monitor-journey-summary.json.

  • acceptance-1: The independent real CLI/socket journey exercised approval, elicitation and human_action. Both durable records cancelled, requirements left active(), previous actions were rejected as stale, and the production projector edited each original local card to cancelled. Each associated task moved from its specific waiting state to pending with its original file intact.

  • acceptance-2: An unrelated pending elicitation remained unchanged and subsequently resolved to B. Cancellation preserved approved, denied, resolved and completed outcomes and answers. bin/sutando request cancel monitor-unknown-id returned exit 1 and -32602 without creating records. Cancelling synthetic unmirrored approval and capability rows created no requirements. Evidence: monitor-journey.jsonl.

  • acceptance-3: Repeated cancellation and restart preserved cancelled pairs, revisions and record counts. Restart also recovered pending requests without modifying their mirrors. A cancelled runtime row with a failed mirror write stayed unreconciled across restart; explicit cancellation then repaired that same mirror exactly once. Evidence: restart and snapshot assertions in monitor-journey.jsonl.

  • acceptance-4: Temporarily setting the private HITL directory to mode 0500 exercised the production writer: cancellation returned exit 1, empty stdout and -32000 Permission denied at its .tmp file creation. Restoring permissions allowed retry to reconcile the existing records, both immediately and after restart. A separate mirror resolved to B before retry retained its terminal status and answer.

  • acceptance-5: The requested integration test and dispatcher/adapter regressions are present and passed. Inspected integration setup: it inherits the supplied environment, uses private temporary state and sockets, bounds readiness/CLI/shutdown waits, supplies synthetic answers and local projection fixtures, and reaps its children. All product subprocesses in this observation loaded the supplied scratch environment, preserving PATH and PYTHONPATH.

  • feedback-1: Direct current-head AST inspection found exactly one MIRRORED_REQUEST_TYPES definition at dispatcher.py:87 containing approval, elicitation and human_action. recover() uses it at line 157 and _cancel() at line 574; the matching literal collection occurs only at the definition. The runtime journey exercised pending-request recovery and cancellation for all three types. Evidence: monitor-feedback-1.json.

/bin/zsh -lc "rg -n 'def |CREATE TABLE|INSERT|runtime_requests' src/runtime-api/request_store.py
rg -n 'fail-under|diff-cover|unmeasured|BASE_REF' scripts/coverage-gate.sh
sed -n '1,180p' scripts/coverage_unmeasured.py"
29:CREATE TABLE IF NOT EXISTS runtime_requests (
47:CREATE UNIQUE INDEX IF NOT EXISTS idx_runtime_requests_idem
48:  ON runtime_requests (idempotency_key) WHERE idempotency_key IS NOT NULL;
49:CREATE INDEX IF NOT EXISTS idx_runtime_requests_status
50:  ON runtime_requests (status);
55:    def __init__(self, db_path: str):
61:        # newer columns, and CREATE TABLE IF NOT EXISTS won't add them — the
65:            "PRAGMA table_info(runtime_requests)").fetchall()}
71:                        f"ALTER TABLE runtime_requests ADD COLUMN {col} {decl}")
76:    def create(self, request_type: str, method: str, actor_id: str,
84:            "INSERT INTO runtime_requests (request_id, request_type, task_id,"
94:    def create_consuming(self, approval_id: str, request_type: str, method: str,
109:                "INSERT INTO runtime_requests (request_id, request_type, task_id,"
117:                "UPDATE runtime_requests SET consumed_at = ? WHERE request_id = ?"
129:    def by_idempotency_key(self, key: str):
134:            "SELECT request_id, fingerprint FROM runtime_requests"
143:    def get(self, request_id: str):
147:            " resolved_at, resolved_by, consumed_at FROM runtime_requests"
168:    def transition(self, request_id: str, new_status: str, result=None,
173:            "UPDATE runtime_requests SET status = ?, result_json = ?,"
181:    def consume(self, request_id: str) -> bool:
185:            "UPDATE runtime_requests SET consumed_at = ? WHERE request_id = ?"
191:    def pending(self) -> list:
193:            "SELECT request_id FROM runtime_requests WHERE status = 'pending'")
196:    def close(self) -> None:
9:#   3. Gates: `diff-cover` compares coverage.xml against the base branch and
26:#   BASE_REF=<ref> bash scripts/coverage-gate.sh  # gate vs another base
34:#   python3 -m pip install coverage diff-cover
46:BASE="${BASE_REF:-origin/main}"
69:    echo "  Install dev deps: python3 -m pip install coverage diff-cover" >&2
72:if ! command -v diff-cover >/dev/null 2>&1; then
73:    echo "coverage-gate: diff-cover not on PATH." >&2
74:    echo "  Install dev deps: python3 -m pip install coverage diff-cover" >&2
78:# Fast path: PRs that touch no Python have no diff to gate. (diff-cover
103:rm -f diff-cover.md
106:rm -f .coverage coverage.xml diff-cover.md
229:diff-cover coverage.xml --compare-branch="$BASE" --fail-under="$FAIL_UNDER" \
230:    --markdown-report diff-cover.md || gate_rc=$?
232:# diff-cover's markdown report carries the per-file table + missing lines;
241:# diff-cover reports only on files IN coverage.xml, so a changed file outside
245:report="diff-cover.md"
246:if unmeasured="$(python3 scripts/coverage_unmeasured.py "$BASE" coverage.xml)" \
247:   && [ -n "$unmeasured" ]; then
250:    printf '  %s\n' $unmeasured
253:        cat diff-cover.md
258:        echo "\`.coveragerc\`, so **diff-cover never examined these lines**:"
260:        printf -- '-   `%s`\n' $unmeasured
#!/usr/bin/env python3
"""Changed Python files that coverage never measured at all.

`diff-cover` reports only on files PRESENT in coverage.xml, so a file outside
`[run] source` is neither covered nor uncovered — it is invisible, and the gate
passes without having looked at it. Naming those files is what separates "not
measured" from "measured and clean".

Usage: coverage_unmeasured.py <base-ref> <coverage.xml> [--rcfile .coveragerc]
Prints one repo-relative path per line; empty output means nothing was missed.
"""
from __future__ import annotations

import configparser
import fnmatch
import subprocess
import sys
import xml.etree.ElementTree as ET
from pathlib import Path


def omit_globs(rcfile: str | Path) -> list[str]:
    """The `[run] omit` patterns, read from coverage's own config.

    Read rather than restated: a hardcoded copy drifts the moment someone edits
    .coveragerc, and drifts silently in the direction of false alarms.
    """
    cp = configparser.ConfigParser()
    try:
        cp.read(rcfile)
    except (configparser.Error, OSError):
        return []
    raw = cp.get("run", "omit", fallback="")
    return [ln.strip() for ln in raw.splitlines() if ln.strip()]


def is_omitted(path: str, globs: "list[str]") -> bool:
    """Coverage matches an omit pattern against the path as a whole."""
    return any(fnmatch.fnmatch(path, g) or fnmatch.fnmatch("/" + path, g)
               for g in globs)


def unmeasured(changed: "list[str]", measured: "set[str]",
               globs: "list[str]") -> "list[str]":
    """Changed files that are neither omitted on purpose nor present in the report.

    `measured` holds coverage.xml's `filename` values, which are relative to a
    `<source>` root, so a path is matched by suffix rather than equality.
    """
    out = []
    for path in changed:
        if is_omitted(path, globs):
            continue
        if any(path == m or path.endswith("/" + m) for m in measured):
            continue
        out.append(path)
    return out


def measured_files(xml_path: "str | Path") -> "set[str]":
    try:
        root = ET.parse(xml_path).getroot()
    except (ET.ParseError, OSError):
        return set()
    return {el.get("filename") for el in root.iter("class") if el.get("filename")}


def changed_py(base: str) -> "list[str]":
    proc = subprocess.run(
        ["git", "diff", "--name-only", "--diff-filter=d", f"{base}...HEAD", "--", "*.py"],
        capture_output=True, text=True,
    )
    if proc.returncode != 0:
        return []
    return [ln.strip() for ln in proc.stdout.splitlines() if ln.strip()]


def main(argv: "list[str]") -> int:
    if len(argv) < 3:
        print(__doc__.strip(), file=sys.stderr)
        return 2
    base, xml_path = argv[1], argv[2]
    rcfile = argv[4] if len(argv) > 4 and argv[3] == "--rcfile" else ".coveragerc"
    for path in unmeasured(changed_py(base), measured_files(xml_path), omit_globs(rcfile)):
        print(path)
    return 0


if __name__ == "__main__":
    sys.exit(main(sys.argv))

Exit: 0

/bin/zsh -lc "python3 - <<'PY'
import ast,json,subprocess,os,time
from pathlib import Path
root=Path.cwd(); base=Path('[local path]'); diag=base/'diagnostics'
env=os.environ.copy(); env.update(json.loads((base/'environment.json').read_text())); env.update(PYTHONDONTWRITEBYTECODE='1',COVERAGE_FILE=str(diag/'.coverage-monitor'),SUTANDO_TELEMETRY='0')
tree=ast.parse(Path('src/runtime-api/dispatcher.py').read_text())
defs=[n for n in tree.body if isinstance(n,ast.Assign) and any(isinstance(t,ast.Name) and t.id=='MIRRORED_REQUEST_TYPES' for t in n.targets)]
assert len(defs)==1
values={n.value for n in ast.walk(defs[0]) if isinstance(n,ast.Constant)}
assert values=={'approval','elicitation','human_action'}
consumers={n.name:[c.lineno for c in ast.walk(n) if isinstance(c,ast.Name) and c.id=='MIRRORED_REQUEST_TYPES'] for n in ast.walk(tree) if isinstance(n,ast.FunctionDef) and n.name in ('recover','_cancel')}
assert all(consumers.get(name) for name in ('recover','_cancel'))
sets=[n.lineno for n in ast.walk(tree) if isinstance(n,(ast.Set,ast.Tuple,ast.List)) and len(n.elts)==3 and all(isinstance(e,ast.Constant) for e in n.elts) and {e.value for e in n.elts}==values]
assert len(sets)==1
feedback={'definition_line':defs[0].lineno,'types':sorted(values),'consumers':consumers,'literal_occurrences':sets}
(diag/'monitor-feedback-1.json').write_text(json.dumps(feedback,indent=2)); print(json.dumps(feedback))
commands=[['python3','-m','coverage','run','--rcfile=.coveragerc','tests/runtime-api-dispatcher.test.py'],['python3','-m','coverage','run','--rcfile=.coveragerc','tests/runtime-api-human-action.test.py'],['python3','-m','coverage','combine','--rcfile=.coveragerc'],['python3','-m','coverage','xml','--rcfile=.coveragerc','-o',str(diag/'monitor-coverage.xml')],['diff-cover',str(diag/'monitor-coverage.xml'),'--compare-branch=8e6ebd5f857a99044f0a0b2d1b3dd4cc95b2a8fe','--fail-under=95','--markdown-report',str(diag/'monitor-diff-coverage.md')],['python3','scripts/coverage_unmeasured.py','8e6ebd5f857a99044f0a0b2d1b3dd4cc95b2a8fe',str(diag/'monitor-coverage.xml')]]
results=[]
for i,argv in enumerate(commands):
    start=time.monotonic(); p=subprocess.run(argv,env=env,cwd=root,text=True,capture_output=True,timeout=60)
    (diag/('monitor-coverage-%d.log'%i)).write_text(p.stdout+p.stderr)
    row={'argv':argv,'exit_code':p.returncode,'elapsed_seconds':round(time.monotonic()-start,3),'tail':(p.stdout+p.stderr)[-600:]}; results.append(row); print(json.dumps(row))
    if p.returncode: break
(diag/'monitor-coverage-commands.json').write_text(json.dumps(results,indent=2))
assert len(results)==len(commands) and all(r['exit_code']==0 for r in results)
PY"
{"definition_line": 87, "types": ["approval", "elicitation", "human_action"], "consumers": {"recover": [157], "_cancel": [574]}, "literal_occurrences": [87]}
{"argv": ["python3", "-m", "coverage", "run", "--rcfile=.coveragerc", "tests/runtime-api-dispatcher.test.py"], "exit_code": 0, "elapsed_seconds": 1.702, "tail": " alreadyTerminal, never flips the row\n  ok   respond refuses a non-approval request type\n  ok   respond reject denies\n\u2500\u2500 schedule / task param edges \u2500\u2500\n  ok   schedule.list without a schedules surface\n  ok   task.* without a task pipeline is a clean -32601\n  ok   request.get without requestId\n\u2500\u2500 configured-surface branches \u2500\u2500\n  ok   schedule.list serves configured rows through the dispatcher\n  ok   task.status with a pipeline but no taskId\n  ok   task.details unknown id\n  ok   task.submit empty text is a ValueError -> -32602\n  ok   request.wait without requestId\n\nPASS \u2014 runtime-api dispatcher\n"}
{"argv": ["python3", "-m", "coverage", "run", "--rcfile=.coveragerc", "tests/runtime-api-human-action.test.py"], "exit_code": 0, "elapsed_seconds": 0.432, "tail": ".HumanActionTests.test_status_returns_request_state) ... ok\ntest_ungranted_caller_cannot_settle_and_leaves_the_row_pending (__main__.HumanActionTests.test_ungranted_caller_cannot_settle_and_leaves_the_row_pending) ... ok\ntest_ungranted_unix_client_cannot_settle_its_own_request (__main__.ProductionComposedSettleTests.test_ungranted_unix_client_cannot_settle_its_own_request) ... ok\ntest_unix_transport_grants_nothing (__main__.ProductionComposedSettleTests.test_unix_transport_grants_nothing) ... ok\n\n----------------------------------------------------------------------\nRan 17 tests in 0.167s\n\nOK\n"}
{"argv": ["python3", "-m", "coverage", "combine", "--rcfile=.coveragerc"], "exit_code": 0, "elapsed_seconds": 0.165, "tail": "Combined 2 files\n"}
{"argv": ["python3", "-m", "coverage", "xml", "--rcfile=.coveragerc", "-o", "[local path]"], "exit_code": 0, "elapsed_seconds": 3.21, "tail": "Wrote XML report to [local path]"}
{"argv": ["diff-cover", "[local path]", "--compare-branch=8e6ebd5f857a99044f0a0b2d1b3dd4cc95b2a8fe", "--fail-under=95", "--markdown-report", "[local path]"], "exit_code": 0, "elapsed_seconds": 1.759, "tail": "-------------\nDiff Coverage\nDiff: 8e6ebd5f857a99044f0a0b2d1b3dd4cc95b2a8fe...HEAD, staged and unstaged changes\n-------------\nsrc/runtime-api/dispatcher.py (100%)\nsrc/runtime-api/ha_adapter.py (100%)\n-------------\nTotal:   8 lines\nMissing: 0 lines\nCoverage: 100%\n-------------\n\n[local path] UserWarning: The --markdown-report option is deprecated. Use --format markdown:[local path] instead.\n  warnings.warn(\n"}
{"argv": ["python3", "scripts/coverage_unmeasured.py", "8e6ebd5f857a99044f0a0b2d1b3dd4cc95b2a8fe", "[local path]"], "exit_code": 0, "elapsed_seconds": 0.106, "tail": ""}

Exit: 0

Regression checks:

  • request-cancel-integration: PASS
  • request-cancel-dispatcher: PASS
  • request-cancel-adapter: PASS
/bin/zsh -c "python3 - <<'PY'
import json,os,subprocess,time,datetime
from pathlib import Path
p=Path('[local path]'); d=p/'diagnostics'
env=os.environ.copy(); env.update(json.loads((p/'environment.json').read_text())); env.update(PYTHONDONTWRITEBYTECODE='1',COVERAGE_FILE=str(d/'.verify-coverage'))
commands=[['python3','-m','coverage','run','--rcfile=.coveragerc','tests/runtime-api-dispatcher.test.py'],['python3','-m','coverage','run','--rcfile=.coveragerc','tests/runtime-api-human-action.test.py'],['python3','-m','coverage','combine','--rcfile=.coveragerc'],['python3','-m','coverage','xml','--rcfile=.coveragerc','-o',str(d/'verify-coverage.xml')],['diff-cover',str(d/'verify-coverage.xml'),'--compare-branch=8e6ebd5f857a99044f0a0b2d1b3dd4cc95b2a8fe','--fail-under=95','--markdown-report',str(d/'verify-diff-coverage.md')],['python3','scripts/coverage_unmeasured.py','8e6ebd5f857a99044f0a0b2d1b3dd4cc95b2a8fe',str(d/'verify-coverage.xml')]]
receipts=[]
for i,argv in enumerate(commands):
    start=datetime.datetime.now(datetime.timezone.utc).isoformat()
    r=subprocess.run(argv,env=env,text=True,capture_output=True,timeout=90)
    log=d/f'verify-coverage-{i}.log'; log.write_text(r.stdout+r.stderr)
    rec={'argv':argv,'start':start,'stop':datetime.datetime.now(datetime.timezone.utc).isoformat(),'exit':r.returncode,'log':str(log)}
    receipts.append(rec); print(json.dumps(rec),flush=True)
    print((r.stdout+r.stderr)[-1600:],flush=True)
    if r.returncode: break
(d/'verify-coverage-commands.json').write_text(json.dumps(receipts,indent=2))
raise SystemExit(r.returncode)
PY"
{"argv": ["python3", "-m", "coverage", "run", "--rcfile=.coveragerc", "tests/runtime-api-dispatcher.test.py"], "start": "2026-10-19T22:15:24.291468+00:00", "stop": "2026-10-19T22:15:26.100771+00:00", "exit": 0, "log": "[local path]"}
he missing executor
  ok   ungoverned action executes without an approval
  ok   its executor actually ran
  ok   the completed result is durable
  ok   a blocking executor is offloaded (loop stayed responsive)
── resolver loop isolation ──
[runtime-api] resolver error (isolated): transient store error
  ok   resolver survives a polling exception (did not die on first error)
── crash recovery ──
[runtime-api] recovered 2 pending request(s)
  ok   recovery relinks a pending approval to its card
  ok   recovery relinks a pending elicitation to its card
  ok   recovered approval is still pending
── approval.respond (device-plane; needs a daemon-resolved grant) ──
  ok   respond WITHOUT a grant is not callable (fails closed)
  ok   ungranted respond leaves the approval pending
  ok   respond requires requestId
  ok   respond requires a valid decision
  ok   respond on unknown request
  ok   respond approves and reports the transition
  ok   approved is durable
  ok   second respond reports alreadyTerminal, never flips the row
  ok   respond refuses a non-approval request type
  ok   respond reject denies
── schedule / task param edges ──
  ok   schedule.list without a schedules surface
  ok   task.* without a task pipeline is a clean -32601
  ok   request.get without requestId
── configured-surface branches ──
  ok   schedule.list serves configured rows through the dispatcher
  ok   task.status with a pipeline but no taskId
  ok   task.details unknown id
  ok   task.submit empty text is a ValueError -> -32602
  ok   request.wait without requestId

PASS — runtime-api dispatcher

{"argv": ["python3", "-m", "coverage", "run", "--rcfile=.coveragerc", "tests/runtime-api-human-action.test.py"], "start": "2026-10-19T22:15:26.100841+00:00", "stop": "2026-10-19T22:15:26.540083+00:00", "exit": 0, "log": "[local path]"}
ree_text_decision_round_trips_the_typed_answer (__main__.AdapterEdgeTests.test_free_text_decision_round_trips_the_typed_answer) ... ok
test_resolve_refuses_an_unknown_requirement_and_a_bad_index (__main__.AdapterEdgeTests.test_resolve_refuses_an_unknown_requirement_and_a_bad_index) ... ok
test_api_complete_resolves_request_and_closes_card (__main__.HumanActionTests.test_api_complete_resolves_request_and_closes_card) ... ok
test_api_decline_and_terminal_is_idempotent_safe (__main__.HumanActionTests.test_api_decline_and_terminal_is_idempotent_safe) ... ok
test_card_done_completes_and_decline_declines (__main__.HumanActionTests.test_card_done_completes_and_decline_declines) ... ok
test_complete_rejects_wrong_type_and_unknown (__main__.HumanActionTests.test_complete_rejects_wrong_type_and_unknown) ... ok
test_request_mirrors_card_with_act_and_outcome_options (__main__.HumanActionTests.test_request_mirrors_card_with_act_and_outcome_options) ... ok
test_status_returns_request_state (__main__.HumanActionTests.test_status_returns_request_state) ... ok
test_ungranted_caller_cannot_settle_and_leaves_the_row_pending (__main__.HumanActionTests.test_ungranted_caller_cannot_settle_and_leaves_the_row_pending) ... ok
test_ungranted_unix_client_cannot_settle_its_own_request (__main__.ProductionComposedSettleTests.test_ungranted_unix_client_cannot_settle_its_own_request) ... ok
test_unix_transport_grants_nothing (__main__.ProductionComposedSettleTests.test_unix_transport_grants_nothing) ... ok

----------------------------------------------------------------------
Ran 17 tests in 0.170s

OK

{"argv": ["python3", "-m", "coverage", "combine", "--rcfile=.coveragerc"], "start": "2026-10-19T22:15:26.540153+00:00", "stop": "2026-10-19T22:15:26.698714+00:00", "exit": 0, "log": "[local path]"}
Combined 2 files

{"argv": ["python3", "-m", "coverage", "xml", "--rcfile=.coveragerc", "-o", "[local path]"], "start": "2026-10-19T22:15:26.698761+00:00", "stop": "2026-10-19T22:15:30.293001+00:00", "exit": 0, "log": "[local path]"}
Wrote XML report to [local path]

{"argv": ["diff-cover", "[local path]", "--compare-branch=8e6ebd5f857a99044f0a0b2d1b3dd4cc95b2a8fe", "--fail-under=95", "--markdown-report", "[local path]"], "start": "2026-10-19T22:15:30.293045+00:00", "stop": "2026-10-19T22:15:32.619635+00:00", "exit": 0, "log": "[local path]"}
-------------
Diff Coverage
Diff: 8e6ebd5f857a99044f0a0b2d1b3dd4cc95b2a8fe...HEAD, staged and unstaged changes
-------------
src/runtime-api/dispatcher.py (100%)
src/runtime-api/ha_adapter.py (100%)
-------------
Total:   8 lines
Missing: 0 lines
Coverage: 100%
-------------

[local path] UserWarning: The --markdown-report option is deprecated. Use --format markdown:[local path] instead.
  warnings.warn(

{"argv": ["python3", "scripts/coverage_unmeasured.py", "8e6ebd5f857a99044f0a0b2d1b3dd4cc95b2a8fe", "[local path]"], "start": "2026-10-19T22:15:32.619688+00:00", "stop": "2026-10-19T22:15:32.732466+00:00", "exit": 0, "log": "[local path]"}

Exit: 0

/bin/zsh -c "python3 - <<'PY'
import ast,json,hashlib
from pathlib import Path
root=Path.cwd(); p=root/'src/runtime-api/dispatcher.py'; tree=ast.parse(p.read_text())
types={'approval','elicitation','human_action'}
defs=[n for n in tree.body if isinstance(n,ast.Assign) and any(isinstance(t,ast.Name) and t.id=='MIRRORED_REQUEST_TYPES' for t in n.targets)]
assert len(defs)==1
assert isinstance(defs[0].value,ast.Call) and defs[0].value.func.id=='frozenset'
assert set(ast.literal_eval(defs[0].value.args[0]))==types
branches={}
for f in ast.walk(tree):
    if isinstance(f,ast.FunctionDef) and f.name in {'recover','_cancel'}:
        uses=[n.lineno for n in ast.walk(f) if isinstance(n,ast.Name) and n.id=='MIRRORED_REQUEST_TYPES']
        assert len(uses)==1,(f.name,uses)
        branches[f.name]=uses
copies=[]
for n in ast.walk(tree):
    if isinstance(n,(ast.Set,ast.Tuple,ast.List)):
        try: value=ast.literal_eval(n)
        except (ValueError,TypeError): continue
        if all(isinstance(v,str) for v in value) and set(value)==types: copies.append(n.lineno)
assert len(copies)==1
receipt={'constant_definition':defs[0].lineno,'types':sorted(types),'shared_uses':branches,'literal_set_copies':copies,'dispatcher_sha256':hashlib.sha256(p.read_bytes()).hexdigest()}
out=Path('[local path]'); out.write_text(json.dumps(receipt,indent=2)); print(json.dumps(receipt))
log=Path('[local path]').read_text()
events=[]
for line in log.splitlines():
    i=line.find('{\"event\":')
    if i>=0: events.append(json.loads(line[i:]))
starts=[r for r in events if r['event']=='daemon-start']; ready=[r for r in events if r['event']=='ready']; stops=[r for r in events if r['event']=='daemon-stop']
assert len(starts)==len(stops)==len(ready)==7
assert {r['pid'] for r in starts}=={r['pid'] for r in stops}
assert all(r['exit_code']==0 and r['reaped'] for r in stops)
assert all(Path(r['socket']).is_relative_to('[local path]') for r in starts)
cli=[r for r in events if r['event']=='cli']; failures=[r for r in cli if r['exit_code']"'!=0]
summary={'"'processes':[{'pid':s['pid'],'argv':s['argv'],'socket':s['socket'],'start':s['at'],'ready':next(r['at'] for r in ready if r['pid']==s['pid']),'stop':next(r['at'] for r in stops if r['pid']==s['pid']),'reaped':True} for s in starts],'cli_count':len(cli),'errors':failures,'cancelled_pairs':[r for r in events if r['event']=='cancelled-pair'],'projection_count':sum(r['event']=='local-projection' for r in events)}
Path('[local path]').write_text(json.dumps(events,indent=2))
Path('[local path]').write_text(json.dumps(summary,indent=2))
print(json.dumps(summary,indent=2))
PY"
{"constant_definition": 87, "types": ["approval", "elicitation", "human_action"], "shared_uses": {"recover": [157], "_cancel": [574]}, "literal_set_copies": [87], "dispatcher_sha256": "13980d15bf1a264aa47eaf781a371fdedd0bd731658a8636f7346fa6025150b4"}
{
  "processes": [
    {
      "pid": 22676,
      "argv": [
        "/opt/homebrew/opt/python@3.13/bin/python3.13",
        "./src/runtime-api/server.py"
      ],
      "socket": "[local path]",
      "start": "2026-10-19T22:15:01.363967+00:00",
      "ready": "2026-10-19T22:15:01.636427+00:00",
      "stop": "2026-10-19T22:15:03.606827+00:00",
      "reaped": true
    },
    {
      "pid": 22988,
      "argv": [
        "/opt/homebrew/opt/python@3.13/bin/python3.13",
        "./src/runtime-api/server.py"
      ],
      "socket": "[local path]",
      "start": "2026-10-19T22:15:03.609605+00:00",
      "ready": "2026-10-19T22:15:03.845547+00:00",
      "stop": "2026-10-19T22:15:04.657467+00:00",
      "reaped": true
    },
    {
      "pid": 23212,
      "argv": [
        "/opt/homebrew/opt/python@3.13/bin/python3.13",
        "./src/runtime-api/server.py"
      ],
      "socket": "[local path]",
      "start": "2026-10-19T22:15:04.677665+00:00",
      "ready": "2026-10-19T22:15:05.071306+00:00",
      "stop": "2026-10-19T22:15:05.724928+00:00",
      "reaped": true
    },
    {
      "pid": 23362,
      "argv": [
        "/opt/homebrew/opt/python@3.13/bin/python3.13",
        "./src/runtime-api/server.py"
      ],
      "socket": "[local path]",
      "start": "2026-10-19T22:15:05.726783+00:00",
      "ready": "2026-10-19T22:15:05.962016+00:00",
      "stop": "2026-10-19T22:15:06.178260+00:00",
      "reaped": true
    },
    {
      "pid": 23376,
      "argv": [
        "/opt/homebrew/opt/python@3.13/bin/python3.13",
        "./src/runtime-api/server.py"
      ],
      "socket": "[local path]",
      "start": "2026-10-19T22:15:06.187948+00:00",
      "ready": "2026-10-19T22:15:06.511429+00:00",
      "stop": "2026-10-19T22:15:06.773714+00:00",
      "reaped": true
    },
    {
      "pid": 23451,
      "argv": [
        "/opt/homebrew/opt/python@3.13/bin/python3.13",
        "./src/runtime-api/server.py"
      ],
      "socket": "[local path]",
      "start": "2026-10-19T22:15:06.775777+00:00",
      "ready": "2026-10-19T22:15:07.142053+00:00",
      "stop": "2026-10-19T22:15:07.264699+00:00",
      "reaped": true
    },
    {
      "pid": 23489,
      "argv": [
        "/opt/homebrew/opt/python@3.13/bin/python3.13",
        "./src/runtime-api/server.py"
      ],
      "socket": "[local path]",
      "start": "2026-10-19T22:15:07.270824+00:00",
      "ready": "2026-10-19T22:15:07.561847+00:00",
      "stop": "2026-10-19T22:15:09.954408+00:00",
      "reaped": true
    }
  ],
  "cli_count": 64,
  "errors": [
    {
      "event": "cli",
      "at": "2026-10-19T22:15:05.279539+00:00",
      "argv": [
        "./bin/sutando",
        "request",
        "cancel",
        "human_action-3363b8439b6b"
      ],
      "exit_code": 1,
      "stdout": "",
      "stderr": "{\"error\": \"-32000: server error: [Errno 13] Permission denied: '[local path]'\"}\n"
    },
    {
      "event": "cli",
      "at": "2026-10-19T22:15:05.702054+00:00",
      "argv": [
        "./bin/sutando",
        "request",
        "cancel",
        "human_action-5167913533c0"
      ],
      "exit_code": 1,
      "stdout": "",
      "stderr": "{\"error\": \"-32000: server error: [Errno 13] Permission denied: '[local path]'\"}\n"
    },
    {
      "event": "cli",
      "at": "2026-10-19T22:15:06.720377+00:00",
      "argv": [
        "./bin/sutando",
        "request",
        "cancel",
        "elicitation-622416ca0e3f"
      ],
      "exit_code": 1,
      "stdout": "",
      "stderr": "{\"error\": \"-32000: server error: [Errno 13] Permission denied: '[local path]'\"}\n"
    },
    {
      "event": "cli",
      "at": "2026-10-19T22:15:09.732953+00:00",
      "argv": [
        "./bin/sutando",
        "request",
        "cancel",
        "unknown-fixture"
      ],
      "exit_code": 1,
      "stdout": "",
      "stderr": "{\"error\": \"-32602: unknown requestId: 'unknown-fixture'\"}\n"
    }
  ],
  "cancelled_pairs": [
    {
      "event": "cancelled-pair",
      "at": "2026-10-19T22:15:02.112313+00:00",
      "request_id": "approval-617113e1d58f",
      "requirement_id": "hitl_617113e1d58f",
      "runtime_status": "cancelled",
      "mirror_status": "cancelled",
      "revision": 2
    },
    {
      "event": "cancelled-pair",
      "at": "2026-10-19T22:15:02.754918+00:00",
      "request_id": "elicitation-55ed55fb77e7",
      "requirement_id": "hitl_55ed55fb77e7",
      "runtime_status": "cancelled",
      "mirror_status": "cancelled",
      "revision": 2
    },
    {
      "event": "cancelled-pair",
      "at": "2026-10-19T22:15:03.368604+00:00",
      "request_id": "human_action-b929e3c52b2c",
      "requirement_id": "hitl_b929e3c52b2c",
      "runtime_status": "cancelled",
      "mirror_status": "cancelled",
      "revision": 2
    },
    {
      "event": "cancelled-pair",
      "at": "2026-10-19T22:15:05.377895+00:00",
      "request_id": "human_action-3363b8439b6b",
      "requirement_id": "hitl_3363b8439b6b",
      "runtime_status": "cancelled",
      "mirror_status": "cancelled",
      "revision": 2
    },
    {
      "event": "cancelled-pair",
      "at": "2026-10-19T22:15:06.062152+00:00",
      "request_id": "human_action-5167913533c0",
      "requirement_id": "hitl_5167913533c0",
      "runtime_status": "cancelled",
      "mirror_status": "cancelled",
      "revision": 2
    }
  ],
  "projection_count": 7
}

Exit: 0

Independent verification, code review and product checks passed on candidate 2bb1d8913c271f4f8da4af2872b46ebe21a7acbb; the published commit has the same tree 910f6abd7111590e83da1a6fa96745eb2b93eef1. Please review the new head.

@qingyun-wu qingyun-wu 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.

Code-owner approve at 949505d, CI green. MIRRORED_REQUEST_TYPES is now the single source in recover() and _cancel(). _cancel only cancels the mirror when the store's CAS transition actually landed 'cancelled', so a request that has already resolved, expired or been cancelled skips it. HitlManager._terminate is a no-op on unknown or terminal ids, so a double cancel is safe. Red-first: with dispatcher.py and ha_adapter.py reverted to base, there are 6 cancellation failures and 9 adapter errors. Merge-order note: #5742 is not stacked on this PR and still hardcodes the ('approval','elicitation','human_action') tuple in _settle. Whichever merges second should rebase and use MIRRORED_REQUEST_TYPES instead of adding a second copy.

@keweichen
keweichen merged commit 3133b05 into main Oct 20, 2026
35 checks passed
@keweichen
keweichen deleted the factory/kc/base-a824ff022dd2c8a24ee7102e-03c45f61e20f branch October 20, 2026 03:40
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