Fix #112: recover 328 replacement characters in the registries, and guard the data files - #114
Merged
Merged
Conversation
…uard data files Fourteen registry files carried 328 U+FFFD replacement characters, mostly where an em dash belongs. They ship: the registries go out in the npm package, in docs/frameworks-registry.js and in the OSCAL/STIX exports. Every character is recovered from the source text rather than assumed. The registries were extracted from the mapping rows, so for each corrupted string the text either side of the character is looked up in the Markdown and the entry JSON, and the character that sits between them is read off. A character is taken only when every match agrees; the window narrows from 24 to 8 characters when a description concatenates several rows, and keeps the raw slice when only one word follows, since trimming to a word boundary could otherwise empty it. All 328 resolved, every one to U+2014. None was guessed, and no other character was found. The guard from T-ACC06 only ever read Markdown, which is why this sat unnoticed. It now also reads data/frameworks/*.json, data/entries/*.json and data/*.json, checking for U+FFFD alone — the arrow heuristic is tuned for prose and diagrams, not JSON. Negative-tested: a replacement character injected into soc2.json fails validation, naming the file and line. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #112. Item 2 of the three follow-ups.
What was wrong
Fourteen files under
data/frameworks/carried 328 U+FFFD replacement characters, across 176 fields:These ship — the registries go out in the npm package, in
docs/frameworks-registry.js, and in the OSCAL/STIX exports.Recovered, not guessed
The registries were extracted from the mapping rows, so the same sentence usually survives intact in Markdown. For each corrupted string the text on either side is looked up in the mapping files and entry JSON, and the character that sits between them is read off the source. A character is accepted only when every match agrees.
Two refinements were needed, both visible in the run:
Result: 328 of 328 resolved, every one to U+2014 (—). Nothing was assumed, and no other character was found in any position.
Guard
The encoding guard from T-ACC06 only ever read Markdown — which is exactly why this sat unnoticed through every prior run. It now also reads
data/frameworks/*.json,data/entries/*.jsonanddata/*.json, checking for U+FFFD only: the arrow heuristic ("A ? B") is tuned for prose and diagrams and would misfire on JSON.Negative-tested: a replacement character injected into
soc2.jsonfails validation with the file and line number; removing it passes.Verification
node scripts/validate.js: 0 errors, 87 warnings, 327 passed (one new check).npm run test:scripts: 85 passed, 0 failed.data/.docs/frameworks-registry.jsregenerated; stats current.🤖 Generated with Claude Code