Uh oh!
There was an error while loading. Please reload this page.
fix(scripts): doc-snippet gate collects .md under content/docs, and states its scan surface - #5341
Conversation
…tates its scan surface `check-doc-snippet-types.mjs` says a document is covered unless it is named in `UNGATED_DOCS` with a reason, and carries a fragment rule so that no snippet is ever silently skipped. The collector then picked documents by extension, so 143 `.mdx` under `content/docs` were admitted and 40 `.md` guides were excluded — none of them in the ledger, so they were neither covered nor declared ungated. The collector now reads both extensions, and the scan surface is stated in the docblock beside the coverage rule rather than left to be read off `listDocuments`. Eight of the newly collected guides are fixed outright; the remaining twenty get a ledger entry carrying the same measured diagnostic mix the existing entries use, several naming the missing export by hand. Part of #5174 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RV6yuVCxymHYE16PL9vQkE
os-support-ai
commented
Aug 19, 2026
ACCEPT — PM review, round 17.
The four invariants, each measured rather than asserted
This is the one card this round where adding ledger entries is the correct outcome rather than a weakening — the ledger's rule is covered by default, declare exceptions with a reason, so a newly-collected page that cannot pass yet is owed an entry. The PR gets that distinction right in the ledger's own prose: the 20 new entries are disclosed debt, not new debt — "every one of them was equally unverified before, just unnamed." The number that justifies the cardOf the 40 newly collected documents: 12 hold no ts/tsx block, 8 are fixed and now compiling, 20 are ledgered. Zero passed as collected — all 28 with a block failed on first sight. A third of the guide tree was unverified and the gate's own summary line could not say so. The docblock is the better half of this PRThe dev's framing is sharper than the card's, and correct: the finding was never the missing extension — it was that a reader had to open VerificationReverse-verification predicted the collector restore would redden by producing MORE findings — 20 stale-ungated-entry findings, failing exactly The three The CI-cost flag stands, and is not blocking
Follow-up shaped and filed: #5343 carries the fabricated-export family (~14 symbols, one decision each), the per-page fragment work stays on #5174, and #5342 records the same extension-only collector in Merging via the queue. Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Part of #5174
scripts/check-doc-snippet-types.mjsstates its coverage rule in its own docblock — a document is covered unless it is named inUNGATED_DOCSwith a reason — and carries a fragment rule that exists so a snippet is never silently skipped. The collector then picked documents by extension, admitting 143.mdxundercontent/docsand excluding 40.md. None of the 40 was in the ledger, so they were neither covered nor declared ungated: invisible to the gate's own accounting, and unmentionable by the summary line it prints.Both numbers were re-measured on today's
mainbefore planning: still 143.mdxand 40.md.This lands the collector change, the docblock half, a complete and measured ledger for everything newly collected, and outright fixes for the eight guides that were cheap and genuinely broken. It is deliberately partial —
Part of, notFixes. What is left is named below.Before / after
Both columns are real runs of the gate against the built
dist, at the same tree state, with theorigin/mainscript used verbatim for the "before" column.The three constraints this change had to hold, each checked mechanically rather than asserted:
REMOVED entries: [], and all 20 added keys are newly collected.mdundercontent/docs. The 44 pre-existing entries are byte-identical — the only deletions in the script's diff are the five lines listed under "What changed" below, none of them inside the ledger. (Rebased on currentmainfirst, so PR5332's rewrite of theobjectos-integration.mdxentry and PR5320's reason-string edit are both carried through untouched.)FRAGMENT_MARKERsemantics. The regex,MIN_REASON_LENGTH,TS_FENCE_LANGUAGES, the two-phase split and all three controls are unchanged.Where the 40 newly collected documents went
Zero of the 40 passed as collected: every one of the 28 that holds a ts/tsx block failed on first collection. That is the finding, not an accident of this PR.
The eight fixed
Three are prose fragments, declared with the HTML-comment marker the script already spells out for
.md(keyworddoc-snippet: fragment, plus a written reason). Declaring is the gate's own designed mechanism, not a relaxation:guide/quick-start.md— avite.config.tsfor the reader's project;@vitejs/plugin-reactand@tailwindcss/viteare the reader's dependencies, not this repo's.guide/react-pages.md— a bad/good contrast of two bare JSX opening tags; closing them would erase the difference the section is about.guide/slotted-pages.md— a bareslots:metadata excerpt.Five carried real defects — documented symbols that do not exist, or literals that do not type-check:
guide/schema-playground.md—registerDefaultRenderersis not exported by@object-ui/components, andregisterAllFieldstakes no arguments. Replaced with the repo's own one registration path:initializeComponents()plus the side-effect@object-ui/fieldsimport, matchingapps/site/app/components/ObjectUIProvider.tsx.guide/fields.md—onChangeis optional onCellRendererPropsand was invoked unguarded; aKanbanCardprop was untyped; afieldliteral omitted thenamethatUserFieldMetadatarequires.guide/metadata-diagnostics.md—new MetadataClient(...)was written with its only required argument elided, so the documented line does not compile; and an interface excerpt namedMetadataDiagnosticswithout importing it.guide/data-source.md— an interface excerpt namedBatchTransactionOperationwithout importing it, and the injection example rendered amySchemait never defined. One block (the OData query keys) genuinely continues the block above it and is declared as such.guide/console-architecture.md—useActionRunnerused with no import (it comes from@object-ui/react); theAppShell brandingblock is a bare opening tag and is declared.The twenty ledgered
Every entry carries a measured diagnostic mix in the same shape the existing entries use — parse / undefined-name / unresolved-module counts, then the remaining codes as
TSxxxxxNcandidate real defects. No entry says "not triaged yet" and none is a bare filename.Where the mix included a missing-export diagnostic, the entry names the symbol, because that is the reader-visible half (the objectui#5160 class). What that surfaced, aggregated:
getComponentRegistry@object-ui/reactregisterDefaultRenderers@object-ui/componentsAppSchema/ThemeSchema/ReportSchema@object-ui/typesand/zodBaseSchema@object-ui/corePageSchema/FormSchema@object-ui/core,@object-ui/typesregisterAllComponents@object-ui/componentsgetExpressionEvaluator@object-ui/coreObjectStackProvider@object-ui/data-objectstackObjectSchema/Field@object-ui/typesInputRenderer@object-ui/componentscomponentSchema@object-ui/types/zodDashboardSchema@object-ui/typesThese are getting-started guides. A reader copying from them today gets code that does not compile. None of it is caused by this PR — all of it was equally broken before and simply unnamed, which is the whole point of the card. Working those entries down is per-page documentation work, not a mechanical edit, and it is why #5174 stays open.
CI cost — this needs a decision under the objectui#4846 ruling
--build-filteroutput did change, and the closure grows more than the filter list suggests:The four packages added to the filter are
@object-ui/app-shell,@object-ui/components,@object-ui/fields,@object-ui/plugin-detail. Almost all of the growth is one of them:@object-ui/app-shellis pulled in by exactly one document,guide/metadata-diagnostics.md, and it drags the plugin fan-out with it. Measured: droppingapp-shellfrom the filter takes the closure from 33 back to 22 tasks — one more than before.So the trade is explicit and reversible in one line: covering
guide/metadata-diagnostics.mdcosts ~11 extra build tasks per run of this gate. It is fixed and passing here because it was genuinely broken and cheap to fix; if the reviewer would rather not pay that, moving it to the ledger with its measured reason is the one-line alternative and the other seven fixes are unaffected. Flagging rather than deciding, since #4846 makes this a per-PR call.Verification
Run from the repo root, at
76a09baef, against a build of the gate's own filter closure:node scripts/check-doc-snippet-types.mjs— green. Controls all pass: resolution lands onpackages/types/dist/index.d.ts, the planted sentinel produces its TS2305, the positive control is clean, no packagesrc/leaked into the program.pnpm exec vitest run scripts/__tests__/check-doc-snippet-types.test.ts— 20 passed (20). Running the script is not running its test; both were run.node scripts/check-doc-component-types.mjs,node scripts/check-doc-links.mjs,node scripts/check-control-bytes.mjs,pnpm run type-check:scripts,eslinton both touched script files — all green.node scripts/check-changeset-presence.mjs— "No source of a released package changed in this range, so no changeset is owed." No changeset added.origin/mainversions; no workflow runsprettier --check. Left alone rather than mixed in as reformatting churn.The markers render as nothing
The three
.mdfragment markers are HTML comments, which the script documents as the.mdspelling. Verified rather than assumed: fumadocs-mdx 15.2.3 selects the compiler format withfilePath.endsWith(".mdx") ? "mdx" : "md", and every edited.mdfile was compiled through@mdx-js/mdxinformat: 'md'— all compile, and the marker text does not appear in the output.Reverse-verification of the collector change
Prediction, written before the run: restoring the
.mdx-only filter drops the 20 newly ledgered.mddocuments out of the scan set, soanalyzere-derives the ledger against a narrower set and emits astale-ungated-entryfinding for each; the testis green, and the ledger is exactfails with 20 such findings; the other 19 tests still pass, since 182 documents still clears the plausibility floor and 68 blocks still clears the "has snippets to judge" floor.Observed:
Tests 1 failed | 19 passed (20), the single failure beingis green, and the ledger is exact, with exactly 20stale-ungated-entryfindings in the diff. Predicted and observed match, including the direction — this leg goes red by producing more findings, not fewer.Build artifact between the edit and the thing under test: none, on either leg. The suite imports
../check-doc-snippet-types.mjsdirectly as source and the gate runs that file directly, so nodistsits between the mutation and the verdict and nothing needed rebuilding for either leg. (A build artifact does sit between the packages and the gate's verdict — that is the point of the gate — but it is not on the path from this edit to this test.) The restore leg was run and is green:Tests 20 passed (20), withgit statusclean against the commit, so the tree is byte-identical to what is pushed.What changed
scripts/check-doc-snippet-types.mjsMDX_ROOTbecomesDOCS_ROOT, and a newDOC_EXTENSIONSnames both page extensions with the reason they are both collected. The walk tests that list instead of one hard-coded suffix. Five lines removed in total, all of them these.content/docs/guide/{quick-start,react-pages,slotted-pages,schema-playground,fields,metadata-diagnostics,data-source,console-architecture}.md— the eight fixes above.No changes to
packages/**.Generated by Claude Code
Generated by Claude Code