Skip to content

Stop resuming implementers after PR completion#328

Merged
khaliqgant merged 2 commits into
mainfrom
ar-254-pr-exit-terminal-fix
Jun 14, 2026
Merged

Stop resuming implementers after PR completion#328
khaliqgant merged 2 commits into
mainfrom
ar-254-pr-exit-terminal-fix

Conversation

@khaliqgant

@khaliqgant khaliqgant commented Jun 14, 2026

Copy link
Copy Markdown
Member

Summary

  • probe for an existing completion PR when an implementer exits with a non-completion reason
  • treat PR-present implementer exits as terminal by handing off to the existing completion/merge-gate path
  • preserve crash resume behavior when no PR exists and keep completion reasons unchanged

Tests

  • npx vitest run packages/factory-sdk/src/orchestrator/factory.test.ts
  • npm run typecheck:node

Review in cubic

@coderabbitai

coderabbitai Bot commented Jun 14, 2026

Copy link
Copy Markdown

Review Change Stack

Caution

Review failed

Pull request was closed or merged during review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: df22f11d-6416-425a-8374-c0d169469cce

📥 Commits

Reviewing files that changed from the base of the PR and between f6b26ff and fcdc86f.

📒 Files selected for processing (2)
  • packages/factory-sdk/src/orchestrator/factory.test.ts
  • packages/factory-sdk/src/orchestrator/factory.ts

📝 Walkthrough

Walkthrough

FactoryLoop.#handleAgentExit gains an early-exit branch for implementer-role exits: it calls a new private #issueHasCompletionPr helper that probes for a non-draft completion PR and, when one is found, calls #completeIssue and returns immediately. On probe failure the helper increments exitPrProbeFailures and returns false. Three new tests cover non-draft, draft, and no-PR exit scenarios; the existing PR-state sweep test is adjusted to trigger completion via review-agent exits only.

Changes

Implementer exit PR-gated completion

Layer / File(s) Summary
Exit handler early path and completion PR helper
packages/factory-sdk/src/orchestrator/factory.ts
Inserts an implementer-role branch in #handleAgentExit that invokes a new #issueHasCompletionPr helper; the helper reads the issue, calls #completionPrForIssue, returns true only for non-draft PRs, and on any probe error increments exitPrProbeFailures and returns false.
New test cases and sweep test adjustment
packages/factory-sdk/src/orchestrator/factory.test.ts
Adds three it(...) blocks for implementer exit with a non-draft PR (completes, releases both agents, clears in-flight), with a draft PR (no completion, resumes implementer), and with no PR (normal resume). Adjusts the PR-state completion sweep to emit worker_exited from the review agent only.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • AgentWorkforce/pear#287: Modifies the same completion-resolution logic in factory.ts, adding a PR-state completion sweep that overlaps with the implementer-exit-triggered immediate completion introduced here.

Suggested labels

no-agent-relay-review

🐇 Hop hop, the implementer ran away,
But left a PR — not a draft — hooray!
No need to resume, no need to retry,
#completeIssue is called on the fly.
The sweep now listens to review alone,
And every test proves the logic is honed! 🌸

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and clearly summarizes the main change: preventing implementers from resuming after PR completion.
Description check ✅ Passed The description is well-related to the changeset, explaining the probe mechanism, terminal exit handling, and preservation of existing behavior.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ar-254-pr-exit-terminal-fix

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed due to a network error.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request updates the orchestrator factory to complete an issue immediately upon an implementer agent's exit if a completion PR already exists, rather than resuming the agent. It adds the #issueHasCompletionPr helper method and corresponding unit tests. The reviewer pointed out a critical issue where draft PRs could trigger premature completion and block the exit handler for up to 120 seconds, and suggested ignoring draft PRs in the check.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

