## Summary
- fetch the Gitea PR base and refs/pull head into explicit remote refs
- diff the fetched PR head instead of local HEAD
- fail nonzero before Codex or auto-post when PR diff construction is empty or fails
- document fail-closed PR behavior
## TDD
- RED commit: 737c0fe67431f23e73d3e24b83b3909d521a120b
- GREEN commit: cf8453c255a9034348bbf41facf42dac368abd21
## Verification
- focused shell regression: 2/2 pass
- bash syntax and ShellCheck pass for changed shell paths
- pnpm typecheck pass
- pnpm lint pass
- pnpm format:check pass
- pnpm test pass: 43/43 Turbo tasks; mosaic package 1278/1278
No network mutation occurs in the regression harness; git fetch, Codex, and PR posting are stubbed.
Closes #795
Fixes #795
Reviewer-of-Record — exact head cf8453c255a9034348bbf41facf42dac368abd21
Verdict: APPROVE (zero blockers) — independent exact-head adversarial/security review. Author lane: ms-795 (Codex sol). Reviewer lane: MS Team Lead (independent Opus). author≠reviewer = PROCESS/LANE-attested under the single jason.woltje account. Base:9ddc6fbd (merge-base == current main). Tree:1858563196148701e500e3a1d0a232e6c16d029d. Scope CLEAN: 3 files (+178/−26), all under packages/mosaic/framework/tools/codex/ (common.sh, README.md, new test-pr-diff-context.sh). No #792 overlap; no mutation of installed ~/.config/mosaic wrappers.
Fix verified
Gitea PR mode now fetches +refs/heads/<base> and +refs/pull/<n>/head and diffs the explicit refs (never local HEAD) — closes wrong-branch/empty-diff in fresh clones.
detect_platform >/dev/null — suppresses provider-detection stdout that was previously captured as diff content (the actual auto-post vector for the #793 misfire).
Fail-closed: return 1 + actionable stderr (no stdout) on unresolved base / fetch fail / diff fail / unsupported platform / empty-diff.
Auto-post is genuinely blocked:codex-code-review.sh:8 + common.sh:5 both set -e; DIFF_CONTEXT=$(build_diff_context pr N) returning 1 exits the script NONZERO at the assignment, before the [[ -z ]] guard (:127) and beforepost_to_pr (:231-233). Defense-in-depth: even without set -e, empty DIFF_CONTEXT → exit 0 still precedes the post.
Test red-first & non-tautological:pr-head case fails if the diff used HEAD (proves RED for old ${pr_base}...HEAD); fail-closed case runs the real CLI with git/tea/codex/pr-review all stubbed and asserts nonzero exit + empty CODEX_LOG (no Codex) + empty POST_LOG (no auto-post) + stderr Error:/PR #795.
No live network/provider mutation in tests (all stubbed) — honors the ratified boundary.
Secrev: no secrets emitted; removed the inline tea login list token-in-curl fallback → strictly less credential exposure.
Gate status
based-on-current-main ✓ · scope clean / no overlap / no installed-wrapper mutation ✓ · independent exact-head RoR APPROVE ✓ · red-first regression ✓ · exact-head CI PENDING at review → merge gated on terminal-green + CI queue guard; head must not move.
## Reviewer-of-Record — exact head `cf8453c255a9034348bbf41facf42dac368abd21`
**Verdict: APPROVE** (zero blockers) — independent exact-head adversarial/security review.
**Author lane:** ms-795 (Codex sol). **Reviewer lane:** MS Team Lead (independent Opus). author≠reviewer = PROCESS/LANE-attested under the single `jason.woltje` account.
**Base:** `9ddc6fbd` (merge-base == current main). **Tree:** `1858563196148701e500e3a1d0a232e6c16d029d`.
**Scope CLEAN:** 3 files (+178/−26), all under `packages/mosaic/framework/tools/codex/` (`common.sh`, `README.md`, new `test-pr-diff-context.sh`). No #792 overlap; **no mutation of installed `~/.config/mosaic` wrappers.**
### Fix verified
1. Gitea PR mode now fetches `+refs/heads/<base>` and `+refs/pull/<n>/head` and diffs the **explicit refs** (never local HEAD) — closes wrong-branch/empty-diff in fresh clones.
2. `detect_platform >/dev/null` — suppresses provider-detection stdout that was previously captured as diff content (the actual auto-post vector for the #793 misfire).
3. Fail-closed: `return 1` + actionable **stderr** (no stdout) on unresolved base / fetch fail / diff fail / unsupported platform / empty-diff.
4. Bonus: `awk '$1==pr'` replaces prefix `grep "^N"` — fixes latent PR-number prefix collision.
### Adversarial findings (all PASS)
- **Auto-post is genuinely blocked:** `codex-code-review.sh:8` + `common.sh:5` both `set -e`; `DIFF_CONTEXT=$(build_diff_context pr N)` returning 1 exits the script NONZERO at the assignment, **before** the `[[ -z ]]` guard (:127) and **before** `post_to_pr` (:231-233). Defense-in-depth: even without set -e, empty `DIFF_CONTEXT` → `exit 0` still precedes the post.
- **Test red-first & non-tautological:** `pr-head` case fails if the diff used `HEAD` (proves RED for old `${pr_base}...HEAD`); `fail-closed` case runs the real CLI with git/tea/codex/pr-review all stubbed and asserts nonzero exit + empty CODEX_LOG (no Codex) + empty POST_LOG (no auto-post) + stderr `Error:`/`PR #795`.
- **No live network/provider mutation in tests** (all stubbed) — honors the ratified boundary.
- **Secrev:** no secrets emitted; removed the inline `tea login list` token-in-curl fallback → strictly less credential exposure.
### Gate status
based-on-current-main ✓ · scope clean / no overlap / no installed-wrapper mutation ✓ · independent exact-head RoR APPROVE ✓ · red-first regression ✓ · **exact-head CI PENDING at review → merge gated on terminal-green + CI queue guard; head must not move.**
RoR WITHDRAWN — verdict in comment 17937 does NOT transfer
Independent prospective-tree review of exact head cf8453c2 / tree 1858563196148701e500e3a1d0a232e6c16d029d identified a blocker the earlier review missed:
test-pr-diff-context.sh is not wired into package.json, .woodpecker/ci.yml, or any test runner — it exists but never executes, so CI can green while the diff-context protection silently regresses.
Coverage also omits codex-security-review.sh (same build_diff_context PR path) and uses main as the base fixture, so a hardcoded-main regression would pass undetected.
Action: rejected head cf8453c2 preserved; repair only these test-enforcement/coverage blockers on a new head, wire the test so CI actually executes and fails-red on regression, extend coverage to the security wrapper + non-main base fixture, rerun CI, and obtain a fresh exact-head RoR. No merge.
### RoR WITHDRAWN — verdict in comment 17937 does NOT transfer
Independent prospective-tree review of exact head `cf8453c2` / tree `1858563196148701e500e3a1d0a232e6c16d029d` identified a blocker the earlier review missed:
- **`test-pr-diff-context.sh` is not wired into `package.json`, `.woodpecker/ci.yml`, or any test runner** — it exists but never executes, so CI can green while the diff-context protection silently regresses.
- Coverage also **omits `codex-security-review.sh`** (same `build_diff_context` PR path) and uses `main` as the base fixture, so a hardcoded-`main` regression would pass undetected.
**Action:** rejected head `cf8453c2` preserved; repair only these test-enforcement/coverage blockers on a **new** head, wire the test so CI actually executes and fails-red on regression, extend coverage to the security wrapper + non-`main` base fixture, rerun CI, and obtain a **fresh** exact-head RoR. No merge.
Fresh independent exact-head review. Author lane: ms-795 (Codex). Reviewer lane: MS Team Lead independent reviewer (sonnet). author≠reviewer PROCESS/LANE-attested (single provider acct jason.woltje). Supersedes all prior #815 RoRs (non-transferable after rebase; zero evidence transfer).
Independently verified facts
PR state: open, mergeable=true
Head SHA (observed):027a99b558463f507179c7d970a2bc7d12b51437 — matches claimed
Base SHA (observed, PR.base.sha):fe7a468c9da23b7ce7961ec3231f8e5f952e29de — matches claimed
Merge-base (observed):fe7a468c9da23b7ce7961ec3231f8e5f952e29de — equals base, i.e. branch sits directly on current main (trivial/fast-forward prospective merge)
Current main branch HEAD (independently fetched via /branches/main):fe7a468c9da23b7ce7961ec3231f8e5f952e29de — confirms base is truly current main
Prospective merge tree: not separately materialized as a distinct SHA by the Gitea API for this PR, but since merge-base == base == current main HEAD, the prospective merge is a clean fast-forward of these 4 files onto fe7a468c; no divergence exists to produce a different tree than the head commit's own tree. (Claimed value 938e730e... was not independently reproducible via a distinct API field and is not required to establish mergeability given the ff relationship confirmed above.)
Scope (observed via /pulls/815/files and .diff): exactly 4 files, all under packages/mosaic/:
No out-of-scope files. No .mosaic/, session.lock, secrets, or unrelated directories touched.
Commits (4):13c50c5 test repro of wrong-diff/fail-open bug → 080a6b4 feat: fetch Gitea PR head, fail closed → 0e50c69 test: enforce PR diff regressions in CI → 027a99b5 test: make PR diff fixtures hermetic. All under issue #795.
Correctness review against main fe7a468c
common.sh's Gitea pr branch of build_diff_context was rewritten to explicitly git fetchrefs/heads/<base> and refs/pull/<n>/head into local remote-tracking refs, then diff those two explicit refs (git diff base_ref...pr_head_ref), replacing the old fallback chain that could silently degrade to git diff main...HEAD (the fail-open bug #795 targets). Each failure path (tea base-branch lookup failure, fetch failure, diff failure, and a final empty-diff check for mode == pr) returns 1 with an actionable Error: ... PR #<n> message to stderr — fail-closed, no silent fallback remains.
codex-code-review.sh/codex-security-review.sh call check_codex then check_jq before build_diff_context, and assign its output via DIFF_CONTEXT=$(build_diff_context "pr" "$PR_NUMBER") at top level (not inside a conditional), so under the script's set -e a nonzero return from build_diff_context aborts the script immediately — before Codex invocation or PR posting. Verified this is exactly what test-pr-diff-context.sh's "empty PR" fixture exercises and asserts (no codex.log, no post.log, stderr contains Error: and PR #795).
jq dependency: Dockerfile.ci (unchanged by this PR, already on main/fe7a468c) bakes jq into ci-base (apk add ... jq) with a comment explicitly noting framework shell tests and Codex wrappers require it — confirms the precondition this PR builds on is already satisfied by ci-base:latest, so check_jq in the review scripts will pass in CI.
CI wiring: packages/mosaic/package.jsontest script becomes vitest run --passWithNoTests && pnpm run test:framework-shell, where test:framework-shell runs bash framework/tools/codex/test-pr-diff-context.sh. Root pnpm test → turbo run test, which fans out to each workspace's test script including packages/mosaic. .woodpecker/ci.yml's existing test step already runs pnpm test, so no separate CI YAML edit is needed — the wiring is correct and real, not just claimed.
The new hermetic test builds two throwaway local git repos ("changed" and "empty" PR-head fixtures) with stubbed tea and codex binaries on $PATH, and exercises both the git-mode fixture path (fetches explicit non-main base/head refs, diffs them, asserts the fixture file content appears) and the jq/fail-closed path (via the real codex-code-review.sh/codex-security-review.sh wrappers hitting an empty-diff PR). No shell-quoting bugs, unguarded globs, or silent-failure paths found; set -euo pipefail plus explicit trap ... EXIT cleanup are used correctly; sensitive env vars (GIT_DIR et al.) are unset defensively so real CI checkout state can't leak into the fixture repos.
No regression risk identified for the GitHub path (gh pr diff) — untouched aside from adding an explicit failure branch, which is strictly safer than before (previously ignored gh failures via 2>/dev/null with no exit check).
Workflow ci: all 9 steps success incl. clone, ci-postgres, install, sanitization, upgrade-guard, typecheck, lint, format, and — the gating step — test (exit_code=0, step id 49227).
Decoded the test step log directly (not trusting any prior summary): it shows the new fixtures actually executing and passing —
ok - Gitea PR mode fetches and diffs explicit non-main base and PR head refs
ok - empty code PR diff fails closed before Codex and auto-post
ok - empty security PR diff fails closed before Codex and auto-post
followed by the rest of the monorepo's turbo test suite completing successfully (43 successful, 43 total).
Findings
No defects found. Scope is clean, the fail-closed diff-construction fix is logically sound and directly addresses the #795 regression (silent fallback to main...HEAD), the CI wiring is real (via package.json → turbo run test → existing test step, no new YAML needed), the jq precondition is already satisfied on ci-base, and exact-head CI (pipeline 1897, including the test step) is green with log evidence the new tests actually ran and passed.
Verdict: APPROVE
No merge; coordinator GO required after this RoR + homelab's independent prospective-tree review converge.
## Reviewer-of-Record — PR #815 (issue #795) @ `027a99b5` — **APPROVE**
Fresh independent exact-head review. Author lane: ms-795 (Codex). Reviewer lane: MS Team Lead independent reviewer (sonnet). author≠reviewer PROCESS/LANE-attested (single provider acct jason.woltje). Supersedes all prior #815 RoRs (non-transferable after rebase; zero evidence transfer).
### Independently verified facts
- **PR state:** open, `mergeable=true`
- **Head SHA (observed):** `027a99b558463f507179c7d970a2bc7d12b51437` — matches claimed
- **Base SHA (observed, PR.base.sha):** `fe7a468c9da23b7ce7961ec3231f8e5f952e29de` — matches claimed
- **Merge-base (observed):** `fe7a468c9da23b7ce7961ec3231f8e5f952e29de` — equals base, i.e. branch sits directly on current `main` (trivial/fast-forward prospective merge)
- **Current `main` branch HEAD (independently fetched via `/branches/main`):** `fe7a468c9da23b7ce7961ec3231f8e5f952e29de` — confirms base is truly current main
- **Prospective merge tree:** not separately materialized as a distinct SHA by the Gitea API for this PR, but since merge-base == base == current main HEAD, the prospective merge is a clean fast-forward of these 4 files onto `fe7a468c`; no divergence exists to produce a different tree than the head commit's own tree. (Claimed value `938e730e...` was not independently reproducible via a distinct API field and is not required to establish mergeability given the ff relationship confirmed above.)
- **Scope (observed via `/pulls/815/files` and `.diff`):** exactly 4 files, all under `packages/mosaic/`:
- `framework/tools/codex/README.md` (changed)
- `framework/tools/codex/common.sh` (changed)
- `framework/tools/codex/test-pr-diff-context.sh` (added)
- `package.json` (changed)
- No out-of-scope files. No `.mosaic/`, `session.lock`, secrets, or unrelated directories touched.
- **Commits (4):** `13c50c5` test repro of wrong-diff/fail-open bug → `080a6b4` feat: fetch Gitea PR head, fail closed → `0e50c69` test: enforce PR diff regressions in CI → `027a99b5` test: make PR diff fixtures hermetic. All under issue #795.
### Correctness review against main `fe7a468c`
- `common.sh`'s Gitea `pr` branch of `build_diff_context` was rewritten to explicitly `git fetch` `refs/heads/<base>` and `refs/pull/<n>/head` into local remote-tracking refs, then diff those two explicit refs (`git diff base_ref...pr_head_ref`), replacing the old fallback chain that could silently degrade to `git diff main...HEAD` (the fail-open bug #795 targets). Each failure path (`tea` base-branch lookup failure, fetch failure, diff failure, and a final empty-diff check for `mode == pr`) returns 1 with an actionable `Error: ... PR #<n>` message to stderr — fail-closed, no silent fallback remains.
- `codex-code-review.sh`/`codex-security-review.sh` call `check_codex` then `check_jq` before `build_diff_context`, and assign its output via `DIFF_CONTEXT=$(build_diff_context "pr" "$PR_NUMBER")` at top level (not inside a conditional), so under the script's `set -e` a nonzero return from `build_diff_context` aborts the script immediately — before Codex invocation or PR posting. Verified this is exactly what `test-pr-diff-context.sh`'s "empty PR" fixture exercises and asserts (no codex.log, no post.log, stderr contains `Error:` and `PR #795`).
- `jq` dependency: `Dockerfile.ci` (unchanged by this PR, already on `main`/`fe7a468c`) bakes `jq` into `ci-base` (`apk add ... jq`) with a comment explicitly noting framework shell tests and Codex wrappers require it — confirms the precondition this PR builds on is already satisfied by `ci-base:latest`, so `check_jq` in the review scripts will pass in CI.
- CI wiring: `packages/mosaic/package.json` `test` script becomes `vitest run --passWithNoTests && pnpm run test:framework-shell`, where `test:framework-shell` runs `bash framework/tools/codex/test-pr-diff-context.sh`. Root `pnpm test` → `turbo run test`, which fans out to each workspace's `test` script including `packages/mosaic`. `.woodpecker/ci.yml`'s existing `test` step already runs `pnpm test`, so no separate CI YAML edit is needed — the wiring is correct and real, not just claimed.
- The new hermetic test builds two throwaway local git repos ("changed" and "empty" PR-head fixtures) with stubbed `tea` and `codex` binaries on `$PATH`, and exercises both the git-mode fixture path (fetches explicit non-main base/head refs, diffs them, asserts the fixture file content appears) and the jq/fail-closed path (via the real `codex-code-review.sh`/`codex-security-review.sh` wrappers hitting an empty-diff PR). No shell-quoting bugs, unguarded globs, or silent-failure paths found; `set -euo pipefail` plus explicit `trap ... EXIT` cleanup are used correctly; sensitive env vars (`GIT_DIR` et al.) are unset defensively so real CI checkout state can't leak into the fixture repos.
- No regression risk identified for the GitHub path (`gh pr diff`) — untouched aside from adding an explicit failure branch, which is strictly safer than before (previously ignored `gh` failures via `2>/dev/null` with no exit check).
### Exact-head CI verification
- Woodpecker pipeline **1897**, repo 47: `status=success`, `event=pull_request`, `commit=027a99b558463f507179c7d970a2bc7d12b51437` (exact claimed head), `ref=refs/pull/815/head`.
- Workflow `ci`: all 9 steps `success` incl. `clone`, `ci-postgres`, `install`, `sanitization`, `upgrade-guard`, `typecheck`, `lint`, `format`, and — the gating step — **`test`** (`exit_code=0`, step id 49227).
- Decoded the `test` step log directly (not trusting any prior summary): it shows the new fixtures actually executing and passing —
- `ok - Gitea PR mode fetches and diffs explicit non-main base and PR head refs`
- `ok - empty code PR diff fails closed before Codex and auto-post`
- `ok - empty security PR diff fails closed before Codex and auto-post`
followed by the rest of the monorepo's turbo test suite completing successfully (`43 successful, 43 total`).
### Findings
No defects found. Scope is clean, the fail-closed diff-construction fix is logically sound and directly addresses the #795 regression (silent fallback to `main...HEAD`), the CI wiring is real (via `package.json` → `turbo run test` → existing `test` step, no new YAML needed), the `jq` precondition is already satisfied on `ci-base`, and exact-head CI (pipeline 1897, including the `test` step) is green with log evidence the new tests actually ran and passed.
### Verdict: APPROVE
No merge; coordinator GO required after this RoR + homelab's independent prospective-tree review converge.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Summary
TDD
737c0fe674cf8453c255Verification
No network mutation occurs in the regression harness; git fetch, Codex, and PR posting are stubbed.
Closes #795
Fixes #795
Reviewer-of-Record — exact head
cf8453c255a9034348bbf41facf42dac368abd21Verdict: APPROVE (zero blockers) — independent exact-head adversarial/security review.
Author lane: ms-795 (Codex sol). Reviewer lane: MS Team Lead (independent Opus). author≠reviewer = PROCESS/LANE-attested under the single
jason.woltjeaccount.Base:
9ddc6fbd(merge-base == current main). Tree:1858563196148701e500e3a1d0a232e6c16d029d.Scope CLEAN: 3 files (+178/−26), all under
packages/mosaic/framework/tools/codex/(common.sh,README.md, newtest-pr-diff-context.sh). No #792 overlap; no mutation of installed~/.config/mosaicwrappers.Fix verified
+refs/heads/<base>and+refs/pull/<n>/headand diffs the explicit refs (never local HEAD) — closes wrong-branch/empty-diff in fresh clones.detect_platform >/dev/null— suppresses provider-detection stdout that was previously captured as diff content (the actual auto-post vector for the #793 misfire).return 1+ actionable stderr (no stdout) on unresolved base / fetch fail / diff fail / unsupported platform / empty-diff.awk '$1==pr'replaces prefixgrep "^N"— fixes latent PR-number prefix collision.Adversarial findings (all PASS)
codex-code-review.sh:8+common.sh:5bothset -e;DIFF_CONTEXT=$(build_diff_context pr N)returning 1 exits the script NONZERO at the assignment, before the[[ -z ]]guard (:127) and beforepost_to_pr(:231-233). Defense-in-depth: even without set -e, emptyDIFF_CONTEXT→exit 0still precedes the post.pr-headcase fails if the diff usedHEAD(proves RED for old${pr_base}...HEAD);fail-closedcase runs the real CLI with git/tea/codex/pr-review all stubbed and asserts nonzero exit + empty CODEX_LOG (no Codex) + empty POST_LOG (no auto-post) + stderrError:/PR #795.tea login listtoken-in-curl fallback → strictly less credential exposure.Gate status
based-on-current-main ✓ · scope clean / no overlap / no installed-wrapper mutation ✓ · independent exact-head RoR APPROVE ✓ · red-first regression ✓ · exact-head CI PENDING at review → merge gated on terminal-green + CI queue guard; head must not move.
RoR WITHDRAWN — verdict in comment 17937 does NOT transfer
Independent prospective-tree review of exact head
cf8453c2/ tree1858563196148701e500e3a1d0a232e6c16d029didentified a blocker the earlier review missed:test-pr-diff-context.shis not wired intopackage.json,.woodpecker/ci.yml, or any test runner — it exists but never executes, so CI can green while the diff-context protection silently regresses.codex-security-review.sh(samebuild_diff_contextPR path) and usesmainas the base fixture, so a hardcoded-mainregression would pass undetected.Action: rejected head
cf8453c2preserved; repair only these test-enforcement/coverage blockers on a new head, wire the test so CI actually executes and fails-red on regression, extend coverage to the security wrapper + non-mainbase fixture, rerun CI, and obtain a fresh exact-head RoR. No merge.ade931a566toaddeaf18d2addeaf18d2to027a99b558Reviewer-of-Record — PR #815 (issue #795) @
027a99b5— APPROVEFresh independent exact-head review. Author lane: ms-795 (Codex). Reviewer lane: MS Team Lead independent reviewer (sonnet). author≠reviewer PROCESS/LANE-attested (single provider acct jason.woltje). Supersedes all prior #815 RoRs (non-transferable after rebase; zero evidence transfer).
Independently verified facts
mergeable=true027a99b558463f507179c7d970a2bc7d12b51437— matches claimedfe7a468c9da23b7ce7961ec3231f8e5f952e29de— matches claimedfe7a468c9da23b7ce7961ec3231f8e5f952e29de— equals base, i.e. branch sits directly on currentmain(trivial/fast-forward prospective merge)mainbranch HEAD (independently fetched via/branches/main):fe7a468c9da23b7ce7961ec3231f8e5f952e29de— confirms base is truly current mainfe7a468c; no divergence exists to produce a different tree than the head commit's own tree. (Claimed value938e730e...was not independently reproducible via a distinct API field and is not required to establish mergeability given the ff relationship confirmed above.)/pulls/815/filesand.diff): exactly 4 files, all underpackages/mosaic/:framework/tools/codex/README.md(changed)framework/tools/codex/common.sh(changed)framework/tools/codex/test-pr-diff-context.sh(added)package.json(changed).mosaic/,session.lock, secrets, or unrelated directories touched.13c50c5test repro of wrong-diff/fail-open bug →080a6b4feat: fetch Gitea PR head, fail closed →0e50c69test: enforce PR diff regressions in CI →027a99b5test: make PR diff fixtures hermetic. All under issue #795.Correctness review against main
fe7a468ccommon.sh's Giteaprbranch ofbuild_diff_contextwas rewritten to explicitlygit fetchrefs/heads/<base>andrefs/pull/<n>/headinto local remote-tracking refs, then diff those two explicit refs (git diff base_ref...pr_head_ref), replacing the old fallback chain that could silently degrade togit diff main...HEAD(the fail-open bug #795 targets). Each failure path (teabase-branch lookup failure, fetch failure, diff failure, and a final empty-diff check formode == pr) returns 1 with an actionableError: ... PR #<n>message to stderr — fail-closed, no silent fallback remains.codex-code-review.sh/codex-security-review.shcallcheck_codexthencheck_jqbeforebuild_diff_context, and assign its output viaDIFF_CONTEXT=$(build_diff_context "pr" "$PR_NUMBER")at top level (not inside a conditional), so under the script'sset -ea nonzero return frombuild_diff_contextaborts the script immediately — before Codex invocation or PR posting. Verified this is exactly whattest-pr-diff-context.sh's "empty PR" fixture exercises and asserts (no codex.log, no post.log, stderr containsError:andPR #795).jqdependency:Dockerfile.ci(unchanged by this PR, already onmain/fe7a468c) bakesjqintoci-base(apk add ... jq) with a comment explicitly noting framework shell tests and Codex wrappers require it — confirms the precondition this PR builds on is already satisfied byci-base:latest, socheck_jqin the review scripts will pass in CI.packages/mosaic/package.jsontestscript becomesvitest run --passWithNoTests && pnpm run test:framework-shell, wheretest:framework-shellrunsbash framework/tools/codex/test-pr-diff-context.sh. Rootpnpm test→turbo run test, which fans out to each workspace'stestscript includingpackages/mosaic..woodpecker/ci.yml's existingteststep already runspnpm test, so no separate CI YAML edit is needed — the wiring is correct and real, not just claimed.teaandcodexbinaries on$PATH, and exercises both the git-mode fixture path (fetches explicit non-main base/head refs, diffs them, asserts the fixture file content appears) and the jq/fail-closed path (via the realcodex-code-review.sh/codex-security-review.shwrappers hitting an empty-diff PR). No shell-quoting bugs, unguarded globs, or silent-failure paths found;set -euo pipefailplus explicittrap ... EXITcleanup are used correctly; sensitive env vars (GIT_DIRet al.) are unset defensively so real CI checkout state can't leak into the fixture repos.gh pr diff) — untouched aside from adding an explicit failure branch, which is strictly safer than before (previously ignoredghfailures via2>/dev/nullwith no exit check).Exact-head CI verification
status=success,event=pull_request,commit=027a99b558463f507179c7d970a2bc7d12b51437(exact claimed head),ref=refs/pull/815/head.ci: all 9 stepssuccessincl.clone,ci-postgres,install,sanitization,upgrade-guard,typecheck,lint,format, and — the gating step —test(exit_code=0, step id 49227).teststep log directly (not trusting any prior summary): it shows the new fixtures actually executing and passing —ok - Gitea PR mode fetches and diffs explicit non-main base and PR head refsok - empty code PR diff fails closed before Codex and auto-postok - empty security PR diff fails closed before Codex and auto-postfollowed by the rest of the monorepo's turbo test suite completing successfully (
43 successful, 43 total).Findings
No defects found. Scope is clean, the fail-closed diff-construction fix is logically sound and directly addresses the #795 regression (silent fallback to
main...HEAD), the CI wiring is real (viapackage.json→turbo run test→ existingteststep, no new YAML needed), thejqprecondition is already satisfied onci-base, and exact-head CI (pipeline 1897, including theteststep) is green with log evidence the new tests actually ran and passed.Verdict: APPROVE
No merge; coordinator GO required after this RoR + homelab's independent prospective-tree review converge.