P1: Complete cancellation propagation outside the established stream path (#225) #230
No reviewers
Labels
No labels
accessibility
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
P1
P2
P3
question
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
Creatidy/scarcity-router!230
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "issue-225-cancel-paths"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Refs #225 (P1, successor of excluded #165; disposition D-083). Completes client-disconnect/cancel propagation on the execution-stream paths outside the already-proven established-stream path. Minimal local fixes; no execution-coordination redesign, no worker-protocol change, no retry of ambiguous execution, and the intentional ambiguous-outcome contract (#165 path 4) is untouched.
Defects reproduced red, then fixed green (deterministic seams, no sleeps)
worker_bridged_adapter.py_await_outcome()/_await_resume(): when the cancel event is set while blocked inpending.take()and a chunk lands in that same call, the branch returnedcancelledwithout informing the worker (the loop never revisits the top-of-loop check). Fix: send the best-effort cancel (honoringcancel_sent, so cancellation effects are never duplicated) before the honest cancelled return; the resume leg keeps dropping its suspension handle.ClientDisconnectedErrorhandling, so a disconnect there left the backend turn suspended with no cancel. Fix: same cancel-before-rethrow wrapper as the ordinary chunk branch (matching the established covered-path semantics)._StreamState._begin():send_response/send_header/end_headerssat outside_write_frame()'s translation, so a header flush failure escaped as rawOSErrorand the coordinator's cancel path never engaged. Fix: translated toClientDisconnectedError._ResponsesStreamState._write_events()(added with #181/D-080) duplicated the untranslated pattern. Fix: identical translation, so both SSE surfaces cancel identically.Red/green evidence
Six new deterministic tests (no timeout/sleep-based correctness):
AdapterUncoveredCancellationTests(4): scriptedPendingAttemptseams place the cancel inside thetake()window / raiseClientDisconnectedErrorfrom the suspension emissions; each failed on the pre-fix source (empty cancel record) and passes post-fix asserting exactly one cancel notice plus the honest outcome. The public loop cannot reach these windows deterministically — the top-of-loop check consumes any cancel set outsidetake()— hence the seams.SseHeaderDisconnectTests(2): failing-header handler stubs; pre-fix raised rawBrokenPipeError(tracebacks atgateway_server.py:775/:919), post-fix raisesClientDisconnectedError.Invariants preserved (verified by the existing suites)
Ambiguous-outcome contract unchanged (
worker_connection_lost/interrupted/TOOL_RESULT_AMBIGUOUS→AdapterAmbiguousError, never retried); no duplicate cancellation effects (cancel_sentguard); no false completed/cancelled outcomes; D-062 tool-continuation and streaming contracts green; PR #164's merged test synchronization untouched.Validation
uv sync --only-dev;make check3063 tests OK / 16 runtime-probe skips (715.5s — includes the 6 new tests);uv run basedpyright0 errors/0 warnings/0 notes;git diff --checkclean. Synthetic/offline only; no live provider, no credentials.Review ordinal record: #1 (initial independent review) reserved for a fresh native read-only Kilo reviewer session (pr-reviewer role) over frozen HEAD
ebb5a4093feda19d4e73e0769ecf4b081596398c, base/merge-base4a182affa4775a4a38b47860ad7622a099c56c4a. Default finite bound 10 whole-PR reviews for this delivery. Source frozen; no pushes/edits during review.Preserved reviewer dispatch payload (native session creation is currently not processing agent-initiated requests; if a reviewer session is started from the Agent Manager UI, begin with exactly this task — note it must review the reconciled final HEAD/base after PR #229 integrates, re-verified at dispatch time):
Reconciled after PR229 integrated at develop2c40e0e1fb79397c97e6fa2b7dac0365d9712c0c. Published HEAD remains
ebb5a4093f; merge-base4a182affa4775a4a38b47860ad7622a099c56c4a. No history rewrite, synchronization merge or reimplementation. git merge-tree is conflict-free, tree7b0416513ab3859277ffbcb98e517d2066ce1b07. Validated that integration tree in the SAME checkout using unreferenced detached validation object4c0981c5afaaf89316ee2bc5d3d0130db0f3f7f6 (not published/on a branch), then restored exact published HEAD. Sanitized env-i/synthetic HOME/TMPDIR, locked dev deps: uv sync --only-dev; make check3063 tests OK/18 skips in725.455s; basedpyright0/0/0; whitespace clean. Two additional skips vs ambient prior run are reported honestly, not claimed executed. Existing reservation #1 is now imminent native GLM-5.3/zai-coding-plan pr-reviewer review of full PR against exact base2c40e0e/HEADebb5a40/merge-base4a182af; default maximum10. Source frozen during review. Native Agent Manager creation is now verified working with proper JSON-null arguments; no owner relay.Actual ordinal1 native reviewer now exists: ses_e7dae7b1cffe7M3L5csT38SQmR (Agent Manager overview busy), requestam-1793187742899-cjvnl6, GLM-5.3/zai-coding-plan, pr-reviewer read-only role. Complete PR correctness/security/UX scope at HEADebb5a4093feda19d4e73e0769ecf4b081596398c, current base2c40e0e1fb79397c97e6fa2b7dac0365d9712c0c, merge-base4a182affa4775a4a38b47860ad7622a099c56c4a. Source frozen; no owner relay, Task/subagents or reviewer environment.
Ordinal1/10 final independent GLM-5.3 correctness/security/UX result retrieved natively from ses_e7dae7b1cffe7M3L5csT38SQmR: APPROVE, findings=[], reviewed HEADebb5a4093feda19d4e73e0769ecf4b081596398c/base2c40e0e1fb79397c97e6fa2b7dac0365d9712c0c/merge-base4a182affa4775a4a38b47860ad7622a099c56c4a. Reviewer inspected complete canonical4-file diff and local exact source; Bash denied in role, so canonical getter refs + frozen-local-source verification used without permission changes. Primary verifies actual Git objects/clean checkout/validated merge tree. Same-source clarification substantiated AC2/4 rather than waiving them: send_cancel writes a frame per call (not write-idempotent); worker_client dispatch sets per-attempt Event, so repeated notices are effect-idempotent. Backend cancellation immediate; old claimed record closes immediately; newly WAITING handles are released through existing absolute-deadline expiry/reaper, callback exactly once per record. Reviewer traced control_server->control_api->registry.expire_due->cancel_suspension and cited existing exactly-once/expiry tests; no material uncertainty, no source change or new lifecycle semantics. UX improves immediate backend stop on disconnect; no new friction. Full sanitized merged-tree gate3063 OK/18 skips,basedpyright0/0/0,whitespace clean. No unresolved findings; proceeding to currentness/authorized merge.