# Golden baseline — v8 Phase 5 Reference artifacts recorded **before** any commons extraction, so that each table-by-table swap in Phase 5 can be proven behaviour-preserving (or rolled back). Generated and checked by one code path: ```bash node scripts/golden-baseline.mjs # check only, exits 1 on drift node scripts/golden-baseline.mjs --write # (re-)bless node scripts/golden-baseline.mjs --write --suite # also refresh suite counts (slow) ``` The gate is `tests/lib/golden-baseline.test.mjs`. ## The artifacts | File | What it pins | Why that layer exists | |------|--------------|-----------------------| | `patterns.json` | `.source` + `.flags` of every RegExp reachable from the walked modules' exports | After a swap a pattern is `new RegExp(jsonString, flags)`. The plan's named hazard — JSON backslash-doubling — is visible **only** on the compiled object. | | ↳ table records | key/value digest of `HOMOGLYPH_MAP`, `TYPOSQUAT_SUSPICIOUS_TOKENS`, `SEVERITY`, the four OWASP maps | Most of what Phase 4 moves is not a regex. A regex-only dump is blind to a broken homoglyph or OWASP-map swap, i.e. blind to the bulk of the payload. | | ↳ file records | sha256 of the five source files in the moving set | The completeness layer, complete **by construction**: it covers regexes inlined in function bodies (`NAMED` at `string-utils.mjs:291`, the BIDI/tag/PUA ranges at 357–404) that no export walk can reach. | | `reference-run.json` | the 61 showcase payloads through the real hook entry points, plus coverage | Byte identity over a corpus that trips a handful of patterns would prove almost nothing, so coverage is recorded and uncovered patterns are listed by name. | | `suite-counts.json` | per-file pass/fail, each file run alone | A total is unattributable, and `npm test` runs files concurrently where three timing-sensitive files flake. Running each alone is the only reproducible recording. | ## Why there is no regex enumerator The obvious design — parse the sources and enumerate every regex literal — was rejected. It needs a JS parser this zero-dependency repo does not have, and a lexical approximation is contaminated by comments and division (`severity.mjs` scores 4 "regexes" that way and exports none). The two-layer split — export walk for what the scanners actually use, file digest for everything else — answers the same question without a parser. ## During a swap A diff here means the swap changed observable behaviour. **Roll the swap back.** `--write` is for deliberately re-blessing a change you have already decided is correct, not for making the gate quiet. ## Known coverage gap The reference run exercises 47 of 83 injection patterns. The other 36 are listed by key under `coverage.uncoveredPatterns` — a swap that breaks one of those is not caught by the reference run, only by the pattern dump. That is an honest limit of the corpus, not a bug in the gate; closing it means growing the conformance corpus (Phase 5 step 5).