docs(layout): compile every README snippet and leave the UNGATED_DOCS ledger - #8063
Merged
Conversation
… ledger Part of objectui#5174 — batch 22 of the UNGATED_DOCS burn-down. `packages/layout/README.md` leaves the ledger and all 7 of its ts/tsx blocks now compile against the built types. The gate file's only change is the two lines of that one entry; its strictness region is byte-identical. Two repairs, both inside ts/tsx blocks: - The "Usage with React Router" block was REFUSED rather than judged: it imports `react-router-dom`, which `@object-ui/layout` declares as a peer dependency, so the specifier reaches a snippet only through this repository's own root install and the gate's bound turns it away. Its three router components are now stood in for by `declare const`s typed to what the block uses them as, which keeps the AppShell / SidebarNav composition — this package's own surface — genuinely checked. That refusal was masking a real diagnostic: `Dashboard` was never defined. - The same block routed `/users` to `Users`, the lucide-react icon it imports for the sidebar, so the page rendered a glyph where its content belonged. An icon is a valid component, so no diagnostic could catch it; the route element is now a separately named page component. - The "Customization" block used `AppShell` with no import (TS2304 twice) and now self-imports it. No `packages/**` source touched, no public type widened, no gate loosened, and no new fragment marker: declared fragments stay at 158. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
Brings in #8046, #8042, #8039. Neither of this branch's two paths is touched by that range; plugin-view source moved, so the forced build and every gate are re-run on the merged head. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
Contributor
✅ 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
|
Contributor
Author
|
Standing down on Generated by Claude Code |
baozhoutao
marked this pull request as ready for review
September 6, 2026 13:56
baozhoutao
pushed a commit
that referenced
this pull request
Sep 6, 2026
Brings in batch 22 (#8063, packages/layout/README.md leaves the ledger) and #8056, which moves packages/fields source and therefore the built types this corpus is judged against. Forced build, gates, probes and tests re-run on the merged head. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
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.
Part of #5174 — batch 22 of the
UNGATED_DOCSburn-down.packages/layout/README.mdleaves the ledger and all 7 of its ts/tsx blocks nowcompile against the built types. The gate file's only change is the two lines of
that one entry.
Notation, read this first
This repository has measured that GitHub's body sanitizer deletes tag-shaped
fragments even inside backticks and fenced blocks. So JSX elements and generic
parameters are spelled out in words below — "an AppShell element", "a
ComponentType of props with an optional className" — rather than in their real
angle-bracket form. The README itself carries the real spellings; this page does
not.
Concurrency
mainmoved under this batch twice, and both moves were absorbed the way thebrief requires.
packages/types/README.md) merged at 12:50:27Z,taking
origin/mainfromed4a2f17cto58cd01a38. This branch had nocommits of its own at that moment, so it was fast-forwarded rather than
carrying a merge commit. The census was taken on both bases and is
byte-identical across them, as is the pick.
origin/maintoa8f4bd75f. Bythen this branch had its implementation commit, so
origin/mainwasmerged (never rebased, never force-pushed). That range touches neither of
this branch's two paths, but it does move
packages/plugin-view/src/ObjectView.tsx— package source, so the built types the corpus is judged against move with it.
The forced build, every gate, every test and the lint readings were therefore
all re-run on the merged head
85ebbcbe9.All 11 open pull requests' file lists were read over the REST files endpoint and
each count reconciled against that PR's own
changed_files: 8049/3, 8048/3,8046/2, 8042/2, 8039/3, 7749/4, 7685/67, 7058/24, 7054/2, 7053/2, 5400/1058.
#5400's 1058-file list was paged to exhaustion (11 pages) because the endpoint
pages at 100 and a truncated list renders as a confident absence. No open PR
touches
packages/layout/README.mdor the gate file. The only README any openPR touches at all is
packages/auth/README.md(PR #7685), which is excludedanyway.
Two neighbours worth naming, neither an exclusion:
packages/layout/package.json. This README importsHome,Users,SettingsandFolderOpenfromlucide-reactand is now compiled againstit, so that bump is the one open change that could move the types these
snippets are checked against.
packages/types/src/field-types.ts, upstream of everything.Live E2E (informational)is red on every branch today for an upstream reason(objectui#7990 / objectstack#16186), not because of this diff.
Ledger arithmetic
a8f4bd75f85ebbcbe9UNGATED_DOCSentriescheck:readme-exports)Both rows were MEASURED, not computed. The base row is a real
pnpm check:doc-snippetsrun (probe M0) with both changed files checked out atbase bytes — on-disk hashes proven equal to the base blobs
f497d997…and9beae7db…— and restored afterwards under a trap. The basecheck:readme-exportsrow is its own run against base README bytes (probe M0b).Programmatic diff of the two
UNGATED_DOCSobjects — both imported as OBJECTS,never diffed as text: removed =
['packages/layout/README.md'], added =[],reason-changed =
[], key order preserved for survivors = true.git diff --numstaton the gate file is exactly0 2. On the branch: layoutentries 0,
packages/NAME/README.mdentries 14 (from 15), control'packages/auth/README.md'1.The strictness region — the
Fence scanningbanner line to EOF, 1178 lines onboth sides — hashes to
f46b5662ba336f026bca3a0003e0b7979789d48d0291fa5760be7d23c8ed0160onorigin/mainand on the branch. Re-measured here on both bases, not inherited;it is the value batches 15 through 21 recorded.
Census and the rung that decided
Re-taken through the gate's exported
analyze()/compileSnippets()over everynon-excluded ledger candidate — once on
ed4a2f17c(17 entries, 13 candidatesafter exclusions) and again on
58cd01a38after batch 21 landed (16 entries, 13candidates). Both runs give the same table and the same pick.
Rung 1 (larger measured debt: blocks, then diagnostics) DECIDES OUTRIGHT:
layout is alone at 7 blocks; every other candidate holds 5 or fewer. Rungs 2 and
3 were never reached.
Assumption A1 is CONFIRMED — every block and diagnostic total matches batch
21's census exactly, including the two per-code figures batch 21 reported as
moving with the compiler program's shape (react-runtime 7 distinct codes,
plugin-ai 3). Neither column is read by rung 1, which decided outright.
Exclusions re-verified against GitHub on this base, not inherited: the root
README.mdis not apackages/NAME/README.md;packages/types/README.mdwasbatch 21's and has now MERGED, so it is out of the ledger entirely rather than
merely reserved;
packages/auth/README.mdis held by open draft PR #7685;packages/plugin-chatbot/README.mdis deferred by the earlier ruling.The ledger's reason string for this page was STALE, as the dispatch warned.
It claimed "3 undefined-name diagnostic(s) … 3 unresolved-module diagnostic(s)".
The measurement reads 2 undefined-name diagnostics and one refused specifier,
not three. That continues the streak batch 21 briefly broke.
The debt, and what each repair did
Seven blocks: three were already clean, two more needed nothing, and the debt sat
in two.
1. The "Usage with React Router" block was REFUSED, not judged. It imports
react-router-dom, and the gate's root bound turned it away:Ruling 4 asks whether that is a real dependency gap or a peer the reader
supplies. It is a peer, and the manifest says so outright:
packages/layout/package.jsondeclaresreact-router-domunderpeerDependenciesat^6.0.0 || ^7.0.0, matching the README's own Installationsection, and does not list it under
dependencies. The gate maps third-partyspecifiers from
dependenciesonly — its header says so deliberately — so a peeris unmapped, the repository root declares it as a devDependency, and the bound
refuses it. No dependency gap, so no two-shipped-surfaces finding under ruling
5, and no manifest was touched.
The repair takes the gate's own first-listed remedy — import only what the
package declares — by standing the three router components in with
declare constbindings typed to what the block uses them as. The block now importsreact,@object-ui/layoutandlucide-react, all of which layout reallydeclares, so the AppShell and SidebarNav composition is genuinely
type-checked instead of being surrendered to a fragment marker. That mattered:
probe P7 shows a wrong
NavItemkey in that block now reds the gate, and a wrongNavItemkey is exactly the defect objectui#3999 recorded on this page.That refusal was masking a real diagnostic. A refused block never reaches the
semantic phase, and behind it
Dashboardwas never defined anywhere in thesnippet — a TS2304 that appears the moment the bound is lifted (probe P3).
2. The same block routed to the icon, and no gate could ever have caught it.
It imported
Usersfromlucide-reactfor the sidebar and then used that samename as the
elementof the/usersroute, so a reader copying the blockrendered a 24-pixel glyph where the page content belonged. A Lucide icon is a
valid component, so the route type-checks either way — probe P4 puts the icon
back and the gate stays GREEN. The route element is now a separately named page
component, and a short prose paragraph says why the two are named apart, because
nothing mechanical will say it for the next author.
3. The "Customization" block used AppShell with no import, TS2304 twice. It
now self-imports it, which is also why this diff hands
check:readme-exportsonemore self-import to judge (489 to 490) rather than fewer.
No
packages/**source touched, no public type widened, no lenient alias added,no gate loosened, and no new fragment marker: declared fragments stay at 158.
Probes — one base measurement and eight probes, each predicted in writing first
Predictions were written to the scratchpad as
5174-b22-PREDICTIONS.md(md5
7a6dbf1800914b511f9f848fc52d46dd) at implementation commit82b1c989dwith a clean tree, before any probe ran, and were not amended. Every mutation
is proven on disk by occurrence counts of both the injected and the deleted text
plus
git hash-objectagainst the HEAD blob; every restore is proven by an emptygit diff HEAD; every leg runs under atrap ... EXIT INT TERMwith absolutepaths, restoring with
git checkout HEAD --against an absolute path rather thana bare checkout from the index. Nothing here is read through a package
dist/:both mutated paths are read from disk by the gate itself, so no rebuild sits
between a mutation and its reading.
9beae7db…both sides)All nine legs ran in the predicted direction. P4 is the one whose prediction
was that the probe would NOT go red, and that is the point of it: it is what
makes the icon-in-route repair a documentation fix rather than a type fix, and
what justifies spending prose on it.
Gates — all at
85ebbcbe9, clean tree, nothing pushed afterExit codes captured by redirect-then-capture, before any pipe; each row quotes
the gate's own verdict line. The build was forced first
(
turbo run build --filter=./packages/* --concurrency=2 --force, 39 successful /0 cached) and again inside the provenance gate (43 successful / 0 cached); every
dist-sensitive gate was then re-run on the force-built dist, as the gate
prescribes. Note the invocation: bare
turbois not on PATH in this container,so
pnpm exec turbois what ran.pnpm check:doc-snippetsexit 0 — "Scanned 227 document(s): 212 covered (110 of them hold a ts/tsx block), 15 ungated" / "Covered blocks: 714 — 556 to compile, 158 declared fragment(s)" / "Root bound: no block imports a specifier that resolves only through this repository's ROOT manifest" / "Semantic phase: 556 of 556 block(s) judged, 0 failed" / "Every covered documentation snippet compiles against the built types."pnpm check:doc-fencesexit 0 — "every TypeScript block in 227 document(s) is fenced ts/tsx/typescript"pnpm check:readme-exportsexit 0 — "490 of them self-imports judged (490 real, 0 wrong-path, 0 fabricated)"pnpm check:doc-typesexit 0 — "Every documented component type is registered."node scripts/check-doc-links.mjsexit 0 — "Links are valid across 17 scan roots."pnpm check:doc-example-readersexit 0 — "OK 80 documented symbol(s), 3947 call site(s)"pnpm check:control-bytesexit 0 — "OK (scanned 6463 tracked text file(s); skipped 85 binary)"node scripts/check-node-esm-load.mjs --force-buildexit 0 — "Provenance leg: 37 of 37 gradable entries were built by this tree." Green on its first run, so no gate had to be re-run over a replayed sibling cache. Its three ERR_UNKNOWN_FILE_EXTENSION lines are the gate's own by-design entries.pnpm type-check:scriptsexit 0node scripts/check-changeset-presence.mjsexit 0 — "2 file(s) changed, 0 of them published source of a package the release covers … no changeset is owed." Noskip-changesetlabel applied: this repository declares with an empty-frontmatter changeset rather than that label, and the presence gate says none is owed, so nothing was labelled at all by this seat.node scripts/check-governed-queue-guard.mjs --teston both paths exit 0 — "NOT GOVERNED — 2 path(s) checked against 5 governed surface(s); none matched"pnpm exec vitest run packages/layout/— "Test Files 19 passed (19) / Tests 202 passed (202)";pnpm --filter @object-ui/layout type-checkexit 0, its output echoingtsc --noEmit && tsc -p tsconfig.test.json, so the test tsconfig is genuinely included.grep -naPover the C0/DEL ranges found nothing (exit 1, zero output bytes).Lint, with the narrowing declared and its three evidence items.
pnpm linthere is
turbo run lintper package, so the repository-wide sweep is CI's run;the narrowed run over exactly this diff is
pnpm exec eslint --no-inline-config --format jsonon both paths — 2 entries, 0errors. eslint's own answer for the README is "File ignored because no matching
configuration was supplied", so the real lint surface of this diff is the one
.mjsat 0 errors and 0 warnings. (1) The population eslint would otherwise judgeis 4361 files by its own count. (2) That run exits 1 with 93 errors and
12170 warnings, all of them in files this diff does not touch — measured, and
reported rather than smoothed, because a reader must not mistake the narrowing
for a green repository. (3)
eslint.config.jsdeclares noproject,projectServiceorparserOptions.project(grep count 0), so type-aware lintingis off and this diff cannot move the verdict on any untouched file.
Readers of the changed paths
Derived with
git grep -lon both paths, not guessed — 22 test files, 642tests, all green in one run. This page is far more heavily pinned than batch
21's was:
scripts/check-doc-snippet-types.mjs— the gate itself, which now COMPILES this page instead of excusing it (P1 proves the entry was what suppressed it).packages/layout/src/__tests__/read this README directly:readme-app-shell-example,readme-sidebar-nav-example,readme-registration-keys,app-shell-docs-nav-example,guide-layout-app-shell-doc,guide-layout-sidebar-nav-doc. Two of them assert doc parity — that an example appears in the README as a contiguous run of lines — and one re-reads every fence mentioning SidebarNav and rejects the string-icon spelling. A3 is CONFIRMED and then some: batch 21's page had exactly one reader; this one has seven.scripts/__tests__/doc-version-claims.test.ts— names this README path; green.scripts/check-readme-exports.mjs— reads this README's self-imports; proven live by P6. This diff ADDS one, so it hands that gate more to check than it had.check-doc-snippet-types.test.tsand six sibling gate suites, plus the six package and example suites that name it.Out of scope, filed rather than repaired here
objectui#8059, unassigned, labelled
findingonly (domain triage is not thisseat's to assign). The gate's root bound refuses a package's own declared peer
— measured: four packages (
app-shell,layout,plugin-designer,plugin-detail) declarereact-router-domas a peer and none as a dependency —and the refusal message names two remedies, neither of which fits a package whose
headline feature IS that peer integration. This batch used a third shape that the
message and the header do not name. That rule is deliberate and documented, so
the card asks only for the remedy text, and changing it would mean editing the
gate's strictness region, which this batch's licence pins byte-identical. The
other three READMEs are covered and green today, so the wall is latent, not
active — but the burn-down will walk into it again.
This PR is a DRAFT and stays a draft: this seat does not flip ready, does not
enable auto-merge, and touches no labels or assignee.
🤖 Generated with Claude Code
https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
Generated by Claude Code