Skip to content

feat(acp): preserve causal prompt correlation - #1239

Open
sethkarten wants to merge 19 commits into
v080/acp-p1-final-corefrom
v080/acp-p2-final-core
Open

feat(acp): preserve causal prompt correlation#1239
sethkarten wants to merge 19 commits into
v080/acp-p1-final-corefrom
v080/acp-p2-final-core

Conversation

@sethkarten

@sethkarten sethkarten commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Stack

P2 child of #1236 only.

Parent-first integration is preserved by an append-only merge commit. Merge #1236 first, then retarget and finalize this PR.

Scope

Exact reviewed P2 causal correlation/lifecycle delta integrated with the final P1 head. Ten P2 paths only; no unrelated Core production duplication.

Verification

  • independent topology and update-queue review: APPROVE
  • Biome and root tsgo --noEmit: passed
  • ACP/daemon/in-process/recursion focused suites: 201/201 passed with inherited RLM_DEPTH and RLM_MAX_DEPTH scrubbed
  • full ACP mode suite: 26/26 passed
  • exact diff and ancestry checks: passed
  • tracked canonical correlation fixture SHA-256: cacde7827aadf186db2ce1af1ea6f3b6d109504fa94945633bd9c0d96106b882

The tracked fixture is commit-bound evidence, not the final distributable Prime Agent artifact. Final artifact creation, create-only publication, fetch-rehash, and fresh PrimeAgentHarness dry-load remain required after the stack is immutable.

No live, paid, model, sandbox, or evaluation run was performed.


Note

High Risk
Large changes to ACP prompt lifecycle, terminal/cancellation semantics, and intercept retry/idempotency affect protocol consumers and paid inference paths; exact-socket shutdown touches rollout-owned daemons.

Overview
ACP session updates now go through a serialized AcpUpdateProducer that stamps every session/update with promptTurnId, monotonic eventSequence, phase (event / responseBoundary / terminalQuiescence), and optional outcome in _meta, instead of firing notifications ad hoc. Prompt turns emit a response boundary and, when no subagents remain, a terminal quiescence envelope with quiescence counters; updates are buffered until session/new commits on the wire, and session/close drains the queue before replying.

Turn completion is driven by live child rosters: getRlmChildSnapshots() on the session, snapshots include children, and the daemon connection merges rlm_child_update into cached snapshots so quiescence is not inferred from stale attach data. Cancellation after a sealed terminal boundary no longer relabels the turn as cancelled.

For the intercept provider, the agent loop injects a per-logical-request X-Prime-Agent-Relay-ID header (caller-supplied values stripped), and AgentSession skips outer auto-retries so idempotency stays at the provider layer.

CLI shutdown --daemon-socket <path> shuts down only a verified same-build daemon via shutdownExactDaemonAndWait (no --force). Release packing skips __pycache__ / .pyc when copying.

Reviewed by Cursor Bugbot for commit cbdff0b. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add causal prompt correlation metadata to ACP session updates

  • Introduces AcpUpdateProducer in acp-mode.ts to serialize all outbound session.update notifications and stamp them with promptTurnId, eventSequence, phase (event/responseBoundary/terminalQuiescence), and outcome (result/error) fields under a namespaced _meta key.
  • Prompt responses now emit a responseBoundary update followed by a terminalQuiescence update (when no child subagents remain), and heartbeats are pinned to connection-scoped turn 0.
  • session/new rejects concurrent admissions while a snapshot is in flight; session/close drains the publish queue before returning; cancellation during a sealed terminal turn no longer relabels the stop reason.
  • Adds AgentSession.getRlmChildSnapshots() to expose a hierarchical live child-agent snapshot used for quiescence accounting.
  • Adds shutdownExactDaemonAndWait to the CLI, allowing shutdown --daemon-socket <path> to stop only a verified matching daemon instance.
  • For intercept provider models, each LLM streaming request now carries a unique X-Prime-Agent-Relay-ID header, and AgentSession no longer outer-retries intercept provider errors.
  • Risk: existing consumers of session.update notifications will see new _meta fields and a changed emission order (boundary then quiescence), which may break clients that do not tolerate unknown metadata.

Macroscope summarized cbdff0b.

Comment thread packages/coding-agent/src/modes/acp/acp-mode.ts
Comment thread packages/coding-agent/src/modes/acp/acp-mode.ts
Comment thread packages/coding-agent/src/core/agent-session.ts Outdated
Comment thread packages/coding-agent/src/modes/acp/acp-mode.ts Outdated
Comment thread packages/coding-agent/src/modes/acp/acp-mode.ts
Comment thread packages/coding-agent/src/modes/acp/acp-mode.ts Outdated
Comment thread packages/coding-agent/src/modes/acp/acp-mode.ts Outdated
@sethkarten
sethkarten marked this pull request as ready for review August 12, 2026 06:18
Comment thread packages/coding-agent/src/modes/acp/acp-mode.ts
Comment thread packages/coding-agent/src/core/agent-session.ts
@sethkarten
sethkarten requested a review from alexzhang13 August 13, 2026 01:18
Comment thread packages/coding-agent/src/core/agent-session.ts

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes and found 1 potential issue.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit cbdff0b. Configure here.

return true;
}
throw error;
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exact shutdown succeeds on missing socket

High Severity

The exact-shutdown catch treats any failure as success whenever existsSync(socketPath) is false. That is not a reliable “daemon gone” signal: Windows named pipes typically do not appear as files, and a refused unverified daemon still running after a handshake error is reported as stopped. Callers then skip shutdown and can proceed as if the process had exited.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit cbdff0b. Configure here.

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