Skip to content

chore(armory): engines.node drift-prevention gate — closes queue #31#84

Merged
jasperboerhof merged 2 commits into
mainfrom
armorer/queue-31-engines-node-drift-gate
May 13, 2026
Merged

chore(armory): engines.node drift-prevention gate — closes queue #31#84
jasperboerhof merged 2 commits into
mainfrom
armorer/queue-31-engines-node-drift-gate

Conversation

@Goosterhof
Copy link
Copy Markdown
Contributor

Summary

Closes war-room enforcement queue #31 — adds a CI-time presence gate so any future workspace package (or the root manifest) that ships without an engines.node declaration fails Gate 6 of the 8-gate pipeline. The declarations themselves landed 2026-04-22 in commit 0605d99 (root + all 10 packages declare engines.node: ">=24.0.0"); without this guard, the next package added to the Armory (fs-auth, fs-validation, future) can ship without the declaration and consumers get silent Node-version mismatches instead of EBADENGINE.

Shape — Option α (fold into scripts/lint-pkg.mjs)

Picked α over a new scripts/check-engines.mjs + 9th CI gate because the engines.node presence check sits in exactly the same domain as the existing publint suggestion-strictness wrapper (queue #33, PR #35 follow-up): both are per-manifest publish-readiness assertions over the same packages/* corpus, both share the same failures[] collection shape, and both already iterate the same loop. Folding keeps the CI gate count at 8 and the script discovery surface small.

Filename scripts/lint-pkg.mjs retained deliberately — renaming to scripts/check-packages.mjs (more accurate now that it covers two assertion classes) would force a parallel edit to the lint:pkg npm-script alias and the .github/workflows/ci.yml npm run lint:pkg step, neither of which is in scope for this PR. The expanded responsibility is documented in the script's header comment.

What this gate asserts

For every package.json in packages/*/ and the workspace root package.json:

  1. If the file is missing engines entirely → fail.
  2. If engines.node is missing or not a non-empty string → fail.

The gate is presence, not value. It does NOT enforce >=24.0.0 specifically — value alignment is a separate doctrine question tracked alongside the CI workflow's node-version. If a future bump moves the corpus to >=26.0.0, the gate does not need editing.

Smoke test — gate fires correctly

Per orders §F:

  1. Temporarily deleted the engines block from packages/storage/package.json.
  2. Ran npm run lint:pkg.
  3. Result: exit code 1, named failure surfaced:
    @script-development/fs-storage: engines field missing (queue #31 — engines.node presence required)
    
    lint:pkg gate FAILED (1):
      - @script-development/fs-storage: engines field missing (queue #31 — engines.node presence required)
    
  4. Reverted the deletion.
  5. Re-ran npm run lint:pkg.
  6. Result: exit code 0:
    lint:pkg gate PASS — 10 packages + root clean (engines.node present; publint suggestions/warnings/errors all treated as fatal).
    

Full local CI matrix — all 8 gates green

Gate Status Notes
1. npm audit PASS (exit 0) 1 high dev-dep advisory (fast-uri) pre-exists on main — not introduced by this PR
2. format:check PASS 532 files, oxfmt clean
3. lint PASS 0/0 warnings/errors, 332 files
4. build PASS 10 packages, tsdown clean
5. typecheck PASS 10 packages, tsc --noEmit clean
6. lint:pkg PASS 10 packages + root clean, engines.node assertion fires on intentional omission
7. test:coverage PASS Per-package 100% thresholds met
8. test:mutation PASS Final 93.33% ≥ 90% threshold

Files changed

Reviewer checklist

  • Diff scripts/lint-pkg.mjs to confirm the assertion is presence-only (no value validation).
  • Confirm the failure message format names the offending package (one-grep diagnosis).
  • Confirm CLAUDE.md update matches the implementation (queue Fix setById reactivity by invalidating adapted cache #31 + 2026-05-12 + commit 0605d99 reference).
  • Smoke-test result above is the proof point — feel free to reproduce locally.

References

Extend scripts/lint-pkg.mjs (Gate 6) with a per-manifest engines.node
presence assertion across the workspace root + all 10 packages. Closes
enforcement queue #31 (drift-prevention half — declarations themselves
landed 2026-04-22 via commit 0605d99).

Option α (fold into existing wrapper). Same domain as the publint
suggestion-strictness — both are per-manifest publish-readiness
assertions — so the failure aggregation, message shape, and CI gate
count (8) stay unchanged. Presence-only check; value alignment
(currently uniform ">=24.0.0") is a separate doctrine question.

Smoke test: temporarily stripped engines from packages/storage/package.json,
ran lint:pkg, confirmed exit 1 with named failure
"@script-development/fs-storage: engines field missing (queue #31 —
engines.node presence required)" and aggregate footer
"lint:pkg gate FAILED (1):"; reverted, re-ran, confirmed exit 0 with
"lint:pkg gate PASS — 10 packages + root clean".
@cloudflare-workers-and-pages
Copy link
Copy Markdown

cloudflare-workers-and-pages Bot commented May 12, 2026

Deploying fs-packages with  Cloudflare Pages  Cloudflare Pages

Latest commit: 73c39e1
Status: ✅  Deploy successful!
Preview URL: https://9467ba26.fs-packages.pages.dev
Branch Preview URL: https://armorer-queue-31-engines-nod.fs-packages.pages.dev

View logs

@jasperboerhof jasperboerhof enabled auto-merge May 13, 2026 16:44
@jasperboerhof jasperboerhof merged commit bef4895 into main May 13, 2026
2 checks passed
@jasperboerhof jasperboerhof deleted the armorer/queue-31-engines-node-drift-gate branch May 13, 2026 16:48
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants