Uh oh!
There was an error while loading. Please reload this page.
docs(guides,tooling): clear ten .md pages off the doc-snippet ledger (#5174 batch 1) - #5951
Merged
Merged
Conversation
…pages Part of #5174 Make every ts/tsx block in these pages either compile against the built dist/ types or carry a fragment declaration with a written reason. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PQ3NihCHE9LUtHoGxo6A9f
Part of #5174 Batch 1 of the UNGATED_DOCS triage: the cheapest ten of the nineteen .md guide entries, chosen by measured total diagnostic count. Each page reaches zero the two honest ways - a block that should compile is made self-contained against the built dist/, a block that genuinely cannot compile carries a FRAGMENT_MARKER declaration with a written reason - and its ledger entry is then deleted. Covered set 159 -> 169 documents; ledger 63 -> 53 entries; zero entries added and no previously-covered document became ungated. Nothing about the gate's strictness moved: everything from the 'Fence scanning' banner to EOF is byte-identical to origin/main. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01PQ3NihCHE9LUtHoGxo6A9f
os-warren
marked this pull request as ready for review
August 24, 2026 04:48
Uh oh!
There was an error while loading. Please reload this page.
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 freeto 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.
Part of #5174
Batch 1 of the
UNGATED_DOCStriage. Ten.mdguide pages leave the ledger; nine stay, with their measured reasons untouched. No gate strictness moved, no entry was added, and no previously-covered document became ungated.Two measurements that re-scope the card before anything else
1. The remaining
.mdguide population is 19, not 51. The dispatch and #5174's deferral note both read "51.mdguides" off the 63-entry ledger. That figure counts every entry whose filename ends in.md, which sweeps in 32packages/*/README.mdentries. Split by where they live:origin/main@baac3f4content/docs/**/*.md— the guide tree, this card's surfacepackages/*/README.md—.md, but not guidescontent/docs/**/*.mdxSo this batch of ten is over half the actual population, not a fifth of it. The 63 total was exactly right; only its
.mdsplit was not.2. The "mechanically clearable now that #5343 landed" assumption is falsified — measured, not assumed. Compiling all 19 pages in one program against the built
dist/produces zeroTS2305/TS2724/TS2614— not one fabricated-export diagnostic anywhere in the guide tree. #5343 (PR #5364) cleared that class completely, and the gate's own docblock already says so: "No entry on this list names a missing export any more." There is nothing left for an already-made symbol decision to be applied to. Every remaining diagnostic is per-page fragment / self-containment judgement, plus a handful of genuinely wrong documented APIs. Per the dispatch's own rule for that outcome the batch stays small; it is ten rather than eight only because the two extra pages measured cheap.⛔ No fabricated symbol was re-decided per page. One decision genuinely outside #5343's table came up and is called out below.
Selection rule: cheapest-first by measured total diagnostic count
Every one of the 19 pages was compiled first, in a single program that reuses the gate's own
analyze()/compileSnippets(), and ranked by total diagnostics. The ten lowest were taken. That rule is defensible on its own terms — it maximises entries removed per unit of review — and it is reproducible: rerun the harness and you get the same ten.Calibration for that harness: it reproduces the ledger's recorded mixes exactly for 17 of the 19 pages, which is what makes the before column trustworthy. (The two that differ are noted at the bottom.)
Cleared — ten entries deleted, 90 diagnostics gone
content/docs/api/schema-reference.mdcontent/docs/plugins/index.mdcontent/docs/guide/architecture-overview.mdcontent/docs/guide/deployment.mdcontent/docs/guide/schema-overview.mdcontent/docs/guide/notifications.mdcontent/docs/guide/public-forms.mdcontent/docs/guide/troubleshooting.mdcontent/docs/guide/expressions.mdcontent/docs/guide/user-state-persistence.mdEach page reached zero the two honest ways, never a third: a block that should compile was made self-contained against the built
dist/, and a block that genuinely cannot compile got aFRAGMENT_MARKERdeclaration carrying a written reason. ⛔ Nothing was cleared by loosening what "covered" means.Left — nine entries, reasons untouched
content/docs/guide/plugins.mdcontent/docs/guide/building-crud-app.mdcontent/docs/rfcs/0001-clipboard-paste.mdcontent/docs/guide/architecture.mdcontent/docs/guide/plugin-development.mdcontent/docs/guide/schema-rendering.mdcontent/docs/guide/theming.mdcontent/docs/guide/layout.mdcontent/docs/guide/component-registry.md274 diagnostics across nine pages — two batches' worth, and
layout+component-registryare 104 between them.The four invariants, measured
Computed by diffing the ledger key sets programmatically —
origin/main's copy of the script and this branch's copy, both run over the same working tree, so the covered-set delta is attributable to the ledger alone.ADDED ledger entries: []·previously-covered docs now UNGATED: []// ── Fence scanningbanner to EOF is identical toorigin/main—scanFences,listDocuments,derivePackageTypePaths,analyze,compileSnippets, the reporting andmain.FRAGMENT_MARKER+MIN_REASON_LENGTHdiffed separately and also byte-identical.DOC_EXTENSIONS,TS_FENCE_LANGUAGES,COMPILER_OPTIONSand all three controls unchanged.REMOVED entries:(the ten deleted, verbatim from the diff):The script diff is 11 insertions, 60 deletions: the ten entries, plus the ledger docblock's own count, which said "19 of these entries are
.mdpages" and would have been false the moment these landed.CI cost under the #4846 ruling: the closure does not grow
--build-filteroutput did change — 15 → 19 filters, adding@object-ui/auth,@object-ui/i18n,@object-ui/plugin-form,@object-ui/plugin-kanban. The number that matters did not:--filter=argumentsThe two task sets are identical — diffed package-by-package from
turbo run build … --dry=json, and the only difference between the two files was a trailing newline. All four newly-named packages were already inside the closure as transitive dependencies of@object-ui/app-shell, which #5341 pulled in viaguide/metadata-diagnostics.md. So ten more covered pages cost this gate zero extra build tasks. Stated rather than absorbed, per #4846; there is nothing here for the maintainer to weigh.Real defects fixed, not just declared
Four documented APIs did not compile against what the packages ship. These are the #5160 class, on the pages a reader copies from most:
guide/deployment.md—createLazyPlugin(() => import('@object-ui/plugin-grid')).@object-ui/plugin-gridhas no default export (dist/index.d.tsopensexport { ObjectGrid, VirtualGrid, ImportWizard };), so the argument is the module namespace, not a component:TS2322, and at runtimeReact.lazywould render the namespace object. Nowasync () => ({ default: (await import('@object-ui/plugin-grid')).ObjectGrid })..then((m) => ({ default: m.ObjectGrid }))spelling infersPasneveron onethenbranch and stays red — theasyncform is load-bearing. The same wrong call is still authored inpackages/react/src/LazyPluginLoader.tsx's own JSDoc, three times, and reaches the published.d.ts. Out of this card's file surface → filed ascreateLazyPlugin's own JSDoc teaches a call that does not compile —import('@object-ui/plugin-grid')has nodefaultexport #5949.guide/troubleshooting.md— the page mountedI18nProviderwithlocale="en"andmessages={messages}.I18nProviderPropsdeclares neither prop; it takesconfig?: I18nConfig. Nowconfig={{ defaultLanguage: 'en', resources }}.guide/troubleshooting.md—const { startMeasure, endMeasure } = usePerformance('MyWidget').usePerformancetakes aPerformanceConfigobject, not a label string, and returns{ config, metrics, markRenderStart, debounce }— neither destructured name exists. NowmarkRenderStart(), which returns the stop function.guide/user-state-persistence.md—createObjectStackUserStateAdapter({ …, kind: 'favorites' }). The option iskey, a dotted namespaced string (ui.favorites), andkindis rejected outright (TS2353). Nowkey: 'ui.favorites'/key: 'ui.recent', plus the missinguseEffectimport and a typeddataSourceparameter.yamlstorage-model section still describe auser_app_stateobject keyed bykind, a designpackages/data-objectstack/src/userState.ts:6-10explicitly rejected in favour ofsys_user_preference. No gate reads ayamlfence, so it is a different defect → filed asuser-state-persistence.md's storage-model section documents auser_app_stateobject keyed bykind— the shipped adapter usessys_user_preferencekeyed bykey#5950.One decision #5343 genuinely did not cover, stated explicitly
guide/public-forms.md's quick start importedrestDataSourcefrom@object-ui/data-rest— a package that does not exist: no such directory underpackages/, and no manifest in the workspace references it. #5343's table enumerates fabricated symbols on real packages; a fabricated module is outside it, so this call is mine and I am naming it rather than folding it in silently. Disposition, in #5053's vocabulary: lives in a neighbour package — the real adapter iscreateObjectStackAdapterfrom@object-ui/data-objectstack, whose declared return type is a genericDataSource, exactly whatEmbeddableFormProps.dataSourcetakes. ⛔ No export was added anywhere.Verification
All at the final commit
31fe8b4, working tree clean, run from the repo root against a build of the gate's own filter closure (turbo run build $(node scripts/check-doc-snippet-types.mjs --build-filter) --concurrency=2, 32/32 successful, serialised under the container's shared heavy-verify lock). Every gate by name with its own printed verdict:node scripts/check-doc-snippet-types.mjs→ exit 0.Scanned 222 document(s): 169 covered (33 of them hold a ts/tsx block), 53 ungated·Covered blocks: 161 — 127 to compile, 34 declared fragment(s).·Syntax phase: every block parsed, so every one of them reached the semantic phase.·Semantic phase: 127 of 127 block(s) judged, 0 failed.·Every covered documentation snippet compiles against the built types.Controls green: resolution landed onpackages/types/dist/index.d.ts, sentinel producedTS2305, positive control 0 diagnostics.pnpm exec vitest run scripts/__tests__/check-doc-snippet-types.test.ts→Test Files 1 passed (1)/Tests 20 passed (20). Running the script is not running its test; both were run, from the repo root.node scripts/check-doc-component-types.mjs→ exit 0.Scanned 183 doc file(s) (.mdx + .md), 1056 code block(s), 883 type literal(s) … 745 registered, 138 exempted.·✅ Every documented component type is registered.node scripts/check-doc-links.mjs→ exit 0.Links are valid across 13 scan roots.node scripts/check-control-bytes.mjs→ exit 0.✅ check-control-bytes: OK (scanned 4939 tracked text file(s); skipped 85 binary).Plus a manualgrep -naPcontrol-byte scan over all 11 changed files: no hits.node scripts/check-changeset-presence.mjs→ exit 0.11 file(s) changed, 0 of them under the src/ of a package the release covers … ✅ No source of a released package changed in this range, so no changeset is owed.None added, per its verdict.node scripts/check-changeset-no-major.mjs→ exit 0.✅ No changeset declares a major bump.eslint . --ignore-pattern 'packages/*/**' --ignore-pattern 'examples/*/**' --ignore-pattern 'apps/*/**' --ignore-pattern 'docs/**'(the complete rootlinttask, not a narrowing — it runs in 9.5s) → exit 0.✖ 26 problems (0 errors, 26 warnings), all pre-existing; the changed.mjsreportserrors=0 warnings=0. Population read from eslint's own--format json: 165 files, of which 0 are.md— a changed.mdlinted directly answersFile ignored because no matching configuration was supplied, so ten of the eleven changed files are outside eslint's population by its own config. The other 46turbo run linttasks are per-package and this diff touches nothing underpackages/*/,apps/*/orexamples/*/.pnpm check(the CLI self-check the lint workflow runs) → exit 0.Analyzing 615 files … ✓ All checks passed.Exit codes were captured before any pipe, and each line above is the gate's own printed verdict rather than a bare
$?.The
.mdfragment marker was re-verified, not inherited24 markers were added and the whole batch leans on them, so #5341's finding was re-measured rather than trusted.
apps/site/node_modules/fumadocs-mdx@15.2.3selects the compiler format by extension —filePath.endsWith(".mdx") ? "mdx" : "md"— and every one of the nine marker-bearing files was then compiled through@mdx-js/mdx3.1.1 in formatmd: all nine compile, and the stringdoc-snippetappears 0 times in every compiled output against 24 occurrences in source. The marker reaches no reader.Reverse verification — prediction written before the run, both legs
Build artifact between the mutation and the thing under test: NONE on either leg. The mutation is markdown the gate reads straight from disk; the
dist/*.d.tsit compiles against is untouched, so no rebuild is required for either leg or for the restore. Both legs proved the mutation reached disk by grepping the specific text meant to change, not by trusting an editor's exit code, and the script carried atrap … EXIT INT TERMrestore.Leg 1 — revert
api/schema-reference.mdtoorigin/mainwhile keeping its ledger entry removed. Predicted: exit 1, exactly one new diagnostic (TS2304: Cannot find name 'BaseSchema'), block counts unchanged, direction MORE findings. Observed: exit 1 ·content/docs/api/schema-reference.md:26:19 TS2304: Cannot find name 'BaseSchema'.·Covered blocks: 161 — 127 to compile, 34 declared fragment(s)·Semantic phase: 127 of 127 block(s) judged, 1 failed. Match, including direction.Leg 2 — revert all ten pages, ledger removals kept. Predicted: exit 1, declared fragments collapse 34 → 10, blocks-to-compile rise, parse failures reappear and the reduced-coverage NOTE prints, roughly the 90 diagnostics measured in the baseline. Observed: exit 1 ·
Covered blocks: 161 — 151 to compile, 10 declared fragment(s)·Syntax phase: 8 block(s) failed to parse and were NOT semantically checked·Semantic phase: 143 of 151 block(s) judged, 29 failed· the NOTE printed · 90 failure lines exactly, matching the baseline total to the unit. Match, including direction.Restore leg — run, not skipped: tree clean against
HEAD, 24 markers back on disk, gate exit 0 with127 of 127 block(s) judged, 0 failed. The tree is byte-identical to what is pushed.Two ledger reasons that have drifted, reported rather than edited
The measurement harness reproduces the recorded mix exactly for 17 of 19 pages. Two disagree, and neither is touched here — re-wording a surviving entry would push this diff outside the batch:
guide/schema-overview.mdrecorded 8 parse diagnostics; 7 measured. (Cleared by this PR anyway.)guide/building-crud-app.mdrecorded20 undefined-name … 4 unresolved-module; 14 and 3 measured. Its entry now over-states its debt by 6 and 1. Worth refreshing when that page is taken.Out of scope, filed unassigned
createLazyPlugin's own JSDoc teaches a call that does not compile —import('@object-ui/plugin-grid')has nodefaultexport #5949 —createLazyPlugin's own JSDoc teaches the call this PR fixed in the guide, three times, and it reaches the published.d.tseditors show on hover. ⛔ Not repairable by adding a default export to@object-ui/plugin-grid— that is a contract change.user-state-persistence.md's storage-model section documents auser_app_stateobject keyed bykind— the shipped adapter usessys_user_preferencekeyed bykey#5950 —user-state-persistence.md's prose andyamlstorage-model section document auser_app_stateobject keyed bykind; the shipped adapter usessys_user_preferencekeyed bykey. Invisible to every gate, since neither reads ayamlfence.Both searched for first; no open issue covered either.
⛔ Not folded in, all deliberately: #5867 (
plaintext-fenced ts/tsx blocks), #5106 / #5342 (the sibling gate's fence and extension axes), #5465 (skills/outside the scan surface). Same gate family, different defects.Generated by Claude Code