Finding
The documented developer environment is held together entirely by strings that
name something in another file, and no test reads any of them.
README.md:40 and CONTRIBUTING.md:15 both document the devcontainer as a
supported way to run this site, and CONTRIBUTING.md:8 states the Node
prerequisite. Those three claims point at .devcontainer/devcontainer.json,
which pins its own Node major, its own forwarded port and its own
postCreateCommand — none of which is checked against anything. The Justfile
is in the same position: 7 npm run targets, zero gates.
Verified at 00b44df, node v26.8.2, 2026-09-20. All of it happens to be
consistent today. Nothing keeps it that way:
| string |
lives in |
points at |
checked by |
NODE_VERSION: '22' x3, node-version: 22 |
.github/workflows/*.yml |
the runtime CI uses |
— |
"node": { "version": "22" } |
.devcontainer/devcontainer.json |
the runtime contributors use |
— |
Node.js 22+ |
CONTRIBUTING.md:8 |
the runtime contributors install |
— |
"forwardPorts": [3000] |
.devcontainer/devcontainer.json |
the dev-server port |
— |
"postCreateCommand": "npm install" |
.devcontainer/devcontainer.json |
npm |
— |
7 npm run <name> |
Justfile |
package.json scripts |
— |
15 npm run <name> |
README.md, CONTRIBUTING.md, AGENTS.md |
package.json scripts |
— |
The failure mode is quiet and lands on contributors, not on CI: rename a
package.json script and just build, the README quickstart and the
CONTRIBUTING setup block all become instructions that fail on first
copy-paste, while every CI check stays green. Bump NODE_VERSION in the
workflows and the devcontainer silently keeps building on the old major, so a
contributor reproduces neither CI's successes nor its failures.
Why the existing gates do not cover it
ci.yml runs npm run test:unit and npm run build:production. Neither
reads the Justfile, .devcontainer/, or a fenced command block.
npm run check is prettier + markdownlint + cspell + markdown-link-check.
None of them resolves an npm run target or a Node version; markdownlint
does not look inside a fenced block's contents.
docusaurus build never sees any of these files.
Disjointness from open PRs
Recommendation
No production change is needed: the contract currently holds.
Priority
- Impact: medium — silent breakage of the documented contributor onboarding path
- Effort: low — one test file, no new dependency
Filed by quality agent (hold-gated mode)
— hive: agent=quality backend=copilot model=claude-opus-5
Finding
The documented developer environment is held together entirely by strings that
name something in another file, and no test reads any of them.
README.md:40andCONTRIBUTING.md:15both document the devcontainer as asupported way to run this site, and
CONTRIBUTING.md:8states the Nodeprerequisite. Those three claims point at
.devcontainer/devcontainer.json,which pins its own Node major, its own forwarded port and its own
postCreateCommand— none of which is checked against anything. TheJustfileis in the same position: 7
npm runtargets, zero gates.Verified at
00b44df, node v26.8.2, 2026-09-20. All of it happens to beconsistent today. Nothing keeps it that way:
NODE_VERSION: '22'x3,node-version: 22.github/workflows/*.yml"node": { "version": "22" }.devcontainer/devcontainer.jsonNode.js 22+CONTRIBUTING.md:8"forwardPorts": [3000].devcontainer/devcontainer.json"postCreateCommand": "npm install".devcontainer/devcontainer.jsonnpm run <name>Justfilepackage.jsonscriptsnpm run <name>README.md,CONTRIBUTING.md,AGENTS.mdpackage.jsonscriptsThe failure mode is quiet and lands on contributors, not on CI: rename a
package.jsonscript andjust build, the README quickstart and theCONTRIBUTING setup block all become instructions that fail on first
copy-paste, while every CI check stays green. Bump
NODE_VERSIONin theworkflows and the devcontainer silently keeps building on the old major, so a
contributor reproduces neither CI's successes nor its failures.
Why the existing gates do not cover it
ci.ymlrunsnpm run test:unitandnpm run build:production. Neitherreads the
Justfile,.devcontainer/, or a fenced command block.npm run checkis prettier + markdownlint + cspell + markdown-link-check.None of them resolves an
npm runtarget or a Node version; markdownlintdoes not look inside a fenced block's contents.
docusaurus buildnever sees any of these files.Disjointness from open PRs
tests/workflow-scripts.test.mjs) scopes itself explicitly topackage.json<->scripts/<-> linter dotfiles <->npm runsteps in.github/workflows.gh pr diff 278contains noJustfile,.devcontainer,README.md,CONTRIBUTING.mdorAGENTS.mdmatch, and noNode-version assertion.
permissions:blocks. This readsworkflows for exactly one other key,
node-version/NODE_VERSION.*.md; this reads theshell commands inside fenced blocks, not links.
check:links/check:markdownwiring.Recommendation
tests/dev-environment.test.mjs(one new test-only file, 8 tests),asserting the eight invariants above in both directions. It is green at
00b44df— this is a guard against future drift, not a bug report — andevery assertion has been mutation-checked to fail on injected drift.
No production change is needed: the contract currently holds.
Priority
Filed by quality agent (hold-gated mode)
— hive: agent=quality backend=copilot model=claude-opus-5