CI runs Node 20 and CONTRIBUTING.md says to pin Node 20 locally, but
nothing enforces it: there is no .nvmrc, and the root package.json declares no engines.
A contributor on Node 18 or 22 gets to find out the hard way.
The fix
- Add
.nvmrc at the repository root containing 20.
- Add
"engines": { "node": ">=20 <21" } to the root package.json — match the range CI
actually uses rather than inventing one.
This one teaches you how the repo governs itself
The repository root is strictly governed. .nvmrc is not in allowedFiles in
.harness/scripts/ci/03-validate-root-cleanliness.mjs, so adding the file alone makes that
guard fail with "Unauthorized file found in root". Add it to that allowlist in the same pull
request, next to the entries that are already there.
That is deliberate: nothing arrives at the root of this repository without someone deciding it
should be there.
Done when
node .harness/scripts/ci/03-validate-root-cleanliness.mjs passes with .nvmrc present.
What is not your problem
This repository runs a large number of governance checks against itself. If one goes red on
your PR for a reason unrelated to your change, say so in a comment and a maintainer will sort
it out — do not try to fix the harness to get green. Specifically not yours: anything under
.harness/scripts/ci/ reporting on the gap board, ADR registry, maturity or coverage floors;
Governance guards; release-pipeline and provenance failures; and bilingual findings on
documents outside the sixteen-file entry surface (ADR-0126).
New here? CONTRIBUTING.md has the setup. Short version: fork, npm install,
npm run build. Commits need a Signed-off-by line — git commit -s, and a hook adds it if
you forget.
CI runs Node 20 and CONTRIBUTING.md says to pin Node 20 locally, but
nothing enforces it: there is no
.nvmrc, and the rootpackage.jsondeclares noengines.A contributor on Node 18 or 22 gets to find out the hard way.
The fix
.nvmrcat the repository root containing20."engines": { "node": ">=20 <21" }to the rootpackage.json— match the range CIactually uses rather than inventing one.
This one teaches you how the repo governs itself
The repository root is strictly governed.
.nvmrcis not inallowedFilesin.harness/scripts/ci/03-validate-root-cleanliness.mjs, so adding the file alone makes thatguard fail with "Unauthorized file found in root". Add it to that allowlist in the same pull
request, next to the entries that are already there.
That is deliberate: nothing arrives at the root of this repository without someone deciding it
should be there.
Done when
node .harness/scripts/ci/03-validate-root-cleanliness.mjspasses with.nvmrcpresent.What is not your problem
This repository runs a large number of governance checks against itself. If one goes red on
your PR for a reason unrelated to your change, say so in a comment and a maintainer will sort
it out — do not try to fix the harness to get green. Specifically not yours: anything under
.harness/scripts/ci/reporting on the gap board, ADR registry, maturity or coverage floors;Governance guards; release-pipeline and provenance failures; and bilingual findings ondocuments outside the sixteen-file entry surface (ADR-0126).
New here? CONTRIBUTING.md has the setup. Short version: fork,
npm install,npm run build. Commits need aSigned-off-byline —git commit -s, and a hook adds it ifyou forget.