Skip to content

Commit 032b9a2

Browse files
committed
docs(types): rewrite the comments objectui#8347 makes false (index signature now gone)
Comment and prose bytes only. Every sentence that said `BaseSchema` (or a node type through it) carries, closes with or ends in `[key: string]: any`, every future-tense "objectui#8347 removes", and every TS2578 note that promised a directive goes unused when its member is deleted, now says what is true at this head: the signature is gone, a deletion is refused on a fresh literal and still rides a widened value, and the zod face keeps its `.passthrough()` reasoning, named as the zod face. AGENTS.md section 5 #0.1 gains the package-local hand-off-type route for a host-written runtime key (objectui#6356). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CPvhwGcirXqBGEdPSb72TZ
1 parent 0334c43 commit 032b9a2

164 files changed

Lines changed: 994 additions & 753 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎AGENTS.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,7 @@ interface BaseSchema {
9090
- **#-1 — English-only codebase.** This is an international OSS project. All user-facing text (component labels, buttons, titles, errors), code comments, docs (`README.md`, `docs/*.md`), and console/log messages MUST be English. No Chinese or other non-English in those. *(This rule governs the **codebase**; this instruction file may use Chinese in operational sections.)*
9191
- **#0 — Strict adherence to `@objectstack/spec`.** All schemas/JSON structures/types MUST follow `@objectstack/spec`. Don't invent schema properties — if the spec says `columns`, don't use `fields`. Check the spec before writing any `interface`/`type`.
9292
- **#0.1 — Fix the metadata, not the renderer (contract-first).** Corollary to #0. This is a metadata-driven system: `@objectstack/spec` is the contract between producers and this renderer. When a piece of metadata "doesn't render," ask **first**: *is it spec-compliant? is this the long-term-correct direction?* If the metadata is off-spec, fix it at the **producer** (and have it rejected at authoring/publish) — do **not** add a lenient fallback/alias in the renderer (reading both `columns` and `fields`, coercing a malformed shape, `??`-defaulting around bad input) to make non-compliant metadata "work." A tolerant fallback fossilizes the wrong convention into a second de-facto contract, dilutes the spec, and hides the producer's bug — one strict contract beats N dialects. We own both ends, so Postel's "be liberal in what you accept" does **not** apply (that's for untrusted boundaries). Change the **spec** only when it is genuinely wrong — deliberately, in `@objectstack/spec`, never by accreting renderer-side fallbacks.
93-
- **The TypeScript authoring face is part of the contract (objectui#7927 ruling, executed by objectui#8347).** `BaseSchema` declares no index signature, so a node literal typed with its node type refuses, at the authoring site, a key no declaration names — a misspelling included. When a key you need is refused, this rule applies unchanged: declare it on the node type that reads it, by reference to the spec row, or fix the producer. ⛔ Never make it compile with `as any`, a cast to `Record<string, unknown>`, a re-added index signature or an open `type: string` arm. Tolerance stays where it is deliberate: renderer props (`ComponentRendererProps` keeps its signature) and the tolerant zod face (`.passthrough()`); the derived strict zod face, `StrictAnyComponentSchema`, refuses an unknown key in metadata that arrives as data. ⚠️ The bound, said per #9: TypeScript excess-checks only a FRESH object literal, so a value that reached its annotation through a wider variable is not re-checked. `packages/types/src/__tests__/base-schema-closed-face-8347.test.ts` pins both directions and that bound.
93+
- **The TypeScript authoring face is part of the contract (objectui#7927 ruling, executed by objectui#8347).** `BaseSchema` declares no index signature, so a node literal typed with its node type refuses, at the authoring site, a key no declaration names — a misspelling included. When a key you need is refused, this rule applies unchanged: declare it on the node type that reads it, by reference to the spec row, or fix the producer; a key only the host writes at runtime is typed on a package-local hand-off type where its producer and consumer live, never on the authoring face (objectui#6356). ⛔ Never make it compile with `as any`, a cast to `Record<string, unknown>`, a re-added index signature or an open `type: string` arm. Tolerance stays where it is deliberate: renderer props (`ComponentRendererProps` keeps its signature) and the tolerant zod face (`.passthrough()`); the derived strict zod face, `StrictAnyComponentSchema`, refuses an unknown key in metadata that arrives as data. ⚠️ The bound, said per #9: TypeScript excess-checks only a FRESH object literal, so a value that reached its annotation through a wider variable is not re-checked. `packages/types/src/__tests__/base-schema-closed-face-8347.test.ts` pins both directions and that bound.
9494
- **#1 — Protocol-agnostic.** Never hardcode `objectql.find()`. Use the DataSource interface; inject `dataSource` via `<SchemaRendererProvider dataSource={...} />`.
9595
- **#2 — Docs-driven.** For every feature/refactor, update package `README.md` **and** `content/docs/guide/*.md`. Not done until docs reflect the code.
9696
- **#3 — "Shadcn-native" aesthetics.** We are "serializable Shadcn". Follow Shadcn's DOM structure (`CardHeader`/`CardTitle`/`CardContent`). Always expose `className` in schema props so users can override via JSON.

‎content/docs/plugins/plugin-chatbot.mdx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -147,9 +147,9 @@ Each registration has its own importable authoring-face type in
147147
nineteen shared rows below are one declaration the two newer faces pick off
148148
`ChatbotSchema` by name, and a scoped row is declared only on the face(s) whose
149149
registration reads it. A key a registration ignores is therefore not a declared
150-
member of its type. It still type-checks (`BaseSchema` ends in an index
151-
signature, so an unlisted key is `any` rather than an error) and still parses
152-
(the Zod twins are `.passthrough()`). It is then dropped silently at render
150+
member of its type. In a typed literal it is a compile error (objectui#8347
151+
removed the `BaseSchema` index signature that typed an unlisted key `any`), but
152+
it still parses (the Zod twins are `.passthrough()`). It is then dropped silently at render
153153
time, on all three registrations alike. `chatbot-floating` used to be the
154154
exception: its registration ended its panel element with an unfiltered props
155155
spread, so three keys its type does not declare (`processVisibility`, `surface`,

‎examples/schema-catalog/test/aspect-ratio-demo-content-6773.test.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,9 +38,9 @@
3838
* and an empty ratio box clears it on the wrapper Radix draws for the ratio
3939
* itself. Its stronger control — the entry's own authored strings on screen —
4040
* is scoped to `NEWLY_REGISTERED_CATEGORIES`, which this family is not in.
41-
* Nor could a parse have caught it: `BaseSchema` is `.passthrough()` and
42-
* carries `[key: string]: any`, so `content` is accepted by zod and by tsc
43-
* alike (the objectui#6157 class-3 shape). `check-doc-component-types.mjs`
41+
* Nor could a parse have caught it: `BaseSchema` is `.passthrough()`, so
42+
* `content` is accepted by zod (and was by tsc, through `[key: string]: any`,
43+
* until objectui#8347) (the objectui#6157 class-3 shape). `check-doc-component-types.mjs`
4444
* rules the question out by name — "NOT in scope, deliberately: whether the
4545
* snippet's OTHER keys are read by the renderer the type resolves to".
4646
*

‎examples/schema-catalog/test/badge-demo-label-6829.test.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,8 +93,8 @@
9393
*
9494
* Arm A restored four demos and did not close the class: `children` was
9595
* declared on `BaseSchema`, accepted by every other container renderer,
96-
* refused by neither zod nor tsc (`BaseSchema` is `.passthrough()` with an
97-
* index signature), and consumed by the pipeline before it could leak to the
96+
* refused by neither zod nor tsc (`BaseSchema` was `.passthrough()` with an
97+
* index signature then), and consumed by the pipeline before it could leak to the
9898
* DOM — so the next author who wrote `children` on a badge drew an empty pill
9999
* again. Arm B (teaching `badge.tsx` to read `children`) widened a published
100100
* renderer's read set, which AGENTS.md #0.1 governs, and was left to

‎examples/schema-catalog/test/button-group-retired-keys-7077.test.ts‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@
1515
* All six fixtures in this category authored keys the shipped types do not
1616
* declare — `buttons[].value` ×17, `buttons[].icon` ×8, group-level `value` ×2
1717
* and `selectionMode` ×2, 29 occurrences over six files. Nothing went red:
18-
* `BaseSchema` is `.passthrough()` and carries `[key: string]: any`, so all 29
19-
* PARSED GREEN and type-checked — admitted unexamined, not refused (the reading
18+
* `BaseSchema` is `.passthrough()` and carried `[key: string]: any` until
19+
* objectui#8347, so all 29 PARSED GREEN and type-checked — admitted unexamined, not refused (the reading
2020
* `component-fixture-declared-keys.test.ts` and
2121
* `undeclared-but-consumed-keys-6150.test.ts` both record), and
2222
* `catalog-gallery-render.test.tsx` fails only on an unregistered `type`. So the

‎examples/schema-catalog/test/card-demo-content-6788.test.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,8 @@
7272
* 1. DECLARED — read off the shipped `CardSchema`'s own zod shape, not a
7373
* hand-copied list, so it follows the platform instead of yesterday's
7474
* vocabulary. `.success` is NOT the probe here and could not be:
75-
* `BaseSchema` is `.passthrough()` and carries `[key: string]: any`, so
76-
* `content` parses green and type-checks. The structural read is the only
75+
* `BaseSchema` is `.passthrough()`, so `content` parses green (and it
76+
* type-checked through `[key: string]: any` until objectui#8347). The structural read is the only
7777
* instrument that sees it.
7878
* 2. READ — the keys `card.tsx` reads, copied as literals on purpose: they
7979
* are the contract this file is about, and a renderer that starts reading

‎examples/schema-catalog/test/catalog-authored-key-6805-6806.test.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -104,9 +104,9 @@
104104
* is objectui#6810, an open `needs-user-decision` card; this file deliberately
105105
* covers only the two renderers these two cards name.
106106
*
107-
* Nor could a parse have caught either: `BaseSchema` is `.passthrough()` and
108-
* carries `[key: string]: any`, so `content` is accepted by zod and by tsc
109-
* alike. `check-doc-component-types.mjs` rules the question out by name.
107+
* Nor could a parse have caught either: `BaseSchema` is `.passthrough()`, so
108+
* `content` is accepted by zod (and was by tsc, through `[key: string]: any`,
109+
* until objectui#8347). `check-doc-component-types.mjs` rules the question out by name.
110110
*
111111
* Module-scope import of `@object-ui/components`, not `beforeAll` (AGENTS.md
112112
* §测试纪律): registering the renderers is an unbounded module load and must

‎examples/schema-catalog/test/component-fixture-declared-keys.test.ts‎

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@
3737
* is therefore round-trip equality, not `.success`.
3838
* 3. **Declared-elsewhere, refused by neither** — `direction` on a
3939
* `radio-group`. `BaseSchema` is `.passthrough()` (`zod/base.zod.js:171`)
40-
* AND carries `[key: string]: any` (`base.d.ts`), so zod and tsc both
41-
* ACCEPT the key. The authority is that `RadioGroupSchema` declares
40+
* AND carried `[key: string]: any` (`base.d.ts`) until objectui#8347, so
41+
* zod and tsc both ACCEPTED the key (tsc refuses it in a typed literal
42+
* now). The authority is that `RadioGroupSchema` declares
4243
* `orientation` (`form.d.ts:377`, `zod/form.zod.js:263`) and nothing reads
4344
* `direction`. The probe must be structural — asserting `.success` here
4445
* would assert nothing at all.

‎examples/schema-catalog/test/kanban-column-cards-6939.test.tsx‎

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -259,9 +259,9 @@ describe('objectui#6939 — the mirror now accepts the spelling every board read
259259
// is STILL green, which is the finding that card had to make rather than
260260
// the one it was sent to make. Two corrections to the paragraph above:
261261
//
262-
// 1. declaring on this face NARROWS, it does not widen — `BaseSchema`
263-
// carries `[key: string]: any` / `.passthrough()`, so a declaration
264-
// can only add validation where there was none;
262+
// 1. declaring on this face NARROWED, it did not widen — `BaseSchema`
263+
// carried `[key: string]: any` / `.passthrough()` then, so a
264+
// declaration could only add validation where there was none;
265265
// 2. `columns[].items` was never refused BY NAME even on the retired
266266
// arm. `KanbanColumnSchema` is a plain (strip-postured) object, so
267267
// `items` was accepted and dropped there too; what refused the

‎packages/components/src/__tests__/action-bar.test.tsx‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ import type { ActionBarSchema } from '@object-ui/types';
1111

1212
/**
1313
* Types each literal below as the `action:bar` node it is rather than as the
14-
* `BaseSchema` `renderComponent` accepts (objectui#11347): once `BaseSchema`'s
15-
* index signature is gone (objectui#8347), a literal checked against
14+
* `BaseSchema` `renderComponent` accepts (objectui#11347): since objectui#8347
15+
* removed `BaseSchema`'s index signature, a literal checked against
1616
* `BaseSchema` may author only `BaseSchema`'s own keys.
1717
*/
1818
const actionBar = (schema: ActionBarSchema): ActionBarSchema => schema;

0 commit comments

Comments
 (0)