fix(scripts): parse a json doc fence strictly with parseJsonFence (objectui#10943) - #10985
Conversation
…eJsonFence objectui#10943, ruled A. `check-doc-expression-carriage.mjs` now judges a `json` fence with `parseJsonFence`, imported from `check-skill-examples.mjs`: `JSON.parse` and nothing else. `jsonc` keeps the four tolerances and the object-body retry, unchanged. Each entry on the unparsed list carries the file, the fence's opening line, its language and the parse error. For `json` the census prints the ruled remedy, 「retag as `jsonc` if the example needs comments or trailing commas」. The existing pin 'has no blind spot on the corpus it ships against' still asserts the list is empty. It now reds a pull request that adds a non-JSON `json` fence. No new script, workflow, test file or gate. The import is a guarded dynamic import(), because that module loads `typescript`. A static import would turn the orphan pin's loud instrument failure into a module-resolution stack trace. The VS Code settings fence in packages/vscode-extension/README.md needs its `//` comments, so it is retagged `jsonc`. CONTRIBUTING.md stops saying that nothing enforces the convention on the docs surface. Claude-Session: https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35U Co-authored-by: Claude <noreply@anthropic.com>
`check:entry-guard` refuses a top-level `try` in a file that exports: it is a statement that runs on import. The guarded `import()` of `check-skill-examples.mjs` is now one `const` declaration. A rejected import settles into `error` rather than throwing, and `requireJsonContract` still raises it inside the CLI's instrument check with the "A failure, not a skip" line. Claude-Session: https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35U Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
|
Standing down on one red check. It is not this PR's.
Generated by Claude Code |
Contract reviewServed-tier: Inputs: card objectui#10943 (body and all four comments — the correction The one red is not this diff's, and it blocks the landing all the same. ① Derived judgmentsRuling A's execution parameters, item by item (comment
The dynamic-import choice — RIGHT, and loud. In substance it is still 「imports Docs:
Scan surface: the strictness lands on the census's whole surface — ② Semver levelNo changeset is RIGHT. ③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
…rict-json-fence-census Claude-Session: https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35U Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
The eager closure is every chunk the entry reaches through static imports — what the browser fetches and parses before the app renders. The entry chunk on its own is a small fraction of it. 📦 Bundle Size Report
Size Limits
|
Fixes #10943
Clause-②: no — a docs-census strength change on repository tooling; no published contract, accept set or public surface changes (a contract review is still owed for the README fence retag)
What changes
This executes ruling A on objectui#10943: the maintainer's 「同意」 on 2026-09-28, recorded in the card's ruling comment
5869344478. The existing carriage censusscripts/check-doc-expression-carriage.mjsnow holdsjsonandjsoncfences to different contracts:json: parsed byparseJsonFence, imported fromscripts/check-skill-examples.mjsand not copied. That function isJSON.parseand nothing else. No tolerance, no object-body retry and no multi-document split applies.jsonc: unchanged. It keeps the four tolerances (comments, raw newlines in strings, trailing commas, elisions) and the object-body retry. The fences the blind-spot measurement reads (the languages the census does not judge) stay on that same tolerant path.jsonit prints the ruled remedy, 「retag asjsoncif the example needs comments or trailing commas」. Forjsoncit keeps the oldsanitizeFenceremedy (H3). The CLI and the pin both print this text fromUNPARSED_PRESCRIPTIONS, so the two cannot drift apart.census.unparsedis empty, and a non-JSONjsonfence now lands on that list. This adds no new script, workflow, test file or gate. The ruling's non-generalisation also holds: thejsonctolerance list is not widened, and no other fence language gains a parse check.json. A new section records the ruling, the posture above and the import mechanics. The exit-code line also names a missing contract as an instrument failure.Why the import is a guarded dynamic
import(), not a static oneThis was measured, not assumed.
check-skill-examples.mjsimportstypescriptandcheck-doc-snippet-types.mjsat load. With a static import, the orphan pin ('is LOUD when the instrument itself is broken') runs the gate with no install. The gate then dies at module link withERR_MODULE_NOT_FOUNDfortypescript, and the probe counted 0 occurrences of the asserted 'A failure, not a skip' line.So the census loads the module with one
constdeclaration holding animport()whose rejection settles into anerrorfield. A top-leveltryis refused bycheck:entry-guardas a statement that runs on import.requireJsonContract()raises the held error inside the CLI's existing instrument check. A one-off probe (renderer and installed spec present,check-skill-examples.mjsabsent) exits 1 with that line.Cost: the census now loads
typescriptat start. Measured start times were about 0.2 s for the census--self-testand about 0.45 to 0.53 s to importcheck-skill-examples.mjs.The surface under strict
json, measured before any change (H2)scanFencesover its whole surface. That surface is imported fromcheck:doc-typesand printed ascontent/docs, apps/*/docs, packages/*/README.md and README.md, so it is notcontent/docsalone.parseJsonFence(body, 'json').jsonfence failed. It is the VS Code settings example under 「⚙️ Configuration」 inpackages/vscode-extension/README.md, which uses//comments because VS Code settings files are JSONC. The README's otherjsonfence (the 「Example Schema」 one) already parses strictly. No fence was simply broken, so there is no docs bug to report.node scripts/check-doc-expression-carriage.mjson this branch prints the per-language row and names any unparsed fence.The retag in
packages/vscode-extension/README.md(for the contract review)This is a published-docs prose change, and it is the smallest one available. One info string changes from
jsontojsoncon the Configuration fence, and the body bytes are unchanged.git diffover the file shows 1 line out and 1 line in. The site pagecontent/docs/utilities/vscode-extension.mdxalready tags its settings examplejsonc, so the README now agrees with it. The other gates that read that fence's tag are green:check:doc-fencesandcheck:doc-types(see Evidence).CONTRIBUTING.md: one sentence this change made falseIts⚠️ This file is outside the claim's declared file surface. The edit was made because a statement this change makes false is owed in the same change; the report names it as a deviation.
json-fence convention paragraph said 「Nothing enforces it forcontent/docstoday」 and called whether a gate should block such a fence 「the open decision objectui#10943」. After this change, both statements are wrong. The sentence now names the census, the pin and the fact that the tolerances apply tojsonconly.Evidence
Readings are at head
33012bd4d6unless a line says otherwise. Base isdeca847a8a.json 221 (221 parsed, 0 unparsed); jsonc 15 (15 parsed, 0 unparsed).json 220 (220 parsed, 0 unparsed); jsonc 16 (16 parsed, 0 unparsed).diffof the two full census outputs differs in that one line only, so the judged findings (nodes,${…}sites, carried count, blind-spot lists) did not move. The--listinventories differ only in the retagged fence's language.--self-testexits 0 and printsControls pass.jsonfence on the real surface, with the//-comment class, planted incontent/docs/guide/expressions.mdthrough objectstack'sscripts/ablation-replace.mjsin wrap mode with its EXIT/INT/TERM restore.11fc05b98f): the pin went RED,Tests 1 failed | 58 skipped (59). The received entry was"lang": "json"with"reason": "invalid-json: Expected property name or '}' in JSON at position 4 (line 2 column 3)". The failure message began: Ajsonfence here is NOT JSON — a docs defect, not a blind spot: retag asjsoncif the example needs comments or trailing commas; …deca847a8a, a separate throwaway checkout): the identical plant left the same pin GREEN,Tests 1 passed | 46 skipped (47). The old tolerant parse read the comment away. This is the strength increase itself.git diff HEADempty. Independently,git diff --quiet HEADexited 0 and the plant marker count went back to 0.node_moduleslacked@vitejs/plugin-react), which is not a verdict. It was re-run after a realpnpm installin that checkout.pnpm exec vitest run --maxWorkers=2over 15 files passed,Test Files 15 passed (15),Tests 911 passed (911). The files are the census test,check-skill-examples.test.ts,markdown-fence-scan.test.ts(it importsscanFences),entry-guard-wiring.test.ts, and every test recorded byscripts/markdown-test-inputs.mjs --listas reading the README orCONTRIBUTING.md. The census test itself went from 47 to 59 tests.pnpm type-check:scripts.--listFilesshows it compiles the edited test.pnpm lint:root: 0 errors. All 34 warnings are in files this PR does not touch.pnpm check:doc-typesnode scripts/check-doc-fence-languages.mjs --self-testandnode scripts/check-doc-fence-languages.mjspnpm check:control-bytespnpm check:new-line-citations, with 0 new citationspnpm check:entry-guardpnpm check:pre-install-import-graphpnpm check:test-path-rootspnpm check:installed-pin-claimsnode scripts/check-doc-links.mjsnode scripts/check-governed-queue-guard.mjs --teston the 4 paths, which prints NOT GOVERNEDnode scripts/check-changeset-presence.mjs, which says no changeset is owed: the four changed files are not published source of any released packagepnpm check:readme-exports: prerequisite not met, because every package'sdist/index.d.tsis absent without a full build. This diff changes no import line in any README.pnpm check:skill-examples: not run, because its module graph is unchanged. The census imports it, and nothing it imports changed. Its test file is in the 15 above.Acceptance notes
These are recorded here and not filed.
content/docs/guide/ci-cd-pipeline.mddescribes the walk ascontent/docs/**, everyapps/*/docs/**tree and the rootREADME.md. It omits the package-README leg, which predates this PR. This change does not make that row false: the CLI it describes still exits 0 regardless. Carrier: none.CONTRIBUTING.mdconvention says a raw newline inside a string is invalid under both tags. The census'sjsonctolerance 2 re-escapes raw newlines, so ajsoncfence stays more tolerant here than the written convention. The ruling keeps that list as is. Observation only.Related: objectui#10088 · PR objectui#10942 (the repairs this lands after) · objectui#7474 (the skills-tree precedent)
Generated by Claude Code