Skip to content

refactor: support direct standard child cancellation - #688

Merged
benbrandt merged 1 commit into
mainfrom
feat/standard-child-cancellation
Oct 26, 2026
Merged

benbrandt merged 1 commit into
mainfrom
feat/standard-child-cancellation

Conversation

@benbrandt

Copy link
Copy Markdown
Member

Summary

Expose Codex's existing child-turn interruption through standard ACP session/cancel, without opening other child mutation controls.

  • Advertise capabilities.cancel: {} only for owned, observable standard children whose current turn can be identified. Revoke with cancel: null when the work ends or becomes unobservable. Idle or history-only children get no grant.
  • Accept the opaque ACP child ID, never a raw provider-ID bypass. Interrupt that child's current turn and observed owned descendant work, not its parent or siblings. A later assignment retains the same child identity and can receive a fresh grant.
  • Withdraw affected permission/elicitation requests locally and reject accepted late replies. Deduplicate in-flight interrupts and permit retry after provider failure.
  • Use receipt-time completion/observability facts and the latest provider turn ID even while rendering is backpressured. A successful interrupt acknowledgement does not fabricate a cancelled outcome; actual provider completion supplies it.
  • Suspend existing grants at parent setup admission. Only the latest successful, non-cancelled setup response can restore them, after its actual wire write (including the full JSON-RPC batch). Failed attempts cannot release current child controls.

Standard v1 opt-in, v2 defaults, and AIR's existing contract are unchanged. Prompt/configuration/load/close/private-extension mutations remain forbidden for standard children. Copied history cannot acquire the original runtime's controls. Dependencies and generated app-server types are unchanged.

Review scope

19 files, +602/-20 lines, mostly tests/snapshots. Runtime work is concentrated in the standard child router, the cancel dispatch, and the successful setup-response boundary. Eight existing standard-child snapshots gain the intended cancel grant/revocation; AIR and ordinary parent-session snapshots are unchanged.

Validation

  • npm run typecheck
  • npm test: 2,095 passed, 40 skipped; final run did not update snapshots. Includes 25 new v1/v2 wire regressions (one v2-only batch case skipped on v1).
  • npm run build
  • npm run test:integration: 17 passed against real Codex 0.164.0 with a local mock Responses API. New v1/v2 cases receive a current cancel grant after reattachment, send session/cancel to the child, observe Codex's actual cancelled ending, and continue prompting the parent independently.
  • npm run bundle:all: all six platform targets compiled.
  • npm run codex-test -- -p 'Reply with exactly child-cancel-ok. Do not read files or use tools.' -c <isolated-scratch-directory> -o summary: live-model smoke completed with end_turn.
  • git diff --check

Wire coverage includes sibling/ancestor isolation, nested descendant cascade, real-ending confirmation and later work, request withdrawal and late replies, in-flight deduplication, raw/foreign/stale IDs, unload under backpressure, newest provider turn targeting, provider-error retry, loaded foreign fork history, delayed replay responses, failures before/after provider setup, and whole-batch freshness.

The full live-model E2E suite was not run. Cross-platform binaries were compiled, not executed on every target OS.

Protocol / provider evidence

  • ACP specification revision 36b3fcc14d1834d6cc2a5ea3f317a49f198c2f79: the subagent RFD cancellation and ownership rules define the object-valued cancel capability, child-directed cancellation, descendant policy, actual completion evidence, and pending requests. The replay freshness boundary forbids historical grants and invalidates failed attempts.
  • SDK reference revision c7e07388feed7a530f8211d0dae4951cb6d26d09, separately checked for capability/notification shapes. Installed SDK 2.0.2 decodes the real v1/v2 test wire. No protocol/schema changes or new RPC methods are needed.
  • Codex's existing turn/interrupt method is exercised directly by the real-app-server child cancellation cases, not inferred from schema alone.

This follows the completed native-subagent extraction; it does not reopen or merge the superseded combined #655.

@benbrandt benbrandt changed the title feat: support direct standard child cancellation refactor: support direct standard child cancellation Oct 26, 2026
@benbrandt
benbrandt merged commit 7524e97 into main Oct 26, 2026
7 checks passed
@benbrandt
benbrandt deleted the feat/standard-child-cancellation branch October 26, 2026 17:11
mrmans0n added a commit to mrmans0n/codex-acp that referenced this pull request Oct 29, 2026
Upstream v2.4.0 (agentclientprotocol#682, agentclientprotocol#688) routes the session-scoped ACP v1 requests through
getAgent(ctx.params), so a standard subagent session rejects client mutations, and imports the
standard subagent modules next to the hook trust imports in CodexAcpServer.ts. No upstream PR
absorbs the downstream hook review.

The two conflicts are context only. The _codex/hooks/trust route keeps upstream's routing of the
neighbouring requests and still forwards reviewToken; CodexAcpServer.ts keeps upstream's new
imports and replaces the hook trust imports with the review's, as before. The sorted +/- lines
of this commit are identical to the original's.

Reviewed against v2.4.0: the execution gate still fences thread/start, thread/resume,
thread/fork, turn/start and review/start by method, so upstream's new child thread/resume
(restoreChild, during session/load inside the reviewed operation) is fenced too; a provider
restart still recreates the standard subagent router before the reviewed session skips the
baseline tracker; the route is registered once, on the ACP v1 chain, where the review is
configured.
Adapted from c07bc0f (original 4d43405).
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.

1 participant