diff --git a/.woodpecker/ci.yml b/.woodpecker/ci.yml index 6c11c855..034783db 100644 --- a/.woodpecker/ci.yml +++ b/.woodpecker/ci.yml @@ -72,9 +72,12 @@ steps: # step-level `when`, because a gate can be disabled by changes outside its own path. gate-verify: image: *node_image + # Woodpecker's shallow marker makes merge-base reject even present parents; + # full history is required for prospective own-tree replay. commands: - *enable_pnpm - apk add --no-cache bubblewrap + - if [ -f .git/shallow ]; then git fetch --unshallow --no-tags origin; fi - pnpm gate:verify depends_on: - install diff --git a/docs/ADMIN-GUIDE/quality-gate-registry.md b/docs/ADMIN-GUIDE/quality-gate-registry.md index cc971f7a..0f785cd5 100644 --- a/docs/ADMIN-GUIDE/quality-gate-registry.md +++ b/docs/ADMIN-GUIDE/quality-gate-registry.md @@ -26,8 +26,8 @@ Do not add an ownerless exception or describe an open delta as pass/green/OK. ## CI behavior -Woodpecker runs `gate-verify` on every pull request and protected-main push without path filtering. This is deliberate: changes outside gate files can make a gate inert. +Woodpecker runs `gate-verify` on every pull request and protected-main push without path filtering. This is deliberate: changes outside gate files can make a gate inert. The step unshallows the checkout first because prospective ancestry and own-tree replay require complete commit history; a shallow boundary must never be interpreted as non-ancestry. Provider evidence input is an optional JSON array of normalized pipeline records containing `commit`, unique integer pipeline `number`, pipeline `status`, and a `gate-verify` step status. The highest numbered rerun is authoritative; ambiguous duplicates fail. Its retention window is provider-controlled and is not overstated by this repository. -Prior commit replay performs a frozen offline install from each commit's own lockfile before running that commit's verifier. Bubblewrap clears the environment, hides operator-home credentials, and disables networking for historical lifecycle and verifier code. A missing cached dependency or unavailable sandbox fails replay; current dependencies are never substituted. +Prior commit replay performs a frozen offline install from each commit's own lockfile before running that commit's verifier. Bubblewrap clears the environment, hides operator-home credentials, isolates process namespaces, and disables networking for historical lifecycle and verifier code. Archived files are snapshotted before install and must remain byte/type/mode-identical afterward. A missing cached dependency, source mutation, or unavailable sandbox fails replay; current dependencies are never substituted. diff --git a/docs/scratchpads/1029-rm-02-gate-registry.md b/docs/scratchpads/1029-rm-02-gate-registry.md index 673e5b8c..8604d555 100644 --- a/docs/scratchpads/1029-rm-02-gate-registry.md +++ b/docs/scratchpads/1029-rm-02-gate-registry.md @@ -58,6 +58,7 @@ The queue guard's `get_state_from_status_json` runs `python3 - <<'PY'` while pro - Codex security review found the Bubblewrap replay shared the runner PID namespace. Replay now unshares PID, IPC, and UTS namespaces, and an abuse-case test proves a sibling runner PID is invisible. - Second review found empty reason diagnostics, final-symlink fixture writes, and lifecycle-script mutation of authoritative history files. Must-fail cases now require a reason pattern; writes use no-follow semantics; and replay snapshots every archived file before install and rejects any changed, deleted, or type/mode-shifted source before executing the verifier. Dedicated negative tests cover all three. - Third code review found ambiguous duplicate provider steps and order-sensitive JSON outcome comparison. Provider evidence now requires exactly one `gate-verify` step in the authoritative rerun, and structural equality normalizes object keys. Both regressions have RED-first tests. Third security review reported no findings. +- Initial PR pipeline #2177 exposed Woodpecker's shallow boundary: the activation parent object was present but marked shallow, so `merge-base --is-ancestor` correctly refused to infer ancestry. The unconditional gate step now unshallows before prospective replay; its wiring test was observed RED before the CI fix. ## Documentation checklist diff --git a/scripts/gate-wiring.test.mjs b/scripts/gate-wiring.test.mjs index 52c81405..cfeda743 100644 --- a/scripts/gate-wiring.test.mjs +++ b/scripts/gate-wiring.test.mjs @@ -16,7 +16,7 @@ test('Woodpecker runs gate verification on every pipeline without a path filter' pipeline.match(/\n gate-verify:\n([\s\S]*?)(?=\n [a-z][a-z0-9-]+:|\nservices:)/)?.[1] ?? ''; assert.match( step, - /commands:\n - \*enable_pnpm\n - apk add --no-cache bubblewrap\n - pnpm gate:verify\n/, + /commands:\n - \*enable_pnpm\n - apk add --no-cache bubblewrap\n - if \[ -f \.git\/shallow \]; then git fetch --unshallow --no-tags origin; fi\n - pnpm gate:verify\n/, ); assert.doesNotMatch(step, /\bwhen:|\bpath:/); });