Repository navigation
Description
Found in the T3 Orchestrator V2 deep dive (report: reports/T3 Code orchestrator deep dive.md on branch coder/i-want-you-to-research-t3-codes-orchestr-fae77a). T3 V2 now polls watched PRs on the server and wakes the agent on failed checks, review comments and conflicts (t3code #15057). Solenta already has most of this. The gap is that its poller never looks at the threads that matter most.
Bugs
- P1: archived threads are skipped (verified).
isPrRefreshCandidatestarts withif (t.archived) return false;(electron/worktrees.js:4319), and a test pins it (electron/test/pr-refresh.test.js:384).sweepCrewarchives finished workers (runner.js:1784-1820). So of the 35 worker PRs in the live store, 34 are archived and stillOPEN, one is archived and merged, and three still hold a worktree. Not checked against GitHub: they may really be merged. - P2: cleanup can delete a running worker's checkout.
maybeCleanupMergedWorktree(worktrees.js:5539-5595) checks for a dirty tree but never checks whether the thread is running. A worker fixing review comments with a clean tree when its PR merges loses its working directory mid-run.
What already exists
refreshPrStates/createPrStateRefresher: a serialized 5-minute pass (worktrees.js:4350-4547, wired inmain.js:779-790).- Host-side
ghrunning under the user's own auth. - Check bucketing, worktree reclaim on merge, and a post-merge re-verify hook.
- Settle-on-merge, computed in the renderer (
src/threadSettle.ts:33-39).
Design (~150–220 lines + ~150 test lines)
- Arm the watch. After
createPrresolves inthread_pr(orchServer.js:678-686), write a main-process-only field on the worker:prWatch: {armedAt, notify: <lead id>, last: {state, mergeable, review, failing[]} | null}. - Poll armed threads even when archived. Change the candidate check to
if (t.archived && !t.prWatch) return false;. Give the existing archived/OPEN rows one state refresh with no notices, so they reach a terminal state and drop out. - Fetch. For armed threads only, one
gh pr view --json number,url,state,mergeable,reviewDecision,statusCheckRollup. Fall back through the existingisUnknownJsonField. - Notify on entering a bad or final state. Compare against
prWatch.last, which is what the lead was last told. Send at most one line per thread per pass, only when entering merged / closed /CONFLICTING/CHANGES_REQUESTED, or when the failing-check set changes. The first observation is silent unless it's already bad. - Deliver through the runner. Add an injected
opts.notifythatmain.jswires torunner.deliverNotice(runner.js:1282-1294). It skips when the lead is missing, trashed or archived. Line:[pr] Worker <id> ("title") PR #N <signal>. <url>. Send the worker the fix with thread_send; merging stays with the user.Persistlastin the same save, so a crash can miss a wake but never duplicate one. - Guard cleanup (P2). Inject
isRunning(threadId)and skip cleanup while the thread is running.
Deliberately left out: reading comments, a 1-minute cadence, agent-performed merges, and watching plain UI PRs (add a per-thread toggle if someone wants that).
Check before shipping: T3 #15388 had wake turns keeping merged threads from settling. Confirm which message timestamp effectiveSettled measures from, so [pr] notice turns can't block settling.
Tests (extend pr-refresh.test.js, which already injects ghTryAsyncFn)
- An armed archived worker is polled with the rich fields.
- A pass-to-fail transition notifies once, then stays quiet.
CHANGES_REQUESTEDandCONFLICTINGnotify.- A merge notifies and cleans up, but not while the thread is running.
- Unarmed threads, and threads whose lead is archived, never notify.
- The unknown-field fallback still works.
There's a soft dependency on #1426: until notices are durable, a crash can lose a PR wake. The next pass after boot detects the transition again.
Activity
currentbits commentedon Oct 4, 2026
GitHub reality check and repros at 615b38a0. Repro tests:
research_notes/T3 orchestrator ACP UX and repros/repros/on branchcoder/i-want-you-to-research-t3-codes-orchestr-fae77a.gh pr viewon the 34 archived worker PRs the store calls OPEN: 29 merged, 3 closed, 2 actually open (appfeedback Click an image in a thread to view it full-size #78, cometx Failed thread load dead-ends on 'Select a thread' with no error or retry #82). They span 5 repos, not only solenta. The one archived plain thread marked OPEN is also merged.effectiveSettled(src/threadSettle.ts) reads no message timestamp. A merged thread settles regardless of time, and stays open only whileworkingorquota-wait. So[pr]wake turns can't keep a merged thread unsettled. Inactivity for threads without a PR is measured fromthread.updatedAt, which notice turns bump, so machine turns restart the 3-day clock there. Consider measuring from the last human message.Suggested split. Ship the P2 running-guard plus a one-time catch-up refresh of archived PR rows now; it's small and fixes 32 stale rows. The rows that are closed but not merged need a closed-PR rule for worktree reclaim. The armed PR watch with lead notifications follows later, after #1426 makes notices durable.
The two PRs that are really open (appfeedback #78, cometx #82) may need the user's attention.
currentbits commentedon Oct 12, 2026
PR #1607 is open for review.
Most of the design here had already shipped as
electron/prWatch.js(#1493 D). This PR adds what was still missing:maybeCleanupMergedWorktreewon't delete a worktree while its thread is running, and the next refresh pass retries the cleanup.Deliberately not included: alerting the lead when a PR merges or closes.
Poll archived worker PRs and wake their lead; never reclaim a running…
Poll archived worker PRs and wake their lead; never reclaim a running…