diff --git a/codev-skeleton/protocols/air/protocol.json b/codev-skeleton/protocols/air/protocol.json index 8d0321a90..b634eae26 100644 --- a/codev-skeleton/protocols/air/protocol.json +++ b/codev-skeleton/protocols/air/protocol.json @@ -65,7 +65,7 @@ }, "checks": { "pr_exists": { - "command": "gh pr list --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'", + "command": "gh pr list --state all --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'", "description": "PR must be created before signaling completion" }, "e2e_tests": { diff --git a/codev-skeleton/protocols/aspir/protocol.json b/codev-skeleton/protocols/aspir/protocol.json index 3c7dbc556..713fec3ec 100644 --- a/codev-skeleton/protocols/aspir/protocol.json +++ b/codev-skeleton/protocols/aspir/protocol.json @@ -114,7 +114,7 @@ }, "checks": { "pr_exists": { - "command": "gh pr list --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'", + "command": "gh pr list --state all --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'", "description": "PR must be created before signaling completion" }, "review_has_arch_updates": { diff --git a/codev-skeleton/protocols/spir/protocol.json b/codev-skeleton/protocols/spir/protocol.json index b046252bb..ca5820fba 100644 --- a/codev-skeleton/protocols/spir/protocol.json +++ b/codev-skeleton/protocols/spir/protocol.json @@ -117,7 +117,7 @@ }, "checks": { "pr_exists": { - "command": "gh pr list --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'", + "command": "gh pr list --state all --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'", "description": "PR must be created before signaling completion" }, "review_has_arch_updates": { diff --git a/codev/protocols/air/protocol.json b/codev/protocols/air/protocol.json index ba9d62877..7fea5bec9 100644 --- a/codev/protocols/air/protocol.json +++ b/codev/protocols/air/protocol.json @@ -67,7 +67,7 @@ }, "checks": { "pr_exists": { - "command": "gh pr list --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'", + "command": "gh pr list --state all --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'", "description": "PR must be created before signaling completion" }, "e2e_tests": { diff --git a/codev/protocols/aspir/protocol.json b/codev/protocols/aspir/protocol.json index 3c7dbc556..713fec3ec 100644 --- a/codev/protocols/aspir/protocol.json +++ b/codev/protocols/aspir/protocol.json @@ -114,7 +114,7 @@ }, "checks": { "pr_exists": { - "command": "gh pr list --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'", + "command": "gh pr list --state all --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'", "description": "PR must be created before signaling completion" }, "review_has_arch_updates": { diff --git a/codev/protocols/spir/protocol.json b/codev/protocols/spir/protocol.json index b046252bb..ca5820fba 100644 --- a/codev/protocols/spir/protocol.json +++ b/codev/protocols/spir/protocol.json @@ -117,7 +117,7 @@ }, "checks": { "pr_exists": { - "command": "gh pr list --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'", + "command": "gh pr list --state all --head \"$(git branch --show-current)\" --json number --jq 'length' | grep -q '^[1-9]'", "description": "PR must be created before signaling completion" }, "review_has_arch_updates": { diff --git a/packages/codev/src/commands/porch/__tests__/bugfix-568-pr-exists-state-all.test.ts b/packages/codev/src/commands/porch/__tests__/bugfix-568-pr-exists-state-all.test.ts new file mode 100644 index 000000000..37c787824 --- /dev/null +++ b/packages/codev/src/commands/porch/__tests__/bugfix-568-pr-exists-state-all.test.ts @@ -0,0 +1,49 @@ +/** + * Regression test for bugfix #568: pr_exists check must use --state all + * + * Without --state all, gh pr list defaults to --state open, which causes + * the pr_exists check to fail when a PR has already been merged before + * the porch gate is approved. + */ + +import { describe, it, expect } from 'vitest'; +import * as fs from 'node:fs'; +import * as path from 'node:path'; + +const ROOT = path.resolve(__dirname, '../../../../../..'); + +describe('bugfix #568: pr_exists check uses --state all', () => { + const protocolDirs = ['codev-skeleton/protocols', 'codev/protocols']; + + for (const protocolDir of protocolDirs) { + const fullDir = path.join(ROOT, protocolDir); + if (!fs.existsSync(fullDir)) continue; + + const protocols = fs.readdirSync(fullDir).filter((name) => { + const jsonPath = path.join(fullDir, name, 'protocol.json'); + return fs.existsSync(jsonPath); + }); + + for (const proto of protocols) { + const jsonPath = path.join(fullDir, proto, 'protocol.json'); + const raw = fs.readFileSync(jsonPath, 'utf-8'); + const parsed = JSON.parse(raw); + + // Find all pr_exists checks across phases + const phases: Array<{ id: string; checks?: Record }> = + parsed.phases ?? []; + + for (const phase of phases) { + if (!phase.checks) continue; + const prCheck = phase.checks['pr_exists'] as + | { command?: string } + | undefined; + if (!prCheck?.command) continue; + + it(`${protocolDir}/${proto} phase "${phase.id}" pr_exists includes --state all`, () => { + expect(prCheck.command).toContain('--state all'); + }); + } + } + } +});