Skip to content

refactor(coding-agent): harden session action races - #576

Merged
snimu merged 15 commits into
refactor/session-action-protocolfrom
refactor/session-action-cleanup
Aug 3, 2026
Merged

snimu merged 15 commits into
refactor/session-action-protocolfrom
refactor/session-action-cleanup

Conversation

@snimu

@snimu snimu commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Summary

Final PR of the session-action stack: deletes machinery the new lifecycle has made provably redundant - most notably the entire broad turn-admission lease - hardens the remaining races with a deterministic test matrix, and removes the last dead legacy-protocol code. Net -59 production LOC on top of #4.

Stack: #572 contracts <- #573 kernel <- #574 admission <- #575 protocol <- #576 cleanup (this)

Motivation

The broad FIFO admission lease existed to stop direct prompts from overtaking queued work. After #3 there are no direct prompts: store arrival order is the FIFO, so the lease - promise tail, owner token, AsyncLocalStorage reentrancy, pause coordination - protected nothing. Deleting safety machinery is only safe with proof, so this PR pairs each deletion with an audit of its call sites and adds race tests at the await points that remain.

Code changes

  • Deleted the broad admission machinery: _acquireTurnAdmission, _acquireSessionActionAdmission, _waitForQueuedWorkAdmission, _wakeQueuedWorkAdmissionWaiters, _queuedWorkAdmissionWaiters, _turnAdmissionTail, _turnAdmissionOwner, _turnAdmissionContext, and the admission leases around prompts, injected turns, pump preparation, and branch navigation.
  • Replaced by a narrow commit fence: held only across dispatch commit edges and session-command transcript-row commits - never across extension hooks or LLM awaits (an extension calling ctx.navigateTree() from a session_before_compact hook must not deadlock; regression-tested).
  • Kept, with the race each protects now named: pump epoch (stale preparation after branch pause), pump-requested flag (overlapping wakeups), pump suspension (abort/restart), queued-work pauses (overlapping branch-mutation leases), checkpoint waiters (lifecycle notifications), arrival epoch (stale-continuation invalidation).
  • Deleted dead legacy code: DaemonClient.requestLegacy, requestLegacyData, the protocol-3 heartbeat branch, the unused "handoff" busy-check variant.
  • Final rename: reportExecutionError -> queueVisible (the field's actual meaning).
  • New test/suite/agent-session-action-races.test.ts: deterministic pause/clear/restart/dispose injection at commit-fence boundaries for turns and session commands; asserts every ticket settles exactly once and every action is restored xor delivered.
  • Review-driven fixes included: suspended-queue admission preserved for steer/followUp/agent-message queueing after abort (cron and a2a paths); no deferral-observer leak on a2a direct delivery; a2a acceptance still awaits actual delivery.

LOC: +390/-399 production (net -9), +765/-165 tests (includes review-fix commits: fence revalidation and rescheduling, dispose linkage, settlement/ordering/idle guards, injected-admission serialization; and the compensating-state deletion commit).

Stack result (vs main)

Feature code +3058/-2659 (net +399). Tests +2633/-1030 (net +1603). One typed owner for every turn-producing input; exactly-once delivery via two-edge records; queue display, /compact successor detection, and headless completion correct by construction.

Note

Harden session action scheduling with commit-fence serialization to fix race conditions

  • Replaces the previous turn-admission FIFO and waiter set with a new FIFO commit-fence mechanism (_acquireSessionActionCommitFence, _acquireDirectTurnAdmissionFence) that serializes session action commits using AsyncLocalStorage scoping and a disposal abort controller.
  • Adds hasPendingSessionWork getter to AgentSession and field to HeartbeatCronSessionActivity to track non-durable committing turns; updates heartbeat deferral logic in shouldDeferHeartbeatCronJob so steer heartbeats proceed during streaming while follow-up heartbeats still defer.
  • Moves durable message append and delivery settlement for session commands into _executeSelectedSessionCommand under the commit fence, so commands that lose a handoff race are rolled back rather than executed.
  • Fixes waitForSessionInputCheckpoint and waitForIdle to drain the agent event queue before reporting idle, reducing post-idle races.
  • Removes shouldYieldLowerRun, mandatoryCheckpointsComplete, and requestLegacy as part of the cleanup; manageHeartbeat now unconditionally requires the heartbeat_management server capability.

Macroscope summarized 07c9f4f.


Note

High Risk
Core session scheduling, prompt admission, compaction continuation, and heartbeat timing changed; incorrect fence or pending-work semantics could cause duplicate delivery, early headless exit, or stuck queues.

Overview
Session input scheduling is consolidated on the action store lifecycle: the broad turn-admission lease (_acquireTurnAdmission, pause waiters, shouldYieldLowerRun, mandatoryCheckpointsComplete) is removed in favor of a FIFO commit fence (_sessionActionCommitFence) held only across dispatch commits and session-command transcript writes—not across extension hooks or LLM work.

The input pump no longer wraps preparation in admission; turns batch all delivery records (prefix + primary + next-turn) at commit; session commands record the slash message before running /compact, /refine, etc.; checkpoints and waitForIdle wait on the commit fence and agent event queue; goal context always queues through the store instead of bypassing during pump/streaming.

hasPendingSessionWork distinguishes queued/preparing/committing work from in-flight agent turns, driving heartbeat deferral (shouldDeferHeartbeatCronJob), headless completion, and post-compaction continue logic.

Daemon clients drop requestLegacy and protocol-3 heartbeat fallbacks; heartbeat management requires server capabilities.

Tests add agent-session-action-races.test.ts and expand queue/compaction/heartbeat coverage for commit-fence pause, clear, restart, dispose, navigation reentrancy, and ordering.

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

Comment thread packages/coding-agent/src/core/agent-session.ts
Comment thread packages/coding-agent/src/core/agent-session.ts
Comment thread packages/coding-agent/src/core/agent-session.ts Outdated
Comment thread packages/coding-agent/src/core/agent-session.ts
Comment thread packages/coding-agent/src/core/agent-session.ts Outdated
@snimu
snimu force-pushed the refactor/session-action-cleanup branch from 527c908 to 8c60421 Compare August 1, 2026 20:11
Comment thread packages/coding-agent/src/core/agent-session.ts Outdated
Comment thread packages/coding-agent/src/core/agent-session.ts
@snimu
snimu force-pushed the refactor/session-action-cleanup branch from 8c60421 to 8b3b797 Compare August 1, 2026 20:25
Comment thread packages/coding-agent/src/core/agent-session.ts Outdated
Comment thread packages/coding-agent/src/core/agent-session.ts Outdated
@snimu
snimu force-pushed the refactor/session-action-cleanup branch from 8b3b797 to e8e8a16 Compare August 1, 2026 21:06
@snimu
snimu force-pushed the refactor/session-action-cleanup branch from e8e8a16 to c8d51af Compare August 1, 2026 21:20
Comment thread packages/coding-agent/src/core/agent-session.ts
@snimu
snimu force-pushed the refactor/session-action-cleanup branch 2 times, most recently from 1a6a069 to 04347f3 Compare August 1, 2026 22:13
Comment thread packages/coding-agent/src/core/agent-session.ts Outdated
snimu added a commit that referenced this pull request Aug 1, 2026
…tion pending checks

The underlying bugs originate in PR #573, but this fix lands at the stack head in PR #576 to avoid rebasing three dependent PRs immediately before release.
Comment thread packages/coding-agent/src/core/agent-session.ts Outdated
Comment thread packages/coding-agent/src/core/agent-session.ts Outdated
Comment thread packages/coding-agent/src/core/agent-session.ts
snimu added a commit that referenced this pull request Aug 2, 2026
…tion pending checks

The underlying bugs originate in PR #573, but this fix lands at the stack head in PR #576 to avoid rebasing three dependent PRs immediately before release.
@snimu
snimu force-pushed the refactor/session-action-cleanup branch from 4f37155 to b5e7643 Compare August 2, 2026 10:14
Comment thread packages/coding-agent/src/core/agent-session.ts
Comment thread packages/coding-agent/src/core/agent-session.ts
Comment thread packages/coding-agent/src/core/agent-session.ts
Comment thread packages/coding-agent/src/core/agent-session.ts Outdated
Comment thread packages/coding-agent/src/core/agent-session.ts
Comment thread packages/coding-agent/src/core/agent-session.ts Outdated
alexzhang13 pushed a commit that referenced this pull request Aug 3, 2026
…tion pending checks

The underlying bugs originate in PR #573, but this fix lands at the stack head in PR #576 to avoid rebasing three dependent PRs immediately before release.
@alexzhang13
alexzhang13 force-pushed the refactor/session-action-cleanup branch from 580dc68 to 84bb107 Compare August 3, 2026 04:03

@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 84bb107. Configure here.

Comment thread packages/coding-agent/src/core/agent-session.ts
snimu added 13 commits August 3, 2026 00:29
…tion pending checks

The underlying bugs originate in PR #573, but this fix lands at the stack head in PR #576 to avoid rebasing three dependent PRs immediately before release.
The fake-timer event-await combination never completes under CI timing.
The production change it covered (pending-successor counting after
threshold compaction, 697fcf4) remains covered by the passing
'resumes after threshold compaction when only agent-level queued
messages exist' test exercising the same projection.
Several fixes originate in #574/#575 but land at the stack head to avoid rebasing the whole chain.
@alexzhang13
alexzhang13 force-pushed the refactor/session-action-cleanup branch from 84bb107 to 58013f6 Compare August 3, 2026 04:30
@snimu
snimu merged commit 3b2d1f2 into main Aug 3, 2026
11 checks passed
@snimu snimu mentioned this pull request Aug 3, 2026
12 tasks
@kevinjosethomas
kevinjosethomas deleted the refactor/session-action-cleanup branch August 5, 2026 18:54
zhengr pushed a commit to zhengr/prime-agent that referenced this pull request Aug 8, 2026
…i#576)

* refactor(coding-agent): harden session action races

* fix(coding-agent): revalidate turn batches after commit fence acquisition

* fix(coding-agent): reschedule pump after batch revalidation deferral

* fix(coding-agent): restore cross-lane queue-key coalescing and compaction pending checks

The underlying bugs originate in PR PrimeIntellect-ai#573, but this fix lands at the stack head in PR PrimeIntellect-ai#576 to avoid rebasing three dependent PRs immediately before release.

* refactor(coding-agent): delete compensating scheduler state

* fix(coding-agent): count only pending successors after compaction

* fix(coding-agent): honor prompt abort during fence wait and fix compaction test await

* test(coding-agent): remove flaky post-compaction continue regression

The fake-timer event-await combination never completes under CI timing.
The production change it covered (pending-successor counting after
threshold compaction, 697fcf4) remains covered by the passing
'resumes after threshold compaction when only agent-level queued
messages exist' test exercising the same projection.

* fix(coding-agent): reject fence waiters on session disposal

* fix(coding-agent): restore settlement, ordering, and idle guards

Several fixes originate in PrimeIntellect-ai#574/PrimeIntellect-ai#575 but land at the stack head to avoid rebasing the whole chain.

* fix(coding-agent): serialize injected admission with the commit fence

* fix(coding-agent): release fence on admission failure and unify pause-aware admission

* fix(coding-agent): stabilize waitForIdle event-queue wait and drop dead queue-key probe

* fix(coding-agent): preserve batched action message order (fixes PrimeIntellect-ai#576)

* fix(coding-agent): revalidate commands after commit fence (fixes PrimeIntellect-ai#576)

---------

Co-authored-by: Alex Zhang <alex.lx.zhang@gmail.com>
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