From 760f48df9cba7a2a2f6b673094f380b9233be0dc Mon Sep 17 00:00:00 2001 From: Tapish Khandelwal Date: Mon, 24 Aug 2026 16:23:04 +0530 Subject: [PATCH 1/6] fix(review-gate): require default author in strict mode --- scripts/check-pr-review-gate.mjs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/scripts/check-pr-review-gate.mjs b/scripts/check-pr-review-gate.mjs index d60c9ed9..f7f32d47 100644 --- a/scripts/check-pr-review-gate.mjs +++ b/scripts/check-pr-review-gate.mjs @@ -24,8 +24,10 @@ const pollIntervalMs = readNonNegativeIntegerArg("--poll-interval-ms", 10_000); const retryAttempts = readPositiveIntegerArg("--retry-attempts", DEFAULT_GH_RETRY_ATTEMPTS); const retryBackoffMs = readNonNegativeIntegerArg("--retry-backoff-ms", DEFAULT_GH_RETRY_BACKOFF_MS); const fixturePaths = readFixturePaths(); -const requiredReviewAuthor = readArgValue("--required-review-author"); -const prFindingAuthor = requiredReviewAuthor ?? DEFAULT_PR_FINDING_AUTHOR; +const requestedReviewAuthor = readArgValue("--required-review-author"); +const requiredReviewAuthor = + strictHeadReview ? (requestedReviewAuthor ?? DEFAULT_PR_FINDING_AUTHOR) : requestedReviewAuthor; +const prFindingAuthor = requestedReviewAuthor ?? DEFAULT_PR_FINDING_AUTHOR; const expectedHeadOid = readArgValue("--expected-head-oid"); const explicitRepo = readArgValue("--repo"); const explicitPr = readArgValue("--pr"); From 2c8e52525d495eccffe0a93d65e49baed1d29c87 Mon Sep 17 00:00:00 2001 From: Tapish Khandelwal Date: Mon, 24 Aug 2026 16:23:04 +0530 Subject: [PATCH 2/6] test(review-gate): cover strict default author --- tests/scripts/check-pr-review-gate.test.ts | 38 +++++++++++++++++++++- 1 file changed, 37 insertions(+), 1 deletion(-) diff --git a/tests/scripts/check-pr-review-gate.test.ts b/tests/scripts/check-pr-review-gate.test.ts index 54055e91..02969f40 100644 --- a/tests/scripts/check-pr-review-gate.test.ts +++ b/tests/scripts/check-pr-review-gate.test.ts @@ -329,6 +329,40 @@ describe("PR review gate", () => { ).toThrow(/No review was found for current head/); }); + it("does not let another author satisfy strict mode without an explicit author", () => { + const fixturePath = writeFixture( + "other-author-current-head-review", + reviewFixture({ + headRefOid: "head-sha", + reviews: [ + review({ + state: "COMMENTED", + commit: "head-sha", + author: "external-reviewer", + }), + ], + }), + ); + + const result = spawnSync( + process.execPath, + [ + scriptPath, + "--repo", + "lamemustafa/pack", + "--pr", + "14", + "--fixture", + fixturePath, + "--strict-head-review", + ], + { cwd: rootDir, encoding: "utf8" }, + ); + + expect(result.status).toBe(1); + expect(result.stderr).toContain("No review was found for current head"); + }); + it("does not count dismissed current-head reviews as satisfying strict review", () => { const fixturePath = writeFixture( "dismissed-head-review", @@ -1149,16 +1183,18 @@ function review({ state, commit, submittedAt = "2026-06-24T17:45:40Z", + author = "chatgpt-codex-connector", }: { state: "APPROVED" | "COMMENTED" | "CHANGES_REQUESTED" | "DISMISSED" | "PENDING"; commit: string | null; submittedAt?: string; + author?: string; }) { return { state, submittedAt, url: `https://github.com/lamemustafa/pack/pull/14#${commit}-${state}`, - author: { login: "chatgpt-codex-connector" }, + author: { login: author }, commit: commit ? { oid: commit } : null, }; } From 2e47ab4747804fb516160ebed06217fe9e25383c Mon Sep 17 00:00:00 2001 From: Tapish Khandelwal Date: Mon, 24 Aug 2026 16:23:33 +0530 Subject: [PATCH 3/6] docs(review-gate): require current-head review --- AGENTS.md | 2 +- docs/AGENT_REVIEW_RECTIFY.md | 19 ++++++++++++------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 11c2b94a..d5f4e720 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -19,7 +19,7 @@ pnpm exec prettier --check . node scripts/verify-extension-package.mjs .output/chrome-mv3 pnpm exec wxt zip && node scripts/verify-extension-zip.mjs # release only pnpm workflow:preflight # before non-trivial edits -pnpm review:gate -- --strict-head-review # PR readiness +pnpm review:gate -- --strict-head-review # PR readiness; requires Codex's current-head review ``` Run the first seven before calling any change complete. Quote the last three lines of the Vitest diff --git a/docs/AGENT_REVIEW_RECTIFY.md b/docs/AGENT_REVIEW_RECTIFY.md index db0de649..7715497b 100644 --- a/docs/AGENT_REVIEW_RECTIFY.md +++ b/docs/AGENT_REVIEW_RECTIFY.md @@ -131,7 +131,7 @@ node scripts/verify-extension-package.mjs .output/chrome-mv3 pnpm exec wxt zip node scripts/verify-extension-zip.mjs git diff --check -pnpm review:gate -- --strict-head-review --required-review-author chatgpt-codex-connector --wait-head-review-ms 180000 --allow-missing-head-review +pnpm review:gate -- --strict-head-review --wait-head-review-ms 180000 ``` `node scripts/run-dependency-audit.mjs` runs `pnpm audit --audit-level high` @@ -141,12 +141,17 @@ there is no PR, network access, or authenticated GitHub CLI session, report that as a PR-readiness verification gap instead of treating it as a pass. -The `Review gate` workflow is allowed to pass with -`--allow-missing-head-review` after waiting for Codex because the external bot can -acknowledge `@codex review` without producing a formal review in a deterministic -time window. Treat that mode as a findings gate: unresolved review threads and -current-head requested-changes reviews still fail, but a missing bot review is an -audit gap to record before merge/release claims. +For local PR readiness, `--wait-head-review-ms` waits for Codex's review on the +current head and then fails if none arrives. A timeout does not waive the +current-head review requirement; otherwise the wait is a timer rather than a +gate. + +The `Review gate` workflow separately uses `--allow-missing-head-review` after +waiting for Codex because the external bot can acknowledge `@codex review` +without producing a formal review in a deterministic time window. Treat that +workflow mode as a findings gate: unresolved review threads and current-head +requested-changes reviews still fail, but a missing bot review is an audit gap +to record before merge/release claims. Do not use it as PR-readiness evidence. For PRs, record the exact local commands or CI run, release ZIP/checksum evidence when a ZIP is produced, and the SHA-256 checksum. Treat late Codex/bot From cd7bd128bacc33ecdcb5e7d62f00c770cea5689a Mon Sep 17 00:00:00 2001 From: Tapish Khandelwal Date: Mon, 24 Aug 2026 16:24:37 +0530 Subject: [PATCH 4/6] style(review-gate): format strict author default --- scripts/check-pr-review-gate.mjs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/check-pr-review-gate.mjs b/scripts/check-pr-review-gate.mjs index f7f32d47..190ecb00 100644 --- a/scripts/check-pr-review-gate.mjs +++ b/scripts/check-pr-review-gate.mjs @@ -25,8 +25,9 @@ const retryAttempts = readPositiveIntegerArg("--retry-attempts", DEFAULT_GH_RETR const retryBackoffMs = readNonNegativeIntegerArg("--retry-backoff-ms", DEFAULT_GH_RETRY_BACKOFF_MS); const fixturePaths = readFixturePaths(); const requestedReviewAuthor = readArgValue("--required-review-author"); -const requiredReviewAuthor = - strictHeadReview ? (requestedReviewAuthor ?? DEFAULT_PR_FINDING_AUTHOR) : requestedReviewAuthor; +const requiredReviewAuthor = strictHeadReview + ? (requestedReviewAuthor ?? DEFAULT_PR_FINDING_AUTHOR) + : requestedReviewAuthor; const prFindingAuthor = requestedReviewAuthor ?? DEFAULT_PR_FINDING_AUTHOR; const expectedHeadOid = readArgValue("--expected-head-oid"); const explicitRepo = readArgValue("--repo"); From a1613edbd4ef18f995eabcc1cbf1898751bc6f79 Mon Sep 17 00:00:00 2001 From: Tapish Khandelwal Date: Mon, 24 Aug 2026 17:19:26 +0530 Subject: [PATCH 5/6] fix(review-gate): require review in packaged PR gate --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 8d119425..e2fb2ad7 100644 --- a/package.json +++ b/package.json @@ -48,7 +48,7 @@ "verify:local": "pnpm install --frozen-lockfile && node scripts/run-dependency-audit.mjs && wxt prepare && prettier --check . && eslint . --max-warnings 0 && tsc --noEmit && vitest run && wxt build && node scripts/verify-extension-package.mjs .output/chrome-mv3 && git diff --check", "verify": "pnpm verify:local", "verify:release": "pnpm verify:local && pnpm verify:clean && wxt zip && node scripts/verify-extension-zip.mjs", - "verify:pr": "pnpm workflow:preflight && pnpm review:gate -- --strict-head-review --required-review-author chatgpt-codex-connector --wait-head-review-ms 180000 --poll-interval-ms 10000 --allow-missing-head-review" + "verify:pr": "pnpm workflow:preflight && pnpm review:gate -- --strict-head-review --wait-head-review-ms 180000" }, "dependencies": { "@wxt-dev/module-react": "^1.1.3", From c6d6e7e2e557f39cd7a5e8b474aeed200ead1e36 Mon Sep 17 00:00:00 2001 From: Tapish Khandelwal Date: Mon, 24 Aug 2026 17:24:36 +0530 Subject: [PATCH 6/6] docs(review-gate): require review in PR template --- .github/PULL_REQUEST_TEMPLATE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 194c74ca..7bb328db 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -79,7 +79,7 @@ Examples: - [ ] `node scripts/verify-github-release-assets.mjs --tag --zip --checksum --provenance ` when release assets exist - [ ] `node scripts/publish-chrome-web-store.mjs --zip .output/ --provenance .output/pack-release-provenance.v1.json --publisher-id --dry-run true` - [ ] `git diff --check` -- [ ] `pnpm review:gate -- --strict-head-review --required-review-author chatgpt-codex-connector --wait-head-review-ms 180000 --allow-missing-head-review` before merge/readiness claim, with missing Codex review recorded as an audit gap if reported: +- [ ] `pnpm review:gate -- --strict-head-review --wait-head-review-ms 180000` before merge/readiness claim; a missing Codex review blocks readiness: ## Artifact Evidence