This repository was archived by the owner on Oct 26, 2026. It is now read-only.
Repository navigation
Commit b403bb3
feat(types)!:
Fixes #8347
Clause-②: yes (narrowing)
`BaseSchema` no longer declares `[key: string]: any`. A node literal
annotated with its node type now refuses a key that no declaration
names, a misspelled key included, and the correct spelling still
compiles. This executes the objectui#7927 ruling ("the TypeScript face
is an executable contract"), with the compile-fail pin that ruling made
non-negotiable. `ComponentRendererProps` keeps its own signature, and a
row in the pin notices if it is ever removed. The zod faces and every
runtime path are unchanged, except `visibleWhen` (below).
Governed: this diff touches `AGENTS.md` and two published-skill files
(`skills/objectui/guides/architecture.md`,
`skills/objectui/rules/protocol.md`), so the PR stays a draft until an
authorized approval is on it (`node
scripts/check-governed-queue-guard.mjs --test` answers GOVERNED for each
of them). Session:
`https://claude.ai/code/session_01CPvhwGcirXqBGEdPSb72TZ` (PM loop round
5, claim `5977679107`, amended for patch round 3 by `5979679543`).
## The maintainer's one open choice: the `props` alias on the TypeScript
face
This PR writes **option A**: `props` is not declared on the TypeScript
authoring face. The renderer still reads it at runtime (the maintainer's
2026-08-18 ruling binds the runtime and leaves the TS face open). So the
two `badge` literals in `components`'
`alias-precedence-cross-channel.test.tsx` that author `props` now carry
an `@ts-expect-error` naming this choice, and `AGENTS.md` §4's abridged
listing drops the `props` member that `BaseSchema` never declared.
- **A (written here):** not declared. The dev measurement on
objectui#11364 found no non-test TypeScript, tracked JSON or objectstack
example that authors a node `props`, and the published skill teaches it
as wrong.
- **B:** `props?: unknown` on `BaseSchema`. `AuthoringNode` derives from
the zod `BaseSchema` shape, so B also needs a zod mirror row and a
parity entry.
- **C:** declared on `AuthoringNode` only.
To flip it, remove the two directives and add the member. Nothing else
in this PR depends on the choice.
## What changed, class by class (one commit each)
1. **The two src sites.** `plugin-kanban`: `ObjectKanban` reads the
gate-written `sort` (the binding's `dataSource.sort`) through
`GateBoundKanbanSchema`, a read type private to the file;
`ObjectKanbanSchema` still declares no `sort` (objectui#8174).
`plugin-timeline`: `TimelineRenderSchema`, the private hand-off type,
declares the `onItemClick` slot `ObjectTimeline` composes;
`TimelineSchema` still declares none. Both compile with the signature
present or absent.
2. **The mechanical rows.** Two schema-to-record test reads convert
through `unknown`; the gantt and map `propertiesBag-10859` fixtures keep
`operator` a literal and type the bag node as its block node.
3. **`BaseSchema.visibleWhen`, Q6 = B.** The TS face is the spec's
`EvaluatedExpressionInput`, by reference. The zod twin is the same
accept set (a string, or the spec's own `EvaluatedExpressionSchema`
envelope) with `EvaluatedExpressionInputSchema`'s verdict and without
its string transform.
4. **The removal, and everything that can only land with it.** The
compile-fail pin; the adjudicated probe and ceiling flips; the two
`props` flips; the valueless envelope `metric-card` pinned refused on
the TS face (Q3 = A); `envelopeStray` and its `complex.ts` note deleted
per the constant's own removal condition; the two
`object-view-slot-key-lists` tripwires flipped;
`partial-schema-collapse-pin.test.ts` deleted per its header, with
`PartialSchema`'s docblock describing the alias as it now works; five
mirror-parity ledger entries (below); and the prose in those files that
described the signature as live.
5. **Docs.** The 13 listed doc blocks plus the
`objectos-integration.mdx` page block (now `regions`, and since round 4
rendered under `SchemaRendererProvider`); the published passages that
described the signature as live; the plugin-calendar README note; the
plugin-dashboard README widget-key passage; the `examples/dashboard.ts`
comment; a dated note on the pending `11564` changeset, whose "until
objectui#8347 removes it" sentence this release makes false.
6. **`AGENTS.md`.** §5 #0.1 gains the rule as shipped: the TS authoring
face is part of the contract, a refused key is declared by reference or
fixed at the producer and never cast past, and the fresh-literal bound
is named with the pin that measures it. §4 drops `props`; #4's `events`
sentence names the face that still keeps one.
7. **The changeset.** `minor` for `@object-ui/types` with the breaking
note; `minor` for `plugin-timeline` (`TimelineRenderSchema`, the
`schema` prop type of the exported `TimelineRenderer`, gains one
optional member); `patch` for `plugin-kanban`.
8. **Patch round 3, after the merge of `main` at `b508ac50`.** The two
published-skill sections (H3 below); the five restored deletion guards
and the reworded test strings (Acceptance notes); `main` merged by a
merge commit, with the type-check of every package `main` moved since
the merge base green afterwards.
9. **Patch round 4, doc and comment bytes only.** The integration
guide's App block installs the adapter through `SchemaRendererProvider
dataSource` (the renderer reads it from `SchemaRendererContext`; a
`dataSource` prop on `SchemaRenderer` reaches only the root component),
and its system-objects comment names only the provider. The parity
ledger's `complex.zod.ts#DashboardWidgetSchema` `component` entry says
the mirror slot's `BaseSchema` fallback stays by objectui#8344's
decision, with no open card retiring it, instead of reserving it for
this card.
## The compile-fail pin, both directions
`packages/types/src/__tests__/base-schema-closed-face-8347.test.ts`,
read by `tsc -p tsconfig.test.json`:
- objectui#7927's P5 on a FRESH literal: `titleFieldd` on a
`CalendarViewSchema` literal is an `@ts-expect-error`, and `titleField`
compiles. The same on `BaseSchema` itself (`classNmae` against
`className`), on a node nested in a slot (`labell` on a `button` child),
and on `PartialSchema`.
- P5 as #7927 ran it, on today's plugin-calendar README block, stays
green with or without the signature (measured on this card's census):
that block is a type alias plus two assignments of declared variables,
and tsc never excess-checks those. So the pin uses fresh literals, and
the bound itself is pinned as a directive-free row, so nobody reads the
file as claiming more.
- Ablation, run on the committed head through `ablation-replace.mjs`
(anchor hit 1 to 0, on-disk blob moved, trap-restored to blob equal to
HEAD, `git diff HEAD` empty): with `[key: string]: any` put back on
`BaseSchema`, the types test program exits 2 with 52 errors, and every
refusal row of the pin turns red (TS2578 on the four misspelling rows,
TS2344 on the two no-index rows). At HEAD the same program exits 0.
## The measurements the dispatch named
**H1, the re-census at BASE `2e818d0b5`, before any kept edit.**
Instrument: every package built (turbo, forced: 40 of 40, 0 cached); the
six `BaseSchema` lines deleted and nothing else; types rebuilt (dist
keeps one signature, `ComponentRendererProps`'); then every tsc program
the workspace type-check scripts name, one job each (90 jobs,
apps/site's generators included, plus the four root programs).
| | programs | red | unique errors | src | tests |
|---|---|---|---|---|---|
| BASE, signature removed alone | 90 | 13 | 81 in 44 files | 3 | 78 |
| BASE control, signature present (the same 13) | 13 | 0 | 0 | | |
| final head `e0a9af67`, removal kept | 90 | 0 | 0 | 0 | 0 |
The 81 fall exactly into the predicted classes: src 3 (`ObjectKanban`
`sort` twice, timeline `onItemClick`); tests 67 adjudicated probe and
ceiling flips (types 49; charts `xAxisKy` twice and `objectNme`;
dashboard `bogusKey` twice and `zzUndeclared7353` four times; grid
`bogusKeyRefusedNowhere` and two `Expect` wrappers; list `visibleWhn`
twice; map `enableClusterng`; tree `zzplTreeAbsentControl8655`,
`objectNaem`; components `content` on `label`), 2 `props` flips, 3
mechanical rows (two schema-to-record casts, one mirror-parity ledger
mismatch), and the 6 gantt and map fixture literals. No site needed a
contract decision. `check:doc-snippets` under the removal at BASE: 14 of
777 blocks failed, the 13 listed plus the `objectos-integration.mdx`
page block (BASE control: 0 failed); doc-examples, doc-types and
skill-examples stayed green.
**The parity ledger.** The mismatch was five pairs whose member is typed
with an `interface` (`AppSchemaRendererNodeSchema.schema`; the `reports`
pairs' `report`, `sections`, `chart`) against a `.passthrough()` mirror
whose `z.input` carries a string index signature. TypeScript grants an
implicit index signature to anonymous and mapped types and never to an
interface. Measured: the declared type is refused, and a one-level
anonymous copy of it fits the same mirror input. They are ledgered as an
artifact of the assignability test, with that reading in each entry's
docblock, and the header's derived figures moved with them.
**H2, the objectui#11573 headroom pin.** `AnyComponentSchema`'s
declaration on the compiler's counter: 12260 before, 12974 after (the
`visibleWhen` twin), limit 900000. Read through a trap-deleted copy of
the pin that writes its reading.
**H3, skill fences.** `check:skill-examples` exits 0 under the removal
at BASE and on every head since. Patch round 3 edits the two `skills/**`
files whose prose the removal made false: the architecture guide's "JSON
Protocol" section and the protocol rule's "Component Schema Structure"
section said the published `BaseSchema` declares its members plus an
index signature, and that `props` / `events` / `properties` reach a node
through it. Both now state the two verdicts a key no member declares
gets, one per face (a compile error in a fresh typed literal on the
TypeScript face, with the fresh-literal bound said as AGENTS.md §5 #0.1
says it; kept and judged by the named reader on the tolerant zod face),
and their teaching fences drop the three keys `BaseSchema` never
declared and end on the same no-index-signature line as AGENTS.md §4.
`props` keeps one sentence stating option A, so a flip to B or C is a
one-sentence edit. Neither fence is a marked example;
`check:skill-examples`, `check:skill-eval-tokens` and
`check:skills-paths` stay green.
**H4.** The flex rows' header and `examples/dashboard.ts` no longer say
"until objectui#8347"; the flex test gains the row that removal promised
(a `text` entry misspelled inside the list is refused, and the
well-formed list's `text` entry compiles).
**H5, `visibleWhen`.** `visible-when-spec-input-8347.test.ts`: the TS
member is `Equal` to the spec's `EvaluatedExpressionInput`; on 13 probe
values the mirror's verdict equals `EvaluatedExpressionInputSchema`'s
and `PageComponentSchema.visibleWhen`'s, read in the same run (the probe
set holds both verdicts); a blank string is refused with the spec's own
sentence; a string parses to the same string, while the spec rewrites it
(the control); an envelope parses to itself; and the envelope a spec
parse writes is accepted by both component faces, a dialect-less one
refused. BaseSchema loses its index signature, so a typed node literal refuses an undeclared key; the compile-fail pin, both directions (objectui#8347) (#11607)1 parent fd060f0 commit b403bb3
202 files changed
Lines changed: 2243 additions & 1677 deletions
File tree
- .changeset
- content/docs
- api
- components
- data-display
- form
- core
- guide
- plugins
- examples/schema-catalog/test
- packages
- components/src
- __tests__
- renderers
- complex
- form/__tests__
- plugin-calendar
- src
- __tests__
- plugin-charts/src
- __tests__
- plugin-dashboard
- src
- __tests__
- plugin-designer/src
- plugin-form
- src
- plugin-gantt/src
- plugin-grid/src
- __tests__
- plugin-kanban/src
- plugin-list/src/__tests__
- plugin-map/src
- plugin-timeline/src
- __tests__
- plugin-tree/src
- plugin-view/src
- __tests__
- react/src
- __tests__
- utils
- types
- examples
- src
- __tests__
- zod
- skills/objectui
- guides
- rules
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
16 | 16 | | |
17 | 17 | | |
18 | 18 | | |
| 19 | + | |
| 20 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
| 1 | + | |
| 2 | + | |
| 3 | + | |
| 4 | + | |
| 5 | + | |
| 6 | + | |
| 7 | + | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
74 | 74 | | |
75 | 75 | | |
76 | 76 | | |
77 | | - | |
78 | 77 | | |
79 | 78 | | |
80 | 79 | | |
81 | 80 | | |
82 | 81 | | |
| 82 | + | |
83 | 83 | | |
84 | 84 | | |
85 | 85 | | |
| |||
90 | 90 | | |
91 | 91 | | |
92 | 92 | | |
| 93 | + | |
93 | 94 | | |
94 | 95 | | |
95 | 96 | | |
96 | 97 | | |
97 | 98 | | |
98 | 99 | | |
99 | 100 | | |
100 | | - | |
| 101 | + | |
101 | 102 | | |
102 | 103 | | |
103 | 104 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
96 | 96 | | |
97 | 97 | | |
98 | 98 | | |
99 | | - | |
| 99 | + | |
100 | 100 | | |
101 | 101 | | |
102 | 102 | | |
| |||
109 | 109 | | |
110 | 110 | | |
111 | 111 | | |
112 | | - | |
| 112 | + | |
113 | 113 | | |
114 | 114 | | |
115 | 115 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
42 | 42 | | |
43 | 43 | | |
44 | 44 | | |
45 | | - | |
| 45 | + | |
46 | 46 | | |
47 | 47 | | |
48 | 48 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
49 | 49 | | |
50 | 50 | | |
51 | 51 | | |
52 | | - | |
| 52 | + | |
53 | 53 | | |
54 | 54 | | |
55 | 55 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
| 30 | + | |
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
25 | 25 | | |
26 | 26 | | |
27 | 27 | | |
28 | | - | |
| 28 | + | |
29 | 29 | | |
30 | 30 | | |
31 | 31 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
27 | 27 | | |
28 | 28 | | |
29 | 29 | | |
30 | | - | |
| 30 | + | |
31 | 31 | | |
32 | 32 | | |
33 | 33 | | |
| |||
0 commit comments