Skip to content

fix(coding-agent): scope continueQueuedMessages to explicit queue-consuming continuations - #4127

Open
Yeachan-Heo wants to merge 5 commits into
devfrom
fix/issue-4124-postmerge-continuation-r2
Open

fix(coding-agent): scope continueQueuedMessages to explicit queue-consuming continuations#4127
Yeachan-Heo wants to merge 5 commits into
devfrom
fix/issue-4124-postmerge-continuation-r2

Conversation

@Yeachan-Heo

Copy link
Copy Markdown
Owner

Regression

Fixes #4124. Dev merge e8a600c557 for #4120 broke AgentSession continuation across all eight coding-agent CI shards: its continuation selection routed every scheduled continuation through continueQueuedMessages() whenever the last message was a non-assistant execution tail. Retry, fallback, auto-compaction, deep-interview, active-goal, TTSR, and todo-reminder continuations then either drained the queue without continuing the current context or failed with No queued messages to continue when nothing was queued.

Local reproduction on exact current dev (6608c201, base of this branch): 99 failing tests across 15 agent-session files, mapping one-to-one onto the issue's shard failure classes:

Shard class Files Fails at HEAD
queued steer/follow-up successor delivery (both 5s timeouts) agent-session-fallback-upstream-count.e2e 10
auto-compaction + manual retry agent-session-auto-compaction-continue, agent-session-manual-retry 5
continuation/goal/retry agent-session-deep-interview-continuation, agent-session-goal-reminder 18
retry/fallback agent-session-retry-fallback, agent-session-fallback-attempt-transaction 10
deep-interview/resilient-retry/reminder agent-session-deep-interview-continuation, agent-session-resilient-retry, agent-session-todo-reminder 43
retry busy recovery / invalid-prompt / retry-delay / TTSR / mid-run compaction / compaction queue agent-session-retry-busy-recovery, agent-session-invalid-prompt-retry, agent-session-retry-cap, agent-session-ssh-refresh, agent-session-midrun-compaction, agent-session-auto-compaction-queue 13

Fix

Smallest safe change to the shared continuation admission boundary in packages/coding-agent/src/session/agent-session.ts:

  • continueQueuedMessages() is now opt-in via a new continueQueuedOnly option on #scheduleAgentContinue and is used only by the explicit queue-consuming scheduled continuations: the follow-up/steer drain scheduled after foreground bash/eval/python settles (#scheduleQueuedFollowUpContinuation and the python-result continuation), which must avoid stale-tail replay.
  • Every other scheduled continuation keeps continue() semantics, restoring the pre-fix(coding-agent): gate queued prompts during busy operations #4120 contract for retry, fallback, compaction, deep-interview, goal-reminder, TTSR, and reminder continuations.

The #4120 queue-fencing intent is preserved: queued prompts still wait for compaction/foreground bash/eval to settle and are delivered through the dedicated queue continuation afterwards.

