Skip to content

spec(types,plugin-detail,vscode-extension): TS twins of the zod-only node arms, the README's Activity tab on its declared properties, and Export to React's typed schema constant (objectui#11515) - #11519

Merged
objectstack-fleet[bot] merged 5 commits into
mainfrom
claude/issue-11515-v1-doc-blocks
Oct 3, 2026

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Fixes #11515
Clause-②: yes (widening)

Part of the preparation for objectui#11466 (V1, draft PR #11512). On PR #11512's head, check:doc-snippets judges 776 blocks and refuses 2: the plugin-detail README's detail-view "With Tabs" example and the Export to React "Output Example" in content/docs/utilities/vscode-extension.mdx. This PR settles both. Measured under a throwaway probe (this branch plus PR #11512's commits, merged without a commit, never pushed), the same gate judges 776 and refuses 0. With V1's own copies of the two documents in that probe, it refuses exactly those 2.

Block 1 — TS twins of the zod-only node arms (ruling A)

Before. @object-ui/types declared no TypeScript type for three arms its zod face already validates: detail-section (views.zod.ts#DetailSectionNodeSchema), app-schema-renderer (app.zod.ts#AppSchemaRendererNodeSchema) and cloud:plan-status (cloud.zod.ts#CloudPlanStatusSchema). SchemaByType of each literal was never, and the parity census carried all three as EXCLUSIONS ("no TS declaration in this package restates the node").

After. Each gains a twin beside its arm's module, member for member:

zod arm TS twin members
views.zod.ts#DetailSectionNodeSchema DetailSectionNodeSchema (views.ts, in ViewComponentSchema) the ten members the arm .picks from DetailViewSectionSchema (title, description, icon, fields required, collapsible, defaultCollapsed, columns, showBorder, headerColor, hideEmpty), each DetailViewSection's own member by indexed access; body / children ?: never
app.zod.ts#AppSchemaRendererNodeSchema AppSchemaRendererNodeSchema (app.ts, in AnySchema) schema?: AppComponentSchema (the arm's member IS AppComponentSchema), basePath?: string, mobileNavMode?: 'drawer' or 'bottom_nav'; body / children ?: never
cloud.zod.ts#CloudPlanStatusSchema CloudPlanStatusSchema (new cloud.ts, in AnySchema) properties: { plan: string }, required and closed; body / children ?: never

No zod schema, validator verdict or runtime behaviour changes. The widening is the TS face's declared surface only, matching what the zod face already publishes (the Clause-② line above).

Pins.

The README's Activity tab. It authored record:activity with items: activityData, the host feed slot the node refuses by name (objectui#11321). It now authors the declared input, properties: { limit: 20, showCompleted: false }, as the plugin-detail guide does; the FeedItem import and activityData go. The note under the example says where the feed comes from. Rendered through DetailTabs and the real registry (a one-off probe, not kept), the tab draws Activity (0), the All Activity filter and No activity recorded, with no unknown-type panel and no error banner. The zod docblock in public-blocks.zod.ts that named this README as a host composition passing items gets a dated parenthesis.

Block 2 — the Export to React generator (ruling A, route changed by measurement)

Before. The emitted constant was unannotated, so every type widened to string; under V1 the one JSX line is refused for every schema (TS2322 against the declared-node union).

The card's annotation, measured. const schema: SchemaNode does NOT compile, today or under V1: SchemaNode also admits number and boolean, which SchemaRendererProps['schema'] leaves out, and the narrowing at the initializer does not reach the body of GeneratedComponent. With it, the JSX line was refused for every schema on both trees, including the documented sample. That is the ruling's own premise ("it exists today and compiles both now and after V1") measured false, so the route follows the ruling's intent instead: a type that exists today, is not DeclaredNode, and compiles against the prop on both trees.

After. The constant is typed SchemaRendererProps['schema'], imported type-only beside SchemaRenderer from the package the file already imports (no new dependency). Emitted output for the documented sample, before and after:

-import { SchemaRenderer } from '@object-ui/react';
+import { SchemaRenderer, type SchemaRendererProps } from '@object-ui/react';
 ...
-const schema = {
+// Typed as the schema SchemaRenderer takes, so each "type" below stays a literal
+// and the compiler checks the schema against the node types it accepts.
+const schema: SchemaRendererProps['schema'] = {

tsc (strict, react-jsx, noUnusedLocals) on the emitted file, against the BUILT packages of each tree:

fixture main, before main, after V1 probe, before V1 probe, after
documented sample (div with an h1 child) 0 errors 0 errors 1 (TS2322) 0 errors
an undeclared child type 0 0 1 1 (TS2322 at the child)
an object with no type 1 1 1 1

The SchemaNode annotation and a satisfies SchemaNode variant were measured on the same grid; the table is in the report on the card.

The documented sample keeps "type": "h1". The card reads h1 as undeclared; it is declared, one of the HTML passthrough tags HtmlElementSchema declares (objectui#8499), and scripts/__tests__/check-doc-component-types.test.ts pins "type": "h1" in this very sample as the registered replacement for heading. Annotated, the h1 sample compiles on both trees (table above, and check:doc-snippets on both). A rewrite to text with variant: 'h1' was tried and reverted when that pin went red; the PM may still order it (one sample edit plus that pin).

Pins. The emitter has tests: export-to-react-compiles.test.ts and export-to-react-preamble.test.ts.

  • The compile pin's stub typed the prop unknown, so it could not see an annotation. A new leg compiles the emitted file against the REAL prop type with no build: @object-ui/types resolves to its source entry, and the @object-ui/react declaration carries the SchemaRendererProps body and its @object-ui/types import read out of packages/react/src/SchemaRenderer.tsx at test time, so it follows the prop when V1 retypes it. Its positive control is a schema with no type, refused on the constant's own line.
  • Ablation, run once and not kept (generator emitting the BASE unannotated constant, restored by blob equality to HEAD): on main the control turns red (the refusal moves from the constant's line to the JSX line); in the V1 probe both legs turn red (the sample is refused with TS2322, widened type: string).
  • The preamble pin names the new import line and the annotated constant; the two documented mirrors (DESIGN.md section 4 and the docs page) follow the new preamble, held by the existing objectui#7976 pin.

Corpus documents re-judged

  • packages/plugin-detail/README.md, "With Tabs": re-authored (above). Its detail-section tab was refused under V1 for want of a TS type; with the twins it compiles under V1 unchanged.
  • content/docs/utilities/vscode-extension.mdx, "Output Example": new preamble and annotated constant; sample unchanged.
  • packages/vscode-extension/DESIGN.md, section 4: new preamble.
  • packages/cli/src/__tests__/validate-passing-keys-11440.test.ts described the README's second tab as the host feed. It now validates the full example document as the README writes it (green on objectui validate), and keeps the host-feed row as the refusal's control.

Pending changesets

  • Dated notes added: 8114-detail-tab-activity-timeline.md (its items, not data bullet and the activityData sentence), 11321-record-feed-host-slots.md (the README as the items composition), 11478-anyschema-declared-node-types.md (ViewComponentSchema's four members; AnySchema gains three).
  • Read and left alone, each still true as written: 10919-cloud-plan-status, 11440-arm-passing-types, 11494-types-app-schema-renderer-schema, 11494-layout-app-schema-renderer-adapter (all state the zod face and the registration; none says the TS face lacks a type), 7837, 7862 and 7976 (Export to React preamble history; the side-effect import, the absent React import and the mirror binding all still hold), and the 25 entries check:changeset-claims lists as naming a touched file (each describes another pair, key or README section).
  • New: 11515-types-ts-twins-zod-only-arms.md (@object-ui/types minor), 11515-vscode-export-react-annotation.md (object-ui patch), 11515-plugin-detail-readme-activity-properties.md (@object-ui/plugin-detail patch).

Verification (head afb660b7)

  • pnpm --filter @object-ui/types run type-check (all three tsc legs), pnpm --filter @object-ui/cli run type-check, pnpm --filter object-ui run type-check: exit 0.
  • pnpm exec vitest run packages/types/ packages/vscode-extension/ plus the cli validate test, the plugin-detail README reader and scripts/__tests__/check-doc-component-types.test.ts: Test Files 349 passed (349), Tests 9299 passed (9299).
  • pnpm check:doc-snippets: 776 of 776 block(s) judged, 0 failed. check:doc-types, check:doc-examples, check-changeset-no-major, check-changeset-presence, check:new-line-citations, check:control-bytes: green. check:changeset-claims is report-only (read above).
  • V1 probe: types type-check exit 0 with the three names out of the 8344 set; the parity, 8344, node-slot-union and AnySchema suites pass; check:doc-snippets judges 776 and refuses 0. The probe's plugin-dashboard build needed four throwaway as never casts at the producer sites PR feat(types,react,core,plugin-dashboard)!: a node slot and SchemaRenderer's schema prop take the declared-node union, V1; the dashboard producers name declared nodes and an envelope's object-metric retires (objectui#11466) #11512 already reports red; they never left the probe.
  • NOT MEASURED: check:sdui-registration-pins (no registration input moved; it needs a console build), repo-wide lint (CI's).

Acceptance notes

  • export-to-react-compiles.test.ts's SAMPLE_SCHEMA still writes the retired body while its comment calls it the empty template's shape (the template writes children). Inert under the hermetic stub; not touched here.

Generated by Claude Code

claude added 5 commits October 2, 2026 22:45
…chema-renderer and cloud:plan-status, parity-paired (objectui#11515)

`@object-ui/types` declared no TypeScript type for three arms its zod face
already publishes. Each gains a twin beside its arm's module
(`DetailSectionNodeSchema` in views.ts, `AppSchemaRendererNodeSchema` in
app.ts, `CloudPlanStatusSchema` in a new cloud.ts), joins `AnySchema`, and
is registered as a `zod-mirror-parity` pair instead of an exclusion.

`cloud:plan-status` measures clean. The other two are born ledgered with
the reading their by-reference member already carries one level up:
`fields` (the DetailViewField `options` divergence) and `schema` (the app
document's SCHEMA-NODE wider reading).

Claude-Session: https://claude.ai/code/session_01XvhGmGAP79ZB8swnkapxPC
Co-authored-by: Claude <noreply@anthropic.com>
…y's declared properties, not the host feed slot `items` (objectui#11515)

`items` is the host's feed slot, which the `record:activity` node refuses
by name. The tab now authors `properties: { limit, showCompleted }`, as the
plugin-detail guide does, and the note below the block says where the feed
comes from: a record host, or the empty state in a bare `DetailView`.
Rendered through `DetailTabs` and the real registry, the tab draws the
block's empty state. The zod docblock that named this README as a host
composition passing `items` gets a dated parenthesis.

Claude-Session: https://claude.ai/code/session_01XvhGmGAP79ZB8swnkapxPC
Co-authored-by: Claude <noreply@anthropic.com>
…chemaRendererProps['schema'], and the doc sample authors declared types (objectui#11515)

Unannotated, every `type` in the emitted constant widens to `string`,
which a prop that discriminates on the literal `type` refuses
(objectui#11466). `SchemaNode`, the annotation the card named, was measured
and does not compile today or under that change: it admits `number` and
`boolean`, which the prop leaves out, and the initializer's narrowing does
not reach the component body. `SchemaRendererProps['schema']`, from the
package the file already imports, compiles in both.

The compile pin gains a leg against the REAL prop type: `@object-ui/types`
resolves to its source entry and the `@object-ui/react` declaration carries
the `SchemaRendererProps` body read out of SchemaRenderer.tsx, with a
positive control refused on the constant's own line. The two documented
mirrors follow the new preamble, and the mdx sample writes `text` with its
`h1` variant.

Claude-Session: https://claude.ai/code/session_01XvhGmGAP79ZB8swnkapxPC
Co-authored-by: Claude <noreply@anthropic.com>
…e pending entries it makes false, and the cli pin on the README's full document

- `@object-ui/types` minor (the three TS twins), `object-ui` patch (the
  Export to React annotation), `@object-ui/plugin-detail` patch (the
  README's Activity tab).
- Dated notes on 8114 and 11321 (the README no longer hands
  `record:activity` its `items`) and 11478 (`AnySchema` gains three members).
- `validate-passing-keys-11440.test.ts` described the README's second tab
  as the host feed; it now validates the full document as the page writes
  it and keeps the host-feed row as the refusal's control.

Claude-Session: https://claude.ai/code/session_01XvhGmGAP79ZB8swnkapxPC
Co-authored-by: Claude <noreply@anthropic.com>
… `h1` node (objectui#11515)

`h1` is a declared type (`HtmlElementSchema`, objectui#8499), and
`check-doc-component-types.test.ts` pins it in this very sample as the
registered replacement for `heading`. With the constant annotated, the
`h1` sample compiles against the built packages today and with
objectui#11466 applied (measured with tsc and with check:doc-snippets on
both trees), so the `text` / `variant: 'h1'` rewrite the card proposed is
not needed and is reverted. The compile pin's documented sample follows.

Claude-Session: https://claude.ai/code/session_01XvhGmGAP79ZB8swnkapxPC
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation package: types plugin tests package: cli labels Oct 2, 2026
@github-actions

github-actions Bot commented Oct 2, 2026

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 25 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/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/__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/index.ts → packages/types/src/index.ts — edited by this change

    GanttConfig itself gains nine members and is a published type, exported by name from packages/types/src/index.ts: lockField, objectField, summaryExtent, defaultCollapsedDepth, borderColorField, dependencyTypes, timeZone, exportFileName, interactions. The entry file's diff is empty only because the export list already named the type — the widening happened at the declaration.

  • 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/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/6349-types-internal-name-collisions-batch-2.md

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

    MenuItem — renamed to AppMenuItem in app.ts. app.ts declared a flat, all-optional interface (type?: 'item' | 'group' | 'separator', label, icon, path, href, children, badge, hidden) — the @deprecated legacy navigation item that AppComponentSchema.menu, AppAction.items and menuItemToNavigationItem read. overlay.ts declared a discriminated union, MenuCommandItem | MenuDividerItem, whose command arm requires label and whose both arms tombstone type as type?: never (objectui#6523) — precisely the key app.ts declares as a three-value enum. Re-pointing either at the other would have made an authored type: 'separator' legal on one side and a type error on the other, so the two names had to part. @object-ui/types continues to publish overlay's union as MenuItem and app's interface as AppMenuItem, exactly as before.

.changeset/6594-headercolor-mirror-enum.md

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

    The nearest precedent is fc62bb490 (.changeset/5853-tablecolumn-type-canonical-union.md), which narrowed TableColumn.type on the same three-ends pattern and exported a TABLE_COLUMN_TYPES tuple for the zod mirror to build its enum from. That shape is not available here and the difference is structural, not a preference: packages/types/src/views.ts is a type-only module, so a tuple there would add a runtime export to the package barrel (a value export cannot ride the barrel's export type block) and a runtime import edge from the zod entry into views.js. fc62bb490 had a second reason to export — producers needed its normalizeTableColumnType() at their emit seam — and headerColor has no producer that needs a runtime value. The literals are therefore written on each half and the anti-drift guarantee is carried by the pin above, which also covers the third end a shared tuple could not reach: the renderer, in a package @object-ui/types must not depend on.

.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/7287-resolve-title-field-shared-ladder.md

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

    def.primaryField — a DetailViewSchema key (@object-ui/types views.ts), read off an OBJECT def and ranked ABOVE the canonical nameField ADR-0079 Phase 2 made the pointer (AGENTS.md Commandment #0.1). No producer can put it there: @objectstack/spec's object schema is a strictObject that answers unrecognized_keys: ['primaryField'], and ObjectSchema.create() throws — which is why objectstack#6326 deleted the identical read from two lint rules. A census across both repos found zero object payloads carrying it (the only writers are three test fixtures), and primaryField appears in zero files of the shipped @objectstack/spec@17.2.0 dist against 68 for nameField. Same shape as the undeclared objectDef.titleField read objectui#6531 measured and Five more consumer-side reads of the undeclared object-level titleField survive #6531 — in ObjectView view-config fallbacks and a useRecordSearch memo key #6557 removed. DetailViewSchema.primaryField is untouched and still honoured by DetailView's own header — it is a view key, and on a view it is legitimate.

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

.changeset/7586-primary-field-consumer-reads.md

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

    primaryField is a DetailViewSchema key (@object-ui/types views.ts) — a view key, which DetailView.resolveDisplayTitle reads off schema and is welcome to. Read off an object def it is undeclared: @objectstack/spec's object schema is a strictObject answering unrecognized_keys: ['primaryField'], and ObjectSchema.create() throws. primaryField appears in zero files of the shipped @objectstack/spec@17.2.0 dist, against 68 for the canonical nameField. objectstack#6326 removed the identical read from two lint rules; objectui#7287 / PR fix(plugin-detail): resolveTitleField delegates to the shared ADR-0079 ladder #7585 removed it from resolveTitleField. These two survived it — and three of this repo's own changelogs already called the probe "not a spec property — always undefined" while the code kept honouring it.

.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-tree-view-handler-slot.md

  • 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/7837-vscode-export-react-side-effect-import.md

  • names packages/vscode-extension/DESIGN.md → packages/vscode-extension/DESIGN.md — edited by this change

    packages/vscode-extension/DESIGN.md, which documented the identical two lines, is corrected in the same commit so the design record does not freeze the defect.

.changeset/7862-vscode-export-react-unused-import.md

  • names src/__tests__/export-to-react-compiles.test.ts → packages/vscode-extension/src/__tests__/export-to-react-compiles.test.ts — edited by this change

    A new pin, src/__tests__/export-to-react-compiles.test.ts, now extracts the template's PRODUCT and compiles it under noUnusedLocals, rather than matching substrings in the generator. The sibling objectui#7837 pin was green for the whole life of this line because it never named it; a compile closes the class instead of one member of it. Its positive control runs on every invocation: re-adding the import must report TS6133, so the harness cannot go quietly, permanently green.

  • names packages/vscode-extension/DESIGN.md → packages/vscode-extension/DESIGN.md — edited by this change

    packages/vscode-extension/DESIGN.md, whose section 4 hand-mirrors this preamble, is corrected in the same commit so the design record does not freeze the defect — the spelling objectui#7837 landed for the same file. What binds the two copies together is still nothing, and objectui#7976 holds that question.

.changeset/7997-detail-view-related-retired.md

  • names packages/plugin-detail/README.md → packages/plugin-detail/README.md — edited by this change

    Documentation. packages/plugin-detail/README.md and content/docs/api/schema-reference.md stop teaching the retired array and gain a migration block each.

.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/8344-node-recursion-point-redirect.md

  • names zod/public-blocks.zod.ts → packages/types/src/zod/public-blocks.zod.ts — edited by this change

    ⚠️ Dated note, 2026-09-28 — a second category module — objectui#10872. Later still in this same release zod/public-blocks.zod.ts joins them as well and imports zod/base.zod.ts too, so both counts in the mechanical note above are two higher, not the one the objectui#10859 note says; the reason the arm cannot be an import is unchanged. The rest of this entry, and that note, are kept as their readings.

.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/9092-inline-locale-declared-face.md

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

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

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

  • names views.ts → packages/types/src/views.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/component-meta-converge-and-deprecate-alias-5893.md

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

    ⚠️ Dated note, 2026-09-29 — the one-occurrence reading above has since moved — objectui#10979. "In-repo, PluginComponentMeta has exactly one occurrence — its own export line" above is the reading of the commit this change landed on (575b71c850), where a whole-tree search for the name returned that one line, in packages/types/src/index.ts. This change then added its own pins and this entry, and later in this same release objectui#5674's retirement of the sibling alias PluginComponentInput (PR objectui#10826) added mentions in its test and its entry. Re-measured on main at 2eaf5be27, the name occurred on 19 lines in 7 files. In non-test source it appeared only on the export line and on one doc-comment line in plugin-scope.ts, and the one file that imported it was this change's own component-meta-single-declaration.test.ts. The text above is kept as the reading of this change.

.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.

.changeset/plugin-detail-8937-parent-scope-residue.md

  • names packages/plugin-detail/README.md → packages/plugin-detail/README.md — edited by this change

    • packages/plugin-detail/README.md (it is in files[], so it ships). It said the node's filter is AND-combined with { [relationshipField]: parentId }, full stop. Since objectui#7299 the parent condition is compiled to match the relationship field's arity, so a multi-valued relationship gets { [relationshipField]: { $contains: parentId } } instead. The paragraph now states both spellings and names the arbiter (@objectstack/spec/data's isMultiValueField). - The claim that the SQL driver decides arity on that same predicate. It does not: driver-sql gates the equality family on its own storage question, which reads multiple as truthy on ANY type. The two rules therefore disagree for a type outside MULTI_CAPABLE_TYPES carrying multiple: true. objectui#9184 moved the arity compiler into @object-ui/core's parent-scope seam and carried the claim with it, so the correction is recorded there — the seam now states the driver's measured rule, records the divergence as a divergence, and points at the upstream card that owns which of the two rules is right (objectstack#17469). RelatedList.tsx's pointer comment and the objectui#7299 test header carried the same sentence and are corrected to match.

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.

Compared the checked-out tree with 059bf1b59 (merge-base with origin/main): 13 file(s) changed outside .changeset/, read against 2053 pending declaration(s) that publish a body (2684 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) 3551.1 KB 3574.6 KB
Main entry chunk (gzip) 150.3 KB 350 KB
Entry file index-CrP9x3sp.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) 571.09KB 136.86KB
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.51KB 66.22KB
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.47KB 11.25KB
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) 142.17KB 38.28KB
plugin-designer (index.js) 231.28KB 48.76KB
plugin-detail (index.js) 245.43KB 64.53KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 172.73KB 44.50KB
plugin-gantt (index.js) 179.16KB 45.06KB
plugin-grid (index.js) 233.13KB 63.89KB
plugin-kanban (index.js) 49.51KB 15.54KB
plugin-list (index.js) 116.63KB 28.97KB
plugin-map (index.js) 25.60KB 8.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.12KB 12.29KB
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 (cloud.js) 0.20KB 0.18KB
types (complex.js) 4.14KB 1.96KB
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: afb660b754e8ff644bcd74dcd5b606e13dc8e853
Local-runs: none

Inputs: card #11515 (body and its 3 comments: claim 5962501941, os-dev report 5963118595, seat answers 5963138450); PR #11519 (body, 19-file list, net diff against main 059bf1b at the head); the head's check-runs; every pending .changeset/*.md at the head (2691 entries, listed from git tree 98d18805, each read as a raw blob); head files read for cross-reference (views.zod.ts, app.zod.ts, cloud.zod.ts, public-blocks.zod.ts, base.ts, views.ts, layout.ts, index.ts, SchemaRenderer.tsx, the react barrel, node-recursion-point-8344.test.ts, check-doc-component-types.test.ts, .changeset/config.json, the vscode-extension package.json). Nothing built, run or re-run.

① Derived judgments

  1. Runtime / zod accept set: unchanged — RIGHT. No zod schema, validator, registration or renderer file is in the diff; the one zod/ touch is a docblock in public-blocks.zod.ts (comment lines only). safeValidateSchema, StrictAnyComponentSchema and objectui validate verdicts do not move, as the PR states.

  2. @object-ui/types TS face widens by three exported types, each the twin of its zod arm — RIGHT.

    • DetailSectionNodeSchema (views.ts) vs views.zod.ts#DetailSectionNodeSchema: the arm is BaseSchema.extend with the detail-section literal, the ten .picked DetailViewSectionSchema members and two tombstones. The twin declares the same ten (title, description, icon, fields, collapsible, defaultCollapsed, columns, showBorder, headerColor, hideEmpty) by indexed access on DetailViewSection, fields required on both faces, name / visible left out on both, body / children ?: never. description narrows BaseSchema's string | I18nLabel to string, as the zod .extend does. Member for member.
    • AppSchemaRendererNodeSchema (app.ts) vs app.zod.ts#AppSchemaRendererNodeSchema: schema?: AppComponentSchema (the arm's member IS AppComponentSchema), basePath?: string, mobileNavMode?: 'drawer' | 'bottom_nav', body / children ?: never. Member for member.
    • CloudPlanStatusSchema (new cloud.ts) vs cloud.zod.ts#CloudPlanStatusSchema: properties: { plan: string } required and closed (the arm's z.strictObject({ plan: z.string().min(1) })), body / children ?: never; .min(1) is a value check a type cannot state and the docblock says so. Member for member.
    • Membership: ViewComponentSchema gains DetailSectionNodeSchema; AnySchema gains AppSchemaRendererNodeSchema | CloudPlanStatusSchema (the third through ViewComponentSchema); SchemaByType is an Extract over AnySchema (index.ts:1072), so the three literals move from never to the twins. All three are re-exported from the barrel. This is the card's clause: the TS face widens to what the zod face already publishes.
    • Parity: EXCLUSIONS loses the three; MIRRORS / Declared gain them; EXPECTED_MIRROR_PAIRS 191 to 194; KnownDrift gains views.zod.ts#DetailSectionNodeSchema: 'fields' (49 / 87 to 50 / 88); WiderThanDeclared gains app.zod.ts#AppSchemaRendererNodeSchema: 'schema', one SCHEMA-NODE arm with its WIDER_ARMS row (3 / 3 / 3 to 4 / 4 / 4; 2 / 1 / 0 / 0 to 3 / 1 / 0 / 0); header prose carries the dated history sentences. The two born-ledgered rows name the same cause as the one-level-up rows that already exist (DetailViewSectionSchema: 'fields', AppComponentSchema: 'areas'). The card's pin "each TS twin equals its zod arm, through the parity ledger" is met: the twins are member-for-member and the measured divergences are inherited from by-reference members the ledger already records. RIGHT.
  3. @object-ui/plugin-detail README (ships in files[]) — RIGHT. The Activity tab authors properties: { limit: 20, showCompleted: false } instead of items: activityData; the FeedItem import and activityData go; the note under the example says where the feed comes from. Checked: RecordActivityBlockSchema.properties is the spec row (propsBag('record:activity', …)), the renderer reads limit / showCompleted (public-blocks.zod.ts:816-817), and items / loading are tombstoned on the node (objectui#11321). Today DetailViewTab.content is SchemaNode | SchemaNode[] and BaseSchema carries [key: string]: any, so the bag compiles; under V1 the declared record:activity face carries properties. This is Ruling A's "authors record:activity's declared input instead of items".

  4. object-ui Export to React generator — RIGHT. The emitted preamble gains type SchemaRendererProps on the existing @object-ui/react import, two comment lines, and const schema: SchemaRendererProps['schema'] =. Checked at the head: SchemaRendererProps is exported at packages/react/src/SchemaRenderer.tsx:1057 and reaches the package entry through packages/react/src/index.ts:9 (export * from './SchemaRenderer.js'), so the emitted import resolves with no new dependency; the prop today is BaseSchema | AuthoringNode | string | null | undefined, which admits the documented sample. Pins: the preamble test names the new import line and the annotated constant; preambleOf finds the binding by a const schema word-boundary regex, so the DESIGN.md section 4 and docs-page mirrors stay bound (objectui#7976) and both follow the new preamble; the new leg compiles the emitted file against the REAL prop (types resolved from source, the prop body read out of SchemaRenderer.tsx) with a positive control refused on the constant's own line.

  5. Forced test / doc edits — RIGHT, in scope. validate-passing-keys-11440.test.ts adds a row validating the README's full document as now written and keeps the host-feed row as the refusal's control; the public-blocks.zod.ts docblock that named the README as the items composition gets a dated parenthesis.

  6. Correctly NOT in the diff. No renderer edit (the claim's ⛔ holds: none of the 19 files is a renderer). No plugin-dashboard casts from the V1 probe. No node-recursion-point-8344 edit: on main that pin reads Equal of ArmsNotAssignableToSchemaNode with never (test lines 223-228) and no MeasuredArmDrift11466 set exists, so the card's "measured set loses each twinned type" pin can only be discharged on PR feat(types,react,core,plugin-dashboard)!: a node slot and SchemaRenderer's schema prop take the declared-node union, V1; the dashboard producers name declared nodes and an envelope's object-metric retires (objectui#11466) #11512 (see ③). check:sdui-registration-pins not measured: no registration input moved. RIGHT.

Public-surface summary: @object-ui/types +3 exported types (+1 module, barrel-only), AnySchema / ViewComponentSchema / SchemaByType widen; object-ui emitted output changes (annotation + type-only import); @object-ui/plugin-detail README text; @object-ui/react untouched; @object-ui/cli test-only; runtime unchanged.

② Semver level

  • New entries at the head: 11515-types-ts-twins-zod-only-arms.md (@object-ui/types: minor, carrying Clause-②: yes (widening)), 11515-vscode-export-react-annotation.md (object-ui: patch), 11515-plugin-detail-readme-activity-properties.md (@object-ui/plugin-detail: patch).
  • Levels — RIGHT. types minor: new exported types and a wider AnySchema, nothing narrows on either face. object-ui patch: a fix to the generator's output; object-ui is in the fixed group and .changeset/config.json sets privatePackages.version: true, the same frontmatter 7837 / 7862 use. plugin-detail patch: README ships in files[] (8114 / 8937 precedent), no source. No entry for @object-ui/cli (test-only) or @object-ui/react (untouched): right. Changeset Declaration, Bump Policy, Fixed Group Check, Claim Re-read and Overwrite Report check-runs are all green.
  • Clause-②: the PR body's Clause-②: yes (widening) matches the claim's line (comment 5962501941) and the types changeset restates it. RIGHT.
  • Pending readings this change makes false — each carries a dated, append-only note in the house form (⚠️ Dated note, 2026-10-02 — … — objectui#11515. … The rest of this entry is kept as the reading of this change.):
    • 11478-anyschema-declared-node-types.md: enumerated ViewComponentSchema's four members and AnySchema's additions; the note names the three new members. RIGHT.
    • 8114-detail-tab-activity-timeline.md: its "items, not data" bullet and the activityData / FeedItem sentence described the README; the note says both no longer do. RIGHT.
    • 11321-record-feed-host-slots.md: named the README as the TSX composition handing items; the note says no example composes items now, refusal unchanged. RIGHT.
  • Left alone, judged one by one, each still true as written (grep over all 2691 for the three type names, the three node literals, AnySchema / ViewComponentSchema, EXPECTED_MIRROR_PAIRS / KnownDrift / WiderThanDeclared / EXCLUSIONS and their figures, activityData / the README / Activity tab / FeedItem, const schema = / Export to React / SchemaRendererProps, SchemaByType):
    • 10919-cloud-plan-status, 11440-arm-passing-types, 11494-types-app-schema-renderer-schema, 11494-layout-app-schema-renderer-adapter: describe the zod arms, registrations and renderers; none says the TS face lacks a type. 11440's "TypeScript face" paragraph names the two TS types THAT change added and is silent on detail-section / app-schema-renderer: silent, not false.
    • 10485, 6955, 8626, 9218, 9529 (detail-section inputs / renderer), 10859, 11441, 11471 (registration), 11363 (AppComponentSchema.mobileNavMode is never on the app document, not the node): runtime readings a TS twin does not touch.
    • 7837, 7862, 7976: the side-effect import, the absent React import, the single JSX element and the mirror binding all still hold; none quotes the @object-ui/react import line or const schema = verbatim.
    • 8021, 8310, 8908, schema-input-bridge-permanent-4622, 11364, 11468: readings of the prop's own union (already dated by 11364 where it moved), not of the generator.
    • Ledger figures: 8338 (42 / 64 to 41 / 63; "EXPECTED_MIRROR_PAIRS does not move"), action-callback-retired-7068 (159 to 158), pin-zod-mirror-parity-header-key-totals, wider-ledger-per-arm-8252, 8458, 11168, zod-mirror-parity-population-5684: each the reading of its own change, not a standing total.
    • 9256-public-blocks-content-channels ("no TypeScript declaration of these nodes", already dated by 11364): the public-block arms, not these three.
      No pending reading is left false without a note. ② holds.

③ Boundary flags

Each deviation and open question in report 5963118595, with the seat's answer in comment 5963138450 and my own check of the head:

  1. Q1 — annotation is SchemaRendererProps['schema'], not the ruling's SchemaNode. Seat: A as landed (seat correction 1). Checked: SchemaNode = BaseSchema | string | number | boolean | null | undefined (base.ts:614); SchemaRendererProps.schema = BaseSchema | AuthoringNode | string | null | undefined (SchemaRenderer.tsx:1057). A SchemaNode-typed constant is not assignable to the prop, so the ruling's premise was false; the landed type is an existing export, is not DeclaredNode, is the prop itself so it follows V1 by reference, and adds no dependency. The ruling's intent (compiles today and after V1) is met. ANSWERED.
  2. Q2 — the docs sample keeps "type": "h1". Seat: A as landed (seat correction 2). Checked: h1 is in HtmlElementSchema's tag union (layout.ts:1886), and scripts/__tests__/check-doc-component-types.test.ts:1798-1801 pins "type": "h1" in vscode-extension.mdx. The sample authors declared types, the ruling's intent. ANSWERED.
  3. node-recursion-point-8344's measured set is not edited on this branch. Checked: main's pin is never with no MeasuredArmDrift11466; that set exists only on PR feat(types,react,core,plugin-dashboard)!: a node slot and SchemaRenderer's schema prop take the declared-node union, V1; the dashboard producers name declared nodes and an envelope's object-metric retires (objectui#11466) #11512. The dev measured in the probe that the set must lose exactly the three names (red with, green without), and the seat carried the deletion, plus the three-hunk zod-mirror-parity.test.ts union (6 / 6 / 8; 3 / 3 / 0 / 2), to PR feat(types,react,core,plugin-dashboard)!: a node slot and SchemaRenderer's schema prop take the declared-node union, V1; the dashboard producers name declared nodes and an envelope's object-metric retires (objectui#11466) #11512's merge of main. ESCALATED to PR feat(types,react,core,plugin-dashboard)!: a node slot and SchemaRenderer's schema prop take the declared-node union, V1; the dashboard producers name declared nodes and an envelope's object-metric retires (objectui#11466) #11512, where the seat says it is recorded. Not a FAIL here: the card's pin is undischargeable on main, and the owner is named.
  4. File-surface additions beyond the claim (DESIGN.md, the public-blocks.zod.ts docblock, validate-passing-keys-11440.test.ts, three dated notes): each forced by an existing pin (the 7976 mirror binding; a docblock and a test that described the README's tab) or by the changeset rule. In scope. ANSWERED.
  5. V1 probe's as never casts and the parity merge resolution: not in the diff (no plugin-dashboard file touched). ANSWERED.
  6. Toolchain note (Node floor 22.13 on main): no contract bearing. ANSWERED.
  7. Out-of-scope finding (export-to-react-compiles.test.ts SAMPLE_SCHEMA writes the retired body while its comment calls it the empty template's shape): in the PR's Acceptance notes, carrier none, inert under the stub. Not blocking; the seat may file it.
  8. Claim's ⛔ No renderer edit: held.

Check-runs on afb660b7, read 2026-10-02T23:36:38Z, 2026-10-02T23:42:56Z and, just before this write, 2026-10-02T23:46:30Z: 36 success at the second read (Type Check, Doc Snippet Type Check, Doc Component Type Check, Changeset Declaration / Bump Policy / Fixed Group Check / Claim Re-read / Overwrite Report, Lint, Build Docs, Build & E2E, Test (dist pins), Test shards 2, 3, 5, 6 and 8 of 8, Spec Main Shape Gate, README Export Check, Bundle Analysis, Live E2E, and the rest), 3 skipped (coverage, dependabot), 0 failure; still in progress at the second read: Test (shard 1/8), Test (shard 4/8), Test (shard 7/8); at the third read all 43 are complete: 40 success, 3 skipped, 0 failure. No red bears on the contract.

Implemented-by: claude/issue-11515-v1-doc-blocks
Reviewed-by: session_01XvhGmGAP79ZB8swnkapxPC

VERDICT: PASS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

2 participants