Plugin API: propagate canonical cancellation to running service tools #352
Open
opened 2026-09-08 02:03:37 +00:00 by nsaspy
·
12 comments
No Branch/Tag specified
master
agent/pi-coder-plugin-2026-09-17
fix/android-remote-listener
ui/chat-message-bubbles
release/v0.1.1-alpha-20260908
fix/default-daemon-endpoint-20260908
ui/650-outrun-shell
fix/400-plugin-capability-composition
fix/tts-idle-cpu-spin
design/android-canonical-reference-2026-09-07
fixtures/voice-recordings
rage/core/388-tool-cancellation-r18
rage/core/388-tool-cancellation-r1
release/v0.1.0-alpha
rage/android/175-terminal-transcript-fence-r4
rage/core/324-expanded-history-sidebar-r2
rage/android/175-terminal-transcript-fence-r3
rage/android/175-focus-release-retry-r2
rage/android/175-focus-release-retry
ci/desktop-idle-cpu-budget
rage/android/175-terminal-transcript-fence-r2
rage/android/175-route-stop-retry-r3
rage/575-transient-send-backpressure-r3
rage/575-transient-send-backpressure-r2
rage/android/175-terminal-transcript-fence
rage/android/175-route-stop-retry-r2
rage/android/175-sink-self-close-r2
rage/android/175-route-stop-retry
rage/android/175-sink-self-close
rage/android/175-audio-focus-sync-loss-r2
rage/android/175-stock-voice-interop-r3
rage/android/175-stock-voice-interop-r2
rage/android/175-audio-focus-sync-loss
rage/android/175-recover-stack-current-4
rage/android/175-stock-voice-interop-r1
rage/android/175-recover-stack-current-2
rage/587-vulkan-current-master-r2
rage/587-dictation-vulkan-current2
rage/575-transient-send-backpressure-r1
tmp-do-not-use-587
tmp-do-not-use-587-2
tmp-do-not-use-587-3
tmp-do-not-use-587-4
rage/587-dictation-vulkan-current2-tree
fix/dictation-ggml-vulkan-rage587
rage/android-campaign-batch-20260906
rage/587-dictation-ggml-vulkan-current
rage/388-toolnode-forwarding-r17-current2
rage/587-dictation-ggml-vulkan-r1
rage/388-toolnode-forwarding-r17-current
rage/575-gateway-send-diagnostics-current
rage/178-device-action-json-depth-r7
rage/175-recorder-failure-precedence-r8
rage/175-terminal-capture-cleanup-r8
rage/175-playback-write-failure-cleanup-r8
rage/575-gateway-send-diagnostics
rage/388-toolnode-forwarding-r17
rage/575-stock-interop-diagnostics-r2
fix/dictate-whisper-cpp-vulkan
rage/575-stock-interop-diagnostics-r1
rage/324-expanded-history-sidebar-r1
rage/178-device-action-json-depth-r6
rage/388-plugin-cancellation-r16
rage/175-recorder-failure-precedence-r7
rage/175-terminal-capture-cleanup-r7
rage/175-playback-write-failure-cleanup-r7
rage/324-native-chrome-r1
rage/175-recorder-failure-precedence-r6
rage/175-terminal-capture-cleanup-r6
rage/175-playback-write-failure-cleanup-r6
rage/324-independent-geometry-r2
rage/175-close-resource-precedence
rage/178-device-action-json-depth-r5
rage/175-recorder-failure-precedence-r5
rage/175-terminal-capture-cleanup-r5
rage/175-playback-write-failure-cleanup-r5
rage/324-independent-geometry-r1
rage/324-screenshot-provenance-r1
rage/324-history-parity-r1
rage/178-device-action-json-depth-r4
rage/175-preserve-recorder-primary-failure-r2
rage/175-capture-terminal-failure-cleanup-r3
rage/175-playback-write-failure-cleanup-r4
rage/324-screenshot-ci-r1
rage/324-unified-copilot-r4
rage/175-capture-terminal-failure-cleanup-r2
rage/175-playback-write-failure-cleanup-r3
rage/324-unified-copilot-r3
rage/175-preserve-recorder-primary-failure
rage/175-capture-terminal-failure-cleanup
rage/178-device-action-json-depth-r3
rage/175-playback-write-failure-cleanup-r2
rage/178-voice-stream-json-depth-r5
rage/160-semantic-first-runtime-r2
rage/175-playback-write-failure-cleanup
rage/178-voice-stream-json-depth-r4
rage/324-unified-copilot-r2
rage/178-device-action-json-depth-r2
rage/178-voice-json-depth-r3
rage/178-voice-ack-json-depth-r3
rage/160-semantic-first-runtime
rage/492-device-action-replay-r6
rage/178-device-action-json-depth
rage/178-voice-json-depth-r2
rage/178-voice-ack-json-depth-r2
rage/178-voice-json-depth-bound
rage/178-voice-ack-json-depth
rage/178-voice-hello-json-depth
rage/178-device-json-depth-bound
rage/178-capability-json-depth-bound
rage/178-android-daemon-restart-stale-turn-r2
rage/492-device-action-replay-r5
rage/492-device-action-replay-r4
rage/178-android-daemon-restart-stale-turn-r1
rage/178-android-json-depth-bound-r2
rage/178-android-json-depth-bound-r1
rage/203-android-playback-session-invalidation-r3
rage/492-device-action-replay-r3
rage/178-android-audio-payload-bound-r4
rage/203-android-playback-session-invalidation-r2
rage/178-android-audio-payload-bound-r3
rage/492-device-action-replay-r2
rage/203-android-ui-close-runtime-ownership-r3
rage/203-android-playback-session-invalidation
rage/178-android-audio-payload-bound-r2
rage/203-android-ui-close-runtime-ownership-r2
rage/178-android-uri-intent-abuse-r4
rage/178-android-audio-payload-bound
rage/203-android-ui-close-runtime-ownership
rage/492-device-action-replay-r1
rage/178-android-uri-intent-abuse-r3
rage/178-android-no-raw-logging-r5
rage/492-device-action-replay-horizon
rage/218-normalizer-config-r4
rage/178-android-uri-intent-abuse-r2
rage/178-android-no-raw-logging-r4
rage/178-android-uri-intent-abuse-r1
rage/218-normalizer-config-r3
rage/178-android-no-raw-logging-r3
rage/178-android-prolog-lifecycle-r3
rage/178-android-no-raw-logging-r2
rage/178-android-prolog-lifecycle-r2
rage/178-android-principal-target-abuse-r2
rage/178-android-no-raw-logging-r1
rage/178-android-prolog-lifecycle-r1
rage/178-android-principal-target-abuse-r1
rage/178-android-device-action-replay-r4
rage/178-android-device-action-replay-r3
rage/178-android-capability-revocation-r3
rage/218-normalizer-config-r2
rage/178-android-trealla-result-overflow-r1
rage/178-android-device-action-replay-r2
rage/178-android-capability-revocation-r2
rage/178-android-auth-revocation-r2
rage/178-android-device-action-replay-r1
rage/178-android-capability-revocation-r1
rage/178-android-auth-revocation-r1
rage/178-android-reconnect-storm-r3
rage/218-normalizer-config-r1
rage/218-normalizer-config-status-r1
rage/324-unified-copilot-r1
rage/217-s1-mini-normalizer-r4
rage/178-android-reconnect-storm-r2
rage/178-reconnect-storm-red-proof
rage/217-s1-mini-normalizer-r3
rage/178-android-release-matrix-r1
rage/217-s1-mini-normalizer-r2
rage/203-android-recorder-failure-diagnostics-r3
rage/217-s1-mini-normalizer-r1
rage/203-android-assistant-role-loss-wiring-r3
rage/216-transcript-normalization-contract-r2
rage/203-android-recorder-failure-diagnostics-r2
rage/203-android-assistant-role-loss-wiring-r2
rage/216-transcript-normalization-contract-r1
rage/203-android-reconnect-scheduler-failure-r2
rage/388-plugin-tool-cancellation-r15
rage/203-android-reconnect-scheduler-failure
rage/203-android-voice-session-invalidation-r4
rage/203-android-voice-session-invalidation-r3
rage/203-android-ui-error-redaction-r3
rage/388-plugin-tool-cancellation-r14
rage/388-plugin-tool-cancellation-r13
rage/400-plugin-capability-composition-r1
rage/203-android-ui-error-redaction-r2
rage/388-plugin-tool-cancellation-r12
rage/203-android-audio-route-rollback-failure-r2
rage/325-atomic-durable-message-append
rage/203-android-state-store-temp-isolation-r2
rage/388-plugin-tool-cancellation-r11
rage/388-plugin-tool-cancellation-r10
rage/203-android-audio-route-rollback-failure
rage/203-android-recorder-failure-diagnostics
rage/203-android-voice-runtime-invalidation-r2
rage/203-android-assistant-role-loss-wiring
rage/203-android-voice-session-invalidation-r2
rage/203-android-ui-error-redaction
rage/388-plugin-tool-cancellation-r9
rage/203-android-state-store-temp-isolation
rage/203-android-connection-error-redaction
rage/203-android-assistant-role-loss-r3
rage/388-plugin-tool-cancellation-r8
rage/203-android-voice-runtime-invalidation-primitives
rage/203-android-assistant-role-loss-r2
rage/203-android-voice-diagnostic-redaction-r2
rage/388-plugin-tool-cancellation-r7
rage/203-android-assistant-role-loss
rage/203-android-voice-session-invalidation
rage/203-android-voice-diagnostic-redaction
rage/174-android-open-app-aliases
rage/388-plugin-tool-cancellation-r6
rage/203-android-assistant-shutdown-fence
rage/388-plugin-tool-cancellation-r5
rage/29-streaming-tts-provider-recovery-r10
rage/203-android-mic-permission-lifecycle
rage/203-android-audio-route-lifecycle
rage/175-android-audio-focus-lifecycle
rage/174-android-device-capabilities
rage/29-streaming-tts-provider-recovery-r9
rage/388-plugin-tool-cancellation-r4
rage/388-plugin-tool-cancellation-r3
rage/29-streaming-tts-provider-recovery-r8
rage/326-desktop-toggle
rage/388-plugin-tool-cancellation-r2
rage/388-plugin-tool-cancellation
rage/29-streaming-tts-current-r7
rage/29-streaming-tts-current-r6
rage/371-plugin-approval-current
rage/29-streaming-tts-current-r5
rage/371-plugin-approval-contract
rage/371-plugin-approval-red
rage/29-streaming-tts-current-r4
rage/196-ui-closed-runtime
rage/196-android-assistant-role
rage/29-streaming-tts-current-r3
rage/175-android-barge-in
rage/175-android-streamed-voice
rage/175-android-manual-voice
rage/29-streaming-tts-current-r2
rage/29-streaming-tts-current
rage/327-bounded-target-edit-distance-recovery-r2
rage/348-dash-prefixed-z85-cli-r2
rage/197-compose-first-usable
rage/348-dash-prefixed-z85-cli
rage/173-android-client-continuity
rage/327-bounded-target-edit-distance-recovery
rage/329-production-secure-listener
rage/329-merge-probe
rage/159-zara1-device-actions-current
docs/refresh-20260905
rage/159-zara1-device-actions-recovery
rage/324-unified-copilot
rage/173-android-auth
rage/327-bounded-target-edit-distance
research/unified-copilot-20260905
rage/133-desktop-daemon-default-regression
rage/133-daemon-default-regression
rage/13-open-app-allowlist-regression
rage/165-user-command-runtime
rage/315-route-backpressure-test-contract
rage/164-user-command-authoring
rage/163-user-command-compiler
rage/162-user-command-persistence
rage/309-prolog-config-recovery
docs/260-customization-wiki
rage/260-customization-diagnostics
rage/159-zara1-device-actions
rage/260-agent-loop-backend-registry
rage/260-backend-registry
rage/260-service-plugin-advice
backup/rage-260-service-plugin-advice-pre-android-merge-20260903
rage/android-172-cross-runtime-parity
rage/zara-004-config-durability
rage/260-prolog-command-advice
feature/long-horizon-tasks
rage/264-config-delta
rage/264-host-delta
rage/264-config-host-delta
rage/rebase-264-long-horizon-tasks
backup/rage-260-prolog-command-advice-pre-rebase-20260903
rage/android-172-resolver-parity
rage/260-python-user-hooks
rage/260-agent-loop-integration
rage/android-172-asset-staging
rage/android-172-native-adapter
rage/260-python-hooks-advice
rage/android-172-jni-bridge
rage/android-172-trealla-runtime
rage/260-hooks-prolog-config
rage/android-172-fixture-runner
fork/prolog-rlm-agentic-runtime
rage/android-172-normalized-results
rage/android-172-assets-v2
rage/core-246-todo-toggle-current
rage/android-172-assets
rage/core-246-todo-toggle-refresh
rage/android-172-portable-prolog-refresh
feature/agent-mode-core
rage/recover-259-run10
rage/android-172-portable-prolog
docs/244-merge-evidence
backup/feature-long-horizon-tasks-pre-rebase-20260902
feat/zara-031-context-management
docs/250-merge-evidence
rage/250-amd-stt-device-routing
rage/159-zara1-capability-advertisement
feat/unified-agent-tui
fix/discord-tools-bash
rage/158-api-service-providers
docs/249-merge-evidence
rage/249-latency-trace-checkpoint
fix/246-disable-todo-surface
codex/zara-discord-plugin-guidance
rage/157-execution-plans
rage/156-prolog-frames
rage/28-post-merge-evidence
perf/zara-027-streaming-llm-impl
rage/155-typed-slots
test/live-smoke-reasoning-budgets
feature/openrouter-rlm-directmode
rage/154-intentframe-contract
chore/backlog-import
rage/195-samsung-assistant-research
feat/android-app
research/aradr-local-tts-voice-cloning
feature/wake-words-edit-distance
perf/zara-027-streaming-llm
docs/134-reentry-assessment
rage/134-daemon-release-gate
rage/131-merge-closeout
docs/rage-130-merge-outcome
docs/rage-17-merge-outcome
fix/zara-016-llm-provider-contracts
build/flake-update-2026-08
rage/191-zara1-tool-approvals
rage/132-visible-stt-regression
codex/copilot-redesign
codex/default-daemon-cli
rage/132-transcript-events
rage/133-post-merge-evidence
rage/133-client-migration
rage/132-post-merge-evidence
rage/132-live-voice
rage/132-live-voice-zara1
rage/131-principal-isolation
rage/131-principal-scope
rage/130-curve-zap-security
rage/130-auth-security
docs/rage-129-merge-outcome
rage/129-zara1-protocol
rage/129-slice-e-lifecycle-red
rage/129-slice-e-endpoint-red
docs/rage-128-merge-outcome
rage/139-daemon
docs/full-feature-sweep
feature/mcp-client-support-current
remove-prolog-rlm
research/daemon-zeromq-voice-service
feature/autoresearch-bootstrap
agent/VAD-patch
agent/prolog-capability-reasoner
agent/whisper-cpp-vulkan-stt
agent/remove-pet-notification-spam
codex/service-plugin-runtime
agent/stt-backends
agent/fix-laptop-stt-quality
feature/prolog-rlm-integration
agent/fix-speaker-echo-loop
agent/stt-gpu-rocm-support
agent/fix-ubuntu-wayland-pets
feature/desktop-theme-contrast
fix/whisper-load-state
agent/mcp-client-support
fix/wake-model-readiness-debug
fix/wake-capture-failure-propagation
fix/wake-audio-health
agent/readme-current-zara
fix/desktop-conversation-migration-repair
agent/fix-voice-runtime-noise
feature/desktop-launch-surface
feature/quick-copilot
feature/conversation-full-chat
feature/desktop-shell
feature/runtime-host
feature/runtime-events
research/desktop-copilot
agent/overhaul-memory-forgetting
agent/fix-command-context-routing
agent/fix-streaming-vad-wake
agent/pets-post-merge-fixes
feature/pets
revert/wake-throughput
fix/wake-word-detection
fix/pulse-shared-mic-ci
fix/shared-mic-capture
feat/zara-timer-alarm-sounds
fix/zara-017-todo-correctness
fix/zara-015-prolog-engine-contract
fix/zara-018-ack-result-events
agent/readme-rewrite
fix/zara-014-wake-lifecycle
fix/zara-013-file-tool-sandbox
fix/zara-012-process-safety
fix/recover-zara-006-011-to-master
revert-36-fix/zara-005-dictation-lifecycle
revert-44-fix/zara-011-dictation-ordering
fix/zara-010-tts-contracts
fix/zara-011-dictation-ordering
fix/zara-007-intent-precedence
fix/zara-008-multi-tool-history
fix/zara-009-memory-fallback
fix/zara-006-timers
fix/zara-005-dictation-lifecycle
fix/zara-003-fail-closed-commands
fix/zara-004-prolog-config-overrides
agent/ci-test-gate
fix/zara-002-config-toml
fix/zara-001-wake-entrypoint
memory
cleanup
device-acceptance-661
v0.1.0-alpha
Labels
Clear labels
bug
Something isn't working
documentation
Improvements or additions to documentation
duplicate
This issue or pull request already exists
enhancement
New feature or request
good first issue
Good for newcomers
help wanted
Extra attention is needed
invalid
This doesn't seem right
question
Further information is requested
wontfix
This will not be worked on
No labels
bug
documentation
duplicate
enhancement
good first issue
help wanted
invalid
question
wontfix
Milestone
Clear milestone
No items
No milestone
Projects
Clear projects
No items
No project
Assignees
Clear assignees
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".
No due date set.
Dependencies
No dependencies set.
Reference
nsaspy/zara#352
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
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?
Upstream handoff from
lost-rob0t/zara-plugins/zara-shell#5zara-shellnow has deterministic bounded timeout and process-group teardown, but its remaining acceptance criterion requires explicit cancellation distinct from timeout.Current Zara service-plugin tools are ordinary
BaseToolinstances returned byServicePlugin.tools(). I could not find a canonical Core cancellation token/signal passed into an in-flight plugin tool invocation. Adding a plugin-specific execution manager +shell.cancelside channel would create a second control plane and make cancellation semantics inconsistent across long-running plugins.Needed Core contract
ToolApprovalControllerand normal tool lifecycle/unload;Concrete consumer
zara-shellcan map that signal to process-group termination and return structuredcancelled=trueevidence while preserving its existing runtime/output/cwd/env bounds. Other long-running service tools could reuse the same contract.No Zara runtime code is being changed from the plugin worker.
Core recovery is now #413 on exact current master
ada24b73ab599d417dfbda6c864854c19b3426e3. r4/#401 is closed unmerged because exact-head CI falsified its hidden RunnableConfig propagation. r5 is TDD-first: public read-only token + sync/async/concurrency/approval/unload acceptance tests are running RED while the next implementation step wires Zara's pinnedlanggraph-prebuilt==1.1.0ToolNode(awrap_tool_call=...)interceptor. No plugin-specific cancel side channel and zeroandroid/**changes.RAGE r5 exact-head outcome: architecture falsified; do not merge #413.
Exact candidate
4e792febeb7b0ebdf834d14810f0676aa9d50ffbran CI #1518. Android APK/native/secret inspection and both shared-mic lanes passed, but the Coretestjob failed deterministically before flake/package.The uploaded
regression-artifactsJUnit report contains 1983 tests / 3 failures, all int/test_plugin_tool_cancellation.py:tool_enteredwith a visible cancellation token;first_started;entered.So the
ToolNode(..., awrap_tool_call=...)+ ContextVar binding does not provide the contract under Zara's exact pinned execution stack. This is design-level evidence, not a flaky runner failure. r5 should be discarded perskills/rage/SKILL.mdrather than patched indefinitely.Next iteration must bind cancellation at Zara's own exact post-approval/post-availability invocation boundary, while preserving the single canonical ToolNode execution path, terminal ToolCancelled authority, exact-invocation isolation, and zero model-visible cancellation arguments/side channels.
RAGE r6 exact-head/merge-ref outcome: second ContextVar architecture falsified; do not merge #420.
CI #1540 exercised branch head
18f548a5857d2badda0206a8046895c12ffc7472as merge ref45abe6893be10daf725315a41e8d4dbca76055ceagainst then-currentmaster27cb2d85a51c735213d807bacfe38a4880994da6.Compatibility lanes stayed green:
Core failed deterministically at the acceptance seam: 1979 passed / 3 failed. Sync, async, and concurrent tool bodies all failed to observe the token/enter before the one-second acceptance boundary. The rejection/no-execution invariant passed.
This proves that wrapping
ToolNode.ainvoke()in a ContextVar scope is insufficient under Zara's pinned LangGraph/LangChain stack, just as r5's ToolNode interceptor was insufficient. We are retiring ContextVar propagation through ToolNode as the cancellation transport rather than adding more patches.r7 research is now constrained to a materially different hidden/injected runtime mechanism (or a canonical executor redesign if the pinned stack lacks one), with the same invariants: approval first, exact invocation isolation, signal-before-cancel, no model-visible/control argument, one terminal ToolCancelled event, and no
android/**changes.RAGE r7 is now PR #425 from exact current master
27cb2d85a51c735213d807bacfe38a4880994da6, candidatef94e9b78fd4048c8237854be05b0bf9149135096.This is materially different from falsified r5/r6 ContextVar designs: it uses LangGraph 1.1.0
InjectedStateas the hidden runtime dependency. Plugin tools opt in with public read-onlyToolCancellationArg; Core creates a private per-invocation signal only after approval + availability and injects its view into that exact one-call ToolNode state. LangGraph's own reference states thatInjectedStateis automatically injected and remains invisible to the model tool-calling interface.Acceptance now covers schema hiding, sync signal-before-side-effect, async signal-before-CancelledError, concurrent isolation, rejection, unload, and spoof attempts. Zero
android/**changes. Exact-head CI #1554 is running; both shared-mic lanes are already green. No merge until Core full tests/flake/package + Android gate are green on this exact SHA.RAGE r9 recovery is now draft PR #446. Immutable Core start was
0a370079f2bf293b320ea72865239e6ee4c08a73; sibling Android then advanced master with #438 only, so no Core file overlap. r8/#431 is closed unmerged after CI #1561 falsified itsAny + InjectedStateexecution. r9 candidate280cae81e000236ea5293c1e2060fa6467bfa255keeps the concreteToolCancellationannotation and uses PydanticSkipValidation()only at the runtime schema boundary, preservingInjectedStatemetadata. Exact-head CI #1595 is queued. If the focused/Core lane still cannot inject the signal, this architecture is retired and the next iteration moves to explicit Core-owned manual argument injection at the existing post-approval/post-availability ToolNode boundary. Zeroandroid/**changes.RAGE r10 is now draft PR #451 from exact canonical
15499557e5994a05d57cc1c0a3ec97857939efda, head6f9dda69b7172e937994a101032b2c4c1fe8404b. r9/#446 is closed unmerged after CI #1595 reproduced the same four focused failures, soInjectedStateis retired. r10 uses LangChainInjectedToolArgonly to hide the argument from the model, then Core explicitly overwritescancellationwith its exact-invocationToolCancellationafter approval/current-binding checks and before the same canonicalToolNode.ainvoke. No ContextVar, no InjectedState, no second executor, zeroandroid/**. Exact-head CI #1607 is queued.r14 / PR #458 is retired unmerged. Exact-head CI #1631 was red in Core: 6 failures / 1985 tests. Android compatibility + Arch mic + Ubuntu mic were green; flake/package correctly skipped after Core failure. Focused cancellation failures: sync tool never entered, async tool never entered, concurrent invocation tool never entered, spoof-guard execution failed before plugin body. Two additional regressions showed
supports_tool_cancellation()assuming every registered test double hasget_input_schema(). Canonicalmasteralso advanced to9bdf9b8d4bcab37da80bbfb31f701e3021b0ef3evia Android #455, so #458 was both red and stale. Do not revive r14 unchanged. Next recovery must prove the transport reaches plugin-body entry before cancellation semantics are evaluated, while retaining one ToolNode/approval boundary and zeroandroid/**changes.r15 / PR #463 is retired unmerged. Exact-head CI #1647 at
9d6e5fa2d6cddd9095f75a136de5702020703a19failed the CoreRun all testsstep; Android unit/native/APK/secret compatibility and both shared-mic lanes were green, while flake/package correctly skipped after Core failed. Canonicalmasteralso advanced to2f4bd28a9428a117f986f06b025d1a35abf5124avia Android #461, so the candidate is both red and stale. Do not recover r15 unchanged. The next #388 iteration must be based on the exact current master and must first isolate the failing Core acceptance from CI #1647 before selecting another cancellation transport. Regression artifact digest:sha256:fad17dc5703029737712c170bb190abc5372cd3d5cf78e2a23c178daaa959224.Fresh r15 failure isolation from CI #1647 / artifact
sha256:fad17dc5703029737712c170bb190abc5372cd3d5cf78e2a23c178daaa959224: there are exactly 3 Core failures, all before cancellation semantics can meaningfully run.test_running_sync_tool_observes_canonical_turn_cancellationtimes out waiting forentered;test_async_tool_sees_signal_before_cancelled_errortimes out waiting for its async entry event;test_cancellation_is_isolated_between_concurrent_invocationstimes out waiting for the first invocation to enter. So r15 is not primarily a signal-ordering bug: the opted-in wrapper path fails to reach plugin-body entry under the exact pinned execution stack. Android and both shared-mic lanes were green on that run. Next #388 iteration should begin from current master by tracing registry wrapper -> ToolNode invocation -> actual BaseTool_run/_arundispatch and prove body entry with a no-cancel control before selecting another cancellation transport. Do not recover r15 unchanged.Additional narrowing from the r15 test matrix/source:
test_registered_wrapper_reaches_original_bodypassed; only the three ToolNode-mediated body-entry tests failed. SoCancellationTransportTool.ainvoke()works when called directly, but the same registered wrapper does not reach the original body through canonicalcreate_tools_node()/ LangGraphToolNode. Current Core constructs oneToolNode(tools)then dispatches each approved/current-bound call viaawait tool_node.ainvoke({"messages": [single_call]}, config). The next control test should therefore compare direct wrapperainvoke(ToolCall)vs ToolNode-mediated invocation with cancellation disabled, before touching signal propagation. That should isolate ToolNode input/dispatch semantics from cancellation itself.Core r16 characterization is now canonical via #569 at merge
bea53760a6c1e91bb0671a509985498d760a49d5(exact candidateea00e250489493ff4e717ca97af905d89a461a5d, CI #1861 fully green). The compiledStateGraph(MessagesState)+ToolNodepath invokes the exact registered tool object's publicainvokewith the typed tool-call mapping (name,args,id) and reaches the plugin body/result. This rules the next cancellation design toward an explicit registered-tool public invocation wrapper keyed by the call id, not another ContextVar transport. No Android changes.RAGE r17 / PR #619 is retired unmerged after exact acceptance CI #1961 at
465ee3dc329f44121864e6c2e0f974a6ba2f7a22falsified the task-local helper. Android unit/native Trealla/debug APK/secret inspection PASS; shared mic Arch PASS; shared mic Ubuntu PASS; CoreRun all testsFAIL, so flake/package/screenshots correctly skipped. The strengthened acceptance added the missing sync-service-tool requirement: a real sync tool body must observe canonical cancellation before releasing owned work.asyncio.current_task().cancelling()cannot be the full transport across that worker-thread boundary. Do not recover #619 or prior ContextVar/InjectedState variants. r16/#569 remains the positive characterization: canonical ToolNode calls the exact registered tool object's publicainvokewith the whole typed ToolCall (name,args,id) and reaches the plugin body. Next design is therefore constrained to a private per-call signal at that proven public wrapper boundary, covering sync + async + concurrent isolation + approval/unload + spoof resistance + timeout distinction, with one ToolNode and one terminalToolCancelledauthority. Zeroandroid/**changes.