Skip to content

v2.3.1-preview.1

@benbrandt benbrandt tagged this 26 Oct 13:01
## 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

- Standard associations for opted-in non-AIR v1 clients and non-AIR v2
clients. AIR retains its existing opt-ins, private updates, generation
identities, and fallback.
- One opaque conversation ID across assignments, idle work, and handler
replacement. Announce immediate parents before children; buffer
unresolved ancestry rather than flattening it.
- Child-owned streamed-item/tool state, plans, titles, permissions, and
elicitation. Accepted URL completion state survives parent attachment
changes; late approval replies are rejected locally when actual work
ends.
- Empty child capabilities and an allowlist boundary for all client
mutations, including private extensions and raw provider IDs. Known raw
IDs are restricted even while announcement publication is backpressured.
Parent cancellation cascades to observed live children; an actual ending
produces idle, observability loss produces unknown.
- Association-only replay and safe reattachment: current provider
parentage must match through known ancestors, inactive owned children
receive future events without loading them, and copied forks cannot
steal the original runtime. Parent history still replays normally; an
explicit advisory says recorded child transcripts are not included.
- Current child snapshots follow the real successful wire write,
including complete JSON-RPC batches. Same-parent setup execution is
serialized without waiting on each other's shared batch delivery.
Closing a parent fences queued reopen attempts.
- Preserve the model reporting already landed in #678: reuse its source
priority and read-only model option helper. Model observations are not
guessed from spawn arguments or parent values; buffered older settings
cannot replace newer observations.

### 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

1. Contract selection, connection-owned identities/restrictions, and ACP
mutation dispatch.
2. Live router admission, child-owned rendering/work/request state, and
existing model reporting.
3. Provider subscriptions and ownership verification; no parent
cwd/MCP/instruction overrides when rejoining a child.
4. Conversation-owned interaction handlers and request cancellation
scopes.
5. Session setup lane, batch-write freshness boundary, and
association-only replay.
6. Behavior-focused tests and wire snapshots for both versions.

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 typecheck`
- `npm run build`
- `npm test`: **1,959 passed**, 38 skipped
- Focused live/wire/queue suites: **44 passed**, 2 v2-only cases skipped
on v1
- `npm 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 model
- `npm run bundle:all`: all six targets compile
- Real live-model no-tool smoke completed with `end_turn`
- `git diff --check`

Existing 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

- ACP specification at `8aa92106feba5cdd0da210a87a39dfee4dc24f13`:
[identity, announcement, and automatic
routing](https://github.com/agentclientprotocol/agent-client-protocol/blob/8aa92106feba5cdd0da210a87a39dfee4dc24f13/docs/rfds/subagents.mdx#L166-L246),
[best-effort replay and response
freshness](https://github.com/agentclientprotocol/agent-client-protocol/blob/8aa92106feba5cdd0da210a87a39dfee4dc24f13/docs/rfds/subagents.mdx#L713-L840).
- Official TypeScript SDK checkout
`c7e07388feed7a530f8211d0dae4951cb6d26d09` and published 2.0.2 for
transport/runtime evidence; normative behavior comes from the spec, not
the SDK implementation.
Assets 2
Loading