Skip to content

feat(types): ObjectGridSchema's zod mirror declares ten members its TypeScript twin declares (objectui#6152 round 6) - #11492

Merged
objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-6152-objectgrid-round6
Oct 2, 2026
Merged

objectstack-fleet[bot] merged 4 commits into
mainfrom
claude/issue-6152-objectgrid-round6

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #6152 (round 6). The card stays open: ObjectGridSchema.resizableColumns stops here with an open question (below), the three spec-derived pairs route to objectui#2231, and the two chatbot displayMode entries stay by decision (objectui#7654 ruling B).

Clause-②: yes
Why yes (mixed): the strict face widens on an object-view's table slot, where nine keys it refused as unknown are now declared. The tolerant face narrows there and on the flat mirror: a wrongly typed value it kept unexamined is now refused at the key. No TypeScript declaration changes shape.

Round 6 in one paragraph

ObjectGridSchema's UnmirroredDeclared entry held eleven keys. Each was measured first: authored writers in both repositories, readers by a type-checker census and a runtime probe through the real SchemaRenderer and registry, and the member of the spec's ComponentPropsMap['object-grid'] row. Ten are MIRRORED on the flat zod ObjectGridSchema: aggregations, bulkActionDefs, conditionalFormatting, grouping, navigation, operations, reorderableColumns, rowColor, rowHeight and singleClickEdit. The eleventh, resizableColumns, is NOT retired: the seat's answer A predates objectui#11276, which moved the authored node into the spec's properties bag, and executing it now would leave that bag accepting a key nothing reads (open question below). UnmirroredDeclared goes from 5 entries / 16 keys to 5 / 6 (spec-derived 3 / 14 to 3 / 4; local 2 / 2 unchanged).

Measured first (base 50c73fed0)

H1 held. A TypeScript-parser count of interface UnmirroredDeclared at the base reads 5 entries / 16 keys, with 11 on objectql.zod.ts#ObjectGridSchema, the eleven the claim names. KnownDrift 49 / 86, RuntimeOnlyDeclared 5 / 30 and RuntimeOnlyNamedAllowList 4 / 23 read the same at the base, at main 401611b2 and at this head.

H2: the authoring side is the spec's for all eleven. A one-off probe through the built faces (AnyComponentSchema, StrictAnyComponentSchema, the spec row, the flat mirror):

  • written flat on an object-grid node, every one of the eleven is refused by name on both faces, toward properties.KEY (flatPropRefusals);
  • in the bag, the spec row judges it: reorderableColumns, resizableColumns and singleClickEdit as booleans, bulkActionDefs as an array of unknown entries, and the other seven as unknown (a properties.grouping: 42 parses on both faces);
  • in an object-view's table slot, which is built from the flat mirror: nine keys were kept unexamined by the tolerant face and refused as unknown keys by the strict face, while navigation and resizableColumns are refused by name (withheld).

So the remaining question per key is the hoisted node's parity (the TypeScript ObjectGridSchema, which ObjectGrid reads) and the table slot that inherits the mirror.

H3: every key is read. Type-checker census over packages/*/src and apps/*/src (5697 files; controls objectName 58 reads, columns 13, resizable 2): every key has a src read in ObjectGrid, and ObjectView reads table.operations and relays six more through tableRelay. The first census run read 0 for the objectName control: its file list had dropped every file directly under a src/ root. That run was discarded and the enumeration fixed. Runtime probe (one-off, deleted): an authored node { type: 'object-grid', properties: { … } } through the real registry, varying one key, with a fetch double recording every request. Every key changed the drawn markup or the adapter calls:

key runtime reading (base)
aggregations the group header query gains a sum of amount, and the header draws it
bulkActionDefs after a row is selected, the bulk bar draws the def's button
conditionalFormatting the matching row gains its background-color
grouping the grid asks queryGroupHeaders and draws grouped sections
navigation clicking a row opens the drawer overlay
operations export: false removes the export button that exportOptions draws
reorderableColumns header cells become draggable="true"
resizableColumns false removes the column resize handle (no resizable written)
rowColor the row's background class changes
rowHeight the row-height toolbar appears
singleClickEdit absent, one click opens the cell editor; false, it does not

Controls: the same document rendered twice is byte-identical; columns changed (the lit control) differs. A first run was stopped by the repository's network-escape guard (a permission read reached a real socket) and its readings were discarded; the recorded run stubs fetch and records each request in the compared log.

H4: singleClickEdit on object-grid is authored, not host-paired. Unlike DataTableSchema (round 5), the spec's object-grid row declares it ("Enter cell edit on single click (default true when editable)"), and the grid supplies its own save path. So it is mirrored here, by reference to the row member, and round 5's runtime-only filing was not copied across.

Authored census. objectui: an AST and JSON walk over 497 JSON files, 1561 Markdown fences and 6083 TS/TSX files, with controls object-grid bag objectName 31 and table.columns 15. It found no document writing any of the eleven in an object-view table slot (two typed tests only). In an object-grid bag, three doc fences write keys this round mirrors: operations in README.md and content/docs/api/schema-reference.md, singleClickEdit in content/docs/plugins/plugin-grid.mdx. The in-code producers are ObjectView (the relayed keys), FieldDesigner / ObjectManager (operations) and the plugin-grid demo. resizableColumns is written nowhere. objectstack main 3a6d92f7 (read by git grep on a self-named ref): its two authored object-grid nodes, the showcase work queues, write objectName / columns / filter only, and nothing in it authors an object-view.

What changed

packages/types/src/zod/objectql.zod.ts, the flat ObjectGridSchema mirror:

key member before after
grouping the spec's GroupingConfigSchema, by reference kept unexamined judged; a padded field name is refused by the spec's own rule
navigation the spec's NavigationConfigSchema, by reference kept judged (the table slot still refuses it by name)
rowColor the spec's RowColorConfigSchema, by reference kept judged
rowHeight the spec's RowHeightSchema, by reference kept the five presets only
reorderableColumns, singleClickEdit the row's own boolean members, by reference kept boolean
aggregations strict { field, type } entry, restating the twin kept judged; unknown member named
operations strict six-toggle object, restating the twin kept judged; a misspelt toggle named
bulkActionDefs strict entry restating BulkActionDef; operation and visible's second arm by reference to the spec kept judged
conditionalFormatting the two-dialect rule, now one private declaration shared with ListViewSchema's mirror kept judged
  • The ten members are those the TypeScript twin declares, so NarrowerThanDeclared and WiderThanDeclaredKeys measure nothing new, and no KnownDrift or WiderThanDeclared row was added. The spec row types seven of the ten as unknown. Binding those would have mirrored nothing, so each member takes the spec schema the twin names, or the twin's own shape.
  • bulkActionDefs is NOT the spec's BulkActionDefSchema by reference. Measured against the twin, that schema is narrower on params (a strict entry with a closed type) and on visible (no ExpressionWire arm), so binding it would have needed a KnownDrift row.
  • ListViewSchema's conditionalFormatting now reads the hoisted rule. Its accept set is unchanged, and the zod ListViewSchema member is the same union.

packages/types/src/objectql.ts: only singleClickEdit's comment. It said @default false, but ObjectGrid reads schema.singleClickEdit ?? true and the spec row says the default is true.

packages/types/src/__tests__/zod-mirror-parity.test.ts: the ObjectGridSchema entry goes from eleven keys to resizableColumns, with the round's route written on it. The four pinned figure sites and the history sentences moved with it (header bullet 5 / 6; both ledger docstrings 6 keys; totals line 5 / 6 with 3 / 4 and 2 / 2; the spec-derived bullet 3 / 4).

Doors, before and after:

door before after
authored object-grid (properties bag) the spec row judges unchanged
object-grid prop written flat on the node refused by name unchanged
object-view table, strict face (objectui validate) the nine refused as unknown keys a declared value parses; a wrong one is refused at the key
object-view table, tolerant face (safeValidateSchema) any value kept unexamined a wrong value refused at the key
ObjectGridSchema.safeParse directly kept judged

