fix(#3840): reject a malformed feature order instead of coercing it (#3851)

* fix(#3840): reject a malformed feature `order` instead of coercing it

`scripts/gen-features.cjs` was the one field validated by coercion rather than
by shape. `Number('')` is 0, and `0x10`, `0b11`, `0o17`, `1e3`, `1.` and `.5`
all coerce to finite numbers, so a fragment declaring a bare `order:` sorted to
position 0 -- ahead of every real feature, in both the body and the generated
table of contents -- with zero violations, a clean `--check` and `--write`
exiting 0. That is a fail-open in a gate whose entire contract is a typed
violation rather than a silent guess.

`order` is now shape-checked against an optionally-signed decimal literal
before coercion, mirroring how ID_RE guards `id`. The finite check stays: the
regex alone would admit a literal long enough to overflow to Infinity.

Surfaced by re-running the feature-implementation directive's design and QA
steps against the code merged in #3845, which shipped without them.

Refs #3840

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

* chore(#3840): backfill changeset PR number

Refs #3840

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>

---------

Co-authored-by: sim <sim@local>
Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Tom Boucher
2026-08-25 08:36:33 -04:00
committed by GitHub
parent fb2d122d7f
commit 308c17505c
4 changed files with 205 additions and 3 deletions

View File

@@ -0,0 +1,5 @@
---
type: Fixed
pr: 3851
---
**A feature fragment declaring a malformed `order:` no longer sorts silently to the top of `docs/FEATURES.md`** — the generator validated that field by coercion, so an empty value read as `0` and hex, octal, binary and exponential values read as numbers, all placing the section ahead of every real feature with no violation and a clean `--check`. (#3840)