Skip to content

feat(types)!: an authored object-gantt takes its props in the spec's properties bag; the flat spelling is refused by name (objectui#10859, batch 6) - #11337

Merged
objectstack-fleet[bot] merged 7 commits into
mainfrom
claude/issue-10859-object-gantt-properties-bag
Oct 1, 2026
Merged

objectstack-fleet[bot] merged 7 commits into
mainfrom
claude/issue-10859-object-gantt-properties-bag

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Part of #10859
Clause-②: yes (narrowing)

Clause-②: yes (narrowing), copied from the PM claim 5924906396: @object-ui/types' authoring faces widen (a spec-shaped object-gantt bag node that is refused today parses) and narrow (a flat object-gantt node that parses today is refused). This is objectui's narrowing-as-minor rule with a BREAKING (authoring) banner in the changeset, as in batches 1 to 5.

Batch 6 of objectui#10859, the last flat-arm block. It executes seat 1's flat-arm answer at PR objectui#11248's ACCEPT (5917261346) for ONE block, object-gantt, following batch 5 (PR objectui#11309) as merged with PR objectui#11312 (one requireRecordSource(type, rungs, at); the cross-seat pointer 5924134305). The card stays open for the designer six and the (ii) / (iii) keys.

What changed

  • packages/types/src/zod/objectql.zod.ts: new ObjectGanttBlockSchema, batch 5's construct. It is BaseSchema + the object-gantt literal + NODE_ENVELOPE + properties = propsBag('object-gantt', stripImportedDefaults(SpecObjectGanttPropsSchema)): the shared helpers and the installed 17.5.0 row by reference, no copy, no new helper. Beside it:
    • dataSource, the spec's ElementDataSourceSchema by reference (the registration is elementDataSourceBlock-wrapped);
    • one aliasKeyRefusal per member of the row, keyed by the row's own key set read off the crossed row ("Did you mean KEY → properties.KEY?"), less label (see Deviations);
    • one aliasKeyRefusal per member of the row's gantt block, pointed at properties.gantt.KEY, plus the flat mirror's legacy dependencyField pointed at properties.gantt.dependenciesField. These are the flat GanttConfig keys the flat mirror declared on the node;
    • body / children refused with the flat mirror's objectui#9256 string;
    • the maintainer's record-source rule read in the bag through the merged requireRecordSource('object-gantt', RECORD_SOURCE_KEYS, 'properties'). It counts a non-empty dataSource.object, so a bag node bound only through dataSource parses on both faces.
  • The arm joins ObjectQLPublicBlockComponentSchema. ObjectGanttSchema (the flat mirror) leaves ObjectQLComponentSchema (9 to 8 arms), stays exported, and stays paired with its TypeScript twin in the parity census. Its docblock gains a "No longer an authoring arm" section.
  • packages/types/src/objectql.ts: the TypeScript ObjectGanttSchema is re-declared, not retired. Its members are unchanged; its docblock says it is the node as ObjectGantt reads it after SchemaRenderer hoists properties, and as code composes it. The TypeScript union's docblock names the zod union's new count.
  • packages/types/src/zod/index.zod.ts (one barrel export) and packages/types/src/zod/README.md (the ObjectQL public-block group lists the arm, 7).
  • objectui's authored flat producers, rewritten to the bag (census below): content/docs/plugins/plugin-gantt.mdx, the three examples/schema-catalog gantt entries, packages/plugin-gantt/README.md.
  • New pins: packages/types/src/__tests__/object-gantt-properties-bag-10859-b6.test.ts (both faces, the row by reference, the flat keys, the record source, the split) and packages/plugin-gantt/src/ObjectGantt.propertiesBag-10859.test.tsx (render through the real registry).
  • Two changesets: .changeset/10859-object-gantt-properties-bag.md (@object-ui/types minor, BREAKING (authoring) banner) and .changeset/10859-plugin-gantt-properties-bag-docs.md (@object-ui/plugin-gantt patch: README and the two touched src/ test files; no runtime change).

Files beyond the claimed surface, each forced:

  • census rows the new export forces: zod-mirror-parity.test.ts (one EXCLUSIONS row; EXPECTED_MIRROR_PAIRS untouched), imported-defaults-8317.test.ts (one IMPORTED row), registered-type-arms-10859-b2.test.ts (the exact literal list gains object-gantt), objectql-union-arms-7363.test.ts (8 arms, object-gantt not among them), public-block-responsive-styles-10872.test.ts (object-gantt joins DECLARES_DATA_SOURCE and the record-source carve-out);
  • fixture triage where a face now judges the bag (the mirror rows keep the post-hoist spelling): content-channel-e3-residual-9256.test.ts, objectql-record-source-refinement-6939.test.ts, strict-face-read-keys-11070.test.ts, the schema-catalog objectql-record-source-render-identity-6939.test.tsx (its anti-vacuity row reads the bag; its PRE_REPAIR render readings hold unchanged) and plugin-gantt's ObjectGantt.catalogPlans-11141.test.tsx (it mounts ObjectGantt directly, so it hoists the catalog bag the way SchemaRenderer does).

Zone 1, measured before building

  1. The inherited reason holds for this arm. Installed @objectstack/spec 17.5.0: ComponentPropsMap['object-gantt'] exists and is the exported ObjectGanttPropsSchema (17 members, strict; its gantt member is the 29-key GanttConfig). PageComponentSchema refuses { type: 'object-gantt', objectName, gantt } with unrecognized_keys ['objectName', 'gantt'] ("Unrecognized key(s) on this page component … ADR-0089 D3a") and accepts the same props in properties. A flat startDateField is refused the same way. Control: a flat action:button actionType is refused the same way. The row exists, so the bag is that row by reference (no mirror bag, unlike object-chart).
  2. Census, with the stop line. At base 5262f7dd3, 138 tracked files name object-gantt: 11 CHANGELOG.md, 27 pending changesets, 77 test files and 23 others:
