Summary
#1165 fixed #1163 by correcting the pre-push build command, and in doing so brought a third copy of it into the tree. The CI-repro command now appears verbatim in three places:
| File |
Audience |
Depth |
.github/PULL_REQUEST_TEMPLATE.md |
outside contributor |
one line + short rationale |
CONTRIBUTING.md (Reproducing the CI build gate) |
contributor deep-dive |
full explanation |
AGENTS.md (Field notes → Building & running tests) |
agents |
full + measurement |
The layering is deliberate — different audiences need different depth, and the template defers to CONTRIBUTING.md. The problem is that nothing gates the three against ci.yml or against each other.
Why this is worth a gate rather than a comment
This is the exact failure mode that produced #1163. That issue existed because AGENTS.md and .github/PULL_REQUEST_TEMPLATE.md disagreed about the same command, and the disagreement went unnoticed because no check compared them. #1165 resolved the disagreement by hand — but by adding a third copy, it made the same drift structurally more likely next time, not less.
Concretely, if the build-solution job in .github/workflows/ci.yml ever changes (a new flag, a different target, a split step), all three docs silently become wrong, and the first signal is a contributor pushing a PR that fails a gate their documented command said they had already cleared.
Line-number drift already bit this once: #1163 cited ci.yml:342 for a step that had moved to :329 before the issue was filed. #1165 replaced line references with job/step-name anchors, which fixes that axis — but not the command-text axis.
Suggested fix
A unit test in tests/Reactor.Tests/Docs/ that parses the Restore and Build steps of the build-solution job out of .github/workflows/ci.yml, and asserts the documented command in each of the three files agrees with them.
There is direct precedent for reading repo files from a unit test: tests/Reactor.Tests/Docs/SwallowedErrorAuditTests.cs:33 does exactly this (const string AuditPath = "docs/specs/044/swallowed-error-audit.md"), and the repo already runs several drift gates in this style — the swallowed-error ledger, the reactor.api.txt two-copy sync, and the ReactorGallery search-index byte-compare.
The oracle should be non-vacuous: it must fail if the CI step changes and the docs don't, so the test needs to derive the expected string from ci.yml rather than hard-coding it alongside the docs. A hard-coded expectation would restate the docs and pass forever.
Notes
Summary
#1165 fixed #1163 by correcting the pre-push build command, and in doing so brought a third copy of it into the tree. The CI-repro command now appears verbatim in three places:
.github/PULL_REQUEST_TEMPLATE.mdCONTRIBUTING.md(Reproducing the CI build gate)AGENTS.md(Field notes → Building & running tests)The layering is deliberate — different audiences need different depth, and the template defers to
CONTRIBUTING.md. The problem is that nothing gates the three againstci.ymlor against each other.Why this is worth a gate rather than a comment
This is the exact failure mode that produced #1163. That issue existed because
AGENTS.mdand.github/PULL_REQUEST_TEMPLATE.mddisagreed about the same command, and the disagreement went unnoticed because no check compared them. #1165 resolved the disagreement by hand — but by adding a third copy, it made the same drift structurally more likely next time, not less.Concretely, if the
build-solutionjob in.github/workflows/ci.ymlever changes (a new flag, a different target, a split step), all three docs silently become wrong, and the first signal is a contributor pushing a PR that fails a gate their documented command said they had already cleared.Line-number drift already bit this once: #1163 cited
ci.yml:342for a step that had moved to:329before the issue was filed. #1165 replaced line references with job/step-name anchors, which fixes that axis — but not the command-text axis.Suggested fix
A unit test in
tests/Reactor.Tests/Docs/that parses theRestoreandBuildsteps of thebuild-solutionjob out of.github/workflows/ci.yml, and asserts the documented command in each of the three files agrees with them.There is direct precedent for reading repo files from a unit test:
tests/Reactor.Tests/Docs/SwallowedErrorAuditTests.cs:33does exactly this (const string AuditPath = "docs/specs/044/swallowed-error-audit.md"), and the repo already runs several drift gates in this style — the swallowed-error ledger, thereactor.api.txttwo-copy sync, and the ReactorGallery search-index byte-compare.The oracle should be non-vacuous: it must fail if the CI step changes and the docs don't, so the test needs to derive the expected string from
ci.ymlrather than hard-coding it alongside the docs. A hard-coded expectation would restate the docs and pass forever.Notes
mainas ofc9225296.CONTRIBUTING.mdinstead, reducing three copies to two. That trades a little contributor convenience (the command is no longer inline where it's read) for one less drift surface; the gate is probably the better fix either way.Build solutionCI job (missing-c Release) #1163 / Docs: make the documented pre-push build actually reproduce theBuild solutionCI job #1165 work rather than folded in, since it's a testing change and Docs: make the documented pre-push build actually reproduce theBuild solutionCI job #1165 was deliberately markdown-only.