Problem
The pr-search forge concept's output contract (PrSearchItem in packages/codev/src/lib/forge-contracts.ts:112) is {number, headRefName, baseRefName} — it carries no state field. Callers therefore cannot tell an open PR from a merged or closed one in the results, and their only defense is encoding state into the search query string itself.
This surfaced during the PR #1331 integration review (pr-search moving to --state all, fixing #759):
Proposal
Add state to PrSearchItem and populate it in each provider script:
- github:
gh pr list --json supports a state field directly.
- gitlab:
glab mr list --output json includes state.
- gitea: no pr-search script exists (concept disabled in the preset) — nothing to do.
Then let callers say what they mean: spawn-worktree filters state === 'OPEN' (belt-and-braces alongside its is:open query), and the consult helpers disambiguate instead of taking prs[0] blind.
Contract-shape note: PrSearchItem is a wire contract; the filtering/ranking policy belongs in the callers, not in the scripts.
References
Problem
The
pr-searchforge concept's output contract (PrSearchIteminpackages/codev/src/lib/forge-contracts.ts:112) is{number, headRefName, baseRefName}— it carries nostatefield. Callers therefore cannot tell an open PR from a merged or closed one in the results, and their only defense is encoding state into the search query string itself.This surfaced during the PR #1331 integration review (pr-search moving to
--state all, fixing #759):spawn-worktree.tsqueriedin:body #<issue>with no state qualifier and treated every hit as an open PR. That was only correct by accident of the old open-only default; under--state allit fatals on merged/closed PRs (reproduced live: issue Shellper reconnect error is swallowed: terminal becomes a silent zombie (no input/output, 'Message sent' logged for dropped frames) until next Tower restart #1198 returns four MERGED PRs that would misreport as "open"). The in-PR fix isis:openin the query — necessary, but it works around the contract gap rather than closing it.findPRForCurrentBranch/findPRForIssueinconsult/index.tstakeprs[0]from results that are relevance-ranked, not newest-first (verified:in:body #1280 --state allreturns 12 results led by [Spec 1280] Post-merge completion records: build-complete + thread FINAL + verify-approval #1409, including the unrelated [Spec 0108] Porch gate notifications via af send #272). With closed/merged PRs in the pool,consult --type prin architect mode can silently select a stale PR for a reused branch or a heavily referenced issue. With astatefield, these callers could filter or rank sensibly instead of trusting search order.Proposal
Add
statetoPrSearchItemand populate it in each provider script:gh pr list --jsonsupports astatefield directly.glab mr list --output jsonincludesstate.Then let callers say what they mean:
spawn-worktreefiltersstate === 'OPEN'(belt-and-braces alongside itsis:openquery), and the consult helpers disambiguate instead of takingprs[0]blind.Contract-shape note:
PrSearchItemis a wire contract; the filtering/ranking policy belongs in the callers, not in the scripts.References