Pins

  • New packages/types/src/__tests__/unmirrored-declared-round6-6152.test.ts (49 rows). For each key it checks that the mirror accepts the declared value and refuses a wrong one at the key, then drives the nine slot keys through the table slot on both faces. It holds that table.navigation / table.resizableColumns stay refused by name, and that the authored node does not move (flat refused by name, bag parses). It pins the two row members by identity, the spec's padded-name rule reaching grouping, the shared conditional-formatting rule by identity with ListViewSchema's, and the strict entries naming unknown members. It also holds that resizableColumns is not a member.
  • grouping-field-padded-refused-7347.test.ts: the census now finds table.grouping on object-view, as the 2026-09-30 evidence comment on 121 declared-but-unmirrored keys across 16 schema pairs — the lane #6058's new UnmirroredDeclared ledger made visible #6152 predicted for the first round that mirrored this key. The table slot gets its own row and so carries the padded-field refusal on every face (the row type gained an optional type so one arm can own two paths).
  • imported-defaults-8317.test.ts: the four new spec crossings are registered, and the mirror reads the row's members through the boundary (stripImportedDefaults(SpecObjectGridPropsSchema).shape.KEY).

Corpus and pending changesets re-judged

  • The three doc fences above write their keys in the object-grid bag, which the spec judges and this round does not touch. content/docs/plugins/plugin-view.mdx's table section lists the relayed keys as declared, and the validator now agrees with it. No corpus document needed a change.
  • .changeset/11276-object-grid-properties-bag.md (pending) said the row declares eleven keys "the flat mirror does not". This round makes that false for ten, so it gets a dated, append-only correction note (+2 / -0, frontmatter and every prior line byte-identical, checked by cmp). check:changeset-claims named 41 more pending changesets. Their paragraphs about the grid, the table slot and the ledgers were re-read, and none is made false.

Reverse verification (predictions written first; objectstack scripts/ablation-replace.mjs, wrap mode, on committed 437408ce; each restore proven by blob == HEAD and an empty git diff HEAD)

No dist leg: every subject here resolves to source (relative imports in the types tests, and the root vitest alias for consumers).

