fix(coding-agent): pause a stalled goal instead of looping continuations - #1113
Closed
romankhadka wants to merge 3 commits into
Closed
fix(coding-agent): pause a stalled goal instead of looping continuations#1113romankhadka wants to merge 3 commits into
romankhadka wants to merge 3 commits into
Conversation
A goal whose continuations repeatedly end without a tool call or new user message cannot progress by re-presenting the same context. After three consecutive stalled continuation windows the goal now pauses as waiting for user input, and it resumes automatically on the next user prompt. An explicit /goal pause still requires /goal resume. fixes PrimeIntellect-ai#986
…/follow-up resume gap - Replace the waitingForUser flag with pausedBy: "user" | "host" so the pause cause is a single field and normalizeGoalState no longer repairs a cross-field invariant. - Collapse the stall detector's accumulator into direct early returns and absorb the single-use progress helper. - Resume a host-paused goal for user input delivered via steer() and followUp(), which bypass prompt(); previously only prompt() resumed it. - Derive regression-test fixtures from MAX_STALLED_GOAL_CONTINUATIONS and cover the followUp resume path.
Contributor
|
Thank you for the report and proposed work. This root cause is now covered by maintainer-owned stacked PR #1165, authored independently from We did not inspect or reuse this PR's diff, branch, commits, implementation code, or tests; its public description/comments were used only as a bug report. To keep one review surface, this PR is superseded by #1165 and is being closed. The complete review stack is #1158–#1165. It is being left unmerged for human review after CI and review-bot findings are cleared. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
goal_contextcontinuations forever when the model was blocked on user input (a required approval, credential, or unanswered question)._getGoalContinuationMessagesnow checks the run for stalled continuation windows before re-arming. When the trailing three goal-context windows all ended without a tool call or a user message, the goal pauses (status: "paused"with a new optionalpausedBy: "user" | "host"field and an explanatorylastReason) instead of injecting another identical context.pausedBy: "host") resumes automatically on the next genuine user message, whether it arrives viaprompt(),steer(), orfollowUp(). Host-generated prompts and custom-message deliveries (heartbeats, agent messages) do not resume it. An explicit/goal pausesetspausedBy: "user"and still requires/goal resume.Design notes
goalContinuationIsStalledingoals.ts), so no extra mutable state is needed: any tool call, user message, or new run resets the window naturally.goal.get) on every continuation is not paused by this change. That variant does observable work each turn and is bounded by a token budget when one is set; the updated continuation prompt instructs blocked models to end the turn without tool calls, which makes sanctioned waiting detectable. Stream-level degenerate repetition is a separate concern (No safeguard against degenerate model repetition: "The the the..." thinking stream until manual abort #1029).pausedByis optional and normalized to exist only whilestatusis"paused"; older builds reading a persisted goal state see an ordinary paused goal. A discriminator was chosen over a boolean so future pause causes extend the same field.Validation
cd packages/coding-agent && npx tsx ../../node_modules/vitest/dist/cli.js --run test/suite/regressions/986-goal-continuation-loop.test.ts test/suite/agent-session-goal.test.ts test/suite/agent-session-queue.test.ts: 147 passednpx tsx ../../node_modules/vitest/dist/cli.js --run test/suite/agent-session-autonomous.test.ts test/kernel-goal-skill.test.ts test/suite/regressions/4482-heartbeat-injected-prompt.test.ts: 38 passed, 3 skipped (kernel skill tests skip without the Python runtime)main(verified by reverting the fix); the explicit-pause test guards existing behavior.MAX_STALLED_GOAL_CONTINUATIONS, and thefollowUp()resume path has its own test.npm run check: passedNote
Pause stalled Goal Mode instead of injecting continuations indefinitely
getContinuationMessagesinagent-session.tsnow pauses the goal (taggedpausedBy: 'host') instead of looping.goals.tsviagoalContinuationIsStalled, which checks the lastMAX_STALLED_GOAL_CONTINUATIONS(3) continuation windows for tool calls or user messages.Macroscope summarized 513f66a.