if (!issue) {
return false
}
return Boolean(await this.#completionPrForIssue(issue))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

high

Issue: Draft PRs trigger premature completion and block the exit handler

In sweepPrStateCompletions, draft PRs are explicitly ignored because they are not yet ready for review or merging. However, in #issueHasCompletionPr, any resolved PR (including draft PRs) is treated as a valid completion signal.

This leads to two major issues:

  1. Premature Completion: The issue will be marked as done in Linear and Slack even though the PR is still a draft.
  2. Blocking the Exit Handler: Since a draft PR is not merge-ready, this.#completeIssue will trigger this.#runCompletionMergeGate, which calls this.#waitForMergeReady. This will block/sleep for up to 120 seconds (12 attempts × 10 seconds) inside the agent exit handler, severely impacting the orchestrator's responsiveness.

Recommendation

Update #issueHasCompletionPr to ensure that draft PRs are ignored, matching the logic in sweepPrStateCompletions.

      const pr = await this.#completionPrForIssue(issue)
      return Boolean(pr && !pr.draft)

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #328 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@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: 6c466f2a4c

ℹ️ 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".

if (!issue) {
return false
}
return Boolean(await this.#completionPrForIssue(issue))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1 Badge Do not complete issues for draft PRs

When an implementer exits and the matching PR is still a draft, this new check treats any resolved PR as completion and calls #completeIssue, which marks the Linear issue done and releases both agents. The existing PR sweep explicitly keeps draft PRs in flight (pr.draft increments completionSweepDraftPr and returns), so this exit path bypasses that guard for the same resolver output. Please inspect the resolved PR and return false for drafts before completing.

Useful? React with 👍 / 👎.

@devin-ai-integration devin-ai-integration 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.

Devin Review found 1 potential issue.

Open in Devin Review

if (!issue) {
return false
}
return Boolean(await this.#completionPrForIssue(issue))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔴 Draft PRs incorrectly trigger issue completion on implementer exit

The new #issueHasCompletionPr method at line 1636 uses Boolean(await this.#completionPrForIssue(issue)) to determine if the issue should be completed. However, #completionPrForIssue can return a PR object with draft: true — both resolveIssuePrFromMount (factory.ts:2525) and resolveIssuePrFromGh (factory.ts:2576) include draft PRs in their results. The existing completion sweep at lines 696-699 explicitly checks if (pr.draft) and skips such PRs, but the new exit handler path does not. This means when an implementer exits (e.g., with worker_exited) after opening a draft PR, the issue will be incorrectly completed instead of allowing the agent to resume and finish work.

Suggested change
return Boolean(await this.#completionPrForIssue(issue))
const pr = await this.#completionPrForIssue(issue)
return Boolean(pr && !pr.draft)
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #328 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@khaliqgant

Copy link
Copy Markdown
Member Author

✅ APPROVE (reviewer: ar-254-review) — AR-254, PR #328 @ 6c466f2
(posted as a comment; gh blocks self-approval on a same-user PR)

Verified independently (checked out the branch, ran it myself):

  • npx vitest run packages/factory-sdk/src/orchestrator/factory.test.ts → 134 passed.
  • npm run typecheck:node → clean.
  • Mutation check: neutralized the new gate in #handleAgentExit → the "completes an implementer exit without resuming when a PR already exists" test FAILS (probe never called, done !== 1). The test genuinely guards the fix; not vacuous.

All 3 acceptance criteria met:

  1. Non-completion exit + PR exists → no resume. #handleAgentExit gates on tracked.spec.role === 'implementer' && await this.#issueHasCompletionPr(record) before the resume/respawn block and routes to #completeIssue. Test asserts fleet.resumes === [], done === 1, agents released issue-done. ✔
  2. Abnormal exit, no PR yet → still resumes. Second test (probe → undefined) asserts the impl resume fires and done stays undefined. Probe IS called (asserted via probedIssues) then falls through. ✔
  3. issue-done/done/completed unchanged — isCompletionReason early-return above the gate is untouched. ✔

Design is right:

  • Reuses existing #completionPrForIssue / #probePrResolver (same signal the completion sweep uses for this relay#1116 case) — no ad-hoc gh call.
  • Fail-safe: #issueHasCompletionPr try/catch → on throw it warns, bumps exitPrProbeFailures, returns false → preserves restart for genuine crashes. A probe outage can't strand a crashed implementer.
  • Gate is below the !tracked || record.dryRun guard → dryRun never completes.
  • No double-complete race: #completeIssue is guarded by #completionInFlight, so exit-path and sweep can't both finalize.
  • role === 'implementer' matches defaultRestartPolicy's role check — reviewers unaffected.
  • The one unrelated test edit (eviction/sweep test now exits only the review agents) is correct, not masking: that test asserts completionSweepCompleted === 2; exiting an impl would now complete via the new exit path and zero that counter. The new exit-path behavior is covered by the two added tests.

Non-blocking note (fast-follow, do NOT hold merge):

  • Draft PRs: default #resolveIssuePr returns draft PRs (only caching is skipped for drafts), so #issueHasCompletionPr is true for a draft. An implementer that exits right after opening a draft PR gets completed (Linear→done + merge gate + Slack) via this path, whereas the completion sweep deliberately backs off on drafts (factory.ts:695-699). Not-resuming is correct (the implementer already exited); the only divergence is completing-while-draft eagerly. Consider reusing the sweep's pr.draft check (or a clarifying comment) so the two paths agree.

Out of scope (correctly): the relay#1116 broker name-release bug itself.

Cleared to merge at the maintainer's discretion (per repo policy I'm not merging). Nice work @ar-254-impl-main @ar-254-impl-linear.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #328 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

3 similar comments
@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #328 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #328 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #328 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

#issueHasCompletionPr treated any resolved PR — including drafts — as a
completion signal, so an implementer exiting while its PR was still a draft
marked the issue done and released both agents prematurely, bypassing the
#sweepPrStateCompletions draft guard. Flagged by gemini/codex/devin at
factory.ts:1636.

Gate on !pr.draft so only a ready PR counts as completion; a draft-PR exit
falls through to the normal resume path. Adds a test for the draft case
(no done, no release, resumes). Full factory-sdk suite green; typecheck clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #328 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@khaliqgant khaliqgant merged commit 99b700d into main Jun 14, 2026
4 of 5 checks passed
@khaliqgant khaliqgant deleted the ar-254-pr-exit-terminal-fix branch June 14, 2026 11:10
@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #328 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

1 similar comment
@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #328 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

ℹ️ pr-reviewer: review only — no file changes were applied to the PR (nothing to commit after review). The notes below are advisory and were not pushed.

pr-reviewer could not complete review for #328 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

pr-reviewer could not complete review for #328 in AgentWorkforce/pear.
The review harness exited with code 1.
No review was posted; this needs operator attention.

@agent-relay-code

Copy link
Copy Markdown
Contributor

Findings

No blocking findings against the current checkout. I made no file edits.

Addressed comments

  • gemini-code-assist[bot]: draft PRs could complete issues prematurely. Stale, already fixed in factory.ts with Boolean(pr && !pr.draft) and covered by factory.test.ts.
  • chatgpt-codex-connector[bot]: same draft-PR completion issue. Stale, same current fix at factory.ts.
  • devin-ai-integration[bot]: same draft-PR completion issue. Stale, same current fix at factory.ts.
  • coderabbitai[bot]: no actionable comments; noted ESLint install/network issue only. No code change needed.
  • devin-ai-integration[bot] review summary: pointed to 1 issue, same draft-PR thread above. Already handled.
  • khaliqgant: human approval plus non-blocking draft-PR note. Already handled in current checkout at factory.ts.
  • agent-relay-code[bot]: repeated harness exit-code-1 comments. No code finding to validate; this run completed review accounting here.

Validation

  • npm ci completed.
  • npm run verify:mcp-resources-drift passed.
  • npm run lint passed with existing warnings only.
  • npm run typecheck:web passed.
  • npm run typecheck:node passed.
  • npm test passed.
  • npx vitest run packages/factory-sdk/src/orchestrator/factory.test.ts -t "implementer exit" passed.
  • npm run build passed.
  • Full npx vitest run failed on an existing timing-sensitive test outside this PR hunk: keeps the live heartbeat fresh while draining a blocking live event burst; it also failed in isolation. I did not change it because that is lifecycle/heartbeat behavior outside this PR’s purpose.
  • GitHub API shows PR Stop resuming implementers after PR completion #328 is already merged, and head SHA check runs checks, playwright, and packaged-mcp-smoke completed successfully.

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