Tests and gates (final head 437408ce; heavy runs through os-verify-lock.sh; each exit code captured before any pipe)

  • pnpm --filter @object-ui/types run type-check (tsc --noEmit, -p tsconfig.examples.json, -p tsconfig.test.json, which judges the ledgers): exit 0.
  • pnpm exec vitest run packages/types/: Test Files 336 passed (336), Tests 8904 passed (8904).
  • Zod-face consumers outside packages/types: every test file that imports @object-ui/types/zod or names safeValidateSchema / AnyComponentSchema / StrictAnyComponentSchema. That is 115 files (schema-catalog, cli, app-shell previews, apps/console, components, scripts and twelve plugin packages), run in two halves: 58 passed (58) / 1286 passed, then 57 passed (57) / 1015 passed.
  • The doc-snippet build closure (turbo run build --concurrency=2, the filter check-doc-snippet-types.mjs --build-filter prints): Tasks: 35 successful, 35 total. Then check:doc-snippets ("776 of 776 block(s) judged, 0 failed"), check:doc-examples, and check:readme-exports: all exit 0.
  • All exit 0: check-changeset-presence ("6 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)"), check-changeset-no-major, check-changeset-fixed, check-changeset-overwrite (report-only; the one appended note), check:changeset-claims (report-only), check:pending-changeset-literals, check:control-bytes, check:new-line-citations ("0 new citation(s)"), check:spec-symbols, check:handler-key-reads, check:element-data-source-declaration, check:test-path-roots, check:unreferenced-sources, check-type-check-coverage ("43/43"), check:doc-types, check:doc-fences, check:component-surface-parity (report-only), check-governed-queue-guard --test over the diff (NOT GOVERNED).
  • Lint, a declared narrowing: eslint --no-inline-config --format json over the 6 changed TS files. The JSON judged 6 files with no ignore notice: 0 errors, and 38 warnings, every one on a pre-existing line (0 on an added line). eslint.config.js sets no parserOptions / projectService, and no eslint-rules/ file reads the disk, so the diff cannot move an untouched file's verdict. The repo-wide pnpm lint is CI's.
  • main was merged once before this PR (54be4dda, bringing in objectui#11485, fix(types): AnySchema includes every declared node type, pinned by an enumeration (objectui#11478) #11486 and feat(types)!: the widget slot's metric-card arm declares MetricCard's registered inputs, and the widget component slot takes the arm (objectui#11467) #11482); the parity file merged with no conflict.

NOT MEASURED: check:sdui-registration-pins (it needs a console build, and no registration input moved); the full pnpm test farm and the repo-wide lint (CI's); plugin-grid / plugin-view behaviour suites (no runtime file changed). The contract record is the seat's to owe on the landing head.

Open question: resizableColumns

The seat's answer A on #6152 ("resizable is canonical; the local half tombstones resizableColumns; its spec half forks to objectstack") was given while the flat mirror was the authored object-grid arm. Since objectui#11276 the authored node's props live in the spec's properties bag, which is ComponentPropsMap['object-grid'] by reference and still declares resizableColumns ("Alternate spelling of resizable"). Pinned by objectui#11276: "the bag is the spec row by reference". So the local half as written would tombstone the TypeScript member and the mirror, and drop ObjectGrid's ?? schema.resizableColumns read. That leaves objectui validate and os validate both accepting properties.resizableColumns, with the flat refusal pointing at it, and nothing reading it. Measured: no document in either repository writes the key. The options, with four axes, are in the report on the card; this PR leaves the key in the ledger.

Acceptance notes (noted, not filed here)

  • The spec's object-grid row types seven of these keys as unknown, so the authored bag accepts properties: { rowHeight: 'comfortable' } or grouping: 42 on both faces. ObjectGrid then falls back silently (for rowHeight, to compact). objectui#11276's PR already reported the row's unknown members as a spec-row finding. The report on the card names it for the seat with its measured reach.
  • BulkActionDef / BulkActionParam (the TypeScript twin) are wider than the spec's BulkActionDefSchema: open params with any type, ExpressionWire predicates, and the runtime actionDef. The mirror follows the twin. A narrowing of the twin would be its own question.
  • The strict face closes undeclared keys at every depth, including a bulkActionDefs param's catch-all that the twin and the tolerant face keep. That is the strict face's own construction, not this member's.

Generated by Claude Code

claude added 4 commits October 2, 2026 16:58
…ui#6152 round 6)

`aggregations`, `bulkActionDefs`, `conditionalFormatting`, `grouping`,
`navigation`, `operations`, `reorderableColumns`, `rowColor`, `rowHeight`
and `singleClickEdit` gain their zod members on the flat `ObjectGridSchema`
mirror, each measured read by `ObjectGrid` and each a member of the spec's
`object-grid` row. `grouping`, `navigation`, `rowColor` and `rowHeight` take
the spec schemas the TypeScript twin names, by reference;
`reorderableColumns` and `singleClickEdit` take the row's own members;
the other four restate the twin's local shapes, the conditional-formatting
rule now shared with `ListViewSchema`'s mirror.

`UnmirroredDeclared` keeps `resizableColumns` on the entry: its ruled
retirement is open again since the authored node moved to the spec's
`properties` bag (objectui#11276).

The TypeScript `singleClickEdit` comment said `@default false`; the
renderer and the spec row both default it to true.

Claude-Session: https://claude.ai/code/session_01XvhGmGAP79ZB8swnkapxPC
Co-authored-by: Claude <noreply@anthropic.com>
… the table slot; changeset

- `unmirrored-declared-round6-6152.test.ts` drives each of the ten mirrored
  keys through the mirror, the `object-view` `table` slot (tolerant and
  strict faces) and the authored `object-grid` node, which does not move.
- `grouping-field-padded-refused-7347.test.ts`: the census now finds
  `table.grouping` on `object-view`, so the table slot gets its own row and
  carries the padded-field refusal on every face.
- `imported-defaults-8317.test.ts` registers the four new spec crossings,
  and the mirror reads the row's boolean members through the boundary.
- One changeset (`@object-ui/types` minor), and a dated, append-only
  correction on the pending objectui#11276 changeset, whose list of keys
  "the flat mirror does not" declare this change makes false for ten.

Claude-Session: https://claude.ai/code/session_01XvhGmGAP79ZB8swnkapxPC
Co-authored-by: Claude <noreply@anthropic.com>
Brings in objectui#11485, #11486 and #11482; the parity ledger merged
without a conflict (#11485 moved rows in other blocks).

Claude-Session: https://claude.ai/code/session_01XvhGmGAP79ZB8swnkapxPC
Co-authored-by: Claude <noreply@anthropic.com>
`tsc -p tsconfig.test.json` refused spreading the readonly `NOT_COVERED`
lists into a `Record<string, string[]>`; copy each list instead.

Claude-Session: https://claude.ai/code/session_01XvhGmGAP79ZB8swnkapxPC
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 41 pending changeset(s) describe a file this change touches

Their bodies publish verbatim into the CHANGELOG at the next release, so this is a request to re-read them against your diff — addressed here because you are the one seat that can answer it without re-deriving anything.

⛔ Nothing here blocks, and nothing here is a verdict on your change. This gate exits 0, is not a required context, and judges name resolution, never meaning: it asked whether a pending body names a file you touched. "Is this sentence still true?" is the one question it will not answer, and the one you are being asked to answer.

.changeset/10872-container-children-channel.md

  • names objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Also in this change, with no behaviour change: objectql.zod.ts's two public-block arms (object-metric, object-master-detail-form) build their properties member with the same propsBag helper as the other public-block arms, instead of a byte copy of it. The member's description text is unchanged.

.changeset/11355-small-p1-sites-r2.md

  • names zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    ObjectChartSchema.isAnimationActive?: boolean is declared on the TypeScript face. Code sets it false for a render with no entrance animation: DashboardRenderer and DashboardGridLayout on the object-chart nodes they build, and DatasetWidget and DatasetReportRenderer on the nodes they hand the chart registration. ChartRenderer honours it. The zod mirror declares no member for it, so it is not an authoring key; zod-mirror-parity.test.ts files it as runtime-only.

.changeset/5903-objectgantt-declared-keys.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    Both halves move together. The TS declaration (packages/types/src/objectql.ts) and its zod mirror (src/zod/objectql.zod.ts) gain the same ten keys at the same requiredness — all optional — and no KnownDrift entry is added. navigation is taken from @objectstack/spec's NavigationConfigSchema by reference rather than restated, matching ObjectGridSchema.navigation.

  • names src/zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Both halves move together. The TS declaration (packages/types/src/objectql.ts) and its zod mirror (src/zod/objectql.zod.ts) gain the same ten keys at the same requiredness — all optional — and no KnownDrift entry is added. navigation is taken from @objectstack/spec's NavigationConfigSchema by reference rather than restated, matching ObjectGridSchema.navigation.

  • names packages/types/src/__tests__/zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    ⚠️ The JUSTIFICATION for that parity clause was retired (objectui#9743); the clause itself stands and did not move. As first written it credited the zod-mirror-parity ratchet with a zero-drift reading for this pair — but at that time the ratchet measured three directions and was structurally blind to the MIRRORED-but-undeclared one (objectui#9711), so a zero from it recorded that it had not looked in that direction, not that nothing was there. objectui#9725 landed the fourth direction, and it covers this pair BY NAME: packages/types/src/__tests__/zod-mirror-parity.test.ts registers objectql.zod.ts#ObjectGanttSchema in both its mirror map and its declaration map; assertionMirroredUndeclaredMatchesLedger requires every registered pair's mirrored-but-undeclared key set to equal that pair's MirroredUndeclared ledger entry — never for a pair the ledger does not name — and assertionNoVacuousMirroredUndeclaredMeasurement refuses a measurement that has degenerated to any. ⛔ Read this pair's verdict off that reconciliation, which re-derives it on every run, rather than off any figure written here; when this paragraph was authored, on 2026-09-18, it required no MirroredUndeclared entry for the pair.

.changeset/5928-classname-style-props-rename.md

  • names zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    Where the non-pair is recorded now. zod-mirror-parity.test.ts keys its existing EXCLUSIONS entry — the mechanism that accounts for every exported const with no TypeScript declaration to mirror, each with its stated reason — to ClassNameStylePropsSchema. Named for its own two keys, the const leaves no like-named declaration for a name-derived pairing to reach for.

.changeset/6051-gantt-flat-config-declared-keys.md

  • names packages/types/src/__tests__/zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    ⚠️ The JUSTIFICATION for that parity clause was retired (objectui#9743) — the same retirement objectui#5903's entry carries, for the same clause and the same reason; the clause itself stands and did not move. As first written it credited the zod-mirror-parity ratchet with a zero-drift reading for this pair, at a time when that ratchet measured three directions and was structurally blind to the MIRRORED-but-undeclared one (objectui#9711), so a zero from it recorded that it had not looked in that direction. objectui#9725 landed the fourth direction, and it covers this pair BY NAME: packages/types/src/__tests__/zod-mirror-parity.test.ts registers objectql.zod.ts#ObjectGanttSchema in both its mirror map and its declaration map; assertionMirroredUndeclaredMatchesLedger reconciles every registered pair's mirrored-but-undeclared key set against that pair's MirroredUndeclared ledger entry — never for a pair the ledger does not name — and assertionNoVacuousMirroredUndeclaredMeasurement refuses a measurement that has degenerated to any. ⛔ Read this pair's verdict off that reconciliation, which re-derives it on every run, rather than off any figure written here; when this paragraph was authored, on 2026-09-18, it required no MirroredUndeclared entry for the pair.

.changeset/6150-undeclared-but-consumed-keys.md

  • names zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    ⭐ AMENDED, and the amendment ships in this same release. The TreeViewSchema slice (604476d97) gave the key a zod arm after all — a NAMED REFUSAL (handlerKeyRefusal(key, 'runtime-slot', label)), never a shape — because "no mirror entry" is not neutral under BaseSchema.passthrough(): it meant an authored { "type": "tree-view", "onNodeClick": { "action": "toast" } } parsed GREEN, survived the parse, and reached a call site that expects a function. ⇒ the three clauses this bullet used to carry are no longer true of the code shipping beside it. The key is now a MEMBER of TreeViewSchema.shape and an authored value is refused BY NAME at path onNodeClick; it has LEFT zod-mirror-parity.test.ts's RuntimeOnlyDeclared for that file's KnownDrift; and it is no longer "the first pair to sit there without also sitting in UnmirroredDeclared" — draining it emptied that difference, so RuntimeOnlyDeclared is now a SUBSET of UnmirroredDeclared and the union of the two equals UnmirroredDeclared itself. ⛔ objectui#6152's ruling is untouched by any of this: what the key still does not have, and never will, is a z.function() shape — no serialized document could satisfy one.

.changeset/6152-object-form-unmirrored-members.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectFormSchema in @object-ui/types (objectql.ts) declared a set of members that its zod mirror in @object-ui/types/zod had never heard of. Every one of them is read by the object-form renderer (ObjectForm in @object-ui/plugin-form). The two published faces answered differently:

.changeset/6175-column-state-persistence.md

  • names zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    Nothing is retired. Both spellings remain declared on DataTableSchema; onColumnReorder stays declared and stays unwired, exactly as the RuntimeOnlyDeclared ledger in zod-mirror-parity.test.ts records it. Which of the two survives is a declared-surface ruling that stays open and is deliberately not settled here.

.changeset/6639-objectgrid-title-mirrored.md

  • names zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    The gain is the typed refusal: the mirror's .passthrough() base was already admitting any title unexamined, and it now enforces the declared string. zod-mirror-parity.test.ts's UnmirroredDeclared ledger records the key as worked off — the ledger's first shrink by repair (97 + 1 mirrored + 23 reclassified is what the seeded "121" now means).

.changeset/6940-rowactions-boolean-mirror.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    The list view's same-named rowActions in zod/objectql.zod.ts — z.array(z.string()), the legacy bare-name action list on ObjectGridSchema — is a different key that is correct as it stands, is in parity with its own TS twin (rowActions?: string[]), and is not touched.

.changeset/7113-chart-data-model.md

  • names objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    .extend() with a NEW key still works and preserves the fold and the refinement; .optional(), z.discriminatedUnion, z.toJSONSchema and safeValidateSchema are all unaffected. Nothing in this repository calls the throwing combinators on either const, and the published surface already ships refined mirrors (objectql.zod.ts, complex.zod.ts, form.zod.ts, app.zod.ts), so the class is not new — but it is a real behaviour change on a published export and it belongs in the release note rather than in a reviewer's file.

.changeset/7200-object-form-section-style-keys-undeclared.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    The authored-metadata type now agrees with @objectstack/spec, whose FormSectionSchema is a strict object declaring neither key, and with the ruling's rationale (maintainer 2026-09-01, verbatim): "retire the reads … Declaring the keys was weighed and not adopted: it would formally invite free Tailwind strings into authored metadata, the exact class the boundary exists to keep out." A ?: never tombstone was not used: ObjectFormSection has no zod mirror (ObjectFormSchema in zod/objectql.zod.ts does not declare sections), so there is no parse door to refuse at, and a tombstone is still a declaration in completion and in the published .d.ts.

.changeset/7265-types-user-filter-field-derives.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    zod/objectql.zod.ts declared two schemas under names @objectstack/spec/ui already exports. They were triaged separately, by reading their sites, and went different ways.

.changeset/7322-object-kanban-group-by-limit.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    Breaking for authored metadata: ObjectKanbanSchema.groupField is RETIRED (objectui#7322, ADR-0049 enforce-or-remove), and the two keys the object-kanban renderer actually reads — groupBy and limit — are now DECLARED and validated on both published faces: the TypeScript interface in objectql.ts and the Zod mirror in zod/objectql.zod.ts.

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Breaking for authored metadata: ObjectKanbanSchema.groupField is RETIRED (objectui#7322, ADR-0049 enforce-or-remove), and the two keys the object-kanban renderer actually reads — groupBy and limit — are now DECLARED and validated on both published faces: the TypeScript interface in objectql.ts and the Zod mirror in zod/objectql.zod.ts.

.changeset/7344-handler-string-any-mirrors.md

.changeset/7352-drill-down-config-mirror.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    DrillDownConfigSchema is the zod mirror of DrillDownConfig, and both declarations that carry drillDown reference it — ChartSchema (zod/data-display.zod.ts) and ObjectDataTableSchema (zod/objectql.zod.ts) — so the published validator under @object-ui/types/zod reads the key for the first time (objectui#7352).

.changeset/7363-objectql-union-arms.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectGallerySchema and ObjectDataTableSchema are members of ObjectQLComponentSchema on both faces — the TS union in objectql.ts and the zod union in zod/objectql.zod.ts — so AnyComponentSchema, and with it validateSchema / safeValidateSchema / objectui validate, has an arm for object-gallery and object-data-table nodes (objectui#7363).

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    ObjectGallerySchema and ObjectDataTableSchema are members of ObjectQLComponentSchema on both faces — the TS union in objectql.ts and the zod union in zod/objectql.zod.ts — so AnyComponentSchema, and with it validateSchema / safeValidateSchema / objectui validate, has an arm for object-gallery and object-data-table nodes (objectui#7363).

.changeset/7632-shared-record-source-config.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    That ladder is published contract on both faces — packages/types/src/objectql.ts and its zod mirror both ship .describe() strings naming getDataConfig's order (77cb489b4, maintainer ruling 2026-09-02), pinned by objectql-record-source-refinement-6939.test.ts — and it was hand-copied into five plugin components with no gate holding them together. A change to the ruled order had five edit sites and nothing that noticed a missed one; that is the AGENTS.md #0.1 drift class.

.changeset/7654-floating-chatbot-trigger-icon-tombstone.md

  • names zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    Every other tombstone in this package pairs ?: never with a retirementTombstone() refusal on the Zod twin. There is no twin here to carry one: FloatingChatbotConfig has no Zod mirror at all, and floatingConfig sits in the UnmirroredDeclared ledger (zod-mirror-parity.test.ts, complex.zod.ts#ChatbotSchema). BaseSchema is .passthrough(), so the whole floatingConfig object rides through unvalidated — before this change and after it. Minting a mirror to host a refusal would be the declared-but-UNMIRRORED axis (objectui#6152), a different defect: a key can be mirrored and inert, or unmirrored and live, and fixing one says nothing about the other. This change does not widen into it.

.changeset/7804-objectql-handler-key-arms.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    The four plain objectql.ts node faces declare the nine handler keys their registered renderers read (the objectql.ts slice): ObjectFormSchema.onCancel / .onError / .onOpenChange / .onStepChange / .onSuccess, ObjectGallerySchema.onCardClick / .onRowClick, ObjectGridSchema.onNavigate and ObjectViewSchema.onNavigate.

.changeset/7804-tree-view-handler-slot.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    'runtime-slot' and not 'retired', measured at this key's own channel. 'retired' publishes "no renderer reads this key, so nothing could ever run it" — true of the two siblings already tombstoned on this arm (onSelectChange, onExpandChange) and flatly false here, since the read is live and INVOKED. ⚠️ No in-repo host builds a tree-view node carrying the key: the channel is wired end to end and only the supplier is absent, which is the same shape as ObjectFormSchema.onStepChange in this card's objectql.ts slice and is not evidence of a dead read. The TypeScript declaration is unchanged and still callable, so a programmatic host supplies it exactly as before.

  • names zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    The pair moves from zod-mirror-parity.test.ts's RuntimeOnlyDeclared to its KnownDrift, which empties the former of the one entry the latter did not also hold — so the two unmirrored ledgers are now in a containment relation, and the cross-ledger figure that recorded their difference states the containment instead.

.changeset/7917-export-breadcrumb-object-tree-zod-schemas.md

  • names objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    AnyComponentSchema declares 107 node component types. 105 of them could be named on the ./zod barrel — ButtonSchema.safeParse(node), which is what a designer, a form builder or a targeted test needs. The arms declaring type: 'breadcrumb' (navigation.zod.ts) and type: 'object-tree' (objectql.zod.ts) could not: both were already export const in their own module, but index.zod.ts — the package's only zod entry point — did not re-export them, so the schemas existed, were maintained, and were applied by the union while no consumer could name them.

.changeset/7963-alert-dialog-footer-keys-retired.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    Nothing else moves. These spellings are overloaded across the tree and every other owner is a live key on a different declaration — FormSchema.cancelLabel, objectql.ts's confirmLabel, plugin-designer's ConfirmDialog React props, plugin-grid's def.confirmLabel, and plugin-form's ModalForm / DrawerForm, which build a local cancelLabel from schema.cancelText. None is an AlertDialogSchema; none is touched, and a pin asserts it. No fixture, catalog schema, example app or doc fence authored any of the three on an alert-dialog node, so no shipped document is stranded.

.changeset/8338-retire-toast-action.md

  • names zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    The parity ledgers drain with it, every figure re-derived by zod-mirror-parity.test.ts's own AST and mirror instruments rather than stepped by hand: KnownDrift 42 entries / 64 keys → 41 / 63 (the entry's whole content, so the entry went too — the ledger's first loss by RETIRING a key rather than by moving either face toward the other), and WiderThanDeclared 23 / 36 / 47 arms, split 6 / 30 / 0 / 11 → 22 / 35 / 45, split 6 / 29 / 0 / 10. The pair itself stays registered, so EXPECTED_MIRROR_PAIRS does not move.

.changeset/8478-describe-line-addresses.md

.changeset/8572-chatbot-body-retired.md

  • names zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    Why this key and not another. It was the ONE place in this vocabulary where body did not mean "what goes inside this component": zod-mirror-parity.test.ts carried the pair under KnownDrift as "two different meanings of one key", and the same collision was the whole reason chatbot was the single arm of the component union whose output was not assignable to SchemaNode. Both ledger rows move with this change, and the two pins that recorded the old state are INVERTED rather than deleted (see below).

.changeset/8735-objectql-mirror-docblocks-not-defaulted.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Correct four zod/objectql.zod.ts docblocks that described the behaviour objectui#8317 removed. Since that change the zod mirrors strip imported @objectstack/spec defaults at this package's import boundary, but the docblocks on HttpRequestSchema, ListColumnSchema, SelectionConfigSchema and PaginationConfigSchema still said, in the present tense, that method, prefix.type, type and pageSize are defaulted on parse — the opposite of what each export does. Each now says the key is declared and accepted but NOT defaulted on parse.

.changeset/8767-object-grid-refuses-string-sort.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    Migration. Write the array: sort: [{ field: 'name', order: 'desc' }]. Both keys are required. SortConfig.order carries no ? in @object-ui/types (packages/types/src/objectql.ts) and no .optional() in its zod mirror, and the protocol's own reusable SortItemSchema requires order as well — measured: that schema refuses [{ field: 'name' }] with invalid_value at 0.order. Do not omit it: this block's array arm interpolates whatever is present, so an omitted order lowers to $orderby: 'name undefined' today. That is pre-existing behaviour on the arm this change does not touch, and it is filed as a successor card rather than widened into here.

.changeset/8801-object-kanban-allow-collapse-retired.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    • the declarations retired here — packages/types/src/objectql.ts and its mirror packages/types/src/zod/objectql.zod.ts; - the pins that assert the retirement — object-kanban-allow-collapse-retired-8801.test.ts and bare-kanban-node-key-retired-8802.test.ts; - a comment in packages/types/src/zod/complex.zod.ts, recording that the deleted retiredZeroReadKanbanKey helper once carried this spelling on the SIBLING arm; - one row of content/docs/api/schema-reference.md; - the .changeset/ release notes that discuss it — this one, the two historical entries covering the sibling arm's own spelling, and objectui#9629's note recording the correction to this paragraph.
  • names packages/types/src/zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    • the declarations retired here — packages/types/src/objectql.ts and its mirror packages/types/src/zod/objectql.zod.ts; - the pins that assert the retirement — object-kanban-allow-collapse-retired-8801.test.ts and bare-kanban-node-key-retired-8802.test.ts; - a comment in packages/types/src/zod/complex.zod.ts, recording that the deleted retiredZeroReadKanbanKey helper once carried this spelling on the SIBLING arm; - one row of content/docs/api/schema-reference.md; - the .changeset/ release notes that discuss it — this one, the two historical entries covering the sibling arm's own spelling, and objectui#9629's note recording the correction to this paragraph.

.changeset/8885-object-chart-drilldown-title-compareto.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectChart.tsx reads all three off schema, and until now neither published copy declared any of them: not the TS interface (packages/types/src/objectql.ts) and not the zod mirror (packages/types/src/zod/objectql.zod.ts). They rode BaseSchema's index signature / .passthrough() and arrived unvalidated. drillDown was the sharpest case — this component's registry inputs advertise it to the designer palette, and @objectstack/spec publishes ChartDrillDownSchema for exactly this carrier, so an author was offered a key that neither published shape mentioned.

  • names packages/types/src/zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    ObjectChart.tsx reads all three off schema, and until now neither published copy declared any of them: not the TS interface (packages/types/src/objectql.ts) and not the zod mirror (packages/types/src/zod/objectql.zod.ts). They rode BaseSchema's index signature / .passthrough() and arrived unvalidated. drillDown was the sharpest case — this component's registry inputs advertise it to the designer palette, and @objectstack/spec publishes ChartDrillDownSchema for exactly this carrier, so an author was offered a key that neither published shape mentioned.

.changeset/8913-object-kanban-columns-declared.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    What moved. ObjectKanbanSchema gains columns on both halves that move together — the TypeScript interface (objectql.ts) and its Zod mirror (zod/objectql.zod.ts). Retiring the bare kanban node type key (objectui#8802) removed the only face that judged a lane, and object-kanban had never declared the key, so it rode BaseSchema's [key: string]: any / .passthrough(): read by the renderer at three sites, named by no published face.

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    What moved. ObjectKanbanSchema gains columns on both halves that move together — the TypeScript interface (objectql.ts) and its Zod mirror (zod/objectql.zod.ts). Retiring the bare kanban node type key (objectui#8802) removed the only face that judged a lane, and object-kanban had never declared the key, so it rode BaseSchema's [key: string]: any / .passthrough(): read by the renderer at three sites, named by no published face.

.changeset/8990-object-kanban-groupby-optional.md

  • names packages/types/src/objectql.ts → packages/types/src/objectql.ts — edited by this change

    @objectstack/spec declares the key optional — groupBy: z.string().optional() on ObjectKanbanPropsSchema — while this package required it on the TypeScript declaration (packages/types/src/objectql.ts) and on the Zod mirror (packages/types/src/zod/objectql.zod.ts). objectui was therefore narrower than the protocol on a published key: ObjectKanbanSchema.safeParse and safeValidateSchema refused an object-kanban node the protocol accepts, and such a node could not be annotated with its own type.

  • names packages/types/src/zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    @objectstack/spec declares the key optional — groupBy: z.string().optional() on ObjectKanbanPropsSchema — while this package required it on the TypeScript declaration (packages/types/src/objectql.ts) and on the Zod mirror (packages/types/src/zod/objectql.zod.ts). objectui was therefore narrower than the protocol on a published key: ObjectKanbanSchema.safeParse and safeValidateSchema refused an object-kanban node the protocol accepts, and such a node could not be annotated with its own type.

.changeset/8992-user-actions-collapse-and-docblock.md

  • names objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    objectql.zod.ts's UserActionsSchema read stripImportedDefaults(Spec).extend({ group, hideFields, rowColor }), an extension that existed only because @objectstack/spec did not declare those three keys while normalizeListViewSchema folded objectui's legacy showGroup / showHideFields / showColor onto them. The protocol adopted all three in 17.3.0 (objectui#5435's ruling), so the extension is now a second local copy of a protocol declaration — the shape two faces start drifting from — and it collapses into the plain by-reference re-export its own note always said it would become.

.changeset/9092-inline-locale-declared-face.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    • AppComponentSchema.label (app.ts) - ObjectGridSchema.label and .description (objectql.ts) - PageNodeSchema.aria.ariaLabel (layout.ts)

.changeset/9309-object-gallery-filter-destination-typed.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectGallerySchema.filter is typed as the destination its own docblock names — QueryParams['$filter'] — on both faces, the TS interface in objectql.ts and the zod mirror in zod/objectql.zod.ts (objectui#9309).

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    ObjectGallerySchema.filter is typed as the destination its own docblock names — QueryParams['$filter'] — on both faces, the TS interface in objectql.ts and the zod mirror in zod/objectql.zod.ts (objectui#9309).

.changeset/9511-record-id-is-a-string.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    The three authorable keys, each on BOTH faces. ObjectFormSchema.recordId (objectql.ts + zod/objectql.zod.ts), DetailViewSchema.resourceId (views.ts + zod/views.zod.ts) and DetailSchema.resourceId (crud.ts + zod/crud.zod.ts). ⚠️ The crud pair is DetailSchema, not DetailViewSchema, and it reaches the same renderer — not by symbol but by data flow: plugin-detail registers the 'detail' node type onto DetailView. A read that follows TypeScript symbols alone finds two keys and is incomplete.

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    The three authorable keys, each on BOTH faces. ObjectFormSchema.recordId (objectql.ts + zod/objectql.zod.ts), DetailViewSchema.resourceId (views.ts + zod/views.zod.ts) and DetailSchema.resourceId (crud.ts + zod/crud.zod.ts). ⚠️ The crud pair is DetailSchema, not DetailViewSchema, and it reaches the same renderer — not by symbol but by data flow: plugin-detail registers the 'detail' node type onto DetailView. A read that follows TypeScript symbols alone finds two keys and is incomplete.

  • names zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    ⭐ The declaration alone would not have been enough, and this is the reusable part. A TypeScript declaration does not run at parse time. The hand-written zod mirror is the only face in this repository that can refuse an authored number, so narrowing the declaration without the mirror would have shipped declared !== enforced on a published surface — and zod-mirror-parity.test.ts would have stayed GREEN through it, because that instrument asserts a mirror accepts everything its declaration declares and a mirror left WIDER passes. Both faces moved together for that reason.

.changeset/9549-tree-filter-declared.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectTreeSchema.filter is declared on both faces, in the shape objectui#9309 settled for ObjectGallerySchema.filter: QueryParams['$filter'] by indexed access on the TS interface in objectql.ts, and the same two-arm union (array first) on the zod mirror in zod/objectql.zod.ts (objectui#9549).

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    ObjectTreeSchema.filter is declared on both faces, in the shape objectui#9309 settled for ObjectGallerySchema.filter: QueryParams['$filter'] by indexed access on the TS interface in objectql.ts, and the same two-arm union (array first) on the zod mirror in zod/objectql.zod.ts (objectui#9549).

.changeset/9550-object-tree-root-barrel.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    ObjectQLComponentSchema declares the node types an ObjectQL block may be. Every one of its arms was a named export of this package's root barrel except ObjectTreeSchema, which was declared in objectql.ts, applied by the union, and re-exported by the ./zod barrel (objectui#7917) — while no TypeScript consumer could name it. There is no ./objectql subpath to reach around the barrel: the package's exports map is pinned by packages/types/src/__tests__/package-exports-manifest.test.ts, and the root barrel was the only route to this type.

.changeset/9606-object-kanban-card-title.md

  • names zod/objectql.zod.ts → packages/types/src/zod/objectql.zod.ts — edited by this change

    Both published faces of the object-kanban arm now name the key: the zod mirror ObjectKanbanSchema in zod/objectql.zod.ts and its TypeScript twin, the ObjectKanbanSchema interface in objectql.ts. Both declare it OPTIONAL, at the same requiredness the other face uses, so the two faces accept and refuse the same documents. (Located and cited by SYMBOL: line addresses in zod/objectql.zod.ts have drifted before, and this change is itself about a drifted mirror.)

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    Both published faces of the object-kanban arm now name the key: the zod mirror ObjectKanbanSchema in zod/objectql.zod.ts and its TypeScript twin, the ObjectKanbanSchema interface in objectql.ts. Both declare it OPTIONAL, at the same requiredness the other face uses, so the two faces accept and refuse the same documents. (Located and cited by SYMBOL: line addresses in zod/objectql.zod.ts have drifted before, and this change is itself about a drifted mirror.)

.changeset/9628-kanban-column-collapsed-honoured.md

  • names objectql.ts → packages/types/src/objectql.ts — edited by this change

    The key was declared on both published faces of the object-kanban arm — the lane element of ObjectKanbanSchema (objectql.ts and its Zod mirror) and the runtime lane KanbanColumn (complex.ts and its mirror) — and read by KanbanEnhanced alone, a module no production source imports. An authored { "id": "todo", "title": "To Do", "collapsed": true } therefore parsed green on both faces and reached a board that did nothing with it: KanbanImpl's only collapse is the SWIMLANE row's, held in viewer state under objectui:kanban-collapsed:ANGLE-BRACKETS(swimlaneField) and never keyed to a lane's declared value. That is the ADR-0049 declared-but-unhonoured shape.

.changeset/object-view-unmirrored-keys-7779.md

  • names zod-mirror-parity.test.ts → packages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    Who is NOT affected: every correctly typed document, and every document that never wrote these keys — absent stays valid on all nine. No renderer changed. The parity ledger (zod-mirror-parity.test.ts) records the move: UnmirroredDeclared 14 entries / 96 keys to 14 / 87, the ObjectViewSchema entry re-derived into the SPEC-DERIVED half because the mirror now references the spec in code.

Read the paragraph, not the line: both false halves of the objectui#8617 claim sat in one paragraph, and correcting either alone would have left it asserting the same wrong thing.

If a claim did go false, correct the body. That is precedented and prose-only, frontmatter untouched; check-changeset-overwrite.mjs will report the correction as its own case 2 ("correcting a declaration on purpose … legitimate"), which is the intended shape — one gate asks for the read, the other records the write.

Not covered, stated so nobody reads this as more: a born-false claim that spells no line address at all (objectui#9495 coordinated one by ORDINAL — "a grep finds that member first" — and deciding that means reading what the sentence means), a claim spelled as a symbol or a package rather than a backticked file name, and a file named ambiguously.

Angle-bracketed names in the quoted prose above are rewritten as ANGLE-BRACKETS(name): GitHub deletes tag-shaped fragments from a stored body, and a quote that silently loses the identifier it is about is worse than a visible repair.

Compared the checked-out tree with 401611b21 (merge-base with origin/main): 6 file(s) changed outside .changeset/, read against 2029 pending declaration(s) that publish a body (2658 pending in total). · run

@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3550.7 KB 3574.6 KB
Main entry chunk (gzip) 150.4 KB 350 KB
Entry file index-CLSWGOUH.js —
Status PASS —

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

Package Size Gzipped
app-shell (consoleActionDispatch.js) 0.20KB 0.19KB
app-shell (index.js) 16.88KB 6.25KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.11KB 3.87KB
auth (ActiveOrganizationStorage.js) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.17KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.54KB 3.46KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.11KB 7.97KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.28KB 2.60KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.50KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 569.83KB 136.77KB
core (index.js) 10.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 230.46KB 63.94KB
fields (index.js) 261.25KB 66.11KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.35KB 12.88KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.49KB 9.23KB
i18n (useSafeTranslation.js) 7.14KB 2.92KB
layout (index.js) 39.36KB 11.18KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.86KB 5.00KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.52KB 2.26KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.04KB 3.92KB
plugin-calendar (index.js) 53.17KB 15.46KB
plugin-charts (index.js) 83.53KB 22.84KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 141.23KB 38.00KB
plugin-designer (index.js) 231.28KB 48.76KB
plugin-detail (index.js) 245.27KB 64.47KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 172.73KB 44.50KB
plugin-gantt (index.js) 179.14KB 45.06KB
plugin-grid (index.js) 232.66KB 63.77KB
plugin-kanban (index.js) 49.51KB 15.54KB
plugin-list (index.js) 116.60KB 28.96KB
plugin-map (index.js) 25.60KB 8.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 38.80KB 11.71KB
plugin-tree (index.js) 14.51KB 5.15KB
plugin-view (index.js) 90.23KB 22.73KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 120.63KB 39.56KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.50KB 2.06KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.50KB 1.99KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.06KB 2.68KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 21.42KB 7.05KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 4.12KB 1.61KB
types (authoring-nodes.js) 0.20KB 0.19KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 3.32KB 1.64KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (dashboard-widget-layout.js) 2.06KB 0.96KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 5.07KB 2.39KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 4.99KB 1.96KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.93KB 7.25KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 437408cebc0782b0994eedf8274ad3eb0a15521d
Local-runs: none

PR objectui#11492, round 6 of card objectui#6152 (draft, not ready, no auto-merge; head repo is the base repo). Inputs, and nothing else: the card body and all 46 comments (the claim 5956749997, the dev report 5957803718, the seat's answer 5957903936 to the round's one open question, the 7347 evidence comment 5908681663, and the carried items of the round-1 to round-5 records), the PR body, its 8-file list, the net diff against main (8 files, +451 / −61, the same 8 paths as the file list), every pending .changeset/*.md entry at the head read as text (2661 entries plus config.json, listed from the .changeset tree 28b75a54658dbc8e05a4df199ab2d8660178862a under the head's root tree, each file's byte size checked against the tree), the TypeScript twin and the zod mirror at the head, and the check-runs on this head. Check-runs on this head, read twice: at 2026-10-02T17:40:29Z, 42 runs with 34 success, 3 skipped (dependabot, coverage, coverage shard) and 5 Test shards (1, 2, 3, 4, 7) still in progress; re-read at 2026-10-02T17:56:45Z just before this post, 43 runs with 40 success, 3 skipped, 0 failure and 0 in progress, Type Check, Lint, Build & E2E and every Test shard among the successes. Gate verdicts are read off those check-runs; nothing was built, run or re-run here. The dev's local censuses, runtime probe, ablations and gate runs are read as declared, not as verdicts. The spec's shapes were read from @objectstack/spec 17.5.0's source at its release tag (the installed version per the head's lockfile; unpkg is denied by the proxy).

① Derived judgments

Published TypeScript face (@object-ui/types):

  1. ObjectGridSchema.singleClickEdit: doc comment @default false to @default true, no shape change — RIGHT. The spec's own row member reads "Enter cell edit on single click (default true when editable)" (component.zod.ts at the 17.5.0 tag), and the renderer's ?? true read is the dev's declared census (ObjectGrid.tsx is outside the diff). No other exported declaration moved: ObjectGridSlotKey already lists the nine slot keys and withholds navigation / resizableColumns, and the diff does not touch it.

Zod accept sets (@object-ui/types/zod: the flat mirror, the tolerant AnyComponentSchema and the strict StrictAnyComponentSchema):

  1. Ten members declared on the flat ObjectGridSchema mirror, each judged against the twin — RIGHT, member by member:
    • grouping, navigation, rowColor: the spec's GroupingConfigSchema, NavigationConfigSchema, RowColorConfigSchema by reference through stripImportedDefaults — the twin's GroupingConfig, NavigationConfig (as ViewNavigationConfig) and RowColorConfig are the spec's own types by import, so parity holds by construction; it is the spelling the gallery, kanban, tree, calendar and list-view arms in the same module already use for navigation and grouping.
    • rowHeight: the spec's RowHeightSchema by reference — at 17.5.0 that enum is exactly the twin's five literals (compact, short, medium, tall, extra_tall), so nothing narrower or wider is declared, and comfortable is refused as the pin says.
    • reorderableColumns, singleClickEdit: the object-grid row's own members by reference (z.boolean().optional() at 17.5.0), equal to the twin's optional boolean; pinned by identity.
    • aggregations: a strict { field, type } entry whose type enum restates the twin's inline union (sum, count, avg, min, max, count_distinct) exactly; strict rather than loose because the twin's entry carries no index signature, the emptyState precedent.
    • operations: a strict six-toggle object restating the twin's six optional booleans; a misspelt toggle is named.
    • bulkActionDefs: a strict entry restating BulkActionDef member for member. operation is the spec's BulkActionOperationSchema by reference (the twin imports BulkActionOperation from the spec, required on both); visible is ExpressionWireSchema beside the spec's BulkActionDefSchema.shape.visible by reference, which is the twin's ExpressionWire | SpecNamedViewBulkActionDef['visible'] because the spec's ObjectListViewSchema.bulkActionDefs is z.array(BulkActionDefSchema) at 17.5.0, so the slot is the same object; params entries are loose with loose options, as BulkActionParam's catch-all declares; actionDef is a string-keyed record, as the twin declares. NOT the spec's BulkActionDefSchema by reference — RIGHT, and measured: at 17.5.0 that schema's params is a strict BulkActionParamSchema with type from the closed FieldType vocabulary, and its visible has no ExpressionWire arm, so binding it would refuse values the twin declares, which is a KnownDrift row, and the card rules that growing KnownDrift is never the remedy.
    • conditionalFormatting: z.array(ConditionalFormattingRuleSchema).optional(), the two-dialect union lifted out of ListViewSchema unchanged, the twin's ConditionalFormattingRule[].
  2. ListViewSchema.conditionalFormatting now reads the hoisted, module-private ConditionalFormattingRuleSchema — RIGHT. Both arms, the SpecRuleConditionSchema the second arm reads, and the member's .describe text are moved, not edited (SpecRuleConditionSchema now sits above the grid's mirror because the grid reads it at module load), so the list-view accept set does not move; the round-6 pin holds the two members to one element schema by identity. KanbanConditionalFormattingRuleSchema keeps reading the same condition schema.
  3. The object-view table slot — RIGHT, and derived rather than chosen: the slot is built as BaseSchema.extend(ObjectGridSchema.shape) minus the identity keys, plus OBJECT_VIEW_TABLE_WITHHELD, partial (objectui#10976), so the nine slot keys flow in and navigation / resizableColumns stay refused by name through the unchanged withheld set. The strict face WIDENS there: nine keys it refused as unrecognized_keys are judged, which is what the TypeScript ObjectGridSlotKey already typed and what ObjectView relays or reads by name per objectui#10976's own list (operations is one of the keys the view reads by name). The tolerant face NARROWS there: a wrongly typed value .passthrough() kept unexamined is refused at ['table', key]. The round-6 pin drives all nine through both faces with a plain-table control, and holds the two withheld keys at invalid_type.
  4. The authored object-grid node (ObjectGridBlockSchema) unchanged — RIGHT. Its bag is the spec row by reference, its flat refusals are read off the row, and it takes only eight tombstone or refusal members off the flat mirror (operators, rowSpecActions, bulkSpecActions, name, placeholder, showFilters, body, children), none of which this diff touches. So a document's object-grid node parses exactly as before on both faces, and AnyComponentSchema / StrictAnyComponentSchema move only through the object-view arm; the pin holds each key refused flat by name and parsing in the bag.
  5. ObjectGridSchema.safeParse called directly (the mirror is re-exported from index.zod.ts) now judges the ten keys where it kept them — RIGHT, and stated in the changeset.
  6. resizableColumns NOT mirrored and kept in UnmirroredDeclared with its reason written on the entry — RIGHT. The seat's answer on 5957903936 is A, hold: the key stays declared, unmirrored and read until the spec row retires it (objectstack#21445); the table slot keeps refusing it by name; the pin asserts it is not a member.

Test-only ledger moves (no published face):

  1. UnmirroredDeclared 5 / 16 to 5 / 6 (spec-derived 3 / 14 to 3 / 4; local 2 / 2 unchanged) — RIGHT, re-added from the diff's own key list: the entry drops ten of its eleven keys and keeps one, so 16 − 10 = 6 keys across the same 5 entries, and the half the entry sits in by membership (objectui#7762) reads 14 − 10 = 4. Every prose site moved with it (the header bullet, both ledger docstrings' "6 keys", the totals line, the spec-derived bullet), the route is written as REPAIR and kept apart from retirement and reclassification, and KnownDrift 49 / 86, RuntimeOnlyDeclared, RuntimeOnlyNamedAllowList, WiderThanDeclared and MirroredUndeclared carry no row in the diff. The objectui#7279 and finding(types): zod-mirror-parity's two ledger docstrings say UnmirroredDeclared records 94 keys; two instruments measure 87 — unmoved since objectui#7779, and outside every pin in the file #8243 pins derive the figures; see the check-run reading below.
  2. grouping-field-padded-refused-7347.test.ts: the census gains an object-view table row (a type member so one arm can own two paths; the expected map is rebuilt per type and sorted) — RIGHT and required: the 7347 evidence comment on this card (5908681663) said the census goes red when another arm starts declaring grouping, and the table slot now does. The padded-name refusal is held on every face at ['table', 'grouping', 'fields', i, 'field'].
  3. imported-defaults-8317.test.ts: four new spec crossings registered (RowColorConfigSchema, RowHeightSchema, BulkActionDefSchema, BulkActionOperationSchema) — RIGHT and required by that boundary pin; GroupingConfigSchema and NavigationConfigSchema were already crossed.
  4. New pin file unmirrored-declared-round6-6152.test.ts (direct mirror per key, both faces on the slot, the withheld pair, the authored node, the by-reference identities, the padded rule reaching grouping, the shared rule identity, strict entries naming an unknown member, the loose param, the three visible spellings) — RIGHT; each assertion names the door it holds.

File surface against the claim 5956749997: all 8 files sit inside the named surface or a dev-declared widening forced by a pin (imported-defaults-8317.test.ts, grouping-field-padded-refused-7347.test.ts) or by the house form for pending changesets; every excluded path (the other spec-derived pairs, the chatbot displayMode pair, strict-authoring-face.ts, any objectstack file) is untouched, and packages/plugin-grid/** is untouched because nothing was retired. No governed surface: the 8 paths are .changeset/** and packages/types/**, and the Governed Surface Queue Guard check-run is success.

② Semver level

  • What the diff publishes, all in @object-ui/types: a zod strict-face widening on the object-view table slot (nine keys); a zod tolerant-face narrowing there and on the flat ObjectGridSchema (a wrongly typed value is refused at the key where it was kept); list-view and the authored object-grid unchanged; no TypeScript shape change (a doc comment only). One released package's sources change, and no renderer package.
  • .changeset/6152-objectgrid-round6-mirrored.md: '@object-ui/types': minor, headed "Breaking for an invalid document, hence minor", naming the ten members and how each is typed, where the move is seen (the strict and the tolerant face on the table slot, and the direct mirror), and what did not move (the bag, resizableColumns, the TypeScript shape, the singleClickEdit comment) — MATCHES what the diff publishes. The fixed release group prices a stated break as minor (the round-1, round-3, round-4 and round-5 precedent, each PASSed at tier). Changeset Declaration, Changeset Bump Policy, Changeset Fixed Group Check, Changeset Overwrite Report and Changeset Claim Re-read are all success on this head.
  • The Clause-②: line reads yes on the PR body (with "Why yes (mixed)"), on the claim 5956749997, and in the changeset body (Clause-②: yes with both directions stated) — RIGHT: a well-formed declaration (yes, no arm), minor meets the floor yes sets, and the two-way effect is written out on all three carriers. Noted, not flagged: rounds 4 and 5 carried the (narrowing) arm after the round-3 record corrected a wrongly (widening)-armed two-way diff; a bare yes with the mixed prose is the spelling the pending corpus uses for two-way diffs (11276-object-grid-properties-bag.md, 11434-designer-readers-types.md, 10859-designer-zod-arms.md among the 44 bare yes entries). The seat may add the arm by body edit without moving the head; nothing turns on it.
  • Pending changesets, judged on the corpus read, not on a list: the one standing reading this diff makes false is .changeset/11276-object-grid-properties-bag.md (its sentence listing the eleven keys "the row declares and the flat mirror does not"). The PR appends one dated note in the house form — "Correction, 2026-10-02 (objectui#6152, round 6)", naming the ten keys as now declared on the flat mirror, resizableColumns as still the row's alone, and the bag as unchanged — as a +2 / −0 hunk after the entry's last line, frontmatter and every prior line intact — RIGHT under 「改成追加说明 (Recommended)」. That entry's "What did not move" sentence (the mirror "unchanged in shape") is a reading of its own change and the note beneath it states the mirror now declares ten, so a CHANGELOG reader is not misled. No other entry is made false: 10976-table-slot-relay.md (the relay list and the withheld set, both unchanged), 6269-objectview-slot-key-lists.md (TypeScript lists only), 7762-object-grid-export-options-bare-array-refusal.md (table.exportOptions, unchanged), 10946-expression-wire-slots-by-reference.md (the list-view and kanban rule unions share one condition schema; still true, and the grid's now shares it), 10872-flat-arm-responsive-styles.md (table.responsiveStyles still refused by name), 9739-object-grid-operators-tombstone.md (its operations sentence is about the spec row), 11068-grid-declared-keys.md / 11068-object-grid-show-filters.md, 7727-conditional-formatting-record-scope.md (app-shell lint only), and the ledger-figure entries (6058, olive-moons-reclassify, pin-ledger-docstring-key-totals, 6639, object-view-unmirrored-keys-7779, 6150, 7804-tree-view-handler-slot, the earlier 6152-* rounds), each of which states a figure at a named revision or already carries a correction that names no live total. The 41 other entries the Changeset Claim Re-read named are inside that corpus read.

③ Boundary flags

Dev-declared deviations (report 5957803718), each answered:

  • resizableColumns not executed under the claim's stop condition, because objectui#11276 moved the authored node into the spec's properties bag after the 2026-09-29 answer was given — answered by the seat on 5957903936 (A, hold) and judged RIGHT at ① 7; the PR already implements the held state, so nothing on this head changes under that answer.
  • The seven row members the spec types as unknown not mirrored by reference to the row — RIGHT: binding z.unknown() would declare nothing, and the ledger measures parity with the TypeScript twin, so each member takes the spec schema the twin names or the twin's own shape (① 2).
  • The conditionalFormatting hoist and the SpecRuleConditionSchema move — judged RIGHT at ① 3.
  • Two test files and one pending changeset outside the named surface — accepted: each is forced by a pin that is green on this head or by the house form (① 9, ① 10, ② note).
  • A scratch Node 22.23.3 on PATH for jsdom, an objectstack read ref fetched for the census and deleted, a refused archive extraction not retried, light gates outside the verify lock, model-free commit trailers, the session-URL PR footer, and the assignee set with zero label writes — accepted: local-run and process matters, not contract matters; CI's toolchain is the verdict here.
  • The dev's first type-checker census (0 reads for the objectName control) and first runtime probe (stopped by the network-escape guard) were discarded and re-run, as declared — the measurement doing its job; neither reading is an input to this record.

open_questions, one, answered by the seat in 5957903936:

  • ObjectGridSchema.resizableColumns: A, hold — resizable stays canonical and the alias retires with no window, but in the protocol first (objectstack#21445), because the public door that accepts properties.resizableColumns IS the spec row; until that lands objectui keeps the alias declared, unmirrored and read. Within existing rulings: objectui#6170's producer-boundary rule, the 2026-09-29 answer's direction (kept; only the order of the two halves changes), and the governing text 「协议为基准:spec 与代码不一致默认改代码对齐;改协议单独立卡」 together with the pm-dispatch skill's 基本裁决原则 line that ranks the spec declaration above the implementation and above the docs face (quoted in full on 5957903936; not reproduced here because it carries angle-bracket characters). B was refused as a silent drop at a public door, and C as the first local refinement reaching into a spec-row bag. Nothing on this head depends on the answer, and the follow-up (the ?: never tombstone, the flat-mirror tombstone naming properties.resizable, the ?? schema.resizableColumns read dropped, the ledger key retired) is a later objectui change once that release is installable. The maintainer's veto window the seat named applies to the answer, not to this head. No escalation.

out_of_scope_findings (report 5957803718), read, none a flag on this head:

  • The spec row's seven unknown-typed members (class c, measured at a public door on 17.5.0): a spec-lane finding; the dedupe against objectui#11276's own report of the same reading is the seat's act, not this record's.
  • The spec half of resizableColumns: filed by the seat as objectstack#21445 in the same act as the answer.
  • BulkActionDef / BulkActionParam wider than the spec's BulkActionDefSchema: the mirror follows the twin, which is this ledger's parity; a narrowing of the twin is its own question.

Noted, not flagged:

  • The UnmirroredDeclared entry prose says the key "stays here until it is answered"; the question is now answered (hold until objectstack#21445 ships), and the round that retires the key rewrites the entry in any case.
  • The PR reads mergeable_state: behind at this reading (main moved after the branch's merge of 401611b2); the parity file is shared fleet-wide and the queue arbitrates, as the claim's serial reading said.
  • The authored object-grid bag still accepts properties: { rowHeight: 'comfortable' } or grouping: 42 on both faces (the row types them unknown), and ObjectGrid falls back silently; the dev names it as a spec-row finding with its measured reach, and this round rightly does not reach into the bag.

Escalations: none. No maintainer decision is needed for this head to land.

Implemented-by: claude/issue-6152-objectgrid-round6
Reviewed-by: session_01XvhGmGAP79ZB8swnkapxPC

VERDICT: PASS

Rendered 2026-10-02T17:57Z · a read-only contract review of PR objectui#11492 on the head named above; the newest record naming this head governs, and any push after it voids it.

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review October 2, 2026 17:59
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 2, 2026 17:59
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 2, 2026
Merged via the queue into main with commit 0d723a3 Oct 2, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-6152-objectgrid-round6 branch October 2, 2026 18:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants