Part of #5174 (batch 17). Removes the 'packages/plugin-detail/README.md'
entry from UNGATED_DOCS in scripts/check-doc-snippet-types.mjs -- the only
change to that file, +0/-2, inside the object literal -- and repairs the
document so all 7 ts/tsx blocks compile against the built types.
The 21 measured diagnostics split into fragment shape and real API drift:
- 6 parse diagnostics: two blocks were not statements at all. The
data-source block held two sibling top-level JSX expressions, and the
custom-Page block was a bare object literal fenced `ts`. Both now bind
their value to a name, with no re-indentation of the content.
- 15 undefined-name diagnostics: blocks used ambient names (DetailView,
accountData, activityData, navigate, deleteAccount) or continued an
earlier block. They now carry real imports plus `declare const`
placeholders typed to the shipped surface.
Three of them were doc lies rather than fragment shape:
- `related[].columns` was documented as a string array. The shipped
DetailViewSchema declares TableColumn[], so the example moves to
{ accessorKey, header } entries.
- The "## Schema" block re-declared DetailViewSchema by hand and had
drifted from the package: it named `RelatedList` (a component, not a
type) for `related`, and omitted primaryField, summaryFields, layout,
columns, onNavigate and history. It now imports the real type from
@object-ui/types and annotates an example with it, so the compiler
keeps it honest.
- The Reference Rail's "per-object opt-out" documented
`ObjectSchema.create({ detail: { hideReferenceRail } })`. That factory
is not importable from @objectstack/spec, and the objectDef `detail.*`
block was retired -- this package's own CHANGELOG records it as an
ADR-0085 removed dead read that is "no longer consulted". The surviving
opt-out is BuildPageOptions, passed to buildDefaultPageSchema, which is
what the block and the matrix bullet naming it now say.
No packages/** source touched, no public type widened, no gate loosened,
and no new FRAGMENT_MARKER: declared fragments stay at 158, so all 7 blocks
earn coverage by compiling.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01MM7kaS4dPpYHV5BsMyu4tQ
Part of #5174 — batch 17 of the
UNGATED_DOCSburn-down.packages/plugin-detail/README.mdleaves the ledger and all 7 of its ts/tsxblocks now compile against the built types. The gate file's only change is the
two lines of that one entry.
Ledger arithmetic
Both sides'
UNGATED_DOCSliterals were imported as objects and diffedprogrammatically (the base copy loaded from
git show HEAD:...):['packages/plugin-detail/README.md'][][]0added /2deletedf46b5662ba336f02…= branchf46b5662ba336f02…, 1178 lines both sides — IDENTICALCoverage moved by exactly this document: covered documents 205 to 206,
covered-with-block 103 to 104, ungated 22 to 21, covered blocks 653 to 660,
to-compile 495 to 502, declared fragments 158 to 158 (zero new
FRAGMENT_MARKER), semantic failures 0 to 0.The base blob of the gate file on
36fc746is9f7afb12…— the same blobbatch 16 recorded on
9de3141a0, so nothing moved in that file onmainbetween the two batches.
What the 21 diagnostics were
6 parse + 15 undefined-name. Most were fragment shape, but three were doc lies
that a reader would have copied:
related[].columnswas documented as a string array. The shippedDetailViewSchemadeclaresTableColumn[], so the example moves to{ accessorKey, header }entries. (The renderer also normalizes barestrings at runtime while the type does not — filed separately, see below.)
DetailViewSchemaby hand and haddrifted from the package: it named
RelatedList(a component, not a type)for
related, and omittedprimaryField,summaryFields,layout,columns,onNavigateandhistory. It now imports the real type from@object-ui/typesand annotates an example with it, so the compiler keepsit honest instead of a hand copy drifting again.
It taught
ObjectSchema.create({ detail: { hideReferenceRail } }).ObjectSchemais not a public export of@objectstack/spec(it is aninternal bundle symbol), and this package's own CHANGELOG records the
objectDef
detail.*block as an ADR-0085 removed dead read that is "nolonger consulted" — a repo-wide grep finds zero readers of it. The surviving
opt-out is
BuildPageOptions, passed tobuildDefaultPageSchema, which iswhat the block and the matrix bullet that named it now say.
numbered "emits automatically when" matrix has two further inaccuracies I did
not touch — the shipped code requires
showReferenceRail === true(anopt-IN, so "automatically" overstates it), and rung 2 attributes the ≥2-related
condition to the objectDef when the code reads
options.related. Those areprose defects in a section this diff only had to stop contradicting; they are
reported for triage rather than repaired here.
Also recorded: the removed entry's own reason string claimed 5 parse
diagnostics where the measurement reads 6. The entry is gone either way, but
the drift is real and is why the census was re-taken rather than inherited.
Probes
Six, every one predicted in writing before it ran (predictions kept at the
scratchpad's
PREDICTIONS.md, written at190c3ce). Every mutation is provenon disk by
git hash-objectagainst the HEAD blob plus occurrence counts ofboth the injected and the deleted text; every restore is proven by an empty
git diff HEAD; every leg runs under atrap ... EXIT INT TERMwith absolutepaths and restores with
git checkout HEAD -- ABS_PATH, never a bare checkout.No rebuild is owed on any leg, and that was reasoned rather than assumed: the
gate reads the mutated bytes straight from the working tree, so no built
artifact sits between a mutation and its reading, and no probe mutates
dist/.205 covered … 22 ungated,653 — 495 to compile,495 of 495 judged, 0 failed. The entry is what suppresses the verification ✅502 of 502 judged, 1 failed,README.md:200:26 TS2339: Property 'push' does not exist on type '(url: string) =+> void'✅500 of 502 judged, 4 failed, 21 diagnostics, every site identical ✅ (split came out TS2552 ×4 / TS2304 ×11 where the prediction wrote ×3 / ×12 — see deviations)check:doc-fencesredpackages/plugin-detail/README.md:212✅DataSourcetonumber)SchemaRendererProviderdeclaresdataSource: any, so only theDetailViewsite can fail. Direction right, count over-predicted ✅check:readme-exportsred, 1 fabricated444 real, 0 fabricated), mutated exit 1 (443 real, 0 wrong-path, 1 fabricated) naming line 94 ✅P4's first attempt is reported rather than smoothed over. It re-fenced
block 7 from
tstojsandcheck:doc-fencesstayed green. That is the gatebeing right, not blind: its binding triage classifier (quoted in its own
docblock) counts a block as code only when the first line starts with
import/export/interface/type X =/const x: T, and block 7'sfirst line is
const asideRegion = {— no annotation, so it is prose by thatruling. Re-aimed at block 5, whose first line is an
import type, and it wentred immediately.
Gates
All redirect-then-capture; the exit code is read before any pipe and each row
quotes the gate's own verdict line. The union was re-run at the final commit
190c3ceand nothing was pushed after it.pnpm check:doc-snippetsScanned 227 document(s): 206 covered (104 of them hold a ts/tsx block), 21 ungated·Covered blocks: 660 — 502 to compile, 158 declared fragment(s)·502 of 502 block(s) judged, 0 failed·Every covered documentation snippet compiles against the built types.pnpm check:doc-fencesevery TypeScript block in 227 document(s) is fenced ts/tsx/typescriptpnpm check:readme-exports444 of them self-imports judged (444 real, 0 wrong-path, 0 fabricated)pnpm check:doc-typesEvery documented component type is registered.node scripts/check-doc-links.mjsLinks are valid across 17 scan roots.pnpm check:doc-example-readersOK 80 documented symbol(s), 3947 call site(s)pnpm check:control-bytesOK (scanned 6435 tracked text file(s); skipped 85 binary)node scripts/check-node-esm-load.mjsProvenance leg: 37 of 37 gradable entries were built by this tree.(see the build note below)pnpm type-check:scriptsnode scripts/check-changeset-presence.mjs2 file(s) changed, 0 of them published source … No source or published contract of a released package changed in this range, so no changeset is owed.check-governed-queue-guard --test(both paths)NOT GOVERNED — 2 path(s) checked against 5 governed surface(s); none matched.node scripts/check-node-esm-load.mjsrun exited 1, and it was right to: turbo shares one cache across every
worktree of a checkout, so my cached build had replayed batch 16's
worktree artifacts (31 of 37 entries pointing at
objectui-issue-5174-b16),and the gate refuses to grade artifacts this tree did not produce. Re-built
with
turbo run build --force(39/39, 0 cached) and re-measured: provenance37 of 37, andcheck:doc-snippetsreturned byte-identical coverage numbers,so no reading in this PR rests on another tree's
dist/.Tests
git grep -lrather than guessed — 15 files: the 8
scripts/__tests__gate suites(including
check-doc-snippet-types.test.ts, which this diff's own editedscript owes), the 4
packages/typesdoc-surface suites,plugin-gantt/readme-navigation-example,react/LazyPluginLoader.jsdocExampleand
examples/schema-catalog/component-fixture-declared-keys—Test Files 15 passed (15)/Tests 593 passed (593).pnpm exec vitest run packages/plugin-detail/—Test Files 132 passed (132)/Tests 1199 passed (1199).pnpm --filter @object-ui/plugin-detail type-checkexit 0 (it runstsc --noEmit && tsc -p tsconfig.test.json, so the test tsconfig is included).TURBO_SCM_BASE=36fc746 turbo ls --affectednames 11 packages, which is turbo's package granularity reacting to a
root-level script edit — the only readers of either changed byte are the 15
files above, so the rest is a declared narrowing to CI, not a skipped run.
pnpm linthere isturbo run lintper package, so the repository-widesweep is CI's run. The narrowed run over exactly this diff is
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 diffis the one
.mjsat 0 errors / 0 warnings.eslint.config.jsdeclares noproject/projectService/parserOptions.project, so type-aware lintingis off and this diff cannot move the verdict on any untouched file — the
population it would otherwise judge is 4351 files by eslint's own count.
Concurrency with batch 16
Batch 16 (PR #7988,
packages/i18n/README.md) is ACCEPTed and draft, not yetmerged. This batch runs concurrently under the licence batches 10/11, 12/13
and 14/15 used: both are removals-only on the gate file, on different lines,
and neither touches the other's document. Exclusions were verified on this
base rather than inherited —
packages/i18n/README.mdis batch 16's,packages/auth/README.mdis held by draft PR #7685,packages/plugin-ganttand
packages/plugin-kanbanbelong to #7302 (PR #7985),packages/plugin-chatbotis deferred, and root
README.mdis not apackages/NAME/README.md.One related card was found already open and deliberately NOT re-filed:
objectui#4286 records that a synthesized
asideregion carriesclassName,which
PageRegionSchemarejects. That is why block 7 binds its region to aplain
constrather than annotating it with a spec region type — annotating itwould have asserted a shape the spec does not accept.
Census and tie-break
Re-taken on this base through the gate's own exported
analyze()/compileSnippets()over all 16 non-excluded candidates. Five sit tied at 7blocks, so the seat's fixed tie-break (larger measured debt first) was needed
this time and picks
packages/plugin-detail/README.md: 21 diagnostics,against collaboration 18, permissions 18, types 6, layout 3.
Out of scope, filed
DetailViewSchema.related[].columnsis typedTableColumn[], butRelatedListdeliberately accepts bare strings — the type and the runtime disagree #7997 —DetailViewSchema.related[].columnsis typedTableColumn[],but
RelatedList.tsxdeliberately normalizes bare-string entries and says soin a comment. The type and the runtime disagree; widening the type is a
contract change for a maintainer, not a rider here.
plugin-detailREADME's "Reference Rail decision matrix" says the rail emits automatically and reads its ≥2-related condition off the objectDef — the shipped synth requires an explicitshowReferenceRailopt-in and readsoptions.related#7998 — the Reference Rail decision matrix's remaining proseinaccuracies described above (the "emits automatically" claim and rung 2's
attribution to the objectDef).
CI note
Live E2E (informational)is red on every branch today for an upstream reason(#7990 / objectstack#16186). It is base-red, not this diff's — not chased here.
Drafted by the
os-devseat for batch 17. This PR stays draft: the seat didnot flip ready, did not enable auto-merge, and touched no labels or assignee.
🤖 Generated with Claude Code
https://claude.ai/code/session_01MM7kaS4dPpYHV5BsMyu4tQ
Generated by Claude Code