Verification

  • Focused regression proof (all eight shard failure classes + foreground bash/eval queue fencing): 238 pass / 1 skip / 0 fail across 16 agent-session files, including agent-session-queued-prompts.test.ts + issue-825-repro.test.ts + input-controller-keybindings.test.ts + input-controller-skill-queue.test.ts (fencing cohort: 93 pass / 0 fail).
  • Broad 70-file AgentSession run: 769 pass / 20 skip / 0 fail (re-run; first run had one unrelated flaky agent-session-eager-todo fsync test that passes in isolation and passes at HEAD — classified unrelated to this change, matching the prior lane's finding).
  • At HEAD the same broad run produced 670 pass / 20 skip / 99 fail.
  • bunx @biomejs/biome@2.5.2 check on the edited file passes; bun --cwd=packages/coding-agent run check:types passes after generating the ignored docs index.

This lane supersedes the crashed prior continuation lane for #4124; the uncommitted work was independently reconstructed against exact dev and this is the only PR for the issue.


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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 1831007df8

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +4978 to +4980
const continueQueued = options?.continueQueuedOnly
? this.agent.continueQueuedMessages.bind(this.agent)
: this.agent.continue.bind(this.agent);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve queue-only overflow recovery

When overflow maintenance finds nothing eligible to compact while the history has a resumable non-assistant tail, #runAutoCompaction deliberately schedules the queued_continue path at lines 14922-14932 only when a follow-up or steer is waiting. With this new default, that path calls agent.continue() and resubmits the same oversized tail instead of consuming the queued message, recreating the replay that overflowNoopWouldReplay is meant to prevent and potentially leaving the user's prompt undelivered. Mark these explicit compaction queue drains as continueQueuedOnly as well.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Fixed on exact PR head a3a3abd0f7160eebf072f04c8207b864a8a44d52.

The overflow no-op queued_continue branches now opt into continueQueuedOnly, and focused follow-up + steer regressions construct the persisted and in-memory resumable tail explicitly. Evidence after rebasing onto current dev (515ef1aa63ca32fc833ee0f3a6a991d6b8e37a1d):

  • exact two regressions: 2 pass / 0 fail
  • full focused file: 21 pass / 1 skip / 0 fail
  • bun --cwd=packages/coding-agent run check:types: pass
  • Biome check on the edited source/test: pass
  • PR head contains exact current base and the worktree is clean

The same PR branch was force-updated with lease; no merge was performed.


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

@Yeachan-Heo
Yeachan-Heo force-pushed the fix/issue-4124-postmerge-continuation-r2 branch from 1831007 to a3a3abd Compare August 10, 2026 01:47
@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

MERGE_READY / LGTM — exact head a3a3abd0f7160eebf072f04c8207b864a8a44d52

Terminal review is clean against current dev base 515ef1aa63ca32fc833ee0f3a6a991d6b8e37a1d.

Contract verification

  • continueQueuedMessages() is selected only by explicit continueQueuedOnly queue-consuming call sites.
  • The overflow no-op queued_continue paths for both queued follow-up and queued steer set that flag, so they consume the queued user turn instead of replaying the resumable oversized tail.
  • Ordinary retry, fallback, promotion, maintenance, reminder, deep-interview, active-goal, and synthetic continuation paths retain continue() semantics.
  • Queued-successor fallback/overflow accounting resets once, inside accepted-run handling; busy/stale attempts do not reset it.
  • The fix(session): resume maintenance continuations correctly #4129 maintenance-continuation fix is refined, not reverted. fix(sdk): bound a session host that attached and then lost its endpoint #4130 changes only SDK host files and has no source overlap.

Exact-head evidence

  • Focused file: 21 pass, 1 skip, 0 fail.
  • Contract subset: 5 pass, 0 fail.
  • Managed fallback/overflow interaction subset: 4 pass, 0 fail.
  • fix(sdk): bound a session host that attached and then lost its endpoint #4130 SDK host interaction file: 13 pass, 0 fail.
  • Mutation proof: removing the overflow no-op continueQueuedOnly flag in a detached exact-head worktree makes both new follow-up/steer regressions fail (0 pass, 2 fail), proving the tests reach and lock the intended selector.
  • Dev CI run 31348031496: success at the exact PR head.
  • Virtual integration validation job 93334609121: success, including checked-out source-head and authoritative-base verification.
  • Fresh frozen-head cohort: cleaner PASS, architect CLEAR/CLEAR/CLEAR + APPROVE, QA/red-team passed, terminal critic OKAY; no findings or blockers.

The unrelated stable MCP/model batch/startup/runSubprocess/modelRoles residuals and shard-1 contract dispute were not absorbed into this verdict. Worktree and remote PR head remain exact and clean. No merge was performed.


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

@probepark

Copy link
Copy Markdown
Collaborator

BLOCKER — verified regression. This PR breaks a test file it does not touch.

Method

Rebased the PR head onto current dev (a2df8e4f9) in a clean worktree — the PR head does not contain dev, so testing the head alone would not have found this.

Result

packages/coding-agent/test/agent-session-auto-compaction-queue.test.ts, which this PR does not modify:

tree result
current dev, unmodified 10 pass / 1 fail
PR head rebased onto dev 9 pass / 2 fail

One of those failures is pre-existing (runs pre-continue compaction before resuming queued messages fails on clean dev too — unrelated, not yours). The new one is:

(fail) AgentSession auto-compaction queue resume > resumes after threshold compaction when only agent-level queued messages exist
  expect(continueSpy).toHaveBeenCalledTimes(1)
  Expected number of calls: 1
  Received number of calls: 0
  at agent-session-auto-compaction-queue.test.ts:230

Cause, isolated to one expression

I reverted only the routing selector, keeping everything else in the PR including the new startsQueuedSuccessor condition:

// PR (agent-session.ts:4980-4982)
const continueQueued = options?.continueQueuedOnly
	? this.agent.continueQueuedMessages.bind(this.agent)
	: this.agent.continue.bind(this.agent);

Reverting just that back to the tail-role selector → 10 pass / 1 fail, i.e. back to the dev baseline. So this one expression is the whole regression; startsQueuedSuccessor is not implicated.

Why

The threshold-compaction resume path reaches #scheduleAgentContinue without continueQueuedOnly. Of the 21 #scheduleAgentContinue call sites, only 6 pass the flag (:9530, :10326, :14932, :14954, :15214, :16730). The threshold-compaction resume is not one of them, so it now takes this.agent.continue, which the test spies on and which correctly reports 0 calls — the queued agent-level message is never drained.

The PR's premise is right: routing on "the last message is a non-assistant execution tail" is the wrong signal, and an explicit flag is the correct fix. The flag is just not yet applied at every site that legitimately drains a queue. The threshold-compaction resume is a genuine queue-consuming continuation and needs continueQueuedOnly: true.

To unblock

  1. Find the threshold-compaction resume scheduler and add continueQueuedOnly: true.
  2. Audit the other 15 flagless call sites the same way — the CHANGELOG entry claims retry, fallback, auto-compaction, deep-interview, active-goal, TTSR and reminder continuations keep continue() semantics, but at least one auto-compaction path demonstrably needs the queue-consuming variant. Verify that list against the code rather than the intent.
  3. Re-run agent-session-auto-compaction-queue.test.ts — it must return to 10 pass / 1 fail (the remaining failure is the pre-existing one).

Also needs a rebase for exact-head CI regardless.

Not questioning the design — the flag is the right call. This is a missed call site, and it is the kind of miss the existing broad-suite evidence in the PR description could not surface, because that run predates current dev.

@probepark probepark 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.

Requesting changes — see the detailed analysis in my earlier comment.

Summary: rebased onto current dev and this PR regresses packages/coding-agent/test/agent-session-auto-compaction-queue.test.ts, a file it does not modify. Clean dev gives 10 pass / 1 fail; with this PR, 9 pass / 2 fail.

Isolated to one expression — reverting only the continueQueued routing selector at agent-session.ts:4980-4982 restores the baseline, so startsQueuedSuccessor is not implicated.

Cause: the threshold-compaction resume reaches #scheduleAgentContinue without continueQueuedOnly, so it now takes agent.continue and never drains the queued message. Only 6 of 21 call sites pass the flag.

The design is right — an explicit flag beats routing on "the last message is a non-assistant execution tail". The flag is just not applied at every site that legitimately drains a queue. Add it to the threshold-compaction resume and audit the other 15 flagless sites against the code rather than the CHANGELOG's intent.

Also needs a rebase for exact-head CI.

@Yeachan-Heo
Yeachan-Heo force-pushed the fix/issue-4124-postmerge-continuation-r2 branch from a3a3abd to e13e945 Compare August 10, 2026 05:56
Yeachan-Heo and others added 5 commits August 10, 2026 06:27
…suming continuations

continueQueuedMessages() whenever the last message was a non-assistant
execution tail. Retry, fallback, auto-compaction, deep-interview,
active-goal, TTSR, and reminder continuations then either drained the queue
without continuing the current context or failed with "No queued messages
to continue" when nothing was queued, breaking AgentSession continuation
across all eight dev CI coding-agent shards (99 local failures across 15
agent-session files).

The queue-consuming continuation is now opt-in via continueQueuedOnly and
used only by the explicit follow-up/steer drain scheduled after foreground
bash/eval/python settles, which must avoid stale-tail replay. All other
scheduled continuations keep continue() semantics.

Focused regression proof: 238 pass / 1 skip / 0 fail across 16
agent-session files covering every shard failure class (fallback attempt
accounting, queued successor delivery, auto-compaction, manual retry,
deep-interview, active-goal reminders, resilient retry, retry-delay, TTSR,
todo reminders, retry busy recovery, mid-run compaction) plus the #4120
fencing cohort (93 pass: queued-prompts, issue-825, input-controller
keybindings/skill-queue). Broad 70-file AgentSession run: 769 pass /
20 skip / 0 fail (re-run; first run had one unrelated flaky
agent-session-eager-todo fsync test that passes in isolation and at HEAD).

Lore-id: 4124-postmerge-continuation-r2
Constraint: preserve ordered follow-up delivery without concurrent model turns
Constraint: keep continueQueuedMessages only for explicit queue-consuming scheduled continuations
Rejected: exact revert of #4120 | drops the bash/eval/python queue-fencing intent
Rejected: role-based selection with assistant-only continueQueuedMessages | still breaks non-assistant retry/compaction tails
Confidence: high
Scope-risk: medium
Reversibility: revert-commit
Tested: 238 + 93 focused plus 769 broad agent-session tests
Not-tested: full 777-file coding-agent suite (remaining shards covered by CI)
Review follow-up: the explicit queue-consuming continuation must also be
used by the auto-compaction queued_continue recovery paths (overflow no-op
with a resumable non-assistant tail, pre/post-compaction queued-message
delivery) and the user-interrupt steering drain. With the default
continue() these drains replay the oversized non-assistant tail and strand
the queued follow-up/steer, recreating the stale-tail replay the #4120
fencing was meant to prevent.

Lore-id: 4124-postmerge-continuation-r2
Constraint: keep continueQueuedMessages only for explicit queue-consuming scheduled continuations
Constraint: preserve ordered follow-up delivery without concurrent model turns
Confidence: high
Scope-risk: narrow
Reversibility: revert-commit
Tested: focused agent-session regression cohorts plus fencing cohort
Not-tested: full 777-file coding-agent suite (CI covers remaining shards)
Auto-compaction overflow no-op recovery must consume queued follow-up and steering messages without replaying the resumable oversized tail. The regressions also keep queued continuation busy handling bound to continueQueuedMessages().

Lore-id: 4124-postmerge-continuation-r2-overflow

Constraint: preserve queue-only overflow recovery from discussion_r3745892872

Constraint: keep retry continuations on continue() semantics

Confidence: high

Scope-risk: narrow

Reversibility: revert-commit

Tested: bun test packages/coding-agent/test/agent-session-auto-compaction-continue.test.ts (21 pass, 1 skip)
Auto-compaction queue resumes are explicit queue-consuming continuations. Assert continueQueuedMessages after threshold and pre-continue maintenance so the regression contract matches the follow-up/steer ingress fix rather than accepting ordinary tail replay.

Lore-id: 4124-current-dev-queue-resume

Constraint: ordinary retry and maintenance continuations retain continue() semantics

Constraint: explicit queued drains use continueQueuedMessages()

Confidence: high

Scope-risk: narrow

Reversibility: revert-commit

Tested: 54 pass, 1 skip across auto-compaction queue, deep-interview continuation, and auto-compaction continuation files
An idle genuine or synthetic steer is an explicit queue drain, but it still used the ordinary continuation path. That replayed continuation ownership, skewed deep-interview attempt accounting, and could consume or supersede ingress through the wrong path. Route the scheduled idle steer through continueQueuedMessages and pin stale-stop behavior to the queue-specific call.

Lore-id: 4124-idle-steer-queue-ingress

Constraint: genuine ingress claims deep-interview ownership exactly once

Constraint: synthetic and agent-attributed ingress cannot supersede genuine ownership

Constraint: ordinary retry/fallback/maintenance continuations retain continue()

Confidence: high

Scope-risk: narrow

Reversibility: revert-commit

Tested: 54 pass, 1 skip across three continuation regression files

Tested: coding-agent package check

Tested: four managed fallback/overflow interaction cases
@Yeachan-Heo
Yeachan-Heo force-pushed the fix/issue-4124-postmerge-continuation-r2 branch from e13e945 to dc09d83 Compare August 10, 2026 06:29
@Yeachan-Heo

Copy link
Copy Markdown
Owner Author

MERGE_READY / LGTM — refreshed exact head dc09d83aa98a4155cad9e17c21956df9abf18c10

This supersedes the prior exact-head verdict. PR #4127 was reconstructed and rebased onto current dev 06bf6d2055f94a77b3e7f5af1920733d48483799; the PR is clean and mergeable.

#4124 production contract

  • Scheduled idle/winding-down steering is now explicitly queue-consuming and routes through continueQueuedMessages().
  • Threshold and pre-continue auto-compaction queue resumes remain explicit continueQueuedOnly drains after the compaction preflight.
  • Ordinary retry, fallback, promotion, maintenance, reminder, deep-interview stop, and synthetic continuation paths retain continue() semantics.
  • Genuine deep-interview ingress claims ownership once and resets the attempt budget on the accepted queued user turn; synthetic and agent-attributed streaming inputs cannot supersede that ownership.
  • Stale assistant stops remain terminal after a newer queued user turn starts.

Verification

  • Three continuation regression files: 54 pass, 1 skip, 0 fail (204 assertions).
  • Owned current-dev rows together: 3 pass, 0 fail.
  • Managed fallback/overflow interaction subset: 4 pass, 0 fail.
  • bun --cwd=packages/coding-agent run check: pass (Biome + TypeScript).
  • Mutation proof:
    • Removing idle-steer continueQueuedOnly fails all three deep-interview continuation/ingress rows: ordinary call counts become 4 vs 3, 1 vs 0, and 7 vs 2.
    • Removing the structural !preparation queue flag fails both compaction queue-resume rows: ordinary continue() becomes 1 vs expected 0 in each.
  • Exact-head Dev CI 31362209223: success.
  • Virtual integration 93374693932: success.
  • Fresh adversarial critic bound to this head/base: OKAY, no blockers.

Scope is limited to #4124. No modelRoles/#4125, MCP/#4136, or notification/replay files were absorbed. Worktree and remote PR head are exact and clean. No merge was performed.


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

@Yeachan-Heo Yeachan-Heo left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

MERGE_READY — owner hold 해제. Exact-head CI가 terminal green이며 현재 확인된 unresolved blocker가 없습니다. Merge/release는 owner-controlled 단계로 남깁니다.


[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.

2 participants