Skip to content

fix(acp): preserve async-result continuation agent_end correlation - #6356

Merged
Yeachan-Heo merged 2 commits into
devfrom
g4-asyncres-corr
Oct 5, 2026
Merged

Yeachan-Heo merged 2 commits into
devfrom
g4-asyncres-corr

Conversation

@probepark

@probepark probepark commented Oct 5, 2026 •

Copy link
Copy Markdown
Collaborator

Why

On a dev build that already contains #6333 (3239206), dbe46ae and 8aa5049 (tank, gjc built from f4b3d1a), ACP still logs acp_prompt_terminal_dropped terminalType=agent_end reason=incomplete_correlation, then acp_prompt_watchdog_expired 340s later (G4 gate FAIL, 15 drops in ~4.5h).

Session evidence (jsonl, UTC):

  • 24e6e6b4: 05:23:18.376 assistant stop -> 05:23:18.382 custom_message async-result -> 05:25:17.058 assistant stop -> 05:25:17.168 custom_message irc:incoming -> 05:25:17.189 dropped agent_end (incomplete_correlation)
  • d76cd5c1: 06:18:05.208 assistant stop -> 06:18:05.212 custom_message async-result -> 06:18:13.803 assistant stop -> 06:18:13.826 dropped

The remaining path: the prompt's turn ends while an async job or subagent is still running. When its result arrives, the yield-queue async-result delivery starts a continuation turn through injectIdle / injectStreaming / the trigger-turn follow-up. That turn was accepted without the active SDK run token, so its terminal agent_end carried no commandId/turnId and ACP dropped it.

Note: the binary's lack of activePromptOwnerHolder/adoptLifecycleBatch symbols is expected. The build uses --minify (scripts/compile-args.ts), and the log site acp_prompt_terminal_dropped is present, so dist == source.

What

  • agent-session.ts: when async-result custom messages become continuations, capture #activeSdkRunToken and pass it through:
    • the streaming follow-up (#queueFollowUpAfterReservation(..., { sdkRunToken }))
    • the idle injection (#acceptSdkAttemptRun(handle, sdkRunToken) in both prompt branches)
    • the trigger-turn follow-up path
  • changelog fragment fix-acp-async-result-terminal-correlation.md
  • one whitespace cleanup in agent-session-concurrent.test.ts

This PR does not touch the provider-error retry path (#handleRetryableError), which open PR #6354 fixes, or the todo-reminder continuation pinned by #6344.

Risk

  • low-risk
  • regression-risk
  • high-risk

Touches continuation run-token ownership in AgentSession, so a wrong token could mis-attribute a terminal to a prompt.

Merge approval is expected to stay red on this agent-authored PR until a maintainer approves the exact head (human-review path, #6037); the contract check itself should be green.

Local tests (command + result)

Run on tank (worktree g4-asyncres-corr):

  • bun test packages/coding-agent/test/session-runtime.test.ts -> 180 pass, 0 fail
  • bun test packages/coding-agent/test/agent-session-retry-busy-recovery.test.ts -> 7 pass, 0 fail
  • bun test packages/coding-agent/test/agent-session-concurrent.test.ts -> 35 pass, 0 fail
  • bun run lint -> rc 0

Local CI gate (prepush)

PREPUSH_CMD rc=0 bun run --workspaces --if-present check:types
PREPUSH_CMD rc=0 bun scripts/telegram-daemon-generation-guard.ts "$(git merge-base origin/dev HEAD)" "$(git rev-parse HEAD)"

Needs e2e

  • After a build with this head is installed on tank, re-measure G4 (gjc-acp-guard.py): the count of acp_prompt_terminal_dropped terminalType=agent_end reason=incomplete_correlation after an async-result continuation should be 0, and acp_prompt_watchdog_expired should not rise.

Acceptance

AC Implementation Local test
AC-1 async-result continuation agent_end keeps active prompt commandId/turnId agent-session.ts injectIdle / streaming injector / trigger-turn follow-up pass sdkRunToken session-runtime.test.ts 180/0, agent-session-concurrent.test.ts 35/0 (existing lifecycle tests; no new dedicated regression test: NOT DONE, see Open questions)
AC-2 check whether dist == source build is --minify; log site present in binary n/a (static check on tank)
AC-3 G4 drop count 0 on new build needs e2e tester re-measure

Open questions

  • No dedicated regression test that drives an async-result continuation through ACP and asserts a correlated agent_end was added (agent assumption: existing lifecycle tests cover it). A reviewer may want one.

Agent

gjc via paseo on tank (worktree g4-asyncres-corr), commits 908a49f, 88c4d15. No fallback.

@probepark probepark changed the title test: clean continuation regression whitespace fix(acp): preserve async-result continuation agent_end correlation Oct 5, 2026

@snowykr snowykr left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Verdict

APPROVED

Summary

Reviewed PR #6356 at 88c4d1561f5c3d6ccbfc57eea75ce914c532f71e against base/merge-base 0f2560745bc3d44b60c4698dfcd0cc0560b620a9. The change propagates the existing SDK run token through async continuation paths so accepted attempts retain the command/turn correlation consumed by the SDK host and ACP. The five review scopes found no actionable defects.

Findings / Required Changes

No blocking or actionable findings.

Non-blocking Observations

  • The diff adds no dedicated regression assertion for an async-result continuation producing an ACP agent_end with the expected commandId/turnId; the changed test file only removes whitespace. A focused end-to-end assertion would directly cover this scenario. This is an optional coverage improvement, not a merge blocker.

CI / Verification

The exact-head Dev CI run 37277112952 completed successfully, including agent-session-concurrent.test.ts, the coding-agent package check, the affected-path aggregate, state-gate shards, and virtual integration validation. A second Dev CI run for the same SHA (37277574967) was skipped; its trigger/reason was not established. No local tests or gates were run during this read-only review.

Axis Coverage

Axis Verdict Coverage
A1 — Intent / Policy / Contract APPROVED No concrete mismatch with the stated fix or existing SDK/ACP correlation contract.
A2 — Architecture / Correctness / Failure APPROVED Existing token ownership and attempt-scope binding are reused; no reachable regression was established.
A3 — Security / Privacy / Trust APPROVED No new trust boundary, authorization decision, or attacker-controlled token source was introduced.
A4 — Verification / Tests / CI APPROVED Exact-head required affected tests and aggregate CI passed; missing dedicated end-to-end coverage is optional.
A5 — Context / Compatibility / Platform APPROVED Consumers, cleanup, and existing ownership abstractions remain consistent; no compatibility or platform defect found.

Limitations

This was a static review of the exact head and its base; no dynamic ACP reproduction was run. No separate intent_projection artifact was supplied or found, so intent was assessed from the pinned implementation, changelog, and contracts. The reason for the skipped same-SHA CI rerun was not verified.

@Yeachan-Heo
Yeachan-Heo merged commit bddbf37 into dev Oct 5, 2026
47 checks passed
@Yeachan-Heo

Copy link
Copy Markdown
Owner

Merged into dev as bddbf37e.

  • snowykr approved the exact head 88c4d15.
  • CI on that head: 22 passed, 0 failed.
  • The branch was 13 commits behind dev. The only overlapping file was agent-session.ts (from fix(acp): keep SDK prompt owner across session continuations #6354), and it auto-merged cleanly.
  • I merged it locally with dev 380f4aaa and ran the 80 test files that import agent-session: no failures on the merged tree, vs 1 on unmodified dev.

—
[repo owner's gaebal-gajae (clawdbot) 🦞]

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.

3 participants