GENERATED VIEW · PRIVATE ARCHIVE · DO NOT SERVE
RobCo Industries · Archive Museum

ci-node-parity.md



MEMORY

memory/localmode-1060dea9-0dc3-42b4-958d-2a6f7a6c0c58/ci-node-parity.md

sha256 563e19c46b182af2 · 3535 bytes · original held in the private archive

--- name: ci-node-parity description: "Why CI runs a Linux+Windows matrix off ONE .nvmrc — the reasoning, the EOL-runtime incident, and the branch-protection trap that renaming CI checks creates. Current versions/check names live in .nvmrc and the workflow files." metadata: node_type: memory type: project originSessionId: 0b7c5f41-bb34-4ab4-93be-fdb363f5eb40 --- *Rewritten 2026-07-20: version numbers, commit hash, test count and status-check names removed — all derivable from `.nvmrc`, the workflow files, git log and GitHub settings. The reasoning below is what memory is for.* ## ⭐ THE REFRAME THAT JUSTIFIED WINDOWS CI **The owner develops on WINDOWS. Every gate he has ever run — every commit, every push — was on Windows. So the "independent" Linux CI was validating a platform NOBODY develops on. Windows CI isn't exotic; it's the job that finally matches reality.** **Strongest single justification:** it is the one environment that would catch an **encoding regression** (the project has a real history of Windows tooling double-encoding non-ASCII source) or a **line-ending/CRLF break**. Both passed clean on a real Windows runner — proof, not assertion. **Cost: effectively zero.** The repo is PUBLIC → CI minutes are free and unlimited. Windows is slower than Linux per run, but the two run **in parallel**, so nothing waits longer. **Cross-platform check that made it safe:** the gate is pure Node; the only Bash is the local git hooks, which CI never uses. ## THE INCIDENT THAT DROVE IT CI had been pinned to a Node version that had already reached **end-of-life**, in *three separate* workflow files, while the owner's local machine ran something much newer. **CI was running an out-of-support runtime for months and nobody was looking.** The skew existed because the version was declared in more than one place. **Node's role here is TEST-RUNNER ONLY** — RobCo is vanilla/no-build, so Node never touches a line of shipped code. The version choice is therefore about **tooling support lifetime**, not app compatibility. That framing is what made the decision small. **The fix, and the rule it leaves behind: ONE authoritative declaration (`.nvmrc`), read by local dev and every workflow. They can no longer drift, because there is only one copy.** Pick the version on support status, never "because it was already installed locally." **Matrix, not duplication:** CI is one job definition run across OSes, not a copied second job. The full gate runs on BOTH OSes, unweakened — not a subset. ## ⚠ THE BRANCH-PROTECTION TRAP (incident 2026-07-13) Converting CI to a matrix **renames its status checks**. `main`'s branch protection still required the OLD check name — which would have **blocked the next `dev → main` release forever, waiting on a check that can never exist again.** `dev` is unprotected, so the change itself landed fine and the trap was invisible until release time. **Standing rule: any change that renames a CI job/check must be paired with updating `main`'s required checks in GitHub Settings — and only the owner can do that.** Flag it to him at the time; don't let it be discovered at the release. ⚠ **This is NOT a laptop outcome and must never be described as one.** It fell out of the (rejected) laptop evaluation but stands entirely on its own — see [[local-ai-delegation-verdict]] for both rejected hardware experiments. Related: [[robco-uos-project]], [[deep-systems-review-2026-07-13]] (the gate's blind spots), [[self-improving-code]].
STAMP · generated for RELEASE v2.8.5 commit 06e5180 (06e51801b38a) · archive input-tree hash c07fbfbdd2e1ddeb · 754 files · no wall-clock timestamp (regenerates identically when nothing changed).