Fix #1637: spawn open-PR collision guard counts merged PRs - #1673
Merged
Conversation
pr-search runs --state all (#759/#1619) so consult can find merged PRs, but the spawn collision guard counted every result as an open PR — refusing afx spawn when the referenced PRs were already merged. - github/gitlab pr-search.sh now emit a normalized `state` field (OPEN/MERGED/CLOSED); gitlab maps glab's lowercase `opened` to OPEN. - PrSearchItem gains optional `state`. - The guard filters to state === 'OPEN' before counting; a missing state (stale pr-search.sh override) is treated as open, preserving pre-fix behavior. --state all stays in the scripts; consult is unaffected. - Regression tests pair both consumers: guard ignores merged/closed, scripts keep merged MRs/PRs visible for consult.
Addresses non-blocking CMAP (claude) nits: - gitlab/pr-search.sh captures glab output before piping to jq, so a failed glab surfaces instead of masquerading as an empty list (POSIX sh has no pipefail) — matching the #1645 convention in pr-list.sh. - Guard predicate broadened from `state === undefined` to `!pr.state` so the gitlab jq's empty-string fallback is also treated as open (conservative), matching the documented intent. Adds a blank-state regression test.
…1645) The capture-then-pipe shape from the previous commit hid `glab` from extractExecutable's first-line heuristic (it skips the `out=` assignment and lands on the `printf` builtin), so forge.test.ts's #1645 check resolved the concept to a builtin. Add an explicit `# forge-executable: glab` declaration, matching github/pr-list.sh's convention.
GitLab's MR state enum is opened/closed/merged/locked. `locked` is a transient merging state that is still effectively open, so normalize it to OPEN alongside `opened`. The spawn guard then counts a locked MR as a collision (recoverable via --force) rather than silently skipping a live one. Pins the mapping in the gitlab pr-search contract test.
…hItem glab's `mr list --output json` emits GitLab-shaped fields (iid, source_branch, target_branch), not the contract's number/headRefName/baseRefName, so the spawn guard printed `PR #undefined` and consult's findPRForIssue couldn't resolve the MR base branch on GitLab. Map them in the jq pass, matching the normalization pattern already in gitlab/pr-list.sh and pr-view.sh. Marked UNVERIFIED per the #920 convention (no live glab in the authoring/CI environment).
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
afx spawnrefused to spawn for an issue with "Found N open PR(s) referencing issue #X" when the referenced PRs were actually merged, forcing--forceafter manual verification. This filters the spawn collision guard to only count genuinely open PRs.Fixes #1637
Root Cause
The spawn collision guard in
checkBugfixCollisions(spawn-worktree.ts) calls thepr-searchforge concept and treated every result as an open PR. PR #1619 (shipped in 3.3.3) deliberately changedpr-searchto--state allsoconsult --type prcould find merged PRs (#759) — correct for consult, but the guard consumed the same concept and inherited merged/closed PRs into its "open" count. Compounding this, the githubpr-search.shemitted onlynumber,headRefName,baseRefNamewith nostatefield, so the guard could not filter client-side.Fix
github/pr-search.sh: addstateto the--jsonfields (gh returnsOPEN/MERGED/CLOSED).gitlab/pr-search.sh: emit a normalizedstate, mapping glab's lowercaseopened→OPENso the contract matches github's convention.PrSearchItemcontract: add optionalstate?: string, documented as normalized.state === 'OPEN'before counting. A missingstate(a stale project-localpr-search.shoverride predating the field) is treated as open, preserving the conservative pre-fix behavior.--state allstays in the scripts — consult still needs merged PRs visible; the guard filters.Test Plan