Repository navigation
feat: add live standard ACP subagent sessions - #682
Merged
Merged
Conversation
benbrandt
added a commit
that referenced
this pull request
Oct 26, 2026
## Scope Sixth standalone extraction from #655, directly on current `main` (`fe3ae92`) after the live core #682 landed. **16 files, +864/-50**, mostly direct tests and snapshots. No negotiation, capability, dependency, or generated app-server changes. Enhances only the existing standard-subagent path: non-AIR v1 still requires client opt-in; non-AIR v2 uses it by default. AIR retains its separate replay and identity rules. ## Changes - Follow both recorded `subAgentActivity` and collab spawn formats, replaying each conversation once, recursively under its immediate parent. Resolve recoverable reversed ancestry, bound cycles, and never guess or change parentage. - Read legacy or paginated child items lazily. Current-provider ownership verification and live subscription restoration happen before item reads. A retained transcript remains displayable without granting ownership or current work state. - Send all selected history before the load/resume response, preserving the live core's actual batch-write freshness boundary. - Reconcile tool/rendering bookkeeping before suppressing duplicate presentation. Replayed completed tools cannot be failed by later cleanup or resurrected by stale running snapshots. Live completion bookkeeping still runs, and completed runnable items do not leave a live permission incorrectly reported as running. - Restore in-progress command classification without resetting streamed-byte tracking. Duplicate live starts do not reset the reporter, and completion does not resend already streamed output. - Report known gaps once at the parent while continuing available sibling replay. Reject mismatched thread identities. Empty history alone invents no gap, ending, failure, or runtime. ### Conservative limits Agent-owned input is not reinterpreted as human input. Incomplete text snapshots have no safe delta cursor and are omitted rather than duplicated over newer buffered deltas; unfinished command replay carries metadata rather than previously streamed bytes. Only renderers with a safe partial form are used for unfinished items. Open-ended provider status strings (such as image generation status) are not treated as completion enums: those items use recorded completion metadata instead, with legacy and paginated regressions. These omissions produce an advisory. Complete retained content is replayed normally. Historical work-state outcomes, directed-session messages, new child controls, and broader configuration reporting remain deferred. Existing provider-parentage checks still prevent copied fork history from stealing the original runtime. ## Coverage **36 new v1/v2 cases** cover both spawn formats, one visit per conversation, nested/reversed ancestry, paginated item ordering, missing/mismatched snapshots, completed-tool reconciliation, running-command restoration, incomplete-text overlap, stale running history, live permissions, cyclic records, close-during-read, and no-replay behavior. Wire assertions verify recorded content precedes the response; no recorded permission or elicitation request is reissued. Real-Codex integration cases now reload finished children and assert that their retained answers replay under the same child IDs, on v1 and v2. The existing fork/cancel/close/terminal-lifetime checks remain in place. ## Validation - `npm run typecheck` - `npm run build` - `npm test`: **1,995 passed**, 38 skipped - Focused live/replay suites: **77 passed**, 2 v2-only cases skipped on v1 - `npm run test:integration`: **15 passed**, with the real Codex 0.164.0 app-server and a local scripted model - `npm run bundle:all`: all six targets compile - Live-model no-tool smoke completed with `end_turn` - `git diff --check` Existing golden files are unchanged. One live-core assertion changes intentionally: an empty retained transcript no longer produces the blanket “child transcripts are not included” advisory. New replay cases verify advisories for actual failures and incomplete/omitted content. The full live-model E2E suite and execution of every OS bundle were not run. Native integration uses the default provider history store; explicit paginated-branch coverage uses SDK-level fixtures. ## Contract references ACP specification `53620d0b325d6815b3cff1ca7e909351d488fdf0`: [best-effort replay, per-session identity/order, gaps, and freshness](https://github.com/agentclientprotocol/agent-client-protocol/blob/53620d0b325d6815b3cff1ca7e909351d488fdf0/docs/rfds/subagents.mdx#L713-L836). Official TypeScript SDK `c7e07388feed7a530f8211d0dae4951cb6d26d09` / published 2.0.2 is runtime evidence, not the normative contract.
SeanLF
added a commit
to SeanLF/claude-code-subagent-harnesses
that referenced
this pull request
Oct 28, 2026
… own name and end 2.3.0 sends subagents in a draft form ACP's schema rejects, so a nested agent was named "subagent" and stayed open until the via agent's run ended. The standard subagent_update landed 14 minutes after 2.3.0 was cut (agentclientprotocol/codex-acp#682); preview.9 has it, with codex 0.165.0. Sean's call: preview.9 is inside the one-day release-age cutoff (24 minutes old at the pin). Checked live through the relay: a subagent's standard announcement, running and idle; a steer; an interrupt; a resumed session. The lockfile changes only codex-acp and codex's own packages, all hashed, no install scripts. Back to a release when 2.3.1 ships; Dependabot opens it. Co-Authored-By: Claude Opus 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_0131zPk82o4yhGkjvhSWGU4o
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Scope: standalone live core
Fifth incremental extraction from #655, on current
main(091f9b2), after #676, #677, #680, and #681 landed. This is the larger atomic feature slice discussed in the split plan: 43 files, +2,898/-181, including 1,573 added test/snapshot lines and 1,301 added runtime lines. No dependency or generated app-server files change.Included
Explicitly deferred
No recursive child transcript replay, history/live item reconciliation, recorded historical work outcomes, new configuration readback/effort reporting, directed-session messages, or child mutation controls. Those remain separate changes after this live core is reviewed and landed.
The current RFD explicitly allows live support without complete child history. Recoverable associations are replayed truthfully; omitted transcripts are not silently presented as complete.
Review order
The async queue-completion gap found while planning the split is fixed here: a session transition waits for async callbacks and propagates rejection without breaking the notification lane. A regression reproduces both ordering and rejection behavior. The old #655 reference helper must not be copied back over this implementation.
Validation
Final validation used main's latest lockfile (including #679):
npm run typechecknpm run buildnpm test: 1,959 passed, 38 skippednpm run test:integration: 15 passed — eight new real-Codex 0.164.0 cases cover active-child reattachment, fork identity/ownership isolation, parent cancel/close, and child terminal output/exit across later parent prompts, on v1 and v2, using a local scripted modelnpm run bundle:all: all six targets compileend_turngit diff --checkExisting AIR and parent-session golden files are unchanged. The fixed-command terminal fixture alone uses full-access mode to avoid CI hosts without sandbox namespace support; production sandbox settings are unchanged. The full live-model E2E suite and execution of every OS bundle were not run.
References
8aa92106feba5cdd0da210a87a39dfee4dc24f13: identity, announcement, and automatic routing, best-effort replay and response freshness.c7e07388feed7a530f8211d0dae4951cb6d26d09and published 2.0.2 for transport/runtime evidence; normative behavior comes from the spec, not the SDK implementation.