Symptom
After a PR is merged, the corresponding builder still appears in the Needs Attention list on the dashboard with a "PR review" badge — even though there is nothing left for the human to do. Observed on shannon today: #1842 port-shannon-landing-page-next (PR #1864 merged 18:35 UTC) was still surfacing under Needs Attention with a 1-day elapsed counter.
Repro: merge a SPIR/AIR/PIR builder's PR via gh pr merge --merge --admin. Builder advances to phase: verified. Refresh the dashboard. Row persists.
Root cause
Two interacting problems that combine to produce the stale row:
1. Data hazard from the v3.1.4 → v3.1.5 transition (already-shipped state)
In-flight builders that crossed the v3.1.4 → v3.1.5 boundary have stale pr_ready_for_human: true in their status.yaml. The v3.1.4 index.ts:advanceProtocolPhase had a line-453 setter that re-set pr_ready_for_human = true on the post-merge porch done (the terminal pr → verified advance). Issue #887 / PR #888 removed that setter, but for builders that already wrote the state under v3.1.4, the stale true remains.
Concrete example: /Users/mwk/Development/cluesmith/shannon/.builders/spir-1842/codev/projects/1842-port-shannon-landing-page-next/status.yaml shows phase: verified, gates.pr.status: approved, pr_ready_for_human: true.
This issue is self-correcting for new builders going forward (#888's removal of line-453 stops the re-set). But the consumer-side filter still has bug #2 below, which we should fix regardless.
2. NeedsAttentionList builder-fallback loop has no merged-PR awareness
The iter-2 fallback in packages/dashboard/src/components/NeedsAttentionList.tsx:buildItems (added per Gemini's catch on PR #874) emits a "PR review" row for any builder with b.prReady === true whose PR didn't appear in the prs array. The intent was to defend against the case "PR missing from cache due to GitHub API pagination or transient failure." But the same code path fires when the PR has been merged — in which case the PR is correctly absent from prs (which lists only OPEN PRs), and surfacing the row is wrong.
The fallback doesn't distinguish "PR cache miss (defensive surface)" from "PR is merged and gone (do not surface)."
Fix
Cross-reference the builder against the workspace's recently-merged PR list (already available in the overview data) before emitting the defensive fallback row. The data we need is already plumbed through: overview.ts:fetchMergedPRsCached populates mergedPRs on the overview response (PROverview[] shape, includes linkedIssue).
Acceptance criteria
Out of scope
Files to touch
packages/dashboard/src/components/NeedsAttentionList.tsx — main change to buildItems signature and loop logic
packages/dashboard/__tests__/NeedsAttentionList.test.tsx — add regression test, update the defensive test
packages/codev/src/agent-farm/servers/overview.ts — confirm mergedPRs is exposed in the response (may already be — verify)
packages/types/src/api.ts — only if the merged-PR shape needs to be added to the overview type
References
Symptom
After a PR is merged, the corresponding builder still appears in the Needs Attention list on the dashboard with a "PR review" badge — even though there is nothing left for the human to do. Observed on shannon today:
#1842 port-shannon-landing-page-next(PR #1864 merged 18:35 UTC) was still surfacing under Needs Attention with a 1-day elapsed counter.Repro: merge a SPIR/AIR/PIR builder's PR via
gh pr merge --merge --admin. Builder advances tophase: verified. Refresh the dashboard. Row persists.Root cause
Two interacting problems that combine to produce the stale row:
1. Data hazard from the v3.1.4 → v3.1.5 transition (already-shipped state)
In-flight builders that crossed the v3.1.4 → v3.1.5 boundary have stale
pr_ready_for_human: truein theirstatus.yaml. The v3.1.4index.ts:advanceProtocolPhasehad a line-453 setter that re-setpr_ready_for_human = trueon the post-mergeporch done(the terminalpr→verifiedadvance). Issue #887 / PR #888 removed that setter, but for builders that already wrote the state under v3.1.4, the staletrueremains.Concrete example:
/Users/mwk/Development/cluesmith/shannon/.builders/spir-1842/codev/projects/1842-port-shannon-landing-page-next/status.yamlshowsphase: verified,gates.pr.status: approved,pr_ready_for_human: true.This issue is self-correcting for new builders going forward (#888's removal of line-453 stops the re-set). But the consumer-side filter still has bug #2 below, which we should fix regardless.
2.
NeedsAttentionListbuilder-fallback loop has no merged-PR awarenessThe iter-2 fallback in
packages/dashboard/src/components/NeedsAttentionList.tsx:buildItems(added per Gemini's catch on PR #874) emits a "PR review" row for any builder withb.prReady === truewhose PR didn't appear in theprsarray. The intent was to defend against the case "PR missing from cache due to GitHub API pagination or transient failure." But the same code path fires when the PR has been merged — in which case the PR is correctly absent fromprs(which lists only OPEN PRs), and surfacing the row is wrong.The fallback doesn't distinguish "PR cache miss (defensive surface)" from "PR is merged and gone (do not surface)."
Fix
Cross-reference the builder against the workspace's recently-merged PR list (already available in the overview data) before emitting the defensive fallback row. The data we need is already plumbed through:
overview.ts:fetchMergedPRsCachedpopulatesmergedPRson the overview response (PROverview[]shape, includeslinkedIssue).Acceptance criteria
OverviewDataexposesmergedPRs(orrecentlyClosed) on the type returned to the dashboard — verify the shape already does this; if not, plumb it throughpackages/types/src/api.ts.NeedsAttentionList'sbuildItemsaccepts the merged-PR list (or equivalent issue-ID set) as input.prReady-driven row, check ifb.issueIdmatches any merged PR'slinkedIssuein the recent window. If yes, skip — the builder is post-merge and the row is stale.prReady: true, builder'sissueIdmatches a merged-PRlinkedIssue→ row NOT emitted.still surfaces a prReady builder when its PR is missing from prs) updated to clarify the scenario: the missing PR must NOT be in the merged list (only "missing-due-to-cache" cases get the defensive emit).Out of scope
pr_ready_for_human: trueon already-verified status.yaml files. Self-corrects over time as new builders use Fix #887: BUGFIX add pr gate (close v3.1.4 pr_ready timing gap) #888's code path; and once this fix lands, those stale-state builders won't surface in Needs Attention anyway.Files to touch
packages/dashboard/src/components/NeedsAttentionList.tsx— main change tobuildItemssignature and loop logicpackages/dashboard/__tests__/NeedsAttentionList.test.tsx— add regression test, update the defensive testpackages/codev/src/agent-farm/servers/overview.ts— confirmmergedPRsis exposed in the response (may already be — verify)packages/types/src/api.ts— only if the merged-PR shape needs to be added to the overview typeReferences