From 3c5e89cfaf21d72f0e140f083683d3be0153eafc Mon Sep 17 00:00:00 2001 From: "claude[bot]" Date: Mon, 14 Sep 2026 17:26:30 +0000 Subject: [PATCH] docs(packages): make the three nested package READMEs compile, and retire their UNGATED_DOCS rows objectui#7308 brought the nested `packages/**` READMEs into `check:doc-snippets`' scan surface ledger-first, writing three `UNGATED_DOCS` rows rather than leaving the pages outside the walk. This pays that debt down. The census was re-derived on this branch's base with the gate's own analyzer before any edit, the rows temporarily lifted, and every figure the rows recorded still held: 20 blocks, 13 failing (3 syntax-phase, 10 semantic), 37 diagnostics, split across the three pages exactly as written. The one reader-visible defect is on `packages/core/src/adapters/README.md`. Its custom-adapter template declared `implements DataSource` while omitting `getObjectSchema`, which the interface requires (TS2420), and wrote `// Your implementation` as the whole body of six methods annotated non-`void` (TS2355 x6). A reader who copied it got a class that does not satisfy the interface it claims. The template now implements all six REQUIRED members and throws from each unimplemented body, so the reader's class type-checks at every step of being filled in. The page's two other blocks were excerpts naming a value the prose introduces; each now declares it. `packages/types/src/zod/README.md` had two `{ ... }` elisions TypeScript reads as a spread with no operand, six excerpts continuing an earlier block's imports, one fence holding a before-and-after pair that declared the same two names twice, and a shape sketch fenced as TypeScript. All four classes are repaired in place; the sketch is re-fenced as an unhighlighted block, which takes it out of the ts/tsx population. `packages/components/src/__tests__/README.md` is the single declared fragment. Both of its specifiers were measured refused in this program before the marker was written: `vitest` is this gate's own ROOT-DECLARED control specifier, so the row's first suggested remedy produces a bound failure by construction, and `./test-utils` is TS2307 because every block compiles at the repository root while that helper is suite-local and unshipped. The block now carries the imports a file in that directory really writes, which is what the page owed its reader. Nothing about the gate's strictness moved, and no row was deleted to clear the ledger. The four objectui#7856 card-2 records below them are untouched. Verification: `pnpm check:doc-snippets` exits 0 over 249 documents, 670 of 670 compiled blocks judged, 0 failed, with the sentinel at TS2305, the positive control at 0, and both bound controls at TS2307 in the same run. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_013VGeMu3p6qEFWR6K6GGLaW --- .changeset/9412-ungated-docs-paydown.md | 27 +++++ packages/components/src/__tests__/README.md | 12 +- packages/core/src/adapters/README.md | 83 ++++++++++--- packages/types/src/zod/README.md | 47 ++++++-- .../__tests__/check-doc-snippet-types.test.ts | 63 +++++++--- scripts/check-doc-snippet-types.mjs | 113 ++++++++---------- 6 files changed, 242 insertions(+), 103 deletions(-) create mode 100644 .changeset/9412-ungated-docs-paydown.md diff --git a/.changeset/9412-ungated-docs-paydown.md b/.changeset/9412-ungated-docs-paydown.md new file mode 100644 index 0000000000..091094a533 --- /dev/null +++ b/.changeset/9412-ungated-docs-paydown.md @@ -0,0 +1,27 @@ +--- +--- + +Pay down the three `UNGATED_DOCS` rows objectui#7308 opened for the nested +package READMEs, so `scripts/check-doc-snippet-types.mjs` compiles all three +pages instead of declaring them unverified. + +The one reader-visible defect is on `packages/core/src/adapters/README.md`: the +custom-adapter template declared `implements DataSource` while omitting +`getObjectSchema`, which the interface requires, and wrote `// Your +implementation` as the whole body of six methods annotated non-`void`. A reader +who copied it got a class that does not satisfy the interface it claims. The +template now carries all six required members and throws from each +unimplemented body, so it type-checks at every step of being filled in. + +`packages/types/src/zod/README.md` had two `{ ... }` elisions TypeScript reads +as a spread with no operand, six excerpts continuing an earlier block's imports, +one fence holding a before-and-after pair that declared the same two names +twice, and a shape sketch fenced as TypeScript. `packages/components/src/__tests__/README.md` +gains the imports a file in that directory really writes, and a fragment +declaration saying why a probe compiled at the repository root cannot resolve +either of them. + +No published file changes: none of the three pages is inside any package +tarball — each package's manifest `files` list carries `dist` and the +package-root `README.md`, and `npm pack --dry-run` reports zero entries under +`src/` for all three. Gate script and its own test suite only, otherwise. diff --git a/packages/components/src/__tests__/README.md b/packages/components/src/__tests__/README.md index 9a45b5ae3e..98868b2438 100644 --- a/packages/components/src/__tests__/README.md +++ b/packages/components/src/__tests__/README.md @@ -99,9 +99,19 @@ The failing tests have discovered legitimate issues with component schemas and p ## Adding New Tests -When adding a new component, follow this pattern: +When adding a new component, follow this pattern — the imports are the ones a +file in this directory writes, so copy the block whole: + ```typescript +import { describe, it, expect } from 'vitest'; + +import { + getAllDisplayIssues, + renderComponent, + validateComponentRegistration, +} from './test-utils'; + describe('NewComponent Renderer', () => { it('should be properly registered', () => { const validation = validateComponentRegistration('new-component'); diff --git a/packages/core/src/adapters/README.md b/packages/core/src/adapters/README.md index e65b2d84cf..fca6f2c99e 100644 --- a/packages/core/src/adapters/README.md +++ b/packages/core/src/adapters/README.md @@ -190,6 +190,11 @@ renderer calls; components do not branch on `provider` themselves. ```typescript import { resolveDataSource } from '@object-ui/core'; +import type { DataSource } from '@object-ui/types'; + +// The `DataSource` the renderer already holds from context. It is what +// `provider: 'object'` resolves to, and the fallback for every other case. +declare const contextDataSource: DataSource; const dataSource = resolveDataSource( { provider: 'api', read: { url: '/api/users' } }, @@ -215,6 +220,10 @@ stay ignorant of which one ran. ```typescript import { runBatchTransaction } from '@object-ui/core'; +import type { DataSource } from '@object-ui/types'; + +// The adapter the view resolved to — see `resolveDataSource` above. +declare const dataSource: DataSource; // `{ $ref: 0 }` resolves to the id minted by operation 0 (the parent). await runBatchTransaction(dataSource, [ @@ -234,39 +243,79 @@ for the capability negotiation that decides which path is taken. ## Creating Custom Adapters -To create a custom adapter, implement the `DataSource` interface: +To create a custom adapter, implement the `DataSource` interface. It requires +**six** members — `find`, `findOne`, `create`, `update`, `delete` and +`getObjectSchema` — and everything else on it is optional. `getObjectSchema` is +easy to miss and is not optional: schema-dependent components call it before they +render, which is why `ApiDataSource` answers it with a minimal stub rather than +omitting it. ```typescript import type { DataSource, QueryParams, QueryResult } from '@object-ui/types'; export class MyCustomAdapter implements DataSource { + // ── The six members `DataSource` requires ─────────────────────────────── + async find(resource: string, params?: QueryParams): Promise> { - // Your implementation + throw new Error(`find(${resource}) is not implemented yet`); } - - async findOne(resource: string, id: string | number): Promise { - // Your implementation + + async findOne( + resource: string, + id: string | number, + params?: QueryParams, + ): Promise { + throw new Error(`findOne(${resource}, ${id}) is not implemented yet`); } - + async create(resource: string, data: Partial): Promise { - // Your implementation + throw new Error(`create(${resource}) is not implemented yet`); + } + + async update( + resource: string, + id: string, + data: Partial, + opts?: { ifMatch?: string }, + ): Promise { + throw new Error(`update(${resource}, ${id}) is not implemented yet`); } - - async update(resource: string, id: string | number, data: Partial): Promise { - // Your implementation + + async delete( + resource: string, + id: string | number, + opts?: { ifMatch?: string }, + ): Promise { + throw new Error(`delete(${resource}, ${id}) is not implemented yet`); } - - async delete(resource: string, id: string | number): Promise { - // Your implementation + + /** + * Required. Return the object's metadata, or a minimal stub + * (`{ name, fields: {} }`) when your backend exposes none — see + * `ApiDataSource` above. + */ + async getObjectSchema(objectName: string): Promise { + return { name: objectName, fields: {} }; } - - // Optional: bulk operations - async bulk?(resource: string, operation: string, data: Partial[]): Promise { - // Your implementation + + // ── Optional: implement only what your backend actually supports ─────────── + + async bulk?( + resource: string, + operation: 'create' | 'update' | 'delete', + data: Partial[], + ): Promise { + throw new Error(`bulk(${resource}, ${operation}) is not implemented yet`); } } ``` +The bodies above **throw** rather than fall off the end: a method annotated +`Promise>` that returns nothing is a type error, and a template +that does not type-check is one a reader copies into a class that does not +satisfy the interface it claims to implement. Replace each `throw` as you go and +the class stays checkable at every step. + ## Related Packages - `@object-ui/types` — the `DataSource`, `QueryParams` and `ViewData` definitions these adapters implement diff --git a/packages/types/src/zod/README.md b/packages/types/src/zod/README.md index 07a12c6b9c..80b62c727a 100644 --- a/packages/types/src/zod/README.md +++ b/packages/types/src/zod/README.md @@ -217,7 +217,7 @@ function validateComponent(config: unknown) { All component schemas follow the @objectstack/spec UI specification format: -```typescript +```text { // Required type: string, // Component type identifier @@ -243,6 +243,8 @@ All component schemas follow the @objectstack/spec UI specification format: ### Error Messages ```typescript +import { ButtonSchema } from '@object-ui/types/zod'; + const result = ButtonSchema.safeParse({ type: 'button', variant: 'invalid-variant' @@ -264,6 +266,8 @@ const result = ButtonSchema.safeParse({ ### Nested Validation ```typescript +import { CardSchema } from '@object-ui/types/zod'; + // Validates nested components in Card const cardWithChildren = CardSchema.parse({ type: 'card', @@ -279,6 +283,11 @@ const cardWithChildren = CardSchema.parse({ 1. **Use safeParse()** for user input validation ```typescript + import { ButtonSchema } from '@object-ui/types/zod'; + + // Whatever arrived from the form, the request body or the config file. + declare const userInput: unknown; + const result = ButtonSchema.safeParse(userInput); if (!result.success) { // Handle errors gracefully @@ -287,6 +296,11 @@ const cardWithChildren = CardSchema.parse({ 2. **Use parse()** for internal configurations ```typescript + import { ButtonSchema } from '@object-ui/types/zod'; + + // A configuration your own code produced, so a throw is the right failure. + declare const internalConfig: unknown; + // Throws error on invalid data const config = ButtonSchema.parse(internalConfig); ``` @@ -301,10 +315,10 @@ const cardWithChildren = CardSchema.parse({ ```typescript import type { ButtonSchema as ButtonType } from '@object-ui/types'; import { ButtonSchema } from '@object-ui/types/zod'; - + // Use type for declarations - const config: ButtonType = { ... }; - + const config: ButtonType = { type: 'button', label: 'Save', variant: 'default' }; + // Use schema for validation ButtonSchema.parse(config); ``` @@ -322,9 +336,15 @@ Zod schemas are designed for runtime validation: ### With React Hook Form ```typescript -import { zodResolver } from '@hookform/resolvers/zod'; import { FormSchema } from '@object-ui/types/zod'; +// `react-hook-form` and `@hookform/resolvers` are YOUR app's dependencies, not +// this package's. These two stand in for `import { useForm } from +// 'react-hook-form'` and `import { zodResolver } from '@hookform/resolvers/zod'` +// so the schema half below is still checked against the shipped types. +declare function useForm(options: { resolver: unknown }): unknown; +declare function zodResolver(schema: unknown): unknown; + const form = useForm({ resolver: zodResolver(FormSchema), }); @@ -354,6 +374,9 @@ export async function POST(req: Request) { ```typescript import { AnyComponentSchema } from '@object-ui/types/zod'; +// Your own store of validated configurations. +declare const registry: Map; + function registerComponent(config: unknown) { // Validate before registration const validated = AnyComponentSchema.parse(config); @@ -365,16 +388,22 @@ function registerComponent(config: unknown) { If you're currently using only TypeScript types: +Before — the type alone, checked only where the literal is written: + ```typescript -// Before (TypeScript only) import type { ButtonSchema } from '@object-ui/types'; -const button: ButtonSchema = { ... }; -// After (with runtime validation) +const button: ButtonSchema = { type: 'button', label: 'Save' }; +``` + +After — the same literal, plus a runtime check at the boundary. Import the type +under an alias, because the Zod twin ships under the same name: + +```typescript import type { ButtonSchema as ButtonType } from '@object-ui/types'; import { ButtonSchema } from '@object-ui/types/zod'; -const button: ButtonType = { ... }; +const button: ButtonType = { type: 'button', label: 'Save' }; const validated = ButtonSchema.parse(button); ``` diff --git a/scripts/__tests__/check-doc-snippet-types.test.ts b/scripts/__tests__/check-doc-snippet-types.test.ts index 557cf6ff62..f98cdda521 100644 --- a/scripts/__tests__/check-doc-snippet-types.test.ts +++ b/scripts/__tests__/check-doc-snippet-types.test.ts @@ -984,7 +984,21 @@ describe('objectui#7308 — the nested package READMEs are in the scan set, ledg expect(new Set(walked).size).toBe(walked.length); }); - it('the widening is VISIBLE to the accounting: block-bearing pages are ledgered, block-free ones are covered', () => { + /** + * objectui#9412 paid the three rows down, so this pin's direction INVERTED: + * where it used to say "every block-bearing nested page is on the ledger", the + * state it now holds is that NONE of them is, and that every one of them is + * covered. Both readings are the same claim about the accounting — the + * widening is visible in it — and the half that was never about the debt is + * kept verbatim: a nested page with no ts/tsx block is covered at zero blocks + * and may not be ledgered. + * + * ⛔ The inversion is not a relaxation. A ledgered nested page would still be + * legal the day somebody writes a row with a reason (`analyze` re-derives every + * row), and the sibling case below is what keeps the row's SHAPE requirement + * live for that day. + */ + it('the widening is VISIBLE to the accounting: every nested page is covered, none is ledgered', () => { const state = analyze({}) as { scans: Map; covered: string[]; @@ -992,31 +1006,48 @@ describe('objectui#7308 — the nested package READMEs are in the scan set, ledg const nested = nestedPackageReadmePages(repoRoot); const withBlocks = nested.filter((doc) => (state.scans.get(doc)?.blocks.length ?? 0) > 0); const withoutBlocks = nested.filter((doc) => (state.scans.get(doc)?.blocks.length ?? 0) === 0); - // Non-vacuous on BOTH halves — this is the assertion that says why three rows - // were written for four pages. + // Non-vacuous on BOTH halves — a nested page that really holds blocks, and a + // nested page that really holds none, are each present in the tree. expect(withBlocks.length).toBeGreaterThan(0); expect(withoutBlocks.length).toBeGreaterThan(0); - expect([...withBlocks].sort()).toEqual( - Object.keys(UNGATED_DOCS as Record) - .filter((doc) => nested.includes(doc)) - .sort(), - ); + // The debt is paid: no nested README is ungated any more. + expect(Object.keys(UNGATED_DOCS as Record).filter((doc) => nested.includes(doc))).toEqual([]); // A page with no ts/tsx block is COVERED at zero blocks and may not be // ledgered: the stale-entry check would refuse it, which is exactly why // leaving it out of the surface to keep the ledger short is not available. - for (const doc of withoutBlocks) expect(state.covered).toContain(doc); + // The block-bearing ones are covered now too, and the gate compiles them. + for (const doc of nested) expect(state.covered).toContain(doc); }); - it('every new ledger row carries a measured count, the phases, and what would have to change', () => { + it('every ledger row a nested page might get still owes a measured count, the phases, and what would have to change', () => { + const shapeFailures = (reason: string) => + [ + [/\d+ `tsx?` blocks?/, 'names no block count'], + [/\d+ diagnostics/, 'names no diagnostic count'], + [/TS\d{4}/, 'names no diagnostic code'], + [/syntax-phase|semantic-phase/, 'does not say which phase was measured'], + [/What would have to change|would have to change/, 'does not say what would have to change'], + ].flatMap(([pattern, complaint]) => ((pattern as RegExp).test(reason) ? [] : [complaint as string])); + + // Non-vacuity, in place of the population this used to loop over: the shape + // checker itself is exercised against a row that satisfies it and one that + // does not, so a nested row reappearing cannot land on a check that has + // quietly stopped checking anything. + expect( + shapeFailures( + '2 `ts` blocks, 4 diagnostics, ALL semantic-phase: TS2304 x4. What would have to change: the ' + + 'excerpts declare the values they use.', + ), + ).toEqual([]); + expect(shapeFailures('this page does not compile')).toHaveLength(5); + + // Today: the nested leg carries no ledger row at all (objectui#9412). The + // loop below is what applies the shape the day one returns. const nested = new Set(nestedPackageReadmePages(repoRoot)); const entries = Object.entries(UNGATED_DOCS as Record).filter(([doc]) => nested.has(doc)); - expect(entries.length).toBeGreaterThan(0); + expect(entries).toEqual([]); for (const [doc, reason] of entries) { - expect(reason, `${doc}: names no block count`).toMatch(/\d+ `tsx?` blocks?/); - expect(reason, `${doc}: names no diagnostic count`).toMatch(/\d+ diagnostics/); - expect(reason, `${doc}: names no diagnostic code`).toMatch(/TS\d{4}/); - expect(reason, `${doc}: does not say which phase was measured`).toMatch(/syntax-phase|semantic-phase/); - expect(reason, `${doc}: does not say what would have to change`).toMatch(/What would have to change|would have to change/); + expect(shapeFailures(reason), `${doc}: ${shapeFailures(reason).join('; ')}`).toEqual([]); } }); diff --git a/scripts/check-doc-snippet-types.mjs b/scripts/check-doc-snippet-types.mjs index 8265663f7d..ae23012253 100644 --- a/scripts/check-doc-snippet-types.mjs +++ b/scripts/check-doc-snippet-types.mjs @@ -1031,6 +1031,56 @@ const TS_FENCE_LANGUAGES = new Set(['ts', 'tsx', 'typescript']); * stays here because this ledger keeps the record of why each declaration * existed, not because the page still carries them. * + * Batch 5 (objectui#9412) paid down objectui#7308's three NESTED package-README + * rows, the whole of that card's debt half. Re-derived first on `8196b10631` + * with this gate's own analyzer, the rows temporarily lifted — `analyze({ ungated + * })` for the population, `compileSnippets()` for the phases, over the closure + * `--build-filter` names (35/35 turbo tasks successful) — and every figure the + * rows recorded on `9ba7e9c3` still held: 20 blocks, 13 failing (3 syntax-phase, + * 10 semantic), 37 diagnostics, split across the pages exactly as written. In + * the same runs the sentinel produced TS2305, the positive control 0, and both + * bound controls TS2307, so the zeros below are readings from a program that + * demonstrably reports non-zero. + * + * Its defect was the one objectui#7308 named first, and it is the kind this gate + * exists for: `packages/core/src/adapters/README.md`'s custom-adapter template + * declared `implements DataSource` while omitting `getObjectSchema` (TS2420), + * and wrote `// Your implementation` as the whole body of six methods annotated + * non-`void` (TS2355 x6). A reader who copied it got a class that does not + * satisfy the interface it claims. The template now implements all six REQUIRED + * members — `find`, `findOne`, `create`, `update`, `delete`, `getObjectSchema` — + * and each unimplemented body throws rather than falling off the end, so the + * reader's class type-checks at every step of filling it in. + * + * Routes, in the two the batches above established: 19 blocks compile (the two + * `{ ... }` elisions on the zod page written as real initialisers, six excerpts + * given their own imports or a `declare const` stand-in, one before/after fence + * split into the two programs it was really holding, and the shape sketch + * re-fenced ```text, which takes it out of the ts/tsx population), and ONE block + * is a declared fragment: `packages/components/src/__tests__/README.md`'s + * "Adding New Tests" pattern. Both of its specifiers were measured refused in + * this program before the marker was written — `vitest` is the ROOT-DECLARED + * control specifier itself, so the row's own first remedy ("the block imports + * `describe`/`it`/`expect` from `vitest`") produces a `[bound]` failure by + * construction, and `./test-utils` is TS2307 because every block compiles at the + * repository root while that helper is suite-local and unshipped + * (`@object-ui/components` lists `dist` in `files`, and `dist/` holds no + * `test-utils`). The row anticipated exactly that and named the marker as its + * alternative. The block imports the two specifiers anyway, because they are the + * ones a file in that directory really writes, and a stand-in would have taught a + * spelling nobody should copy; the marker costs no coverage here, since the block + * imports no documented package surface at all. + * + * ⚠️ One claim in the retired zod row was FALSE and is corrected rather than + * carried forward: it said `packages/types` "lists the whole of `src/` in its + * manifest `files`", so `src/zod/README.md` ships in the npm tarball. It does + * not. That manifest's `files` is `['dist', 'README.md', 'CHANGELOG.md', + * 'LICENSE']`, and `npm pack --dry-run --json` in that package reports 134 + * entries, none of them under `src/` and exactly one README — the package-root + * one. The page was still worth clearing, on the reason every other row here + * gives: it is a page a reader copies from. It is not worth clearing because it + * ships, and a later card should not plan around that. + * * objectui#5343 then read that list back and cleared it for the getting-started * pages: no entry for `content/docs/guide/**` or for * `content/docs/api/schema-reference.md` names a missing export any more. Every @@ -1057,66 +1107,9 @@ const TS_FENCE_LANGUAGES = new Set(['ts', 'tsx', 'typescript']); * @type {Record} */ const UNGATED_DOCS = { - // objectui#7308 — the nested package READMEs, LEDGER-FIRST. Measured on - // `9ba7e9c3` with this gate's own analyzer against the closure `--build-filter` - // names (35/35 turbo tasks successful): `analyze({ ungated: {} })` for the - // population, `compileSnippets()` for the phases, with the surface widened and - // these rows NOT yet written — which is the only order in which the numbers - // below are readings rather than justifications. - // - // The census, with each population named: the widening adds 4 documents - // (245 -> 249 in the scan set) carrying 20 `ts`/`tsx` blocks, of which 13 fail - // — 3 in the syntax phase and 10 in the semantic phase — for 37 diagnostics. - // - // ⚠️ Only THREE rows appear below for those four documents, and the missing - // fourth is mechanical rather than an exclusion: `packages/plugin-gantt/docs/ - // verification/README.md` holds no `ts`/`tsx` fenced block at all (its fences - // are `sh`), so it joins the COVERED tier at zero blocks, and a row naming it - // here would fail this gate's own re-derivation as a stale entry — "an entry - // naming a file that ... holds no `ts` / `tsx` block at all, fails as a stale - // entry". ⛔ That is the opposite of keeping the ledger short by quietly leaving - // a page outside the surface, which is the defect objectui#7308 reported. - // - // ⚠️ These three rows are DEBT, not a terminal state — unlike the objectui#7856 - // card 2 rows below, which are records nobody may repair. A package README is a - // page a reader copies from, so every row here can and should leave by the page - // compiling. Paying it down is its own card; ⛔ softening this gate is not a way - // to pay it. - 'packages/components/src/__tests__/README.md': - '1 `ts` block (fence 104), 9 diagnostics, ALL semantic-phase: TS2593 x3, TS2304 x5, TS2552 x1. The ' + - "block is the page's \"Adding New Tests\" pattern: a bare `describe`/`it` body with no imports at all, " + - 'so the Vitest globals (`describe`, `it`, `expect`) and the three local helpers it calls ' + - '(`validateComponentRegistration`, `renderComponent`, `getAllDisplayIssues`) are all undefined names. ' + - 'What would have to change: the block imports `describe`/`it`/`expect` from `vitest` and the three ' + - 'helpers from wherever this test suite ships them — or, if the helpers are suite-local and have no ' + - 'importable home, the block gets a `FRAGMENT_MARKER` saying so.', - 'packages/core/src/adapters/README.md': - '5 `ts` blocks (fences 36, 70, 191, 216, 239); 2 of them compile untouched. 3 fail with 9 diagnostics, ' + - 'ALL semantic-phase: TS2304 x2, TS2355 x6, TS2420 x1. Two are excerpts naming a value the prose ' + - 'introduces but the block never declares (`contextDataSource` at fence 191, `dataSource` at fence 216). ' + - "⚠️ The third is a DOCUMENTED-API defect rather than a snippet-hygiene one, and it is the first thing " + - 'this widening found: the custom-adapter template at fence 239 declares `class MyCustomAdapter ' + - "implements DataSource` while omitting `getObjectSchema`, which `DataSource` requires (TS2420), " + - 'and its six method bodies are `// Your implementation` comments under non-`void` return annotations ' + - '(TS2355 x6). A reader who copies it gets a class that does not satisfy the interface it claims. What ' + - 'would have to change: the template gains `getObjectSchema` and returns a value from each body (or ' + - 'declares the bodies elided), and the two excerpts declare the value they use.', - 'packages/types/src/zod/README.md': - '14 `ts` blocks (fences 88, 110, 140, 151, 220, 245, 266, 281, 289, 301, 324, 334, 354, 368); 5 compile ' + - 'untouched. 9 fail with 19 diagnostics: 3 fail in the syntax-phase (fences 220, 301, 368 — TS1109 x10, ' + - 'so their semantic half is UNMEASURED, not clean) and 6 fail in the semantic-phase (TS2304 x8, ' + - 'TS2307 x1). Three ' + - 'classes, each with its own remedy. (1) Fence 220 is a SHAPE SKETCH — a bare object literal at ' + - "statement position with `?:` optionality markers written on keys and `type: string` standing where a " + - 'value goes; its fence language should be one this gate does not compile. (2) Fences 301 and 368 write ' + - 'the elision `{ ... }` literally, which TypeScript reads as a spread with no operand. (3) The six ' + - 'semantic failures are EXCERPTS that continue an earlier block’s imports — `ButtonSchema`, ' + - '`CardSchema`, `userInput`, `internalConfig`, `useForm`, `registry` — plus one specifier no imported ' + - 'package declares (`@hookform/resolvers/zod`, TS2307), which is the bound this header states rather ' + - 'than a page defect. What would have to change: each excerpt made self-contained against the built ' + - '`dist/*.d.ts`, the two elisions written as real initialisers, and the sketch’s fence relabelled. ' + - '⭐ This page SHIPS: `packages/types` lists the whole of `src/` in its manifest `files`, so it is ' + - 'inside the npm tarball a reader downloads — which is why objectui#7308 filed it first.', + // objectui#7308's three nested-package-README rows were PAID DOWN by + // objectui#9412 and are gone from this object. Their record is in the header + // above, under "Batch 5"; nothing was softened here to retire them. // objectui#7856 card 2. Measured on `fedfa3e4` with this gate's own analyzer // against the closure `--build-filter` names (35/35 turbo tasks successful): // `analyze({ ungated: {} })` for the population, `compileSnippets()` for the