Repository navigation
docs: every json fence under content/docs parses; annotated ones are jsonc (objectui#10088) - #10942
Conversation
…e `jsonc`
A `json`-tagged fence is what a reader copies into a metadata file, so it
must survive `JSON.parse`. The convention applied is the one
`scripts/check-skill-examples.mjs` (`parseJsonFence`) already states for the
skills tree: `json` parses strictly; `jsonc` is JSON plus comments (and
trailing commas), one document per fence.
- raw newlines inside a `${...}` string: the expression moves onto one line
(no JSON dialect admits a raw newline in a string);
- several documents in one fence (bad/good pairs): one fence per document,
the `//` label becomes the line above it;
- `[...]` / `"..."` elisions: removed, leaving an empty list or the bare node;
- a package.json member excerpt: wrapped in braces;
- a comment that carries information the page states nowhere else (a file
name, a member annotation, a counter-example's error): the fence is
retagged `jsonc`; comments the page already states are dropped.
page-actions-refusal-7926.test.ts pinned layout.md's four unparseable
elided fences as its blind spot; the count is zero now, so those four page
nodes are judged by that census.
Refs objectui#10088
Claude-Session: https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35U
Co-authored-by: Claude <noreply@anthropic.com>
The only source file the branch touches is a test in @object-ui/types. Claude-Session: https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35U Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35U Co-authored-by: Claude <noreply@anthropic.com>
|
changeset-claim-re-read
|
✅ 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
|
Contract reviewServed-tier: Inputs: card #10088 (body and both comments), PR #10942 (body, file list, net diff against Check-runs on the head (the gate verdicts): all 43 completed, none failed — 40 ① Derived judgmentsEach fence, judged on whether it still teaches what its page says it teaches.
The The moved test pin — Accept set and public surface: no non-test ② Semver level
③ Boundary flags
Implemented-by: VERDICT: FAIL One commit closes it: the CONTRIBUTING.md paragraph named in ①. Every other judgment on this head is right and the re-review is a diff of that one file. Generated by Claude Code |
Claude-Session: https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35U Co-authored-by: Claude <noreply@anthropic.com>
…uthors read it One paragraph under "Writing Documentation", beside the SPECIMEN-to-plaintext fence rule. It says a `json` fence must pass strict JSON.parse, annotation goes under `jsonc`, how to rewrite the shapes no JSON dialect admits, that the skills tree enforces the same contract (`parseJsonFence`), and that nothing enforces it for content/docs today; objectui#10943 is the open decision on a gate. 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
|
Contract reviewServed-tier: Inputs: card #10088 (body and all three comments: the claim, the round-0 report, the REWORK 1 report), PR #10942 (body, all three comments including the earlier Check-runs on the head (the gate verdicts): 42 check-runs on What moved since the earlier record's head ① Derived judgmentsThe ten files judged on the earlier head — every per-fence judgment there (retags to The new CONTRIBUTING.md paragraph, claim by claim against this tree:
The earlier record's failing item — is it met? Yes. The convention is now stated where a Accept set and public surface: unchanged from the earlier head — no non-test ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS Generated by Claude Code |
Fixes #10088
Clause-②: no — published docs examples and a repo gate; no accept set or public contract surface moves
Every
json-tagged fence undercontent/docsnow survivesJSON.parse. A fence that annotates JSON with comments is taggedjsonc, and it parses under that dialect too. No gate script and no workflow changed. Whether a gate should block on this is raised as its own decision in the report, not landed here, as the card's acceptance asks.The convention (named, not invented)
It is the contract
scripts/check-skill-examples.mjsalready states inparseJsonFencefor the skills tree (objectui#7474 brought that corpus to "parses under its own tag"):json—JSON.parseand nothing else. It is what a reader copies into a.jsonmetadata file.jsonc— comments (and trailing commas) removed, then one JSON document. The tag tells the reader that the fence carries annotation, which is how a deliberate note is told apart from a mistake. Ajsonfence that does not parse is a mistake..... Those shapes become one-line strings, one fence per document, and removed elisions.Per fence (lines at the base commit
733fd5ac65)guide/deployment.md:277//file-name caption (railway.json (excerpt))jsoncguide/expressions.md:223//member note ('item' is scoped data)jsoncguide/expressions.md:337${…}stringjsonguide/expressions.md:351${…}stringjsonguide/expressions.md:364${…}stringjsonguide/expressions.md:380${…}stringjsonguide/expressions.md:529// ❌ Badlabel, one document, then a dangling// ✅ Goodlabel for the tsx block belowjsonguide/expressions.md:673//labelsjson×2guide/expressions.md:687json×2guide/expressions.md:701json×2guide/layout.md:237//member comment +[...]maxWidth),[...]changed to[]jsonguide/layout.md:507[...][]jsonguide/layout.md:660//comments +[...]paddingdefault),[]jsonguide/layout.md:743//comment +[...][]jsonguide/schema-rendering.md:273${…}stringjsonplugins/index.md:355//standing for the elided keys ("on the node itself")jsoncutilities/runner.mdx:213package.jsonmember excerpt (an object body)jsonutilities/runner.mdx:246//for elided keys ("not apropsenvelope")jsoncutilities/runner.mdx:292"..."elision membersjsonutilities/runner.mdx:496//file-name captionjsoncutilities/vscode-extension.mdx:187// ❌ Error: Unknown property, the counter-example's pointjsoncguide/troubleshooting.md:369jsoncfence holding three documents, rejected by bothparseJsonFence(…, 'jsonc')andjsonc-parserjson×3The last row is outside the
jsonpopulation. It is in the claim's file surface and is the same defect class: its tag's grammar rejects its body. It gets the same mechanical split as rows 8–10, so the convention holds for the whole ofcontent/docswith no exception.The premise, re-measured
The instrument walks
git ls-files content/docs(.md/.mdx), pairs fences with the repo'sscripts/markdown-fence-scan.mjs, and runs strictJSON.parseon every fence whose language is exactlyjson. Controls run in the same command:{"a":1,}is REJECTED and{"a":1}is ACCEPTED.733fd5ac65: 184 files, 203jsonfences, 21 failing. The PM probe's 209 / 24 also counted the sixjsoncfences, three of which fail a strict parse.fields/location.mdxandguide/record-edit-modes.mdare correctly taggedjsoncand parse under it (both instruments).guide/troubleshooting.mdis the+row above.jsonfences, 0 failing; 11jsoncfences, 0 failing underparseJsonFence(…, 'jsonc')and underjsonc-parser(with the error list read). Controls: a comment is ACCEPTED, while[...]and two documents are REJECTED by both.Why the one existing gate was not tightened
The gate that reads these fences is
scripts/check-doc-expression-carriage.mjs, which is report-only. It normalises away five shapes the 21 used, not two: comments, raw newlines, elisions, the object-body retry, and several top-level documents. It treatsjsonandjsoncalike. At the base commit it printed231 json/jsonc fence(s), 231 parsed, 0 UNPARSED (1 parsed as an object body). I left it alone for two reasons:${…}carriage inside annotated fences, and "reaches 0 unparsed over the whole tree, which takes four tolerances beyondJSON.parse". The card says the same thing: "Not a defect in that gate — it was built for a different question".check-doc-expression-carriage.test.ts› "has no blind spot on the corpus it ships against" assertscensus.unparsedis empty on the real tree. That test runs on every pull request that touchescontent/docs:node scripts/markdown-test-inputs.mjs --changed -lists all eight pages this PR touches, so the test job inci.ymlruns everything. Parsingjsonstrictly would therefore make a non-JSONjsonfence block the merge. The card's acceptance covers exactly this: "if the answer is 「it should」, that is raised as its own decision rather than landed inside this card". The report raises it.After the change, the census reads the same content. It printed
417 node(s) … 68 ${…} site(s) … 65 of them carriedbefore and after, and the three findings are identical apart from line numbers. The fence count went from 231 to 236 (json 221 → 221, jsonc 10 → 15), and nothing is parsed as an object body any more.The one test that changed, and a mutation that shows it can fail
packages/types/src/__tests__/page-actions-refusal-7926.test.tspinnedguide/layout.md's four unparseablejsonfences (the[...]elisions) as its blind spot, by exact count. That count is now zero. So the census judges those fourpagenodes (noactions, content underchildren) instead of skipping them. An unparseablejsonfence on that page was already red before, as 5 against the pinned 4, so the pin is no stronger or weaker than it was.Mutation, run with objectstack's
scripts/ablation-replace.mjsfrom the committed headf957ff9252: anchor"children": []hit ×1 and was replaced by"children": [...](anchor 1 → 0, blob570a150066be → c26fd61cea62). The pin then failed withAssertionError: expected [ Array(1) ] to deeply equal [], namingcontent/docs/guide/layout.md:660(Tests 1 failed | 10 passed). Restored withblob == HEAD (570a150066be) and git diff HEAD is empty.Local verification (final head
f1edd2dd3d, after mergingorigin/main29c76e573c)pnpm exec vitest runover the 25 testsscripts/markdown-test-inputs.mjsnames as readers of the touched pages, plus 5 grep-found neighbours:Test Files 30 passed (30),Tests 1173 passed (1173), run under the verify lock.pnpm --filter @object-ui/types type-check: exit 0.tsc -p tsconfig.test.json --listFileslists the changed test (1 hit).check:doc-fences,check:doc-types,check:doc-example-ids,check:doc-example-readers,check:control-bytes,check:new-line-citations(0 new citation(s)) anddocs:check-links: all exit 0.node scripts/check-changeset-presence.mjs: exit 0, with an empty-frontmatter changeset for the onesrc/test file.check-changeset-no-major: exit 0.node scripts/check-doc-expression-carriage.mjs: exit 0,236 … 236 parsed, 0 UNPARSED,Blind spot: none.check:doc-snippets,check:doc-examples. Reason:THE GATE COULD NOT RUN, because 34 packages are unbuilt in this worktree. The narrowing was measured instead: across the 8 touched pages,scanFencesfromcheck-doc-snippet-types.mjsreturns the same 52 ts/tsx/typescript blocks at the base and at the head. Body, quote depth and fragment-marker binding are all unchanged (28 are fragment-declared). A control confirms that a detached marker reads as changed. CI runs both gates in full.Acceptance notes (observations, not filed)
packages/vscode-extension/README.md:125is ajsonfence with//comments (VS Code settings are JSONC). It sits on the carriage surface, outsidecontent/docs, and is the only json/jsonc fence there that fails under its own tag. Carrier: none.guide/layout.mdteachesmaxWidthandpaddingon apagenode. A source grep ofrenderers/layout/page.tsxfinds noschema.maxWidthorschema.paddingread, but AGENTS.md says a grep zero cannot answer "no renderer reads this key", so this is unmeasured, not asserted. Carrier: none.guide/schema-rendering.md's Memoization claim is the card's unmeasured neighbour. It is still unmeasured: this PR did not take a reading in either direction.content/docs, the test job's decision step readsmarkdown-test-inputs.mjsand runs everything.Session:
https://claude.ai/code/session_01EBx9rvB7dufCz4at53x35UGenerated by Claude Code