Repository navigation
fix(acp): support root session replacement in V2 - #1
nullStack65 wants to merge 1 commit into
Conversation
An agent can replace the root session behind the same ACP connection: omp's /fresh starts a new provider session and publishes every later session/update under a new id while the original id stays the one session/load replays. The V2 runtime treated those updates as a foreign child session, so the thread went silent for the rest of the turn. Add a generic, default-off runtime capability (AcpSessionRuntimeOptions.adoptRootSessionReplacement) that adopts a new live root session id first seen while a root prompt is in flight, at most once per prompt, and projects adopted notifications back onto the durable setup id. Prompts, cancellation, session loading, and item identity keep using the durable session; foreign ids seen while idle stay rejected. The ACP Registry adapter exposes the opt-in per instance through AcpRegistrySettings. The frozen bespoke reference is PR pingdotgg#11973; this slice carries only the provider-neutral adoption mechanism.
|
ENVFIX1:STD-OMP START Executing the retained OMP4a40 focused test obligation once, without installation or a model call.
The original execution owner will collect the exact child PID/PGID, finite deadline, exit, test counts, output hash, source pins, and denied-operation evidence. |
|
ENVFIX1:STD-OMP RESULT The single authorized direct
The unchanged command was not retried. The exact remaining primitive is a no-install Vite/Vitest startup mode that redirects |
|
ENVFIX1:STD-IMPORT-CLOSURE RESULT — OMP4a40/res4cfa read-only artifact/runtime qualification Outcome: Exact inputs preserved
Import classification
Observed runtime and load evidence
Candidate/source correspondence
Precise DEV materializer primitive
Bounded no-live-effect validation after materialization # From each of the three workspace package roots: resolution only
node --input-type=module -e 'for (const s of ["effect/Effect","effect/Schema","@t3tools/shared/hostProcess"]) { try { console.log(s, import.meta.resolve(s)) } catch (e) { console.error(s,e.code); process.exitCode=1 } }'
# Candidate syntax and top-level import audit
for f in "$CANDIDATE"/*.mjs; do "$NODE24" --check "$f"; done
rg -n '^import .* from "(effect/|@t3tools/shared/)|^import "(effect/|@t3tools/shared/)' "$CANDIDATE" -g '*.mjs'
# Entry wrapper, then actual help path, with no writes or network
sandbox-exec -p '(version 1)(allow default)(deny network*)(deny file-write*)' "$NODE24" --input-type=module -e "await import('file://$CANDIDATE/bin.mjs')"
sandbox-exec -p '(version 1)(allow default)(deny network*)(deny file-write*)' "$NODE24" "$CANDIDATE/bin.mjs" --helpThe top-level audit must return no |
|
ENVFIX1:Standards — RESULT: Node24 no-evaluation TypeScript format qualification Outcome: QUALIFIED for the narrow syntax/type-erasure boundary; not qualified for linking, import evaluation, native loading, transitive closure, or runtime acceptance. Exact identities:
Commands and direct results:
Boundaries verified:
Limitations / next predicate:
|
|
ENVFIX1:Standards — CORRECTION to Node24 no-evaluation TypeScript format result The earlier direct The narrow QUALIFIED verdict rests solely on this exact bounded chain:
That chain exited 0, produced erased-output SHA-256 Limitations are unchanged: this does not prove dependency resolution, deployed |
|
ENVFIX1:OMPREG START/RECONCILED — bounded installed OMP 18.2.4 no-auth registry inspection Scope: read installed executable/catalog/docs and supported nonsecret effective config only for |
|
ENVFIX1:OMPREG RESULT — endpoint resolved; pilot route NOT qualified Installed executable: Safety result: NOT a sole/single-request/no-spillover route. Effective config is Receipt: Next exact primitive: a task-scoped, source-backed effective request policy that demonstrably disables session retries and model fallback and pins OpenRouter upstream routing ( |
|
ENVRESUME:RUNTIME START Reconciled the existing OMP 18.2.4 no-auth registry result. I am qualifying a task-scoped, isolated policy only: retry disabled, model fallback disabled, exact enabled-model selector, and OpenRouter upstream routing fence. No provider/API/auth/secret/funds/pilot call; no project source write or install. I will return exact executable/config hashes, effective readback, and any remaining unsupported primitive. |
|
ENVRESUME:RUNTIME RESULT Task-local OMP request-policy boundary qualified without provider access. Installed omp/18.2.4 SHA 780a47a5e5668807f5ac1ca37067ddbc528a64edcdf964286bf346f7a83e0609 accepted and read back retry.enabled=false, retry.modelFallback=false, enabledModels=[openrouter/openai/gpt-5.6-luna]. The separately bound future selector is openrouter/openai/gpt-5.6-luna@openai; installed source at decimal offset 138696092 projects the parsed suffix to provider.only=[openai]. A network-denied, auth-helper-denied, protected-secret-denied models read exited 0 and found exactly one matching catalog row. Provider/API/inference/auth/funds/pilot calls: 0. Source head/tree remained 9ba3a54 / 6c9ada799401b4bc3febaa4795066c79d0a0b6e3. Receipt: /Users/businessaccount/Documents/t3-investigation-20260929/execution/standards-parallel-included-execution-20261005/OMP-TASKLOCAL-NO-PROVIDER-POLICY-QUALIFICATION-20261006.json This qualifies the policy boundary only. Authentication, current balance, funded pilot authorization, ACP lifecycle, and native execution remain separate open predicates; no pilot was started. |
What this is
Fork-held slice for the V2 architecture (
USE_GENERIC_ACP_V2_WITH_SMALL_GENERIC_FIXES). It adds the generic, provider-neutral root-session-replacement capability the V2 ACP runtime needs so an agent that swaps its root session behind the same connection (omp/fresh) does not go silent.pingdotgg/t3code#28293d45b305632c72cbb8fd8a6dd5077b94c25d7eb5orchestrator-v2-base-3d45b3056(3d45b3056)feat/acp-root-session-adoption-3d45b3056(9ba3a54d83c0fc4f8317ae605bd6a6a528213396)4749035bda13b4b6260499caedbc0d69a2f60e6fpingdotgg/t3code#11973@4f9419b72bb92bebc6669dd95f345e1ccdf4bcedProblem
An agent can replace the root session on the same ACP connection. Real omp 18.2.4 behavior, proven live:
session/new, addressable, replayable viasession/load);/fresh;session/updatenotification arrives under a new id B, including the direct response to the/freshprompt;session/listonly ever shows A;/fresh.Design (generic, no provider branches)
AcpSessionRuntimeOptions.adoptRootSessionReplacement(defaultfalse) plusonRootSessionReplacedfor diagnostics.session/load,session/close, model/config requests, and assistant item identity all keep using the durable id.AcpRegistrySettings.rootSessionReplacement(defaultfalse, generic, usable by future agents). No global relaxation for every registry agent. Noif agent === "oh-my-pi"anywhere.Net change: 6 files, ~+609/-5.
Tests
apps/server/src/provider/acp/AcpJsonRpcConnection.test.ts— new root-session-replacement block (all green, 47/47 total):root before fresh)onRootSessionReplacedreports each change onceAdditional green:
AcpRegistryAdapterV2.test.ts3/3 — includes a new end-to-end test through the real registry runtime with the instance opt-in.AcpAdapterV2.test.ts105/105 (V2 provider adapter runtime policy).OrchestratorReplayFixtures.integration.test.ts73/73 (V2 replay fixtures).apps/servertsc --noEmit: clean.packages/contractstsc --noEmit: clean.vp linton every changed file: clean.git diff --check: clean.darwin-x86_64distribution, so the pre-existing E2E test failed on this host. Same failure reproduces on the base snapshot3d45b3056(ACP Registry agent fixture-agent has no compatible distribution for darwin-x64), classified as a base/host fixture gap, now fixed in the fixture (no production code).Live zero-inference proof (real omp 18.2.4, registry PR pingdotgg#613 metadata)
OMP updated to 18.2.4; local binary sha256
780a47a5...matches the exactdarwin-x86_64sha256 inagentclientprotocol/registry#613(eed36bcaa677749b0bdf24010dfc3883834612c9). Registry JSON served from an injected HttpClient using the exactoh-my-pi/agent.jsonmetadata;commandPathpointed at the localomp;authMethodId: "agent". No model prompt; only local commands (/context,/fresh,/rename).Through the patched V2 registry adapter (
rootSessionReplacement: true):session/new:01a0b151-096c-.../contextfix(acp): support root session replacement in V2 #1 →Context window: 272000 tokens (6% used)(updates flow)/fresh→Fresh provider session started (1 provider state pruned)./contextfix(server): opt-in fail-closed policy for codex thread resume #2 (post-fresh) →Context window: ...— updates continue through the patched runtime/freshunchanged:01a0b151-096c-...Direct
AcpSessionRuntimewithadoptRootSessionReplacement: true:startid A =01a0b151-102d-...;session/listcontains A/fresh→onRootSessionReplaced { previousSessionId: A, sessionId: 01a0b151-12be-... }(live identity observed without overwriting A)session/cancelsucceeds on A/contextafter/freshsucceedssession/load(A)returns A;session/listafter load still contains ADependencies / not covered here
agentclientprotocol/registry#613(oh-my-pi18.2.4). This branch does not vendor registry metadata.