llm-security/tests/fixtures
Kjell Tore Guttormsen b1ba1fbdc6 refactor(llm-security): v8 Phase 5 step 4 - swap codepoint tables to commons
First consumer swap of step 4. ZERO_WIDTH_CHARS (5), the Unicode Tag range,
BIDI_CHARS (9) and HOMOGLYPH_MAP (28) stop being hardcoded constants in
unicode-scanner.mjs and string-utils.mjs and are built from the vendored
commons artifact codepoints/carriers.json by the new lib/codepoints.mjs.

Started here rather than at injection-patterns, which the plan ordered first:
that table is the one table that cannot be loaded verbatim (the
hybrid-xss:script-tag divergence is directional, and loading the lexicon as-is
would reverse the 90f576f recall fix). The codepoint tables were measured
byte-equal to the source constants BEFORE the swap - same members, same
values, same insertion order on HOMOGLYPH_MAP - so they load verbatim.

Proof the swap is content-preserving: the golden dump differs in exactly one
record, the sha256 of string-utils.mjs, which changes by construction when a
table leaves the file. All 83 regex records and the
table:string-utils:HOMOGLYPH_MAP digest are byte-identical, and
reference-run.json is unchanged at 61/61. patterns.json is re-blessed for the
file digest alone.

The gate is proven red-capable against the SUBJECT, both directions:
- dropping U+00AD from the vendored zero_width table fails the new
  codepoints gate by name, twice;
- altering one homoglyph value reddens the golden table digest AND a
  behavioural homoglyph test.
That second direction is a property the swap creates rather than preserves:
the golden gate now transitively pins the vendored commons data, where before
it pinned a source literal and a commons mutation was invisible to it.

NOT ported: commons carries cyrillic_confusables (13), and unicode-scanner.mjs
declares a set by that name - but nothing reads it. The homoglyph-mixing
detector tests isCyrillic(cp), the whole U+0400-U+04FF block. Loading it would
move dead data into the load path, so the dead const stays where it is and is
recorded instead. The recorded v8.x-B i/x drift between that set and the
lexicon class is therefore latent, not live. commons' private_use table has no
constant behind it here at all.

Graceful-empty is kept deliberately: codepoints.mjs is on string-utils'
import path and hooks import string-utils in fresh per-tool-call processes, so
a module-load throw would break the tool call rather than degrade the scan.
The loud half is the test, which asserts exact per-table counts through the
real default commons root - the same shape as the lexicon load-assertion.

Drive-by, unavoidable: the deleted JSDoc carried the "~25 entries" claim for a
28-entry table (v8.x-C). It needed a re-bless of the same file digest this
swap already forces, so it closes here at no extra cost.

Suite 2158 -> 2164, all green.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X7XEEFrAJsREqa9N4tpfm8
2026-08-10 21:28:09 +02:00
..
ast-scan fix(llm-security): AST-taint clears taint on reassignment (#29) + sink test coverage (#28) 2026-07-18 10:14:51 +02:00
commons-empty/codepoints refactor(llm-security): v8 Phase 5 step 4 - swap codepoint tables to commons 2026-08-10 21:28:09 +02:00
dep-test feat(ultraplan-local): v1.6.0 — /ultraresearch-local deep research command 2026-04-08 08:58:35 +02:00
entropy refactor(entropy): B5 — two-stage context-classified suppression pipeline 2026-04-29 15:13:13 +02:00
ide-extensions test(llm-security): add JetBrains fixture tree + build helper 2026-04-18 10:49:49 +02:00
memory-scan fix(memory-poisoning): E15 — add .claude/agents/*.md to target glob 2026-04-29 14:13:01 +02:00
posture-scan feat(llm-security)!: v8 Phase 3 complete - riskScoreV1, posture heuristic, docs 2026-08-09 10:25:03 +02:00
signature-scan feat(llm-security): add SIG signature scanner with decode-pipeline matching 2026-06-20 09:28:52 +02:00
skill-scan/hyperframes-like test(llm-security): hyperframes-like fixture for narrative coherence 2026-04-29 12:49:19 +02:00
supply-chain fix(llm-security): v8 Phase 1 — Berry lockfile, nested-v1 recursion, per-occurrence strip attribution 2026-08-02 21:10:47 +02:00
transcripts test(hooks): cover pre-compact-scan happy-path, modes, size-cap 2026-04-17 14:44:52 +02:00
trigger-scan feat(llm-security): add TRG trigger-abuse scanner 2026-06-20 09:19:54 +02:00
workflows fix(llm-security): YAML/workflow parser divergence — block scalars + bare if: (#32,#33,#43) 2026-07-18 10:35:56 +02:00