docs(plugin-map): compile the README's snippets against the shipped surface - #8271
Conversation
…urface Part of objectui#5174 (batch 35): burn down the `packages/plugin-map/README.md` row in `UNGATED_DOCS` so `check-doc-snippet-types` compiles the page instead of ledgering it. - Fences 53/71: `const schema: ObjectMapSchema` with the type import from `@object-ui/types`. They parsed and "passed" before only because nothing bound them — measured with a length-preserving decimal-literal negative control on both an outer member and a nested `map` key. - Fence 135 (the three shapes `locationField` reads): the three bare record literals were the page's one parse failure (TS1005). They document three runtime-accepted INPUT shapes rather than one authorable value, so they become a table citing `extractCoordinates()` — the parser that decides the shape per record. - Fence 161: `declare const dataSource: ObjectMapProps['dataSource']` retires the live TS2304. `ObjectMapProps` is a real export of this package. The row's `TS2322x1` claim was stale for a fourth consecutive measurement. The page now reads zero, so the row is deleted rather than rewritten. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
…-snippets-batch35-plugin-map
✅ 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
|
|
ACCEPT (batch 35, Verified from the diff and the tree, not the report:
Next: CI convergence → flip ready → post-flip guard → auto-merge SQUASH → queue confirmation → landing probe ( Generated by Claude Code |
|
Armed: PR #8271 flipped ready at 2026-09-07T07:30:13Z on head Generated by Claude Code |
|
LANDED: merged at 2026-09-07T07:46:37Z as Generated by Claude Code |
Part of #5174 (batch 35:
packages/plugin-map/README.md)Burns down the page's
UNGATED_DOCSrow inscripts/check-doc-snippet-types.mjsso the gate COMPILES its snippets instead of ledgering them. Base sha320c84121(carries PR #8260, batch 34);origin/mainmoved to35e63669dmid-task and was merged in with a merge commit (never rebased), so every reading below is re-measured on the merged heada5c153e8d.Two files:
packages/plugin-map/README.md(+23/-10) andscripts/check-doc-snippet-types.mjs(-2, exactly this page's ledger row). No edit topackages/plugin-map/src/**orpackages/types/src/**; no fragment marker; no widened or loosened type; no@ts-expect-error.Census reading 1 — ledger-literal, on the base
Measured with the gate's OWN analyzer (
scanFences+compileSnippetsexports, same built.d.tsclosure, same controls) with this page moved into the compiled tier; not a hand-written regex.tststs';' expected.(never reaches the semantic phase)tsxCannot find name 'dataSource'.Totals: 4 ts/tsx fences, 1 parse failure, 3 semantically judged, 1 failed. By code:
parse:TS1005x1,TS2304x1.Harness controls on that run: sentinel 1 diagnostic (TS2305 — the harness CAN fail), positive 0, resolution landed on
packages/types/dist/index.d.ts, 0 src leaks.The row's
TS2322x1is confirmed STALE — a fourth consecutive measurement finds no TS2322 on this page (batches 32, 33 and 34 measured the same absence). The rest of the row was accurate in count but wrong in wording, in the same way batches 31-34 found: "blocks fencedtsthat are bare object literals or elided bodies" is ONE block, not blocks, and there is no elided body anywhere on the page; the undefined name is a single ambientdataSource, not "blocks continue an earlier block".Blind spot, stated
The page also carries a
bashfence (line 20) and atextfence (line 31). Neither is in this gate's ts/tsx population, so neither is measured here and neither is relabelled by this PR — reported, not repaired. Nothing else on the page is fenced.Negative control — length-preserving, decimal literals
Two mutations of the BASE page, each applied to a scratchpad copy so the tracked tree was never touched, each byte-length-identical to the text it replaced (so no offset shifts for an unrelated reason) and each a DECIMAL literal (batch 34's octal corollary: an all-zero pad parses as an octal literal and measures nothing).
objectName: 'stores',becomesobjectName: 12345678,(8 chars for 8)latitudeField: 'lat',becomeslatitudeField: 12345,(5 chars for 5)That is the measurement the repair rests on: fences 53 and 71 were not "passing", they were UNBOUND. A bare
const schema = { ... }compiles because nothing is ever asked of it, and the gate's green over this page's two clean fences was carrying no information at all — outer members and nestedmapmembers alike.Per-fence decision
const schema: ObjectMapSchema = ..., withimport type { ObjectMapSchema } from '@object-ui/types';added to the blockpackages/types/src/index.ts:421) and present on the builtdist/index.d.ts. One fence, one module (batches 25-34's idiom), so the import is repeated rather than inherited.declare const dataSource: ObjectMapProps['dataSource'];stand-in, andObjectMapPropsimported alongsideObjectMapany: the declaration is derived from the component's own props type, so it goes stale loudly if that prop's type moves.Fence 135: the teaching decision, on the four axes
The block documented the three shapes
locationFieldreads. Three options were weighed; (c) a fragment marker was excluded by the brief and is not defensible anyway — a marker here would declare "cannot compile" about a block that a table makes unnecessary.(a) Three typed bindings (each literal bound to a Record of string to unknown, or similar).
locationcolumn be parsed?", and a binding answers a question nobody asked.extractCoordinates()tests the value's shape at runtime, per record. A green binding would teach a guarantee that does not exist — exactly the lenient-consumer shape commandment #0.1 refuses, one level up in the docs.(b) A Markdown table citing the parser — CHOSEN.
parseFloat-ed after trimming, that the array form must be exactly two elements).extractCoordinates()inpackages/plugin-map/src/ObjectMap.tsx— instead of a second, weaker copy of it. This is the shape batches 31-34 landed for type-shape fences.Cost, stated: the table is prose, so no gate re-verifies it. That is the honest trade — the alternative was a compiled block that verified nothing while looking as though it did. The same paragraph now also cites the range test and the excluded-records notice, which live in that same file (
ObjectMap.tsx:891and:1044).Per-key table — every key the examples write
Key-surface bound (objectui#7927) applies at the OUTER level and only there:
ObjectMapSchema extends BaseSchema, which carries an index signature, so an annotation checks member TYPES and never keys.ObjectMapConfig(packages/types/src/objectql.ts:2249) is a plain interface with NO index signature — measured, not assumed, in leg 4 below — so the nestedmapkeys ARE key-checked. This is the first batch on this worklist where a nested config is genuinely key-checked.typeObjectMapSchema.type(objectql.ts:2283)ObjectMap.tsx:226,:287,:330objectName:2296:846,:943, andgetDataConfig/resolveRecordSourceObjectNamestaticData:2303getDataConfig, read SECONDmap:2317, typedObjectMapConfig:371(schema.map ?? null),:366formap.stylemap.latitudeFieldObjectMapConfig:2250extractCoordinates:431-433map.longitudeField:2252:431-433map.titleField:2256:884map.descriptionField:2258:887dataSource(prop)ObjectMapProps.dataSource(ObjectMap.tsx:64)ObjectMapRendererindex.tsx:57onMarkerClick(prop)ObjectMapProps.onMarkerClick(ObjectMap.tsx:75)Nothing on the page writes an undeclared key, so there is no phantom to drop and no undeclared-but-read proposal from the examples themselves.
The brief's assumption A2 is FALSIFIED — reported, nothing changed
The dispatch assumed
ObjectMapPropsdeclares onlyschema,dataSource?,className?,data?, which would have madeonMarkerClicka phantom prop the README teaches. It is not.ObjectMapProps(packages/plugin-map/src/ObjectMap.tsx:62) declares TEN members, and the builtpackages/plugin-map/dist/index.d.tsships all ten:schema,dataSource?,className?,data?,onMarkerClick?,onRowClick?,onEdit?,onDelete?,enableClustering?,clusterRadius?. The README's props table lists exactly those (minusschema's siblings it folds into prose) and teaches no phantom. The separate runtime route the brief asked about —ObjectMapRendererspreading the rest of its props intoObjectMapatindex.tsx:57— exists, but it is spreading DECLARED props, so it is not the undeclared-but-read case."What this component does not read" — every claim verified against the renderer
markersnot readschema.markersread anywhere inpackages/plugin-map/src/; themarkersidentifiers in the file are the internal cluster arrayslayersnot readheightnot read, container is 300px through 600pxschema.heightread; the wrapper ish-[300px] sm:h-[400px] md:h-[500px] lg:h-[600px]atObjectMap.tsx:1058useGeolocationnot read, a user-initiated button insteadschema.useGeolocationread; the button is at:1082-1089(aria-label="Show my location",data-testid="map-geolocate")icon/color/popupnot readschema.icon/.color/.popupreadfilter.mapno longer read, and says so in the consolewarnOnLegacyFilterMapConfig()at:210-243detects the legacy stash and warns;getMapConfigreads config only fromschema.mapAlso spot-checked and correct: the default field names when no
mapblock is present (latitude/longitude/location/description, and deliberately NO title default — objectui#5953,:415-422), and the camera claims (FIT_PADDING_PX = 48,FIT_MAX_ZOOM = 12,EMPTY_VIEW_ZOOM = 2,UNFITTED_CENTER_ZOOM = 3inpackages/plugin-map/src/camera.ts). No teaching defect found in this section, so nothing here is repaired.One inconsistency found while verifying the last row is NOT on this page and NOT in this PR: that console warning names
nameas a default title field, which objectui#5953 removed on purpose. Filed as objectui#8270 (findinglabel, unassigned); it is a one-string change insrc/**, out of this batch's surface.The
mapview alias — batch 33's host-only reading does NOT transferRead before writing anything: unlike
tree,mapIS an authorable view type here.ObjectViewSchema.defaultViewType(packages/types/src/objectql.ts:1804) includes'map'.NamedListView.type(:1988) includes'map'.ViewTypeSchema(packages/types/src/zod/views.zod.ts:26) includes'map'.object-mapunder namespaceplugin-mapandmapunder namespaceview(packages/plugin-map/src/index.tsx:62-79), both resolving to the same renderer.The page's existing statement — that
mapis "the bare spec view-type name (ViewTypeSchema's'map'), for a node authored with it directly" and that inside anObjectViewamapview compiles to anobject-mapnode — is therefore correct as written and is left unchanged. objectui#5321's host-composition-only ruling coverstreeandchart, notmap.Census reading 2 — after the repairs, on the merged head
tststsxTotals: 3 ts/tsx fences, 0 parse failures, 0 bound failures, 3 of 3 judged, 0 failed. Same harness controls (sentinel 1 / TS2305, positive 0, 0 src leaks).
Ledger decision
The page reads ZERO after the repairs, so its
UNGATED_DOCSentry is DELETED rather than rewritten, per the ledger contract. Nothing is parked on a filed defect, so no marker is left behind. The ledger now holds 2 rows (README.mdandpackages/fields/README.md); the gate reports227 covered ... 2 ungated, up from 226 covered / 3 ungated.Strictness region
The region from the
Fence scanningbanner to EOF, byte-identical as required:320c84121: sha2562749d53ae3a8df033a53b8d7a354fa7e22ee2d1a17f6ad0c3d61122e904e084ba5c153e8d: sha2562749d53ae3a8df033a53b8d7a354fa7e22ee2d1a17f6ad0c3d61122e904e084bIdentical. The only change to the gate script is the removal of this page's ledger row, which sits above that banner.
Positive control — four legs, on the committed tree
Each leg mutates the committed README, proves the mutation reached DISK before reading any result, runs the real gate, restores, and proves the restore by STATE. Every leg ran under a
trap ... EXIT INT TERMwhose restore isgit checkout HEAD -- ABSOLUTE_PATH(never a baregit checkout -- PATH, which would take the mutation back out of the index). HEAD blob forpackages/plugin-map/README.mdona5c153e8d:00f02c24f025cfbb1711eb7b2ce7c558f9afef2b.objectName: 42f48a08e96f061b65f5dbc6b3a2c91f387ed710c9[semantic] packages/plugin-map/README.md:60:3 TS2322: Type 'number' is not assignable to type 'string'.thisKeyIsInvented: 'x'c06a1e3af10904d48da9b92ff23defbc5924c98bmap.latitudeField: 420645625e27470790cd4cd79a42b0b58823a039f2[semantic] packages/plugin-map/README.md:62:5 TS2322: Type 'number' is not assignable to type 'string'.map.invenTedNestedKey: 'x'9dbfd3e47a201a39252abbbe3625c4c06b412f0b[semantic] packages/plugin-map/README.md:63:5 TS2353: Object literal may only specify known properties, and 'invenTedNestedKey' does not exist in type 'ObjectMapConfig'.After every leg:
git hash-objecton the path equals00f02c24f025cfbb1711eb7b2ce7c558f9afef2bandgit diff HEAD -- PATHis 0 bytes. Restore proven by state, not by an exit code.What legs 2 and 4 measure together — the objectui#7927 bound, stated precisely for the first time on this worklist:
ObjectMapSchema extends BaseSchema, whose index signature swallows any invented top-level key. Leg 2 is that bound, measured.mapkeys ARE checked, both ways: leg 3 catches a wrong VALUE (TS2322) and leg 4 catches an invented KEY (TS2353), becauseObjectMapConfigdeclares no index signature. Assumption A5 in the brief is CONFIRMED by measurement.So the annotation this PR adds buys real key-checking over the
mapblock — the part of these schemas an author most often misspells (latitudeFieIdis the misspelling objectui#5018 exists because of) — while the outer level stays type-checked-but-not-key-checked. That asymmetry is the honest description of what a green run over this page now means.Gates, pinned to
a5c153e8dExit codes captured by redirect-then-capture (never read through a pipe), and quoted from each gate's own verdict line.
pnpm check:doc-snippetsScanned 229 document(s): 227 covered (124 of them hold a ts/tsx block), 2 ungated/Semantic phase: 624 of 624 block(s) judged, 0 failed./Every covered documentation snippet compiles against the built types.pnpm exec vitest run scripts/__tests__/check-doc-snippet-types.test.ts scripts/__tests__/check-doc-fence-languages.test.tsTest Files 2 passed (2)/Tests 123 passed (123)pnpm exec vitest run scripts/__tests__/Test Files 115 passed (115)/Tests 3415 passed (3415)pnpm exec vitest run packages/plugin-map/Test Files 20 passed (20)/Tests 112 passed (112)pnpm check:doc-typesEvery documented component type is registered.pnpm check:readme-exports530 of them self-imports judged (530 real, 0 wrong-path, 0 fabricated)— assumption A4 confirmed: the new@object-ui/typesimport is a CROSS-package import, which this gate does not judge, and theObjectMap/ObjectMapPropsself-imports are both real exports ofpackages/plugin-map/dist/index.d.tspnpm check:doc-fencesevery TypeScript block in 227 document(s) is fenced ts/tsx/typescriptpnpm type-check:scriptstsc -p tsconfig.scripts.jsonpnpm lint:root32 problems (0 errors, 32 warnings)— all pre-existingno-explicit-anywarnings, none in either changed filepnpm check:control-bytesOK (scanned 6579 tracked text file(s); skipped 85 binary)grep -naPcontrol-byte self-scan of both changed pathspnpm check:entry-guard70 scripts/ file(s) — no entry guard outside the baselinenode scripts/check-changeset-presence.mjsNo source or published contract of a released package changed in this range, so no changeset is owed.— so no changeset is added, and no label is used to buy onenode scripts/check-governed-queue-guard.mjs --teston both changed pathsNOT GOVERNED — 2 path(s) checked against 5 governed surface(s); none matched.The gate's build closure was rebuilt before every reading:
pnpm exec turbo run build $(node scripts/check-doc-snippet-types.mjs --build-filter) --concurrency=2, 35 of 35 tasks successful, re-run after the merge.Batch 36 forecast, measured on
a5c153e8dBoth remaining ledger rows, measured with the same analyzer:
packages/fields/README.md— 2tsxfences, 0 parse failures, 3 semantic diagnostics across 2 blocks: TS2307 (Cannot find module './MyCustomColorPicker') at fence 25, and TS7031 x2 (implicitanyon the destructuredfield/value) at fence 37. The row's wording is stale in the familiar way: what it calls "2 undefined-name diagnostic(s)" are implicit-any diagnostics, not undefined names; its "1 unresolved-module" half is accurate.README.md— 5 fences, 0 parse failures, 6 semantic diagnostics across 3 blocks: TS2552 + TS2304 x3 (the four undefined namesmyAPI,MySidebar,SchemaRenderer,schema) and TS2420 + TS2355 (the elidedDataSourceimplementation). This row is ACCURATE, count and classification both — the only row on the ledger that is.Plugin-map was the last of the package READMEs on this worklist.
🤖 Generated with Claude Code
https://claude.ai/code/session_01FhBNJcLRZLe8M87VcUgpKr
Generated by Claude Code