class files action
authored page-node producers plugin-gantt.mdx (10 nodes and the Schema API block), the 3 schema-catalog entries, packages/plugin-gantt/README.md (8 nodes) rewritten
component mounts (post-hoist schema prop, no hoist) plugin-gantt.mdx "Task Click", README "Interactive Gantt" and "Integration with Data Sources" kept flat, now said so
runtime composers ListView.tsx, ObjectView.tsx (flatten a stored gantt view, write the flat GanttConfig keys and the search pair) kept flat; they render through SchemaRenderer and never meet the zod faces
the declarations objectql.ts, objectql.zod.ts this change
renderer and registration ObjectGantt.tsx, plugin-gantt/src/index.tsx, register-plugins.ts none
names the type, no node shape known-schema-types.ts, public-blocks.ts, record-source.ts, comments (ValueDataSource.ts, plugin-tree/src/index.tsx, registerCatalogBlocks.ts), two scripts/check-* ledgers, prose (component.prompt.md, data-source.md) none
governed skills/** skills/objectui/guides/page-builder.md "Gantt plugin example" (one flat node, plus prose teaching the flat field keys on the node) listed, not rewritten (governed path)

Stop line: not tripped. No objectui context builds anything from the zod ObjectGanttSchema object: its only non-test reader was the ObjectQLComponentSchema union, and that union's only reader is AnyComponentSchema. The non-page contexts that keep the flat spelling depend on the TypeScript twin (the composers, ObjectGantt's schema prop) or on the registration's inputs (the sdui-parser html tier), not on that object.
3. The arm, as above. ObjectGanttSchema is re-declared, not retired.
4. Producers: rewritten as above; one governed producer listed.
5. Pins: below. The objectui#10859 ratchet does not move: object-gantt was never refused at type.

Batch 5's finding, re-measured. On base, safeValidateSchema already accepts the flat { type: 'object-gantt', dataSource: { object: 'task' }, gantt } (PR objectui#11312 counts the binding on every arm), so the finding no longer reproduces on the flat arm. For the bag arm it is answered: a dataSource-only bag node parses on both faces (pinned), and dataSource: { object: '' } with no rung is refused.

Zone 2, re-measured

  1. Held: each symbol is where the order located it at 5262f7dd3.
  2. Held: 23 non-test, non-changelog, non-changeset files name object-gantt (table above).
  3. Held: no open PR edits these regions. PR objectui#11333 also edits strict-face-read-keys-11070.test.ts; git merge-tree --write-tree HEAD against its head 139a49137 exits 0, and against origin/main 5262f7dd3 exits 0.

Tests (heavy runs through os-verify-lock.sh, slot issue-10859)

  • Base measurement (source, before any edit): the bag node { type: 'object-gantt', properties: { objectName, gantt } } refused by safeValidateSchema (RECORD_SOURCE_REQUIRED at the root) and by the strict face (the same, plus unrecognized_keys ['properties']); the flat node accepted on both.
  • Green, union at the final head 0c673ccb8: pnpm exec vitest run packages/types/ packages/cli/ scripts/__tests__/: Test Files 510 passed | 2 skipped (512), Tests 13626 passed | 2 skipped (13628), VERDICT command-exit 0. pnpm exec vitest run packages/plugin-gantt/ examples/schema-catalog/: Test Files 130 passed | 1 skipped (131), Tests 2911 passed | 114 skipped (3025), VERDICT command-exit 0 (the skips are the zone-conditional skipIf pins). The second run holds every test that reads a markdown file this PR changes outside packages/types and scripts (markdown-test-inputs.mjs ledger), readme-navigation-example.test.ts among them.
  • Arm-list consumer sweep (declared narrowing): 232 tracked test files outside packages/types and packages/cli that name AnyComponentSchema, StrictAnyComponentSchema, safeValidateSchema, ObjectQLPublicBlockComponentSchema, ObjectQLComponentSchema, ObjectGanttBlockSchema, nodeOracles, KNOWN_SCHEMA_TYPES, propsLevelOf, PUBLIC_BLOCKS, unmirroredAlias, collectArms, getPublicConfigs, ComponentPropsMap, validateSchema or StrictAuthoringFace, or reference check-handler-key-read-sites, block-config-schema-parity, registry-inputs-spec-parity, strict-authoring-face, zod-mirror-parity, objectql.zod, index.zod, ObjectGanttSchema, object-gantt or plugin-gantt. Three chunks, at ceead94ad plus the two triage edits later committed byte-identical as c572b020c: 78 passed / 1 failed (79) (the render-identity anti-vacuity row, then triaged), 73 passed / 1 failed (74) (the catalog-plans pin, then triaged), and 79 passed plus the two triaged files: Test Files 81 passed (81) / Tests 1610 passed, VERDICT 0. Later commits add the render pin, the docs and the changesets; their markdown readers are re-run in the final union above.
  • Build / type-check: pnpm --filter @object-ui/types build && pnpm --filter @object-ui/types type-check, VERDICT 0 (dist completeness: 1 package(s) complete (138 emitted files verified)); the b6 pin is in tsconfig.test.json's --listFilesOnly. After pnpm --workspace-concurrency=2 --filter '@object-ui/plugin-gantt^...' --filter '@object-ui/example-schema-catalog^...' build (VERDICT 0): @object-ui/plugin-gantt type-check and @object-ui/example-schema-catalog type-check, VERDICT 0 (the two plugin-gantt pins and the catalog render-identity pin are in their test programs).
  • Runtime ablation (objectstack scripts/ablation-replace.mjs, two nested WRAP legs plus the driver's own EXIT/INT/TERM trap with an absolute path and a blob check): the flat arm restored, i.e. ObjectGanttBlockSchema out of the public-block union (anchor x1 to x0, blob bc957ee9 to 8390b06a) and ObjectGanttSchema back into ObjectQLComponentSchema (anchor x1 to x0, blob to e5be71a8; on disk ObjectGanttBlockSchema, x0 in the public union and ObjectGanttSchema, x1 in the ObjectQL union). Over 13 test files (the two new pins, the census and triaged files, the catalog pins and the objectui#10859 ratchet): Tests 93 failed | 783 passed (876). Red: 78 b6 rows, 4 of 6939, 3 catalog validate rows, 2 of 9256, 2 of 10872, one each in 7363, b2 and 11070, and the render pin's validator row. Green: the census files whose subject is the export itself (zod-mirror-parity, imported-defaults-8317), the ratchet, the catalog-plans pin (a direct mount), every render row, and the 26 b6 rows that read the spec or the arm directly (the lit controls, the per-member page-component split, the row-by-reference row, the binding and channel refusals the flat arm shared, the spec-divergence row and the flat-mirror row). Direction red, as expected. Restored: blob == HEAD bc957ee9, git diff HEAD empty (both tool legs and the driver). Vitest aliases @object-ui/types/zod to source, so no build sat between the mutation and the run.
  • Type-level reverse validation (same tool): the bag replaced by z.strictObject({ objectName: z.string().optional() }).optional() made tsc -p tsconfig.test.json exit 2 with exactly one error, TS2344: Type 'false' does not satisfy the constraint 'true' on the bag Equal row of the b6 pin. Restored, blob == HEAD, git diff HEAD empty.
  • Render (committed pin, real registry, recording adapter): the bag queries find('task', …) with its own $filter and $orderby and hands the chart one task per row, titled by its gantt block; the two flat spellings a composer builds (the gantt block on the node, and the flattened GanttConfig keys) make the identical call and hand the chart identical tasks; a bag bound only through dataSource queries the bound object; a bag on inline rows draws them with no host query; control: a bag naming another object queries that object and never task. The catalog render-identity pin draws the three bag entries exactly as its recorded pre-repair DOM.

Gates (exit codes captured before any pipe)

  • exit 0: check:control-bytes ("OK (scanned 9809 tracked text file(s); skipped 85 binary)"; a self-scan over the 23 changed files gives 0 hits), check:new-line-citations ("VERDICT new-cross-file-line-citations: 0 new citation(s)"), node scripts/check-changeset-presence.mjs ("15 source file(s) of 2 released package(s) changed, and this change declares 2 changeset(s)"), changeset:check ("No changeset declares a major bump."), check:handler-key-reads ("OK 140 arm(s), 212 registration(s) (138 keyed onto an arm), 56 reachable handler read(s), 56 judged"), check:spec-symbols, check:element-data-source-declaration ("14 gate-consuming file(s) checked"), check:component-surface-parity, check:installed-pin-claims, check:test-path-roots, check:vi-mock-specifiers, check:vi-mock-inherit, check:vi-mock-override-shape, check:unreferenced-sources, check:esm-specifiers, type-check:coverage ("43/43 packages compile their tests"), check:registry-bare-names, check:prompt-keys, check:pending-changeset-literals, census:changeset-polarity, check:skill-examples.
  • docs: check:doc-types, check:doc-fences, check:doc-example-ids, check:doc-example-readers, docs:check-links ("Links are valid across 17 scan roots."), node scripts/markdown-test-inputs.mjs --audit ("108 candidate test files, all adjudicated; 80 declared entries, all present."), and the whole root scripts/__tests__/ suite (in the union above). After the check-doc-snippet-types.mjs --build-filter closure build (turbo "Tasks: 35 successful, 35 total"): check:doc-snippets ("Semantic phase: 698 of 698 block(s) judged, 0 failed."), check:doc-examples, check:readme-exports, each exit 0.
  • check:changeset-claims (report-only): five pending changesets describe what the validators say about an object-gantt written flat (6475-gantt-block-face-declared, 6939-objectql-record-source-refinement, 9256-e3-residual-content-channels, 11070-strict-face-read-keys, 11117-datasource-objectname-waiver). They are not edited; this change's types changeset names how those readings happen in the bag now, so the release notes read together.
  • node scripts/check-governed-queue-guard.mjs --test over the 23 paths: "NOT GOVERNED".
  • eslint narrowing: pnpm exec eslint --no-inline-config --format json over the 15 changed .ts / .tsx files: 0 errors, 37 warnings, the same count file for file as the base blobs linted through --stdin (the new and the other touched files carry 0). Population: each touched package lints .; eslint.config.js sets no type-aware parser project, so no untouched file's verdict can move. The full pnpm lint is CI's.

Deviations

  • label is not refused flat. The order asks for one aliasKeyRefusal per bag member. label is a row member AND a node-level key of the spec's own PageComponentSchema (its display label): measured, the spec's page component accepts label on an object-gantt node while it refuses every other row member written there. Refusing it would make objectui refuse a spec-valid document, so label keeps BaseSchema's member. The pin re-derives the split from the installed spec for every row member, so a spec that moves it turns the pin red.
  • The flat mirror's GanttConfig members and dependencyField are refused by name on the bag arm, beyond the row-key set: they were declared members of the flat mirror, and their bag home is the row's gantt block (batch 5's precedent for locationField / titleField). The key set is the row's own gantt member, read off the crossed row.
  • search / searchableFields (flat-mirror members, absent from the row) are left undeclared on the bag arm, as batch 4 left the row-absent members of object-form: unjudged by the tolerant face, refused by the strict one, refused by the row inside the bag. A list view writes them onto the node it composes, which never meets these faces.
  • Second changeset, @object-ui/plugin-gantt patch: the README, and two test files under src/, which the presence gate counts as published source.
  • Comments this change made false, or that were already false next to the edit, corrected in passing: requireRecordSource's docblock said neither object-map nor object-gantt has a ComponentPropsMap row (both have had one since 17.5.0); the flat mirror's gantt member comment and the TypeScript twin's gantt comment said the mirror reaches validate through AnyComponentSchema; the ObjectQLComponentSchema docblock's opening sentence named two departed arms out of four.
  • The harness attribution reminder asked for model-named commit trailers and a different PR footer. Per AGENTS.md and the role file, the commits carry the model-free pair and this body the session-URL footer.

Acceptance notes

  • The bag follows the spec row, which is not the flat mirror. Measured: the row types markers as an array of unknown and navigation as unknown, so properties.markers: [{ date: 5 }] and properties.navigation: { mode: 'nope' } parse, where the flat mirror refuses both (invalid_type at markers.0.date, invalid_value at navigation.mode). The row's own contract, taken by reference; no producer writes either.
  • The governed producer skills/objectui/guides/page-builder.md "Gantt plugin example" authors a flat object-gantt node (objectName and gantt on the node), which objectui validate refuses after this change, and its prose says the flat field keys may be written on the node. check:skill-examples exits 0 on it (it does not run safeValidateSchema). Per the answer's step 4 it goes through the governed path; batch 4 noted its object-form sibling on objectui#11183.
  • The README's "A maximal node" carries bind on the node, which the spec's page component refuses (unrecognized_keys ['bind']) while objectui's BaseSchema declares it. The flat node at base carried the same key; unchanged here.
  • The sdui-parser html tier spells this node flat by design, as batch 5 recorded for the other bag-armed blocks.

Written in session https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec (the dispatching seat's session; this dev ran as its subagent).


Generated by Claude Code

claude added 6 commits October 1, 2026 04:53
…properties bag (objectui#10859, batch 6)

ObjectGanttBlockSchema is the authored object-gantt arm: BaseSchema + the
literal + NODE_ENVELOPE + properties = the installed 17.5.0
ComponentPropsMap['object-gantt'] row by reference through propsBag, the
dataSource binding, one aliasKeyRefusal per row member (less the node-level
label the spec's page component also declares), the flat mirror's GanttConfig
members and dependencyField alias pointed at properties.gantt.KEY, the
objectui#9256 channel refusals, and the record-source rule read in the bag
through requireRecordSource(..., 'properties'). It joins
ObjectQLPublicBlockComponentSchema; the flat ObjectGanttSchema mirror leaves
ObjectQLComponentSchema (9 to 8) and stays exported. The TypeScript twin is
re-declared as the post-hoist, code-composed reading, not retired.

Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec
Co-authored-by: Claude <noreply@anthropic.com>
…iage it forces (objectui#10859, batch 6)

New pin object-gantt-properties-bag-10859-b6.test.ts: both faces accept the
bag (object-bound, inline, provider, dataSource-only, node-level label), the
flat spelling is refused by name on both faces (row members to
properties.KEY, GanttConfig members and the dependencyField alias to
properties.gantt.KEY), the row is judged by reference with no authored
default, the record source is read in the bag and counts the binding, and
the flat mirror stays published.

Forced census rows: zod-mirror-parity (one EXCLUSIONS row),
imported-defaults-8317 (one IMPORTED row), registered-type-arms-10859-b2
(literal list), objectql-union-arms-7363 (9 to 8),
public-block-responsive-styles-10872 (DECLARES_DATA_SOURCE and the
record-source carve-out). Fixture triage where a face now judges the bag:
content-channel-e3-residual-9256, objectql-record-source-refinement-6939,
strict-face-read-keys-11070. The three schema-catalog gantt entries move
their props into the bag.

Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec
Co-authored-by: Claude <noreply@anthropic.com>
…ui#10859, batch 6)

The three schema-catalog gantt entries now write their props in the
properties bag. The render-identity pin's anti-vacuity row reads the bag
(its PRE_REPAIR readings hold unchanged, since SchemaRenderer hoists it),
and the catalog-plans pin, which mounts ObjectGantt directly, hoists the
bag the way SchemaRenderer does before drawing each plan.

Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec
Co-authored-by: Claude <noreply@anthropic.com>
… rendered (objectui#10859, batch 6)

Through the real registry and a recording adapter: the bag queries its
object with its own filter and sort and hands the chart one task per row;
the two flat spellings code still composes make the identical call and hand
the chart the same tasks; a dataSource-bound bag queries the bound object; a
bag on inline rows draws them without a host query; control: a bag naming
another object never queries the fixture's.

Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec
Co-authored-by: Claude <noreply@anthropic.com>
…sets (objectui#10859, batch 6)

content/docs/plugins/plugin-gantt.mdx and packages/plugin-gantt/README.md
author their object-gantt nodes as { type, properties: { ..., gantt } }; the
flat field-mapping keys are described as the ObjectView / ListView handoff,
and the direct ObjectGantt mounts keep their flat schema prop, now said so.

Changesets: @object-ui/types minor with a BREAKING (authoring) banner, and
@object-ui/plugin-gantt patch for the README and the two new src/ pins.

Claude-Session: https://claude.ai/code/session_011p7ikEivgXefNDaE5S5Uec
Co-authored-by: Claude <noreply@anthropic.com>
…i#10859, batch 6)

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

github-actions Bot commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 49 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/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/6470-gantt-dependency-field-deprecated.md

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

    packages/plugin-gantt/README.md's ObjectGanttSchema example authored the singular; it was the only in-repo site that did, and it now authors the plural with the alias named as legacy. No runtime code, fixture, example app or catalog schema authored it.

.changeset/6475-gantt-block-face-declared.md

  • names content/docs/plugins/plugin-gantt.mdx → content/docs/plugins/plugin-gantt.mdx — edited by this change

    Maintainer ruling, objectui#6475 (2026-08-27), Option A — enforce as-is, immediately, no warning window (the startup-stage no-gradualism rule, objectstack#12668: transitions do not get phased windows without named external-user evidence, and none exists here). A census of every gantt block reachable through ObjectGanttSchema in this repository — the examples/schema-catalog fixtures, content/docs/plugins/plugin-gantt.mdx, and the published skills/objectui/guides/page-builder.md guide — found zero blocks missing the trio.

.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/7627-shared-record-source-reader.md

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

  • names objectql-record-source-refinement-6939.test.ts → packages/types/src/__tests__/objectql-record-source-refinement-6939.test.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/7694-chart-series-chart-type-alias-refusal.md

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

    • Before: series: [{ name: 'revenue', chartType: 'line' }] validated green through @object-ui/types/zod (safeValidateSchema, objectui check / objectui validate, any pipeline that keeps parse()'s output) — and the key was gone from the output, so a consumer of the parse result drew that series in the chart's own family, precisely what the author was overriding. On the TypeScript face the key was merely an excess property on a fresh literal; a widened object carrying it assigned structurally. - After: the same document REFUSES at series[i].chartType (issue code invalid_type) with one message on both channels — the parse-time issue and the .describe() metadata: Unrecognized key(s) on this chart series: \chartType`. Did you mean `chartType` → `type`? …followed by the reason and the remedy. Writetype: 'bar' | 'line' | 'area'. On the TypeScript face ChartDataSeries.chartTypeis a?: nevertombstone, so both the fresh literal and the widened assignment aretsc errors. - **Both written** ({ type: 'bar', chartType: 'line' }) is refused at chartTypealone — the key is not folded ontotypeand no precedence is minted between the two spellings. - **Which documents to scan.** The narrowing does not stop atChartDataSeriesSchema; it reaches every document through the parents that embed it — ChartSchema.series (zod/data-display.zod.ts, z.array(ChartDataSeriesSchema)) and, one level further out, ReportSectionSchema.chart (zod/reports.zod.ts, ChartSchema.optional()). Authors meet it through safeValidateSchema() (zod/index.zod.ts, which parses AnyComponentSchema) and through the CLI's objectui validate command (packages/cli/src/cli.ts). In practice: every chartnode'sseries[], and every report section whose chart` carries one.

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

  • names index.zod.ts → packages/types/src/zod/index.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/8344-node-recursion-point-redirect.md

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

    Two mechanical notes for anyone editing the wiring. AnyComponentSchema is built in zod/index.zod.ts from all 13 category modules and 14 modules import zod/base.zod.ts, so the arm cannot be an import — z.lazy defers evaluation, not the module graph. It is a written option slot that index.zod.ts fills inside AnyComponentSchema's own initializer, and it is a z.union option rather than a z.lazy holder because z.lazy memoises its getter: a holder would let whichever module graph parsed first decide the accept set for the whole process. Both constraints are measured, and the reasoning lives on defineNodeComponentUnion in zod/base.zod.ts.

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

    Two mechanical notes for anyone editing the wiring. AnyComponentSchema is built in zod/index.zod.ts from all 13 category modules and 14 modules import zod/base.zod.ts, so the arm cannot be an import — z.lazy defers evaluation, not the module graph. It is a written option slot that index.zod.ts fills inside AnyComponentSchema's own initializer, and it is a z.union option rather than a z.lazy holder because z.lazy memoises its getter: a holder would let whichever module graph parsed first decide the accept set for the whole process. Both constraints are measured, and the reasoning lives on defineNodeComponentUnion in zod/base.zod.ts.

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

.changeset/8499-node-slot-registered-arms.md

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

    Why 49 is acceptable here where 2 was a defect: the 2 were data blocks a consumer had a standing reason to validate on their own, and objectui#7917 (PR feat(types): re-export BreadcrumbSchema and ObjectTreeSchema from the zod barrel (objectui#7917) #8777, open at the time of writing, and the holder of zod/index.zod.ts) exists to export exactly those. The 47 added here are HTML primitives and two input aliases — they have no per-tag consumer to serve, and exporting a SemanticElementSchema / HtmlElementSchema pair would publish a NAMED authoring surface (z.enum families, not per-tag schemas) that this card's ruling does not cover: the ruling is "arm the registered renderers", not "add public exports to @object-ui/types". So the metric is left to move and said out loud instead. ⇒ Whoever next runs that measurement should expect 49, and whoever wants the number back down should treat naming these families as its own decision. If PR feat(types): re-export BreadcrumbSchema and ObjectTreeSchema from the zod barrel (objectui#7917) #8777 lands first, the same movement reads 0 to 47.

.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/8598-zod-subpath-single-bundled-module.md

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

    The defect. This package declares "sideEffects": false, and src/zod/index.zod.ts fills the node recursion point as the initializer of its AnyComponentSchema const. tsc emitted that barrel as a module whose only other content is re-exports — so a bundler resolving import { CardSchema } from '@object-ui/types/zod' followed the re-export to dist/zod/layout.zod.js, needed nothing from the barrel's own body, and the flag let it drop that body whole. The fill went with it, and every child slot then validated against the pre-spec(types): redirect the node recursion point from BaseSchemaCore to AnyComponentSchema — measured at 9 newly-refused documents, and it drops 118 phantom strict refusals #8344 BaseSchemaCore arm — the ~21 base keys and nothing type-specific — with no error, no warning and no way for the guard inside the dropped code to notice. objectui#8344 shipped that window DECLARED and pointed here to close it.

.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/9067-zod-barrel-named-arms.md

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

    Two new exported symbols, both on packages/types/src/zod/index.zod.ts:

.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/9659-node-recursion-point-inert-clause.md

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

    Prose amended where this change falsified it, ⛔ not rewritten. zod/index.zod.ts said defineNodeComponentUnion "wraps it rather than replacing it" — true only while a wrapper existed. zod/base.zod.ts's note on the loose parameter bound still names ChatbotSchema's record body in the present tense; the paragraph is kept for the reason it records and carries an AMENDED note saying the exclusion set that pin reads is now empty.

.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 770cc5ba4 (merge-base with origin/main): 21 file(s) changed outside .changeset/, read against 1897 pending declaration(s) that publish a body (2510 pending in total). · run

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3585.8 KB 3607.4 KB
Main entry chunk (gzip) 150.4 KB 350 KB
Entry file index-BaL1QxYS.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.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 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.28KB 136.83KB
core (index.js) 10.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 229.96KB 63.80KB
fields (index.js) 261.05KB 66.23KB
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.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.49KB 9.23KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 40.95KB 11.48KB
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.01KB 3.93KB
plugin-calendar (index.js) 52.98KB 15.39KB
plugin-charts (index.js) 84.09KB 22.93KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 139.34KB 37.30KB
plugin-designer (index.js) 216.45KB 44.60KB
plugin-detail (index.js) 244.79KB 64.47KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 173.70KB 44.63KB
plugin-gantt (index.js) 173.11KB 43.10KB
plugin-grid (index.js) 231.53KB 63.58KB
plugin-kanban (index.js) 49.32KB 15.48KB
plugin-list (index.js) 116.63KB 28.97KB
plugin-map (index.js) 23.54KB 7.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 33.91KB 10.00KB
plugin-tree (index.js) 11.20KB 3.89KB
plugin-view (index.js) 90.32KB 22.76KB
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) 119.55KB 39.23KB
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 (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 3.19KB 1.62KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
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) 4.74KB 2.26KB
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) 21.59KB 7.71KB
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

Spec Main Shape Gate is red on this head (0c673ccb8), and the red is not this PR's. From the domain:ui seat 2 that dispatched this PR.

  • What fails. Job 110235799672 compiled objectui against @objectstack/spec built from objectstack main at b3d7a70864a7. It found five diagnostics in five files:
    • packages/types/src/__tests__/chartconfig-aria-retired-4044.test.ts:69;
    • packages/types/src/__tests__/dashboard-aria-retired-contract-twins.test.ts:53;
    • packages/types/src/__tests__/record-details-top-level-9040.test.ts:174;
    • packages/types/src/__tests__/twins-spec-by-reference-9736.test.ts:125;
    • packages/runner/src/LayoutRenderer.tsx:194.
  • Why it is not this PR's.
    • None of the five files is among this PR's 23 changed files.
    • The same five diagnostics fail the gate on other open PRs and in the merge queue, for example the merge_group runs 36820487997 and 36820533994.
    • The cause is upstream: objectstack main now gives a retired key a branded [REMOVED] Key retired type.
  • The fix. objectui#11330 (p0) carries the repair. domain:ui seat 1 claimed it at 05:38Z (comment 5925455871) and has a dev on it. No fix PR exists yet, so there is nothing to port into this PR.
  • What happens next. No re-run now: the gate would compile the same objectstack main and fail the same way. When the objectui#11330 fix lands on main, this branch takes a base merge, and that re-runs the gate. The contract review of this PR continues meanwhile. Landing waits for a green gate.

domain:ui seat 2 · CI note · 2026-10-01T05:54Z


Generated by Claude Code

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 0c673ccb8ca35bdfb4cb812c89b36eba822c0bb0
Local-runs: none

PR objectui#11337 (objectui#10859, batch 6, object-gantt), judged against the diff on main at 5262f7dd3, the card (body and all 33 comments: the flat-arm answer 5917261346, batch 4's ACCEPT 5921869420, batch 5's ACCEPT 5923448876 and release 5923615879, the cross-seat pointer 5924134305, the claim 5924906396, the dev report 5925492282) and the head's check-runs. Context reads, not runs: @objectstack/spec 17.5.0 at its tag (component.zod.ts, page.zod.ts, view.zod.ts, i18n.zod.ts), objectui files at the head by the contents API (objectql.zod.ts, objectql.ts, base.zod.ts, the 6939 pin, page-builder.md, the gantt docs), issue objectui#11183 and PR objectui#11317. ⛔ Not the dispatch order's conclusions, not the report's own account.

① Derived judgments

  1. The inherited reason holds for this arm — right. ComponentPropsMap['object-gantt'] is the exported ObjectGanttPropsSchema at 17.5.0 (component.zod.ts:5455): a strictObject of 17 members (objectName, data, staticData, filter, sort, gantt, navigation, label, skipWeekends, holidays, persistLayout, viewName, markers, criticalPath, showBaselines, readOnly, mobileReadOnly), its gantt the 29-key GanttConfigSchema (view.zod.ts:1889, strict). The spec's PageComponentSchema is strict with node-level type, id, label, properties, events, style, className, responsiveStyles, visibleWhen, visibility, dataSource, aria (and the retired responsive), so a flat objectName / gantt / startDateField is unrecognized_keys there, as the b6 pin's lit control holds. Answer A (5917261346, inherited from 5906817482) applies by the parent's reason.
  2. Census and stop line — right as far as the input set reaches. The class table's rows are each confirmed where the diff and the head reach them: the five authored producers are rewritten (below); the three component mounts (plugin-gantt.mdx "Task Click", README "Interactive Gantt" and "Integration with Data Sources") keep the flat schema prop and now say why; the composers are untouched; skills/objectui/guides/page-builder.md is untouched at the head (its flat node at :279-291, plus the prose at :297-302 teaching flat keys on the node). The stop line: in objectql.zod.ts the zod ObjectGanttSchema's only non-test reader was ObjectQLComponentSchema, now removed, and the barrel export stays; the 138-file count itself is not re-measured here (read-only), and a repo-wide reader search is outside this input set.
  3. ObjectGanttBlockSchema — right. BaseSchema + the literal + NODE_ENVELOPE + properties = propsBag('object-gantt', stripImportedDefaults(SpecObjectGanttPropsSchema)) + dataSource = stripImportedDefaults(SpecElementDataSourceSchema).optional() + the refusals + the objectui#9256 tombstones (the flat mirror's OBJECT_GANTT_NEITHER_CHANNEL string, unchanged) + requireRecordSource('object-gantt', RECORD_SOURCE_KEYS, 'properties'). The shared helpers by import (public-blocks.zod.ts, tombstone.zod.ts, imported-defaults.js), no copy, no new helper; the construction is ObjectMapBlockSchema's line for line. The pin holds the row by reference (key-set equality, toBe on the boundary's memoised copy, 12-probe equivalence, no default authored) and the type-level Equal of the bag's input to ObjectGanttProps | undefined. It joins ObjectQLPublicBlockComponentSchema (7), the barrel exports it, zod/README.md lists it.
  4. The label exception — right, and it accepts exactly what the spec accepts. label is the ONE row member that is also a PageComponentSchema node-level key (the key lists above; data collides with objectui's BaseSchema, not with the spec, and the refusal overrides it as the docblock says). The arm transcribes the split (OBJECT_GANTT_NODE_LEVEL_ROW_KEYS = ['label']) and the pin re-derives it from the installed spec per row member (unrecognized_keys membership against PageComponentSchema, expected key !== 'label'), so a spec that moves the key reddens the pin. The node keeps BaseSchema.label, which at the head is stripImportedDefaults(I18nLabelSchema).optional() — the spec's own string | inline locale map, by reference — so the flat label accepts what the spec's page component accepts, and the pin's label: 7 control refuses on both faces as the spec does.
  5. The refusals beyond the row-key set — right. OBJECT_GANTT_FLAT_CONFIG_REFUSALS reads its keys off the crossed row's gantt member (.shape.gantt.unwrap().shape), which is GanttConfigSchema's 29 keys at 17.5.0 — the same SpecGanttConfigSchema.shape.* members the flat mirror declares flat — each pointed at properties.gantt.KEY; dependencyField (the mirror's legacy alias, not a spec key) is pointed at properties.gantt.dependenciesField, which IS a GanttConfigSchema key. Batch 5's locationField / titleField call, generalised to the block the row names. The pin iterates the spec's block keys with a lit control per key.
  6. search / searchableFields undeclared — right. The flat mirror's only members outside the row, the gantt block and the arm's own declarations (dataSource, body, children); batch 4's row-absent treatment; pinned as unjudged on the tolerant face, unrecognized_keys on the strict face, refused inside the bag by the row.
  7. The record-source rule — right. The merged requireRecordSource(type, rungs, at) at the head reads the three rungs in properties when at === 'properties' and counts the node's binding through dataSourceSuppliesObject (non-empty dataSource.object), with the refinement's when option set to always run, so it reports beside the flat-key refusals. Pinned on both faces: the bare node, the empty bag, a gantt-only bag and dataSource: { object: '' } each refused at the root with RECORD_SOURCE_REQUIRED naming the three properties.* rungs and the binding; each rung alone and the dataSource-only node accepted. The flat mirror keeps its node-level call unchanged. Batch 5's carried finding is closed for this arm.
  8. The flat mirror and the twin — right. ObjectGanttSchema leaves ObjectQLComponentSchema (9 to 8; the b2 exact list, the 7363 count and not.toContain), stays exported, stays census-paired (the new EXCLUSIONS row names the arm and pairs the TS twin with the flat mirror), gains the "No longer an authoring arm" section; its members are untouched (comment-only hunks). The TypeScript ObjectGanttSchema is re-declared (docblock only; members unchanged), still in the TS union, pinned at type level (assertionTwinStaysPublished).
  9. Producers — right. Rewritten to the bag at the head: plugin-gantt.mdx (10 nodes and the Schema API block), the three catalog entries ({ type, properties: { staticData, gantt } }), packages/plugin-gantt/README.md (8 nodes). The governed skills/objectui/guides/page-builder.md is listed, not rewritten, per the answer's step 4.
  10. Census rows and fixture triage — each forced, each pin keeps its subject. zod-mirror-parity (one EXCLUSIONS row, EXPECTED_MIRROR_PAIRS untouched), imported-defaults-8317 (one IMPORTED row), registered-type-arms-10859-b2 (exact literal list), objectql-union-arms-7363 (8), public-block-responsive-styles-10872 (DECLARES_DATA_SOURCE and the record-source carve-out). Triage: content-channel-e3-residual-9256 adds the AUTHORED_REQUIRED spelling and keeps the mirror row; objectql-record-source-refinement-6939 reads doc.properties for its entries, which are the three map and three gantt catalog entries only (verified at the head, :88-89); strict-face-read-keys-11070 moves one row to the bag; the catalog render-identity-6939 anti-vacuity row reads properties.staticData / properties.gantt.titleField and its PRE_REPAIR readings stand (the render goes through SchemaRenderer, which hoists); catalogPlans-11141 mounts ObjectGantt directly, so readPlan hoists the bag the way SchemaRenderer does and the plans' date and dependency rows keep their subject.
  11. Comments corrected in passing — each true at the head. requireRecordSource's docblock no longer says neither block has a row (both have one at 17.5.0); the mirror's gantt comment and the TS twin's say the mirror REACHED validate through AnyComponentSchema until batch 6; the union docblock's opening names all four departed arms and "the last four paragraphs" are the ELEVEN / TEN / NINE / EIGHT paragraphs present.
  12. Ablation and the type-level reverse — consistent, not re-run. The b6 pin has 104 runtime rows (8 + 71 + 13 + 10 + 2 by describe); 26 read the spec or the arm object directly and stay green with the flat arm restored, 78 red; 78 + 4 (6939) + 3 (catalog validate) + 2 (9256) + 2 (10872) + 1 each (7363, b2, 11070) + 1 (render pin validator row) = 93, the reported count. The reverse leg's one TS2344 is the bag Equal row, and assertionInstrumentFires holds the instrument non-vacuous.
  13. Check-runs on the head — 43 with filter=latest, every one completed: 39 success, 3 expected skips (Test (coverage), its matrix row, dependabot), 1 failure, Spec Main Shape Gate (job 110235799672). The red is not this diff's — measured here, not taken from the seat's CI note. That workflow resolves objectstack main by REST and compiles objectui against a spec built from it (b3d7a70864a7), not against the installed 17.5.0 this arm reads. Its 14 annotations name five diagnostics in five files — packages/runner/src/LayoutRenderer.tsx:194 and, under packages/types/src/__tests__/, twins-spec-by-reference-9736:125, record-details-top-level-9040:174, dashboard-aria-retired-contract-twins:53, chartconfig-aria-retired-4044:69 — none among this PR's 23 files, all of the branded [REMOVED] Key retired shape. The workflow's own run list is red on every head since 04:38Z (other PR branches, and the merge groups for PRs 11316, 11317 and 11325) after green runs at 04:20Z and 04:26Z, and objectui#11330 (p0, pm:dispatched) carries the repair, listing the same five sites off another PR's head. So the conclusion stands as the tree's verdict against spec main, not as a verdict on this diff. The gate is a required context of main, so landing waits for it green: a base merge after objectui#11330 lands, on a head this record does not name. Every gate family this diff touches is green on this head: Type Check, Lint, the eight Test shards, Test (dist pins), Build & E2E, Build Docs, the five changeset runs, the doc checks, Skill Example Check, Governed Surface Queue Guard, Line Citation Gate, Control Byte Scan, Pre-Install Import Graph Check.

② Semver level

  • @object-ui/types minor (.changeset/10859-object-gantt-properties-bag.md) with the **BREAKING (authoring):** banner: the published accept set NARROWS (a flat object-gantt node that parsed on both faces is refused by name) and WIDENS (a spec-shaped bag node that was refused parses). That is objectui's narrowing-as-minor rule with the banner, as batches 1 to 5 shipped. Part of #10859 is the PR body's first line.
  • @object-ui/plugin-gantt patch (.changeset/10859-plugin-gantt-properties-bag-docs.md): the README and two test files under src/ (ObjectGantt.propertiesBag-10859.test.tsx, __tests__/ObjectGantt.catalogPlans-11141.test.tsx); no runtime file in the diff. Right, and batch 5's plugin-map shape.
  • Clause-②: yes (narrowing) is the PR body's second line, key-initial, value then arm in the fixed spelling; the backticked restatement on line 4 is a quoted-and-continued line the reader skips, and the first declaration governs. Against the BUILT diff: yes because ObjectGanttBlockSchema widens what AnyComponentSchema and the strict face accept; (narrowing) because the flat spelling leaves both faces. Both facts are in the diff, so the one combination that names both is the right one. The Changeset Declaration, Bump Policy, Claim Re-read, Fixed Group and Overwrite Report runs on the head are green.

③ Boundary flags

open_questions: []. Deviations, each judged:

  1. label not refused flat — right (①.4); the one row member the spec's page component declares at node level, measured, with the split pinned per member.
  2. The 29 GanttConfig members and dependencyField refused toward properties.gantt.KEY — right (①.5); the key set is the row's gantt member read off the crossed row, and the alias points at a real spec key.
  3. search / searchableFields undeclared on the bag arm — right (①.6), batch 4's precedent for row-absent members.
  4. Batch 5's finding no longer reproduces on the flat arm after objectui#11312 — right; the merged helper counts the binding on every arm, and the bag arm pins it closed on both faces.
  5. The second changeset — right (②).
  6. Comments corrected in passing — each verified true (①.11).
  7. The arm-list sweep run at ceead94ad plus the two triage edits later committed byte-identical — accepted; the head's own check-runs are the gate.
  8. The attribution reminder — the commits carry the repo's model-free pair and the PR the session-URL footer; declared, consistent with AGENTS.md as the report states, and not a correctness question for this diff.

Out-of-scope notes, against the filing classes and measured reach:

  • The governed page-builder.md flat gantt example — carrier objectui#11183 is right, and a pointer comment is owed. Batch 4's same-family note 5922065881 on objectui#11183 was taken up as a rider in that card's claim 5923347428, PR objectui#11317 (skills-seat ACCEPT 5924123994, still open and unmerged at this review), so the family's taught-docs migration is the live carrier and the governed path (maintainer approval on that PR). The dev wrote nothing to objectui#11183 (api_writes: 3, right); the pointer is the seat's, at ACCEPT or release, as 5922065881 was. It should name both the os:check fence (:281-291) and the prose at :297-302, which teaches that the flat keys "can also be written on the node" — a sentence objectui validate now contradicts.
  • markers as unknown-array and navigation as unknown in the row — an observation, rightly 承接者:无: the row's contract by reference (batch 4's sections posture), no producer writes either, and the spec's own comment keeps markers unknown by design. Measured reach: properties.markers: [{ date: 5 }] and properties.navigation: { mode: 'nope' } parse in the bag where the flat mirror refused them. Batch 5 already recorded navigation for the spec seat; markers joins it. Not this batch's.
  • The README "maximal node" writes bind on the node — pre-existing (the flat node at base carried it), unchanged, and an observation: objectui's BaseSchema declares bind and the spec's page component refuses it, so objectui validate accepts an example os validate refuses. The page-builder kanban example has the same key. A BaseSchema-wide question, not this arm's.

The PR body: each sentence checked is true at this head — the arm, the union counts, the five producers and the one governed listing, the 23 files and their forcing, the per-face base measurement, the draft state, the two changesets, the label measurement and the dataSource-only reading.

Implemented-by: claude/issue-10859-object-gantt-properties-bag
Reviewed-by: session_011p7ikEivgXefNDaE5S5Uec

VERDICT: PASS


Generated by Claude Code

@github-actions

github-actions Bot commented Oct 1, 2026

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3585.6 KB 3607.4 KB
Main entry chunk (gzip) 150.4 KB 350 KB
Entry file index-LGIE2ItZ.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.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 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.28KB 136.83KB
core (index.js) 10.00KB 3.96KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 229.96KB 63.80KB
fields (index.js) 261.05KB 66.23KB
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.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.49KB 9.23KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 40.55KB 11.41KB
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.01KB 3.93KB
plugin-calendar (index.js) 52.98KB 15.39KB
plugin-charts (index.js) 84.09KB 22.93KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 139.34KB 37.30KB
plugin-designer (index.js) 216.54KB 44.64KB
plugin-detail (index.js) 244.79KB 64.47KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 173.70KB 44.63KB
plugin-gantt (index.js) 173.11KB 43.10KB
plugin-grid (index.js) 231.53KB 63.58KB
plugin-kanban (index.js) 49.32KB 15.48KB
plugin-list (index.js) 116.63KB 28.97KB
plugin-map (index.js) 23.54KB 7.83KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 33.91KB 10.00KB
plugin-tree (index.js) 11.20KB 3.89KB
plugin-view (index.js) 90.32KB 22.76KB
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) 119.55KB 39.23KB
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 (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 3.19KB 1.62KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
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) 4.74KB 2.26KB
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) 21.59KB 7.71KB
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
objectstack-fleet Bot marked this pull request as ready for review October 1, 2026 07:08
@objectstack-fleet
objectstack-fleet Bot enabled auto-merge October 1, 2026 07:08
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Oct 1, 2026
Merged via the queue into main with commit db0beb2 Oct 1, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-10859-object-gantt-properties-bag branch October 1, 2026 07:24
os-litant pushed a commit that referenced this pull request Oct 1, 2026
…jectui#11168 slice 3, round 3)

origin/main db0beb2: PR B (#11351, 17dc167), objectui#11331 (bef9f20)
and #11337 (db0beb2). Two conflicts, both resolved by measurement:

- apps/console registry-inputs-spec-parity.test.ts: the per-owner total.
  Census of the merged ledgers: unjudgedBlocks 2 (object-gantt,
  object-timeline), offSpecInputs 0, unpublishedKeys 3, refusedArms 0
  (B emptied the map), memberPins 0, so objectui#11168 owns 5; 8652 and
  8649 stay 0. Neither side's 6 or 7.
- packages/app-shell i18n.ts (en and zh): B's deletions of
  option.layout.inline / grid kept, with this branch's reworded
  object-form.columns row.

Claude-Session: https://claude.ai/code/session_01VhxTqosz7wn54ahqyxgERT
Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation examples package: types plugin tests

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants