#1050 C1 ROUND 4 — PIPELINE CASE-COVERAGE DENOMINATOR

IDENTITY / SCOPE
- predecessor head: 0e2eef1c1261444b83c089df6047a2a06592d5c6
- branch: feat/1050-install-state-machine-red-fixture
- only open requirement: pipeline-level expected-case/executed-case set equality
- unchanged/fenced: tools/fixtures/greenfield-expected-red.tsv, tools/verify-greenfield-expected-red.sh, #869, P6 detector/producer, absolute-P3 CLI linking, and per-case fixture dispositions
- status language: believed-fixed, pending jarvis validation

STALE-RULING WITHDRAWAL HONOURED
Requirements 1-3 were withdrawn after pipeline 2242 at 0e2eef1c reached terminal green and showed P6 failure propagation, absolute-P3 CLI use, and an executed git-absent arm. A temporary local P6-consumer edit made while the stale ruling was in flight was restored before this change set; tools/e2e-install-test.sh has no final-tree delta. Requirement 5 alone remains in this round.

RED-FIRST
Before the change, .woodpecker/greenfield-install.yml had no pipeline-level initialized marker store, no per-case success marker, and no final exact-set gate. A static assertion for a final run-on-failure case-coverage step failed. Pipeline 2242's green result proved that all three cases ran once, but no gate required that population on a later run.

IMPLEMENTATION
- tools/verify-greenfield-case-coverage.sh is a new pipeline-level instrument; the existing per-case verifier is unchanged.
- Expected case names are derived from the first TSV field of tools/fixtures/greenfield-expected-red.tsv and sorted uniquely. There is no literal expected count.
- Marker storage is scoped by ${CI_PIPELINE_NUMBER}-${CI_WORKFLOW_NUMBER}. The init action validates the manifest and empties only that run directory, so stale markers cannot satisfy a retry or later run.
- Every case/contract step explicitly depends on initialization. Each unconditional case step calls mark only after its exact tools/verify-greenfield-expected-red.sh invocation succeeds.
- The final greenfield-case-denominator step explicitly depends on all four case/contract steps, has status eligibility [success, failure], emits cases_defined=N cases_executed=M, and compares sorted expected and actual case-name sets. Missing or unexpected names fail even when the two counts are equal.
- A newly defined manifest case changes the expected set automatically and fails until a corresponding successful case step marks it.

MEASURED CONTROLS
1. Skipped expected arm:
   rc=1
   [fixture-suite] cases_defined=3 cases_executed=2
   [fixture-suite] missing_case=next-git-absent
2. Count-inflation control (one expected missing, one unexpected added):
   rc=1
   [fixture-suite] cases_defined=3 cases_executed=3
   [fixture-suite] missing_case=next-git-absent
   [fixture-suite] unexpected_case=unexpected-case
3. Stale-marker initialization control (same run re-initialized after markers existed):
   rc=1
   [fixture-suite] cases_defined=3 cases_executed=0
   missing_case rows emitted for all three expected names
4. Exact-set positive control:
   rc=0
   [fixture-suite] cases_defined=3 cases_executed=3
5. Future manifest case control:
   rc=1
   [fixture-suite] cases_defined=4 cases_executed=3
   [fixture-suite] missing_case=future-case

WORKFLOW / FOCUSED VALIDATION
- bash -n new subject and test: PASS
- shellcheck new subject and test: PASS
- bash tools/verify-greenfield-case-coverage.test.sh: PASS
- test statically proves each mark follows its exact per-case verifier, every producer depends on initialization, the final gate depends on the complete matrix, and final status eligibility includes success+failure
- woodpecker-cli lint --strict .woodpecker/greenfield-install.yml: PASS
- Prettier check for workflow/package/PRD: PASS
- git diff --check: PASS

CURRENT-HEAD FIXTURE MEASUREMENTS TAKEN BEFORE THE STALE RULING WAS WITHDRAWN
These measurements were run from 0e2eef1c before requirement 5 changed only pipeline instrumentation. They are retained as measured outcomes, not as justification for modifying requirements 1-3.
- next checkout/git-present: fixture rc=1; resolved @next=0.0.50-next.2207; P0/P1/P2/P3/P7 PASS; P4/P5/P6/P8/P9 FAIL; installer_exit=1; done_claims=0; P6 reason was dead enforcement hooks active count=2.
- next checkout/git-absent: fixture rc=1; P0/P6/P7 PASS; P1/P2/P3/P4/P5/P8/P9 FAIL; installer_exit=1; done_claims=0.
- /home free before the first run: 8.5G; after concurrent authorized fleet reclaim completed: 11G; no be-coder-05 generated payload was deleted because active fixture work made that churn.

INDEPENDENT REVIEW CYCLE
- Initial Codex code review: REQUEST_CHANGES, confidence 0.96; one blocker found that the first draft omitted depends_on ordering and could race initialization/final checking.
- Disposition: accepted. Added explicit init -> all case/contract steps -> final dependency graph and a regression assertion for every dependency edge.
- Initial Codex security review: risk NONE, confidence 0.94, zero findings. The sandbox could not create its own temp directory; local focused/full tests provide the dynamic evidence.
- First post-dependency code re-review: REQUEST_CHANGES, confidence 0.99; the case extractor treated the production manifest's comment lines as case names, while the synthetic test omitted comments.
- Disposition: accepted. Case derivation now excludes blank/comment lines; the focused test includes representative comments and executes init/mark/check against the repository's real manifest.
- Post-dependency security re-review: risk NONE, confidence 0.96, zero findings.
- Final Codex code re-review after the comment fix: APPROVE, confidence 0.94, 8 files, zero findings. It confirmed ordering, run scope, fail-closed set equality, PRD alignment, and negative controls.
- Final Codex security re-review: risk NONE, confidence 0.96, 8 files, zero findings.

FINAL LOCAL BASELINES
- pnpm test:installer: PASS, including the new coverage suite
- pnpm typecheck: PASS, 45/45
- pnpm lint: PASS, 25/25
- pnpm format:check: PASS
- bash -n + ShellCheck for new shell surfaces: PASS
- Woodpecker strict lint: PASS
- git diff --check: PASS
- /home free before/after local baselines: 11G

PENDING BEFORE PUSH
- commit, queue guard, one push, provider attribution read-back
- announce the new full SHA to rev-security-02; do not merge or close
