Skip to content

chore(deps): resolve @objectstack/* 17.5.0, and the zod 4.6.5 it requires, in pnpm-lock.yaml (objectui#11073) - #11086

Merged
os-zhuang merged 29 commits into
mainfrom
claude/issue-11073-objectstack-17-5-bump
Sep 30, 2026
Merged

os-zhuang merged 29 commits into
mainfrom
claude/issue-11073-objectstack-17-5-bump

Conversation

@objectstack-fleet

@objectstack-fleet objectstack-fleet Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Fixes #11073

Clause-②: no — consumes the already-published @objectstack 17.5.0 contract by version; objectui adds no key, export or flag of its own, and every accept-set movement arriving through spec-by-reference pairs is enumerated in the PR for review

⏸ Current state: seat amendment (domain:devx seat 2, session_01TdiauJaVCHuj45EzZGUxHh, 2026-09-30T02:59Z; head c385748)

The body below was written at round 1, on the lockfile-only head b732e17. This section is current; where the two differ, this section governs.

Draft, awaiting a human merge. The diff is 5,370 changed lines, over the 5,000-line human-merge line; no governed path is touched.

  • It lands through the merge queue after an APPROVED review from os-zhuang or hotlong.
  • ⛔ No seat flips it ready or arms auto-merge before that approval.
  • Contract review at CONTRACT_REVIEW_TIER on this head: PASS (5903181734).
  • CI on this head: all green, Live E2E included. 42 success; 3 skipped by design (coverage matrix, dependabot).

No expected reds.

Rounds and commits:

  • Round 1 (cb3b89a…174c4a7): seat rulings Q2/Q3/Q4/Q6/Q8 and the woken cards' re-reads.
    • Q3 blast radius: 29 plain unions, 1106 probes, 0 accept-set moves, 187 error-shape moves.
    • Tripwire-text deletions: the percent-scale clamp (81de0ff), the quickAdd carve-out, and two block-config exemptions (8053108).
  • Round 2 (base 174c4a7):
    • 569e923: the flow designer moves to 17.5.0 (objectui#11088 decision 2 = A). A new wait node is seeded PT1H, visible and editable. The decision form offers mode, the screen form states its create default, and preview script nodes use function.
    • 2abb653: prose-only corrections to seven pending changesets this bump made false (Q12).
    • 048e7f6: changeset lines.
    • 92ac539: the eager-closure re-baseline (decision 1 = A).
  • Round 3 (283c97c, Q13):
    • @object-ui/data-objectstack and @object-ui/app-shell raise @objectstack/spec to ^17.5.0, and app-shell raises zod to ^4.6.1. The lockfile moves only those three specifiers; the resolution census is unchanged.
    • check:spec-floors --cross-check over a full build of 283c97c reads 0 findings.
    • ⚠️ Round 2's 「spec-range-floors exit 0」 is withdrawn: it read a data-objectstack dist built before 865a81d.
  • Round 4 (119f4d3, sync with main 8a5ae3d, merged as a merge commit):
    • One textual conflict: the number-field scale block in @object-ui/fields. Both intents are stacked: this branch's unclamped scale (81de0ff), then main's objectui#11026 useGrouping read and its hand-off to formatDisplayNumber.
    • The lockfile did not move; the resolution census is identical.
    • The flow start node takes objectui#11067's platform-event drop. The PT1H wait seed, the decision mode and the screen create default are intact.
  • Round 5 (cdd84c7, Q14 = A): the Q3 pin reads StrictAnyComponentSchema through the zod/index.zod barrel. objectui#8345's guard (the barrel is the only entry into the deep module's cycle) is green again. Test-only; no changeset.
  • Round 6 (objectui#11111 ruled, record 5902351047; base cdd84c7):

Eager-closure budget re-baseline (objectui#11088, decision 1 = A).

  • Measured with CI=true vite build of the console on this branch, against control a5841be35 built the same way (330 of 2446 chunks each):
    • vendor-objectstack 1,237,912 → 1,703,690 (+465,778);
    • aggregate 3,183,235 → 3,648,737 gzip bytes (+465,502). All of the growth is vendor-objectstack; the other rows net −276 bytes.
    • On the merged head 119f4d3: aggregate 3,650,586 (+1,849 from main's 21 commits), vendor-objectstack unchanged at 1,703,690. CI Bundle Analysis reads 3565.6 KB against 3607.4 KB: PASS.
    • The ruling's 413.8 KB is the overage above the retired ceiling (3563.2 KB against 3149.4 KB).
  • What it buys: the console's client-side validation answers as a 17.5.0 server does, with the same refusals (retired keys by name, the terminal unknown-key refusal, the new object-level checks) and the same schemas. It also unblocks the twenty cards waiting on this bump. It is not a new console capability.
  • Paid back at the source by spec: the root entry stops carrying the migration and conversion registries (about 1 MB of prose), so a console first screen no longer downloads os migrate text (the upstream payback of objectui#11088 D1) objectstack#20646 (the spec root entry sheds the migration and conversion registries) and objectui#11101 (metadata-admin-only spec validation leaves the first screen). The ceiling and BASELINE come down with each.
  • New constants: MAX_EAGER_CLOSURE_GZIP_BYTES 3,694,000 over BASELINE 3,648,737 (headroom 0.50x the regression constant); vendor-objectstack 1,723,000 over 1,703,690 (0.21x). REGRESSION_THIS_GATE_MUST_CATCH_BYTES is not moved.

Changeset levels: @object-ui/types, core and app-shell minor; fields, components, plugin-list, console and data-objectstack patch. objectui marks breaking changes minor with the semantics in the body (AGENTS.md §9).

Superseded statements in the body below (this section governs):

  • H2's "zod@4.4.3 stays in the lock ONLY as fumadocs-mdx's own dependency": it is gone from the lock since 32b7f52.
  • Round 1's "No manifest range moves in this PR": four manifests move (@object-ui/types, core, data-objectstack and app-shell; Q8 and Q13).

Owed after merge: the BASELINE.squashMerge back-fill in scripts/check-eager-closure-budget.mjs (the field's own instruction). The ceiling and BASELINE come down with each payback.

Cards named here are cited as rulings, payback cards or holders, never beside a closing keyword; Fixes #11073 is the only one.

What this PR is, at this head

pnpm-lock.yaml now resolves @objectstack/* 17.5.0 (was 17.4.0), plus the zod 4.6.5 that 17.5.0 requires. No manifest range moves in this PR and no objectui package version moves. The PM asked for the draft to open at the first compilable step, so this body records the readings taken on the lockfile-only head. Commits that adapt objectui to the published contract follow on this branch. The final gate readings, commit by commit, go into the os-dev-report comment on objectui#11073. Any later change to this body is for the seat to write.

It is expected to be RED on this head, for measured reasons (below). ⛔ No red here is waved through or re-run.

H1 — premise (measured)

  • Base origin/main c80236e: the lock resolved @objectstack/{spec,types,sdui-parser,lint,formula,core,client} at 17.4.0, and npm latest for all seven is 17.5.0.
  • Manifests declare caret ranges only: @objectstack/spec at ^17.0.0 in 23 places, ^17.4.0 in 6, ^17.1.0 in 2 and ^17.3.0 in 1; @objectstack/client at ^17.3.0 in 2; formula and lint at ^17.0.0 in 2 each.
  • objectui's pnpm.overrides (root package.json) and pnpm-workspace.yaml hold no @objectstack entry.
  • ⇒ every range already admits 17.5.0, so a within-range regeneration moves the resolution without touching a range.

H2 — how the lock was regenerated, and everything that moved

Regenerated by pnpm 10.31.0 only. ⛔ Not edited by hand.

  • pnpm update -r "@objectstack/*" was tried first and REJECTED. It rewrote 30 manifests (every range raised to ^17.5.0, and script keys reordered), and it re-resolved unrelated packages: seroval, seroval-plugins, bson, @mongodb-js/saslprep, @microsoft/tsdoc-config, is-core-module, fast-uri, brace-expansion, use-sync-external-store, and a second dompurify. None of those is @objectstack-caused.
  • The route used instead: raise each @objectstack/* specifier to ^17.5.0 for ONE pnpm install; restore every manifest byte-for-byte to HEAD; run a second pnpm install, which reconciles the importers back to their declared ranges. The same raise-and-restore was then applied to the five direct zod specifiers (see below).
  • Resolution census against the base lock (package@version keys, both directions):
    • removed: the seven @objectstack/* at 17.4.0;
    • added: the seven @objectstack/* at 17.5.0, and zod@4.6.5;
    • nothing else. No importer specifier line changes.
  • Peer-suffix re-keys that follow from zod@4.6.5 (same versions, new snapshot keys): ai@7.0.65, @ai-sdk/gateway, @ai-sdk/mcp, @ai-sdk/provider-utils, @ai-sdk/react, and the fumadocs-core / fumadocs-mdx / fumadocs-ui snapshots of apps/site.
  • zod@4.4.3 stays in the lock ONLY as fumadocs-mdx's own dependency, unchanged from base. @object-ui/site type-checks green with it.

Why zod moves (forced by the published 17.5.0 contract, not drift)

@objectstack/spec@17.5.0 and @objectstack/core@17.5.0 raise their zod range from ^4.4.3 to ^4.6.1. With only the @objectstack/* entries moved, the lock resolved spec's zod to 4.6.5 while objectui's own direct zod ^4.4.3 importers (types, app-shell, components, plugin-timeline, test-support) stayed on 4.4.3. Zod stamps its minor version into its types, so the two copies do not type-check against each other:

  • pnpm --filter @object-ui/types build failed with TS2345 in src/zod/views.zod.ts, bottoming out at "The types of '_zod.version.minor' are incompatible between these types. Type '4' is not assignable to type '6'."
  • After the lock resolves objectui's zod ^4.4.3 to the same 4.6.5 (a range it already admits; no manifest edit), the same build exits 0.

Gates read on this head (b732e17)

gate result
pnpm install --frozen-lockfile exit 0, "Lockfile is up to date"
pnpm --filter @object-ui/types build exit 0 (was TS2345 before the zod resolution)
turbo run build --filter=!@object-ui/site --concurrency=2 43/43 tasks successful
turbo run type-check --concurrency=2 (unfiltered, 45 packages incl. @object-ui/site) 81/81 tasks successful
vitest run packages/types/ RED: 56 failed in 15 files, 6376 passed
control: the same on the base tree (17.4.0 installed, detached worktree at c80236e) 6432/6432 passed, 279/279 files

So every one of the 56 reds is caused by the bump. The full suite is being read in four shards; its result is in the report comment.

H3 / H4 — what the bump moves, by cause

The reds fall into three causes. Each row names the upstream change that forced it.

Cause A — zod 4.4 to 4.6 internals (forced by the spec's zod ^4.6.1)

  1. A .default() member now reports _zod.optin === 'defaulted', a rung zod 4.4.3 did not have (it answered 'optional'). imported-defaults-8317.test.ts ("no member became REQUIRED", 26 rows) compares the rung by equality, and the 9034 census counts a default-under-default as already optional. The production walker is NOT affected: walk() turns an inner 'defaulted' into 'optional' before isAlreadyOptional reads it, and the probe row "answers every probe exactly as the spec does" stays green for every imported schema. Adaptation: test-only, re-expressing "omissible" as either rung.
  2. zod's own strict-object unrecognized_keys is now continue: true (non-aborting). In a union where the other arm aborts, the non-aborted arm is returned ALONE (handleUnionResults, whose code is unchanged).
    • GridSchema.columns (8516): the out-of-vocabulary key is now reported directly, as unrecognized_keys naming xxl at columns, instead of inside an invalid_union. The test's intent (the key is named) holds, and the author's message is better. Mechanical re-pin.
    • ⚠️ The dashboard widget slot (objectui#9256 in content-channel-public-blocks-9256.test.ts; strict-widget-slot-registered-inputs-11022.test.ts): { type: 'metric-card', value: 42, body: [] } now yields ONE unrecognized_keys naming value and body. The by-name refusal ("metric-card reads NEITHER content channel") is GONE, and value, a registered input, is misreported as unrecognized. Base yields invalid_union carrying both arms. This is a regression in what an author (or an AI) is told, and restoring it is a design choice → left red, taken to the seat as a decision.

Cause B — spec 17.5.0 makes an unknown-key refusal terminal

17.5.0's closed objects mark every unrecognized_keys issue continue: false (markUnknownKeyRefusalTerminal in the spec's dist). zod skips even a when-guarded check once the payload is explicitly aborted, so the two superRefine pointers (each carrying a when that always answers true) on ObjectViewSchema no longer run: checkNamedViewCalendarAliases (objectui#8355) and checkNamedViewKanbanStrayGroupBy (objectui#10321).

  • The document is still REFUSED (by the spec, at listViews.KEY.calendar / .kanban).
  • The spec's own message now guides dateField correctly ("does not say which end of the range it binds … Write the one you mean").
  • For endField and kanban.groupBy it is a generic unrecognized-key message, so objectui's specific pointer is lost on the named-view route.
  • Keep, rebuild or retire the pointer is a decision → left red.

Cause C — the published contract moved, read by reference (the accept sets the seat's review reads)

objectui surface (mirror by reference) 17.4.0 17.5.0 direction
DetailViewFieldSchema.options[].visibleWhen (spec SelectOptionSchema) a whitespace-only string and a source-less { dialect, ast } envelope accepted both refused narrower
element:number dataSource.filter (spec ElementDataSourceSchema) the MongoDB-style record form (incl. $and/$or) and a CEL envelope accepted only the ViewFilterRule array [{ field, operator, value }] shape change, narrower for the record form
nested calendar block (spec CalendarConfigSchema) allDayField refused by name allDayField accepted wider
record:highlights props (spec RecordHighlightsProps) aria, fields, layout adds requiredPermissions, redactFields, enforceFieldSecurity wider
named view listViews.KEY (spec ViewSchema) pageName, tabs live both refused by name as retirement tombstones narrower
spec ListViewSchema object-level checks checkListViewPageMount present gone no objectui accept-set change (objectui never attached it)
spec DashboardWidgetSchema object-level checks none checkDashboardWidgetStageOrder, checkDashboardWidgetMetricMeasureArity objectui's .shape mirror does not carry them, so objectui's door is now WIDER than the spec on both rules
spec JoinedReportBlockSchema erased (unknown) typed (z.ZodObject) the objectui#10916 tripwire fires; the divergence pins compile green on 17.5.0

H4 — consumer breaks

  • Workspace build and type-check: no break (43/43, 81/81).
  • Runtime (a test, not a type-check): ⚠️ the flow designer's fresh wait node. defaultNodeExtras('wait') seeds { waitEventConfig: { eventType: 'timer' } }. Spec 17.5.0's FlowNodeSchema refuses a timer wait with no timerDuration (its message: a timer wait with no duration "parks the run forever while reporting success"). So a node the designer just created is refused at save. Failing check: flow-canvas-seeds.spec-parse.test.tsx, row "wait: a freshly added node parses as a spec FlowNode" (base: parses). Which default to seed is a product decision → left red.

What the follow-up commits on this branch do, and what they leave red

Mechanical, each forced by a named upstream change (Cause A1, A2 for GridSchema.columns, and the Cause C re-pins that follow the spec by reference or follow a tripwire's own written instruction):

  • the optin rung re-expression (8317, 9034);
  • the GridSchema.columns issue-shape re-pin (8516);
  • the objectui#10296 tripwires, done as their docblocks instruct at the pin bump: flip both rows to refusals, and delete the gated WIDER rows, their WIDER_ARMS entries and the SpecEnvelopeAdmitsSourceless gate;
  • the element:number dataSource.filter rows re-pinned to the spec's verdicts, and REBUILT_CLEAN emptied (the spec's schema no longer reaches a z.lazy);
  • the record:highlights PREMISE member list;
  • the calendar spec-type fence (the doc fence tracks the SPEC type, so it gains allDayField) and the nested key list;
  • the 7715 ListView row losing checkListViewPageMount, as its own message instructs.

Left RED on purpose, each with options in the report (needs_decision):

  • Cause A2 widget-slot message regression (9256, 11022);
  • Cause B named-view pointers (8355, 10321);
  • pageName / tabs still declared on objectui's TypeScript named-view face while the protocol now retires them (7779; the objectui#8980 ruling kept them "declared inert" under a protocol that still declared them);
  • the flow wait seed (H4);
  • two sites that are consuming-card scope:
    • the 7715 DashboardWidget census row is objectui#9111's criterion;
    • the objectui#10916 tripwire is objectui#10940's burn-down, whose card says it "should land WITH that bump" — a published-type change this claim's surface excludes.

Floors

This PR raises no floor. No code in it imports a 17.5.0-only export. The ^17.5.0 floors are left to the consuming cards, each at the moment it first imports a 17.5.0-only export: objectui#11013, objectui#11021, objectui#10188, objectui#7759, objectui#7347, objectui#8649, objectui#9217, objectui#10107 and objectui#9830. Each is unblocked by this landing; none is concluded by it.

Acceptance notes

  • Consumer zod skew. A consumer whose own lock holds zod 4.4.x and resolves @objectstack/spec 17.5.0 through objectui's ^17.x ranges gets the same two-copy split measured above. That state already exists for any consumer today; it is not created here. Whether objectui's zod floor should rise to ^4.6.1 beside the consuming cards' spec floors is an open question in the report, not an edit here.
  • The 11-card addendum's objectui#9111 reading. The addendum on objectui#11073 reads "Not met: objectui#9111 (checkDashboardWidgetStageOrder is still not exported on 17.5.0)". Measured here: it IS exported on 17.5.0 from @objectstack/spec/ui, and not from the root entry. The 7715 census sees it through /ui.
  • The probes behind these readings were untracked scratch files, deleted before any commit; none is part of the diff.

Generated by Claude Code

…i#11073)

Regenerated by pnpm 10.31.0, not by hand: every @objectstack/* specifier was
raised to ^17.5.0 for one `pnpm install`, then every manifest was restored to
HEAD and a second `pnpm install` reconciled the importers back to their
declared ranges. No manifest range moves in this commit.

Claude-Session: https://claude.ai/code/session_01TdiauJaVCHuj45EzZGUxHh
Co-authored-by: Claude <noreply@anthropic.com>
… @objectstack/spec@17.5.0 uses (objectui#11073)

@objectstack/spec@17.5.0 and @objectstack/core@17.5.0 raise their zod floor
from ^4.4.3 to ^4.6.1. With only the @objectstack/* entries moved, the lock
resolved spec's zod to 4.6.5 while objectui's own direct `zod ^4.4.3`
importers (types, app-shell, components, plugin-timeline, test-support) stayed
on 4.4.3. Zod stamps its minor version into its types
(`_zod.version.minor`), so the two copies are type-incompatible and
`pnpm --filter @object-ui/types build` failed with TS2345 in
src/zod/views.zod.ts ("Type '4' is not assignable to type '6'").

Regenerated by pnpm 10.31.0, not by hand: the five direct `zod` ranges were
raised to ^4.6.1 for one `pnpm install`, then restored to HEAD and reconciled
by a second `pnpm install`. No manifest range moves; ^4.4.3 already admits
4.6.5.

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

github-actions Bot commented Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 113 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/10864-app-shell-spec-floor.md

  • names packages/app-shell/src/views/metadata-admin/previews/simulator/flow-sim-validate.ts → packages/app-shell/src/views/metadata-admin/previews/simulator/flow-sim-validate.ts — edited by this change

    packages/app-shell/src/views/metadata-admin/previews/screen-spec.ts imports predicateSlotRefusal from @objectstack/spec/automation; packages/app-shell/src/views/metadata-admin/previews/simulator/flow-sim-validate.ts imports structuralConditionRefusal from the same subpath plus EVALUATED_EXPRESSION_SOURCE_REQUIRED and EvaluatedExpressionSchema from @objectstack/spec/shared. @objectstack/spec was declared as ^17.3.0, so any resolution landing on 17.3.0 (which the range allows) gets a module that names exports its own declared spec dependency does not have.

.changeset/5793-spec-range-floors.md

  • names pnpm-lock.yaml → pnpm-lock.yaml — edited by this change

    Nothing a consumer installs today changes: normal resolution already picks the newest 17.x, and pnpm-lock.yaml still resolves 17.2.0 on this edge after the bump. The change is to the declared floor only, which is why it is scored patch rather than minor — the same reasoning objectui#5753 used for the other direction on this dependency.

.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/5905-componentinput-inputtype-tombstone.md

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

    The write was measured as a no-op before it was deleted, and re-measured on this branch's base rather than inherited from the card. A structural census over every inputs: array in the repository (211 regions, all tracked TS/TSX/JS sources) scores inputType at exactly ONE authoring site — the plugin-markdown registration — against name 953, type 969, label 966, description 194, enum 119, required 86 and binding 4 in the same pass over the same regions, so the instrument was not blind. The other 192 in-repo inputType hits are a DIFFERENT face: FormField.inputType (zod/form.zod.ts), the text-input renderer's prop, and SchemaBuilder.inputType, none of which sit on a ComponentInput. The publication path is unchanged and was re-confirmed: packages/sdui-parser/src/index.ts forwards exactly seven keys per input — name, type, of, required, enum, binding, description — so an authored inputType could not reach the published sdui.manifest.json even in principle.

.changeset/5920-flow-runner-translation-overlay.md

  • names flow-sim-validate.ts → packages/app-shell/src/views/metadata-admin/previews/simulator/flow-sim-validate.ts — edited by this change

    ⚠️ Dated note, 2026-09-28 — the declared floor has since moved again — objectui#10864. At this change @object-ui/app-shell declared ^17.3.0, and the paragraph above is kept as the reading of that change: 17.3.0 was in fact the first release exporting the resolver family this fix uses. Later in this same release the floor was raised again, to ^17.4.0, because two other shipped app-shell sources (screen-spec.ts, flow-sim-validate.ts) import four symbols (predicateSlotRefusal, structuralConditionRefusal, EVALUATED_EXPRESSION_SOURCE_REQUIRED, EvaluatedExpressionSchema) that 17.3.0 does not export — a defect this changeset's own range did not introduce and did not need to guard against. @object-ui/app-shell now declares ^17.4.0.

.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/6050-gantt-navigation-basepath.md

  • names src/readme-navigation-example.test.ts → packages/plugin-gantt/src/readme-navigation-example.test.ts — edited by this change

    No gate in this repo could have caught the original defect, and that is why the fix ships with a measurement rather than a re-reading: check-doc-snippet-types compiles ts/tsx fences and check-doc-component-types reads type literals, and both are structurally blind to a metadata key in a README — the former's own header records schema-key validity as "a different question … left unruled on purpose". src/readme-navigation-example.test.ts closes that hole for this example by EXTRACTING the fence from the README on every run and parsing it against NavigationConfigSchema, with a control asserting the same parse still rejects an undeclared key by name, so the green cannot come from a schema that accepts everything.

.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/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/6286-explain-batch-cap-from-spec.md

  • names scripts/check-spec-symbol-derivation.mjs → scripts/check-spec-symbol-derivation.mjs — edited by this change

    No value changes and no behaviour changes. The spec exports 200, which is what the local copy said, verified by resolving the installed package and reading the export — both statically (dist/security/index.d.mts) and at runtime through the same specifier the source now uses. What changes is reference identity: if the server relaxes or tightens the cap and the spec follows, the client follows too, instead of paginating at the old boundary with no signal anywhere. The cap's whole point is that an over-cap request is refused with 400 VALIDATION_FAILED rather than truncated, so a client that silently disagrees with it is exactly the drift scripts/check-spec-symbol-derivation.mjs argues about — and could not catch here: when this change landed, both of its scanners skipped non-exported declarations, and this const was module-local (objectui#5899). objectui#6291 has since removed that filter from both scanners.

.changeset/6306-action-icon-type-resolution.md

  • names action-button.tsx → packages/components/src/renderers/action/action-button.tsx — edited by this change

    Scope is this one renderer. type: schema appears in exactly two files under renderers/action/ — action-button.tsx (already correct) and action-icon.tsx; action:group and action:menu compose their members differently and are untouched.

  • names action-icon.tsx → packages/components/src/renderers/action/action-icon.tsx — edited by this change

    Scope is this one renderer. type: schema appears in exactly two files under renderers/action/ — action-button.tsx (already correct) and action-icon.tsx; action:group and action:menu compose their members differently and are untouched.

.changeset/6349-name-authority-batch-3.md

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

    @object-ui/components — ComboboxOption now IS @object-ui/types' declaration. The component declared its own { value, label }, a strict subset of the ComboboxOption that @object-ui/types declares for ComboboxSchema.options and mirrors in form.zod.ts ({ value, label, disabled? }). The component now re-exports the types declaration (through the @object-ui/types/form subpath — the root barrel does not publish the name), so the name ComboboxOption exported from @object-ui/components gains the optional disabled?: boolean member. Every value that type-checked before still does — nothing narrows and no key changes type; the one thing that moves is keyof ComboboxOption, so a consumer that EXHAUSTS the type (a Record over its keys) will need the new key. Note that the Combobox component itself does not read option.disabled — that member was already declared on the @object-ui/types face and is now visible on this one too; it is recorded as a separate finding, not changed here.

.changeset/6349-types-internal-name-collisions-batch-1.md

  • names ui-action.ts → packages/types/src/ui-action.ts — edited by this change

    ActionSchema — renamed, because the two shapes are unrelated. crud.ts and ui-action.ts both declared it. Measured member-by-member they share 9 keys out of 28 each: crud.ts extends BaseSchema and pins type: 'action' (a UI node — a button in a component tree), ui-action.ts extends nothing and types type as ActionType (a spec-v2 action definition, with name, locations, params, target). Re-pointing either at the other would silently hand a consumer a different type, so this took the rename branch (objectui#5044 is the precedent for choosing the surviving name). ui-action.ts's declaration is now spelled UIActionSchema — the name src/index.ts has always PUBLISHED it under, via export type { ActionSchema as UIActionSchema }, which is now a plain re-export. The package's public surface is unchanged: ActionSchema still means crud.ts's legacy shape and UIActionSchema still means ui-action.ts's, exactly as before. Nothing outside ui-action.ts imported the old spelling — there is no ./ui-action subpath in exports, so the old name was never reachable from outside the package.

.changeset/6361-spec-floor-17-2-0.md

  • names pnpm-lock.yaml → pnpm-lock.yaml — edited by this change

    Nothing a consumer installs today changes: normal resolution already picks the newest 17.x, and pnpm-lock.yaml still resolves 17.2.0 on both edges after the bump — only the recorded specifier: moves. No source and no behaviour changes, which is why this is scored patch, on the reasoning 111741454 used for the same remediation on @object-ui/plugin-detail.

.changeset/6396-previous-values-dom-leak.md

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

    Scope is the runtime leak only. The declared key stays exactly as declared (packages/types/src/form.ts, packages/types/src/zod/form.zod.ts are untouched): it has a live consumer, so there is nothing here for the enforce-or-remove channel.

.changeset/6488-carry-over-field-keys.md

  • names MetadataService.fieldKeyCarryOver.test.ts → packages/app-shell/src/services/MetadataService.fieldKeyCarryOver.test.ts — edited by this change

    Two properties keep the fix from becoming its own mirror image, both pinned in MetadataService.fieldKeyCarryOver.test.ts:

.changeset/6499-inactive-values-retained.md

  • names flow-node-config.ts → packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.ts — edited by this change

    • New inactiveRetainedKind(field, node, fields) in flow-node-config.ts — a pure read that reports a field rendered ONLY because the stored-value re-show rule fired. It distinguishes 'controller-off' (a real toggle the author can switch back on) from 'no-controller' (the __legacy__ render-only keys, where no such toggle exists and saying otherwise would be a fresh lie). - FlowNodeConfigField renders the notice beside the affected control, with a "Clear value" action so the author can discard the residue deliberately. Read-only inspectors show the notice without the action. - Coverage is every showWhen group in the inspectors, pinned mechanically: all 33 gated fields across the descriptor tables, plus the two runtime producers (an engine-published configSchema and a connector input schema) that mint groups no source file contains.

.changeset/6519-retired-field-key-strip.md

  • names plugin-designer/src/MetadataFieldsPage.tsx → packages/plugin-designer/src/MetadataFieldsPage.tsx — edited by this change

    Unifying the three retired-key lists on this seam is deliberately not part of this change: it spans plugin-designer/src/MetadataFieldsPage.tsx, which objectui#6489 owns in flight.

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

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

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

.changeset/6620-escalation-enabled-default.md

  • names flow-node-config.spec-reconciliation.test.ts → packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.spec-reconciliation.test.ts — edited by this change

    The reconciliation assertion in flow-node-config.spec-reconciliation.test.ts now covers the whole escalation block rather than notifySubmitter alone, and derives every expected value from the installed ApprovalEscalationSchema instead of pinning literals. This is the substance of the fix as much as the flip is: the previous tripwire for this key read only the hand-written table, so a spec bump could never redden it and the divergence went live unnoticed. A vacuity guard fails if the spec stops materialising defaults for the block, so the ledger cannot quietly become a comparison against nothing.

.changeset/6625-retire-fieldmeta-decimals.md

  • names GridField.tsx → packages/fields/src/widgets/GridField.tsx — edited by this change

    buildFieldMeta computed decimals: overrides.decimals ?? meta?.decimals ?? meta?.scale on every call and the value reached nothing. Re-measured on this branch's base (efdc6c62): zero .decimals member reads across @object-ui/fields, @object-ui/i18n, @object-ui/components, @object-ui/core and plugin-dashboard itself — the only non-comment occurrence was the write being removed here. The positive control in the same query shape fires: .scale member reads hit NumberField.tsx, GridField.tsx and fields/src/index.tsx. So the zero is a finding, not a broken query. The overrides.decimals ?? head of that chain had already lost its only feeder when objectui#6425's ruling removed the authored read from ObjectDataTable.enrich(); RecordDetailDrawer, the only other buildFieldMeta caller, passes no overrides at all. Both halves retire together, so the key leaves in one move.

  • names fields/src/index.tsx → packages/fields/src/index.tsx — edited by this change

    buildFieldMeta computed decimals: overrides.decimals ?? meta?.decimals ?? meta?.scale on every call and the value reached nothing. Re-measured on this branch's base (efdc6c62): zero .decimals member reads across @object-ui/fields, @object-ui/i18n, @object-ui/components, @object-ui/core and plugin-dashboard itself — the only non-comment occurrence was the write being removed here. The positive control in the same query shape fires: .scale member reads hit NumberField.tsx, GridField.tsx and fields/src/index.tsx. So the zero is a finding, not a broken query. The overrides.decimals ?? head of that chain had already lost its only feeder when objectui#6425's ruling removed the authored read from ObjectDataTable.enrich(); RecordDetailDrawer, the only other buildFieldMeta caller, passes no overrides at all. Both halves retire together, so the key leaves in one move.

.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/6694-dashboard-lookup-reference-meta.md

  • names packages/fields/src/index.tsx → packages/fields/src/index.tsx — edited by this change

    ⚠️ The copy set is three keys where ObjectGrid's RELATIONAL_META_KEYS is nine, and the difference is measured per key, not preferred. The grid's cells are EDITABLE, so its extra keys drive the inline picker's query (LookupField / UserField read id_field, description_field, lookup_filters, lookupFilters); these two widgets are read-only and their render path ends at a cell renderer. packages/fields/src/index.tsx reads exactly reference_to, reference and display_field off a cell's field prop; titleFormat is never read off a field meta at all (its readers take it off the object schema, which arrives here through useRefObjectSchema(reference_to)), and reference_to_field has zero member reads anywhere in the repo. Copying the other six would mint six members written on every call and read by nothing — precisely what objectui#6625 (decimals) and objectui#6597 (referenceTo) retired from this same file.

.changeset/6726-find-envelope-records-arms.md

  • names plugin-view/src/ObjectView.tsx → packages/plugin-view/src/ObjectView.tsx — edited by this change

    | module | what it does | | --- | --- | | components/src/hooks/related-count-store.ts | related-list tab badge count | | components/src/renderers/basic/data-list.tsx | element:repeater rows | | components/src/renderers/basic/elements.tsx | element:number client-side aggregate | | components/src/renderers/basic/record-picker.tsx | element:record_picker options | | plugin-detail/src/renderers/record-activity.tsx | record:activity self-fetch | | plugin-detail/src/renderers/record-history.tsx | record:history self-fetch | | plugin-view/src/ObjectView.tsx | non-grid (kanban / calendar / gallery / timeline) fetch |

.changeset/6776-metadata-admin-lazy-registration.md

  • names packages/app-shell/package.json → packages/app-shell/package.json — edited by this change

    • packages/app-shell/package.json's sideEffects array now names views/metadata-admin/register-builtins (the new leaf that performs the five registrations) instead of views/metadata-admin/index. The five registrations still run at package load, bare-imported by the package entry, so nothing a consumer could observe changes — but the array is a contract every consumer's bundler reads, so the swap is stated here rather than left to a diff. - The package barrel's 25 metadata-admin runtime re-exports (and 11 type-only ones) now point at their leaf modules. Same names, same types. They are unreachable from outside the package by any other path — exports is root-only — so no import an out-of-package consumer can write is affected.

.changeset/6794-notify-submitter-default.md

  • names flow-node-config.spec-reconciliation.test.ts → packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.spec-reconciliation.test.ts — edited by this change

    A reconciliation assertion in flow-node-config.spec-reconciliation.test.ts keeps the two sides pinned. It reads the expected value out of the installed spec rather than pinning the literal 'true': objectui is the consumer of that contract and must not become a second source of truth for it. A vacuity guard alongside it fails if the spec ever stops materialising the key at all, so the comparison can never quietly become a comparison against undefined.

.changeset/6837-reference-to-arm-deletion.md

  • names fields/src/index.tsx → packages/fields/src/index.tsx — edited by this change

    Three readers were deliberately left alone. LookupCellRenderer (fields/src/index.tsx), LookupField and UserField read FieldMetadata — ObjectUI's OWN contract, whose LookupFieldMetadata declares reference_to and never declares reference. They are fed by the emitters above and by published example schemas (examples/schema-catalog/src/schemas/fields-lookup/*.json), so narrowing them would break in-repo producers, and plugin-grid's relationalMetaCopySet.derivation.test.ts re-derives its read set from exactly those three sources — where reference_to is recorded with verdict adapter-stamped. DetailViewFieldSchema is likewise untouched.

.changeset/6938-checkbox-wrapper-class.md

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

    packages/components/src/renderers/form/checkbox.tsx:36 reads cn("flex items-center space-x-2", schema.wrapperClass) — classes on the wrapper div around the box and its label — and neither the TypeScript interface in packages/types/src/form.ts nor the zod mirror in zod/form.zod.ts declared the key. It compiled through BaseSchema's index signature and parsed through .passthrough(), admitted unexamined. The same key, on the same class of read, is declared on FileUploadSchema and FilterBuilderSchema (objectui#6150); the checkbox was left out only because its doc page's schema block is a six-line summary.

.changeset/6939-kanban-column-cards.md

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

    Breaking, deliberately. KanbanColumn declared its card list as items in complex.ts and in the zod mirror complex.zod.ts. Every board reads cards. Measured on origin/main 78a3cc238: KanbanImpl.tsx reads .cards on 12 lines, KanbanEnhanced.tsx on 8, and bucketCardsIntoColumns twice more as col.cards || []; .items had zero read sites in either board (a same-shaped .title control on the same two files returns 8 and 3, so those zeros are readings and not a mis-shaped probe). Both catalog entries, the plugin docs and content/docs/api/schema-reference.md all author cards.

.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/7070-no-invented-gantt-date-fields.md

  • names plugin-view/src/ObjectView.tsx → packages/plugin-view/src/ObjectView.tsx — edited by this change

    • app-shell/src/views/ObjectView.tsx — the console object page. The inline branch becomes ganttViewOptions, the sibling of calendarViewOptions and timelineViewOptions: the declared block spread whole, title floored at 'name', no date field invented. - plugin-list/src/ListView.tsx — the render branch AND the capability gate. - plugin-view/src/ObjectView.tsx — generateViewSchema, the authored object-view element route, which bypasses ListView entirely.

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

  • names complex.zod.ts → packages/types/src/zod/complex.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.

  • names form.zod.ts → packages/types/src/zod/form.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/7122-objectstack-family-17-3-0.md

  • names pnpm-lock.yaml → pnpm-lock.yaml — edited by this change

    @objectstack/client, core, formula and lint each pin @objectstack/spec EXACTLY, so resolving the spec alone to 17.3.0 left the console bundling TWO copies of it. Moving the family with it in pnpm-lock.yaml collapses the duplicate; every declared range already admitted 17.3.0, so no manifest moved.

.changeset/7125-dashboard-empty-state-keys-retired.md

  • names DatasetWidget.tsx → packages/plugin-dashboard/src/DatasetWidget.tsx — edited by this change

    Not touched: table.noRows ('No rows to display') and engine.form.noRows (packages/app-shell/src/views/metadata-admin/i18n.ts, read at widgets.tsx) — two different, same-named keys in different namespaces. Nor the comments in WidgetEmptyState.tsx, DatasetWidget.tsx, ObjectDataTable.tsx and PivotTable.tsx that record WHY three widgets with three strings became one shared empty state; the packs' own comment keeps that rationale and now names the retirement instead of a row that is gone.

.changeset/7166-retire-inert-fieldmeta-copies.md

  • names packages/fields/src/index.tsx → packages/fields/src/index.tsx — edited by this change

    applyRelationalMeta writes the copy set onto the fieldMeta that generateColumns hands to ANGLE-BRACKETS(CellRenderer) as the field prop — six JSX passes across the three column-building paths, and nowhere else. For a relational column that resolves to LookupCellRenderer, which reads exactly reference_to, reference, display_field, displayField, reference_field and options; a user column resolves to UserCellRenderer, which destructures { value } and reads no field meta at all. Measured by receiver rather than by count: packages/fields/src/index.tsx, the file holding every cell renderer, contains zero occurrences of the three retired keys, against a control of 22 occurrences of the display_field / displayField / reference_to spellings the cell does read.

.changeset/7173-ai-pending-actions-inbox-i18n.md

  • names scripts/check-eager-closure-budget.mjs → scripts/check-eager-closure-budget.mjs — edited by this change

    The ten pack blocks are locale DATA, and locale data lands in the console's eager framework chunk, so scripts/check-eager-closure-budget.mjs raises that chunk's ceiling from 512,000 to 524,000 gzipped bytes and re-pins its baseline onto a fresh measurement (502,405 to 514,863). Attributed by three console builds: the merge parent reads 510,192, this branch with the ten aiApprovals blocks cut reads 510,192 again, and this branch reads 514,863 — so the whole 4,671-byte delta is the pack data and nothing else. Headroom is kept at the line's own convention (9,137 bytes, 0.10x the regression the gate must catch) rather than widened; most of the overage was pre-existing drift, with the merge parent already at 510,192 of the 512,000 allowed.

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

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

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

.changeset/7313-object-calendar-record-source.md

  • names plugin-calendar/src/ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    ObjectCalendar resolves its records through the shared ladder (resolveRecordSourceConfig in @object-ui/core, called from plugin-calendar/src/ObjectCalendar.tsx): data first, then staticData, then objectName. The published TypeScript interface REQUIRED objectName and declared neither data nor staticData; the published Zod mirror did the same. So an object-calendar node authored on staticData — the route the plugin page documents twice — rendered correctly and was refused by safeValidateSchema, and could not be annotated with its own type (TS2741: Property 'objectName' is missing).

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

    A widening. A node authoring staticData or data without objectName now validates (it always rendered — the read is resolveRecordSourceConfig(schema), keyed on the three). Every document that validated before still validates: objectName alone still parses, an empty one included, because presence is !== undefined. The one shape the refinement refuses (none of the three) was refused before too, at objectName. The two static-data examples in content/docs/plugins/plugin-calendar.mdx are now annotated ObjectCalendarSchema and compile under the doc-snippet gate.

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

  • names packages/core/src/utils/normalize-list-view.ts → packages/core/src/utils/normalize-list-view.ts — edited by this change

    Who is NOT affected. The VIEW-LEVEL kanban config is untouched: kanban.groupField there is a live legacy alias of the spec's groupByField (packages/core/src/utils/normalize-list-view.ts maps it; plugin-list's ListView and plugin-view's ObjectView still read it). groupField is dead only on the object-kanban NODE. The declarative kanban node (KanbanSchema) is untouched, BaseSchema's unknown-key policy is byte-identical (an undeclared key still passes through), and the renderer is unchanged — boards authored the documented way rendered before and render now. One in-repo fixture authored groupField on this node (packages/types/src/__tests__/kanban-conditional-formatting.test.ts); it now authors groupBy. No doc snippet, catalog entry, skill or app in this repository authored groupField on an object-kanban node.

.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/7499-gantt-non-axis-floors-omitted.md

  • names plugin-view/src/ObjectView.tsx → packages/plugin-view/src/ObjectView.tsx — edited by this change

    • plugin-list/src/ListView.tsx — the object-gantt render branch. - plugin-view/src/ObjectView.tsx — generateViewSchema, the authored object-view element route, which bypasses ListView entirely.

.changeset/7530-predicate-envelope-declared.md

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

    • ExpressionWire (type, main entry) — the TypeScript wire union, in packages/types/src/expression.ts. - ExpressionWireSchema (@object-ui/types/zod) — its runtime twin, hoisted out of zod/form.zod.ts (where it was module-private) into zod/expression.zod.ts and imported by both base.zod.ts and form.zod.ts. One envelope type, reused by reference; no second spelling.
  • names form.zod.ts → packages/types/src/zod/form.zod.ts — edited by this change

    • ExpressionWire (type, main entry) — the TypeScript wire union, in packages/types/src/expression.ts. - ExpressionWireSchema (@object-ui/types/zod) — its runtime twin, hoisted out of zod/form.zod.ts (where it was module-private) into zod/expression.zod.ts and imported by both base.zod.ts and form.zod.ts. One envelope type, reused by reference; no second spelling.

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

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

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

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

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

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

.changeset/7635-spec-173-comment-repairs.md

  • names scripts/check-installed-spec-pin-claims.mjs → scripts/check-installed-spec-pin-claims.mjs — edited by this change

    Two of the five sites are now watched. They are written as single-line claims about the installed pin, which moves them out of scripts/check-installed-spec-pin-claims.mjs's ledger of known-stale debt and into the population that gate re-derives at every bump; their ledger entries are deleted in the same change, as that gate's both-direction ratchet requires. The remaining three sit on facts no instrument reads, and say so rather than reading as live.

.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/7703-chatbot-dark-keys-retired.md

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

    Each member goes to ?: never on packages/types/src/complex.ts and to retirementTombstone(...) on packages/types/src/zod/complex.zod.ts — both halves, in lockstep, the convention MarkdownSchema.sanitize (objectui#6972), TimelineSchema.timeScale (objectui#6355) and ObjectViewSchema.viewTabBar (objectui#7779) already carry. Each refusal names the key, says why it is retired, and points at what to write instead; one string feeds both the parse-time message and the .describe() metadata, so the two cannot drift.

.changeset/7712-kanban-calendar-filter-input.md

  • names ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    ObjectKanban.tsx sends the authored key to the query as $filter: schema.filter and ObjectCalendar.tsx does the same, and @objectstack/spec's ComponentPropsMap declares filter on both blocks (measured: safeParse accepts it, and refuses an undeclared key by name on the same call). But none of the four registrations that publish those two renderers listed filter in inputs, and sdui-parser's validateTree reports unknown-prop for every key no inputs entry claims. So an author writing the one spelling that WORKS was told it was unknown — objectui#6678's shape, where a correct write draws the same diagnostic as a write that does nothing. That is worse than an inert key: it actively punishes the correct behaviour, and the honest response to it is to delete working metadata.

.changeset/7722-wrapper-class-five-more.md

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

    Each of renderers/form/switch.tsx, textarea.tsx, date-picker.tsx, select.tsx and renderers/data-display/list.tsx reads schema.wrapperClass onto its wrapper element, and neither the TypeScript interface (form.ts, data-display.ts) nor the zod mirror (zod/form.zod.ts, zod/data-display.zod.ts) declared the key. The reads compiled through BaseSchema's index signature (objectui#5155) and the values parsed through .passthrough(), admitted unexamined. The same key, on the same class of read, is declared on CheckboxSchema (b74a8598d), FileUploadSchema and FilterBuilderSchema (objectui#6150); these five were left out only because their doc pages never listed it.

.changeset/7735-zod-mirrors-stop-authoring-defaults.md

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

    What changed. All 41 .default() call sites under packages/types/src/zod/ are removed — layout.zod.ts 22, crud.zod.ts 11, form.zod.ts 5, views.zod.ts 2, app.zod.ts 1. @object-ui/components reconciles the third face a separate finding found: flex's registration defaultProps.align seeded 'center', the value its own renderer never applies, so a designer-made node laid out differently from a hand-authored one; it now seeds 'start'.

.changeset/7772-page-block-kanban-group-by-control.md

  • names core/src/utils/normalize-list-view.ts → packages/core/src/utils/normalize-list-view.ts — edited by this change

    The view-level kanban.groupField alias (core/src/utils/normalize-list-view.ts) is live and untouched — node-level retirement and the view-level alias are different things.

.changeset/7773-kanban-adapter-groupfield-write.md

  • names normalize-list-view.ts → packages/core/src/utils/normalize-list-view.ts — edited by this change

    Who is NOT affected — the boundary is node-local. Every VIEW-LEVEL groupField read is untouched and still live: it is a legacy alias of the spec's groupByField on the kanban view config, mapped by normalize-list-view.ts, and both adapters still resolve lanes through it (ObjectView.tsx's kanbanCfg.groupField ||, ListView.tsx's groupByField || groupField). Authoring options.kanban.groupField on a list-view or object-view keeps working exactly as documented in packages/plugin-list/README.md. groupField is dead only on the generated object-kanban NODE.

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

    Who is NOT affected — the boundary is node-local. Every VIEW-LEVEL groupField read is untouched and still live: it is a legacy alias of the spec's groupByField on the kanban view config, mapped by normalize-list-view.ts, and both adapters still resolve lanes through it (ObjectView.tsx's kanbanCfg.groupField ||, ListView.tsx's groupByField || groupField). Authoring options.kanban.groupField on a list-view or object-view keeps working exactly as documented in packages/plugin-list/README.md. groupField is dead only on the generated object-kanban NODE.

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

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

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

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

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

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

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

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

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

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

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

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

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

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

.changeset/8067-component-input-member-kind.md

  • names apps/console/src/__tests__/registry-inputs-spec-parity.test.ts → apps/console/src/__tests__/registry-inputs-spec-parity.test.ts — edited by this change

    A registration's type: 'array' said a value was a list and stopped there, so a member that drifted from @objectstack/spec was invisible to every layer that reads a declaration. page:header.actions is the measured cost: the contract declares z.array(z.string()) ("Action IDs"), the renderer read the members as ActionDef objects, and the repo-wide parity gate in apps/console/src/__tests__/registry-inputs-spec-parity.test.ts stayed green for the whole life of the drift because both sides carried the key and neither could say what was inside it. What settled it was a maintainer ruling, not a test — and even after the fix, "these are ids" survived only as English in the registration's description.

.changeset/8171-calendar-sort-input.md

  • names ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    objectui#7712's defect, one key over. ObjectCalendar.tsx lowers the authored key onto its own query as $orderby: convertSortToQueryParams(schema.sort), and @objectstack/spec's ComponentPropsMap['object-calendar'] declares sort (measured on 17.2.0: safeParse({ objectName, sort }) returns success: true, while the same strict schema on the same call refuses bogusProp by name — that control is what makes the acceptance a verdict). But neither of the two registrations that publish this renderer — plugin-calendar:object-calendar and view:calendar — listed sort in inputs, and sdui-parser's validateTree reports unknown-prop for every key no inputs entry claims. So an author writing the one spelling that WORKS was told it was unknown — objectui#6678's shape, where a correct write draws the same diagnostic as a write that does nothing.

.changeset/8174-kanban-calendar-filter-sort.md

  • names ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    filter had four declaration faces and only three of them named it: @objectstack/spec declares it (ComponentPropsMap['object-kanban'] and ['object-calendar']), both plugins' registration inputs publish it, and both renderers read it — ObjectKanban.tsx lowers schema.filter onto $filter, ObjectCalendar.tsx lowers schema.filter onto $filter and schema.sort onto $orderby through convertSortToQueryParams. This package's own published faces (the TypeScript interface and its zod mirror) named none of them, so an authored value reached the renderer only through BaseSchema's index signature and the mirror's .passthrough() — admitted, never examined. That is the same reasoning finding(types,plugin-kanban): ObjectKanbanSchema requires groupField (zero read sites) and declares neither groupBy nor limit — no working object-kanban node is assignable to any declared type #7322 used to move groupBy and limit into this same interface.

.changeset/8317-strip-imported-defaults.md

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

    Decision batch Redesign examples based on new JSON project specification #69 (objectui#7735) ruled a principle: a validator validates; it does not write values into an author's document. PR fix(types,components): the zod mirrors stop authoring defaults #8299 delivered it for the 41 .default() call sites written in this package's own mirrors. Measured afterwards, 57 ZodDefault nodes were still reachable from the published @object-ui/types/zod barrel, every one inside a subschema imported by reference from @objectstack/spec — so safeValidateSchema went on substituting on those keys, with 41 stripped and 57 not and no way to tell which was which from the document. Batch [WIP] Fix action run issue in CI/CD pipeline #90 ruled that the principle holds for every key the validator answers, and those 57 are now stripped where the spec enters this package (.removeDefault(), the established local pattern, applied through zod/imported-defaults.ts).

.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/8355-retire-calendar-date-aliases.md

  • names calendar-date-alias-refusal-8355.test.ts → packages/types/src/__tests__/calendar-date-alias-refusal-8355.test.ts — edited by this change

    ⚠️ Dated note, 2026-09-28 — a named view's options.calendar nesting is no longer judged inside — objectui#7928. Later in this same release ObjectViewSchema.listViews became the protocol's strict ObjectListViewSchema record, by reference, and that record refuses a named view's options bag whole (unrecognized_keys at listViews.KEY, naming options). So an alias written under listViews.KEY.options.calendar no longer draws an issue naming the key or the remedy. The named view's calendar block still does: the protocol refuses the alias there as an unrecognized key, and this entry's check adds the pointer at the key beside it. A stored body that @object-ui/app-shell's ViewPreview relays has its options.calendar folded onto the calendar block first (foldStoredListOptions). The list view's two nestings and both object-calendar surfaces are unchanged; calendar-date-alias-refusal-8355.test.ts in @object-ui/types re-derives each surface. .changeset/7928-listviews-by-reference-fold.md (PR objectui#10821) states what ships; the text above is kept as the reading of this change.

  • names ObjectView.calendarAliasRefused-8355.test.tsx → packages/plugin-view/src/__tests__/ObjectView.calendarAliasRefused-8355.test.tsx — edited by this change

    Pinned by calendar-date-alias-refusal-8355.test.ts (@object-ui/types, all five surfaces, the per-surface consequence split, the compile-time face, and the structural guard that listViews stays out of the object's shape), ListView.calendarAliasRefused-8355.test.tsx (@object-ui/plugin-list) and ObjectView.calendarAliasRefused-8355.test.tsx (@object-ui/plugin-view) — both reading the node their producer really emits through a spy registration, which is the only census that can see a key arriving through a spread — and the inverted ledger rows in calendarUnionReads-8651.test.tsx (@object-ui/plugin-calendar).

  • names calendarUnionReads-8651.test.tsx → packages/plugin-calendar/src/__tests__/calendarUnionReads-8651.test.tsx — edited by this change

    Pinned by calendar-date-alias-refusal-8355.test.ts (@object-ui/types, all five surfaces, the per-surface consequence split, the compile-time face, and the structural guard that listViews stays out of the object's shape), ListView.calendarAliasRefused-8355.test.tsx (@object-ui/plugin-list) and ObjectView.calendarAliasRefused-8355.test.tsx (@object-ui/plugin-view) — both reading the node their producer really emits through a spy registration, which is the only census that can see a key arriving through a spread — and the inverted ledger rows in calendarUnionReads-8651.test.tsx (@object-ui/plugin-calendar).

.changeset/8415-filter-builder-condition-id.md

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

    Breaking for authored metadata: a filter-builder CONDITION must now declare id (objectui#8415). It is declared on both published faces — the TypeScript interface FilterBuilderCondition in complex.ts and the Zod mirror FilterBuilderConditionSchema in zod/complex.zod.ts — so a key the renderer has always required is finally validated instead of silently discarded.

.changeset/8466-calendar-color-allday-fields.md

  • names ObjectCalendar.tsx → packages/plugin-calendar/src/ObjectCalendar.tsx — edited by this change

    ObjectCalendar.tsx's getCalendarConfig reads FIVE flat keys off the node, and packages/plugin-calendar/README.md teaches all five in one sentence — "point titleField / startDateField / endDateField / allDayField / colorField at your own fields when they differ." Only three of the five were declared. The other two reached the renderer through BaseSchema's [key: string]: any on the TypeScript face and its .passthrough() on the zod mirror: admitted, never examined. A misspelling therefore left the calendar silently colourless while every published gate passed.

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

.changeset/8478-zod-pins-complex.md

.changeset/8478-zod-pins-form-layout.md

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

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

    • SemanticElementSchema (zod/layout.zod.ts) — the seven HTML sectioning tags renderers/layout/semantic.tsx registers: aside main header nav footer section article. - HtmlElementSchema (zod/layout.zod.ts) — the 37 safe flow/inline tags renderers/basic/html-elements.tsx registers (h1…h6, p, a, ul, img, …), plus the per-tag keys that module forwards to the DOM (href, target, rel, title, src, alt, width, height, dateTime, cite). ⚠️ Dated note, 2026-09-27 — that set has since gained code — objectui#10756. At this change TAGS and this arm both named 37 tags; both now name 38, and the parity pin counts 38. The rest of this entry is kept as the reading of this change. - InputShorthandSchema (zod/form.zod.ts) — email / password, the two aliases renderers/form/input.tsx registers onto the input renderer with inputType pinned. inputType is deliberately NOT declared on this arm: the wrapper spreads its own value last, so an authored one is overwritten. ⚠️ Dated note, 2026-09-28 — inputType is now declared on this arm, as a refusal — objectui#8762. Later in this same release the arm declares inputType on both faces and refuses it by name (?: never on the TypeScript face, a retirementTombstone on the zod mirror, at path inputType), with guidance pointing at { "type": "input", "inputType": "email" }. So "inputType is deliberately NOT declared on this arm" no longer holds; the reason does, since the wrapper still spreads its own value last. The rest of this entry is kept as the reading of this change. - UiCalendarSchema (zod/form.zod.ts) — ui:calendar, the date-picker primitive renderers/form/calendar.tsx registers under exactly that key (skipFallback, because bare calendar belongs to the plugin-calendar view).

.changeset/8516-8556-mirror-partial-record-narrowing.md

  • names __tests__/mirror-partial-record-narrowing-8516.test.ts → packages/types/src/__tests__/mirror-partial-record-narrowing-8516.test.ts — edited by this change

    The spelling is z.partialRecord, and that is load-bearing. ⛔ Not z.record(z.enum([…]), …): measured on zod 4.4.3, the plain record over an enum key REQUIRES every member, so { md: 2 } stops parsing — it would trade this divergence for its exact opposite, and on exportConfigs it would re-impose the total-Record authoring face objectui#6121's maintainer ruling removed. That measurement is pinned executably in __tests__/mirror-partial-record-narrowing-8516.test.ts, at compile time (the inferred map is Partial<RecordANGLE-BRACKETS(…)>, not RecordANGLE-BRACKETS(…)) and at run time (one accepting row per member), so it cannot rot into folklore.

.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/8649-detail-renderer-undeclared-keys.md

  • names packages/plugin-detail/src/renderers/__tests__/detailRendererUndeclaredKeys-8649.test.ts → packages/plugin-detail/src/renderers/__tests__/detailRendererUndeclaredKeys-8649.test.ts — edited by this change

    This is an alignment, not a widening: the accept set of this face moves to the contract's and never past it. The pin that says so re-derives the contract side on every run rather than restating it (packages/plugin-detail/src/renderers/__tests__/detailRendererUndeclaredKeys-8649.test.ts).

.changeset/8653-listview-title-retired-rowactiondefs-pinned.md

  • names packages/plugin-view/src/ObjectView.tsx → packages/plugin-view/src/ObjectView.tsx — edited by this change

    title — retired. ListView resolved its export filename through schema.label || (schema as any).title. @objectstack/spec/ui's ListViewSchema refuses title by name (unrecognized_keys: ['title']) while ObjectGridPropsSchema accepts it; packages/types mirrors the platform contract rather than ruling over it, so declaring title on ListViewSchema would have made this repo accept what the platform save gate rejects. That asymmetry is also why objectui#6639 could take the declare branch for ObjectGridSchema.title one package over and this site could not. A parse-based census of apps/ examples/ content/ and packages/ found zero list-view nodes authoring title, so the retirement costs no author a filename. Over that same corpus the instrument reports three object-grid nodes carrying the key: two authored ones, both in content/docs/api/schema-reference.md, plus one that is not authored at all — packages/plugin-view/src/ObjectView.tsx composes title: schema.table?.title onto a grid node it builds, so it is a producer writing the key rather than an author declaring it. ObjectGrid's own title reads are untouched — they remain declared, ruled and read.

.changeset/8655-object-tree-props-schema-typed.md

  • names ObjectTree.schemaTyped-8655.test.ts → packages/plugin-tree/src/ObjectTree.schemaTyped-8655.test.ts — edited by this change

    What the re-measurement then surfaced, reported rather than tidied: six more reads became answerable, five declared and one — filter — not. Its verdict is declare-by-mirror-alignment and it is ⛔ NOT executed here, because the two files that would carry it are held by an in-flight branch; the ledger row in ObjectTree.schemaTyped-8655.test.ts reddens the day it lands. tree is declared by the protocol on the VIEW and on zero element faces, so declaring it on the node would fork rather than mirror the contract, and retiring the read needs a producer census a text search cannot make. navigation belongs to a blocked card and is ledgered, ⛔ not ruled.

.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/8755-bulk-lookup-depends-on.md

  • names plugin-grid/src/__tests__/bulkLookupDependsOnReach-8755.test.tsx → packages/plugin-grid/src/__tests__/bulkLookupDependsOnReach-8755.test.tsx — edited by this change

    ⚠️ The bulk param schema does not license the key, and must not be cited as if it did. @objectstack/spec's BulkActionParamSchema "accepts" dependsOn — and accepts a nonsense key in the same run, because it is not strict; the strict sibling ActionParamSchema refuses both. That accept is a null reading, pinned with both controls in plugin-grid/src/__tests__/bulkLookupDependsOnReach-8755.test.tsx leg B. Whether the key should become authorable by contract here — by closing that schema, or by giving the bulk surface the field-backed param route resolveActionParams gives the single-record dialog — is upstream of this repository and stays open.

.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.
  • names packages/types/src/zod/complex.zod.ts → packages/types/src/zod/complex.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/8841-tree-view-config-derive.md

  • names scripts/check-spec-symbol-derivation.mjs → scripts/check-spec-symbol-derivation.mjs — edited by this change

    What was wrong. @object-ui/types published TreeViewConfig as a hand-written interface — a copy of the protocol's ListView.tree block under a second name — and the copy declared a fifth key, titleField. @objectstack/spec@17.4.0 refuses that key there by name: TreeConfigSchema is a strictObject since spec objectstack#15469 closed the .passthrough() window 17.3.0 left open. So this package's published face accepted what the contract rejects, and an author who followed @object-ui/types was refused at publish with Unrecognized key(s) on this tree configuration: 'titleField'. The copy was invisible to scripts/check-spec-symbol-derivation.mjs, which matches spec symbols BY NAME — a hand copy renamed away from the spec's symbol has nothing for its rule 1 to match (objectui#4592's recorded blind spot).

.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/9012-core-spec-floor.md

  • names normalize-list-view.declaredSpecFloor-9012.test.ts → packages/core/src/utils/__tests__/normalize-list-view.declaredSpecFloor-9012.test.ts — edited by this change

    scripts/check-spec-range-floors.mjs was green before and after, and would be green at any floor here: its criterion is symbol PRESENCE, and UserActionsConfigSchema is exported by every version above. The floor is held instead by normalize-list-view.declaredSpecFloor-9012.test.ts, which carries firing controls proving its comparator can redden.

.changeset/9040-retire-record-details-layout.md

  • names packages/types/src/__tests__/record-highlights-layout-9187.test.ts → packages/types/src/__tests__/record-highlights-layout-9187.test.ts — edited by this change

    • packages/types/src/__tests__/p1-spec-alignment.test.ts wrote layout: 'stacked' on this interface and read it back. Both lines are gone, with the reason stated at the site and a live-key read-back put in their place so the leg is not quietly shrunk. Its RecordHighlightsComponentProps neighbour keeps its own layout — a different key on a different face. - packages/types/src/__tests__/record-details-top-level-9040.test.ts ledgered the divergence as OPEN. Those legs become the retirement's own: a keyof absence assertion (with a declared key read through the identical form as its control), a @ts-expect-error literal, and a new source-text leg. - packages/types/src/__tests__/record-highlights-layout-9187.test.ts read this declaration as TEXT, using its three-value layout as the lit control for a two-member assertion about the sibling. That control MOVED to RecordChatterComponentProps.position — a three-value union the contract genuinely declares — as that file's own instruction required. It was never to be deleted outright, and it is not.

.changeset/9067-zod-barrel-named-arms.md

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

    • InputShorthandSchema (zod/form.zod.ts) — the email / password shorthand arm. - UiCalendarSchema (zod/form.zod.ts) — ui:calendar, the date-picker primitive renderers/form/calendar.tsx registers, a different component from the calendar plugin view that owns the bare literal.

.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/9109-flow-node-unbacked-defaults.md

  • names flow-node-config.spec-reconciliation.test.ts → packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.spec-reconciliation.test.ts — edited by this change

    flow-node-config.spec-reconciliation.test.ts's unbacked register is now empty, and its re-measurement was rewritten to walk the scope table rather than the register's own rows — written the old way, an emptied register contributes no case, runs nothing and still reports green.

.changeset/9187-record-highlights-layout-two-values.md

  • names record-highlights-layout-9187.test.ts → packages/types/src/__tests__/record-highlights-layout-9187.test.ts — edited by this change

    ⚠️ The layout one interface up, on RecordDetailsComponentProps, is a different divergence and was not touched by this change: the contract refuses that key by name, and its removal was objectui#9040's. Copying either declaration onto the other is refused at publish. The union landed here is pinned against the installed spec, in both directions, in record-highlights-layout-9187.test.ts.

.changeset/9278-end-outcome-select.md

  • names packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.ts → packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.ts — edited by this change

    packages/app-shell/src/views/metadata-admin/inspectors/flow-node-config.ts declared the end group's outcome key as a free-text box with placeholder: 'success · failure'. EndConfigSchema.outcome is a closed enum of completed | refused defaulting to completed, and FlowNodeSchema discriminates an end node's config through it — so both printed words are refused at parse, not ignored at run time. Measured against the installed @objectstack/spec (17.4.0), with the accepted row in the same output so the refusals are a reading rather than a dead probe:

  • names FlowNodeInspector.declaredDefault.test.tsx → packages/app-shell/src/views/metadata-admin/inspectors/FlowNodeInspector.declaredDefault.test.tsx — edited by this change

    The control is now a select whose options are exactly the spec's enum, declaring defaultValue: 'completed' so an unset key states on the trigger what the runtime applies to it, and the invented placeholder is gone. Both are derived from the installed spec, as FlowConfigField.defaultValue's doc comment requires of a declaration outside the escalation ledger, and both are reconciled against EndConfigSchema in FlowNodeInspector.declaredDefault.test.tsx — through zod's public toJSONSchema rather than a respelled literal, so the claim cannot quietly rot at the next spec bump. The zh-CN overlay gains the two option labels and the help line.

.changeset/9280-record-highlights-entry-icon-retired.md

  • names packages/types/src/record-components.ts → packages/types/src/record-components.ts — edited by this change

    • packages/types/src/record-components.ts — RecordHighlightsComponentProps.fields[]'s object arm: { name; label?; icon?; type?; readonly? } → { name; label?; type?; readonly? }. The key is removed, not tombstoned: the contract's arm is $strict, so the refusal an author needs already exists upstream and arrives named (invalid_union at the entry). A ?: never tombstone buys nothing here — it is the remedy for a non-strict mirror that would otherwise strip in silence, which is not this arm. - packages/plugin-detail/src/renderers/record-highlights.tsx — the entry normalizer stops copying icon: f?.icon into the normalized entry. That read was unreachable, not merely unused: no author could feed it past the $strict arm, and HeaderHighlight renders no .icon on the far side either, so the copy had no consumer in either direction. - packages/plugin-detail/src/index.tsx — the registry manifest's fields input description sketched the entry as {name,label?,icon?,type?,readonly?} → {name,label?,type?,readonly?}. The inputs ARE the published contract (gen-manifest.ts serializes them into sdui.manifest.json and sdui-intrinsics.d.ts), so leaving the sketch standing would have gone on teaching AI and human authors a key that gets the whole document refused at publish.
  • names packages/plugin-detail/src/index.tsx → packages/plugin-detail/src/index.tsx — edited by this change

    • packages/types/src/record-components.ts — RecordHighlightsComponentProps.fields[]'s object arm: { name; label?; icon?; type?; readonly? } → { name; label?; type?; readonly? }. The key is removed, not tombstoned: the contract's arm is $strict, so the refusal an author needs already exists upstream and arrives named (invalid_union at the entry). A ?: never tombstone buys nothing here — it is the remedy for a non-strict mirror that would otherwise strip in silence, which is not this arm. - packages/plugin-detail/src/renderers/record-highlights.tsx — the entry normalizer stops copying icon: f?.icon into the normalized entry. That read was unreachable, not merely unused: no author could feed it past the $strict arm, and HeaderHighlight renders no .icon on the far side either, so the copy had no consumer in either direction. - packages/plugin-detail/src/index.tsx — the registry manifest's fields input description sketched the entry as {name,label?,icon?,type?,readonly?} → {name,label?,type?,readonly?}. The inputs ARE the published contract (gen-manifest.ts serializes them into sdui.manifest.json and sdui-intrinsics.d.ts), so leaving the sketch standing would have gone on teaching AI and human authors a key that gets the whole document refused at publish.

.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/9491-walkabledef-rest-null.md

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

    packages/types/src/zod/node-derivation.ts declares the def member set both zod walkers in this package read. It declared rest?: z.ZodType — i.e. z.ZodType | undefined — while zod 4 spells "this tuple has no rest element" as an OWN rest key holding null, minted by const rest = hasRest ? _paramsOrRest : null in its tuple factory.

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

    This is the declaration, not a behaviour change. Nothing here changes what either walker does with the value; the accept set of every exported schema is untouched. objectui#9088 already repaired the one arm the inaccurate type misled — the tuple arm in zod/imported-defaults.ts, which normalised the absent case to undefined because the declared type said that was the absent case, and so rebuilt every rest-less tuple through a === comparison that could never match. This change corrects the type that licensed it, so the next arm written against it is told the truth and tsc agrees with the truth instead of with the mistake.

.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 views.ts → packages/types/src/views.ts — edited by this change

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

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

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

.changeset/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/9550-plugin-tree-import-object-tree-schema.md

  • names ObjectTree.schemaTyped-8655.test.ts → packages/plugin-tree/src/ObjectTree.schemaTyped-8655.test.ts — edited by this change

    Nothing about the type changes — the imported name and the narrowing resolve to the same declaration, which ObjectTree.schemaTyped-8655.test.ts asserts invariantly and independently through ObjectTreeProps['schema']. What changes is that the renderer no longer carries a derived restatement of a published type. A type nobody can import mints one of those per consumer, and each one is correct on the day it is written — that is the second-authority shape objectui#6349 is burning down, and this was one of its instances rather than a tidy-up.

.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/9880-undrawable-view-kinds-both-legs.md

  • names normalize-list-view.ts → packages/core/src/utils/normalize-list-view.ts — edited by this change

    Compiled both ways rather than argued. With the published pin @objectstack/spec@17.4.0 installed, turbo run type-check --filter=@object-ui/core exits 0 before and after this change. With a spec built from objectstack main injected in its place, the same command reported the TS2353 in normalize-list-view.ts before and does not report it after; the diagnostics that remain on that leg come from other files, are reproduced against the pristine source, and are not this change's.

  • names normalize-list-view.undrawableBothLegs-9880.test.ts → packages/core/src/utils/__tests__/normalize-list-view.undrawableBothLegs-9880.test.ts — edited by this change

    normalize-list-view.undrawableBothLegs-9880.test.ts pins all of it over a SIMULATED vocabulary, because any single run installs only one spec: the retirement direction, the addition direction, and the old spelling's TS2353 kept as a firing control.

.changeset/action-callback-retired-7068.md

  • names ui-action.ts → packages/types/src/ui-action.ts — edited by this change

    Where the live meaning lives. Post-success navigation is the spec's onSuccess block, { navigate, openIn }, declared on UIActionSchema (ui-action.ts) and forwarded to the runner (objectui#5934). A success or failure notice is successMessage / errorMessage — adjacent keys on the same legacy ActionSchema, NOT retired, and still accepted on both faces.

.changeset/console-form-container-specs-one-declaration-5596.md

  • names scripts/check-spec-symbol-derivation.mjs → scripts/check-spec-symbol-derivation.mjs — edited by this change

    Both types are therefore derived from the spec's own FormSection / FormView with named narrowings — the repo's sanctioned form for a spec-shaped local type (scripts/check-spec-symbol-derivation.mjs) — rather than restated. Every key the two layers agree on comes from the spec and cannot fall behind it; the four positions where this layer is deliberately narrower are each named in an Omit list and restated once next to its reason: fields keeps the converged 26-key leaf (deriving it would silently re-open [finding] A THIRD inline copy of the form-field authoring contract lives in apps/console FormPage.tsx — objectui#5040 converged only the app-shell two #5542), and label / description / visibleWhen / visibleOn keep the shapes this repo's renderers and evaluators actually consume rather than the spec's I18nLabel and ExpressionInput. apps/console's submitBehavior union — previously hand-written under the comment "Mirrors the spec FormView.submitBehavior union" — is now read back off the shared type, making the mirror structural. @object-ui/app-shell re-exports both names from its package root (type-only, erased at build — nothing is added to the bundle), because a type that cannot be imported is a type that gets retyped.

.changeset/host-dispatch-action-keys-5611.md

  • names actions/actionKeys.ts → packages/core/src/actions/actionKeys.ts — edited by this change

    Adds an exported HOST_DISPATCH_ACTION_KEYS (sole member overrideNotice) to actions/actionKeys.ts and unions it into KNOWN_ACTION_KEYS, which is the fourth input to that set and the first one that is not an authored-surface mirror. Measured before and after on the exact dispatch the bar composes: the warning went from one call naming overrideNotice to none, KNOWN_ACTION_KEYS grew by exactly one member, and an action carrying a real typo alongside it still warns — naming targt only.

.changeset/i18nlabel-inverted-pin-5612.md

  • names ui-action.ts → packages/types/src/ui-action.ts — edited by this change

    The I18nLabel "inverted pin" now watches the premise it claims to watch, and ui-action.ts no longer imports a symbol it never uses (objectui#5612, objectui#5613).

.changeset/listview-comment-pair-4559.md

  • names scripts/check-spec-symbol-derivation.mjs → scripts/check-spec-symbol-derivation.mjs — edited by this change

    objectui#4966 — formatActionLabel's docblock now sits above formatActionLabel. It had drifted two declarations up, so the exported parseSortConfig carried two stacked leading comments and the helper carried none. This one was not cosmetic: because parseSortConfig is exported, vite-plugin-dts copied the misattributed block into dist/ListView.d.ts, so every consumer's editor hover and TypeDoc introduced the sort parser with a sentence about action labels. Moving the block removes it from the .d.ts; formatActionLabel is module-private, so its now-correct docblock does not appear there. It also matters to scripts/check-spec-symbol-derivation.mjs, whose rule 2 reads the comment block attached to a declaration — a misattributed docblock is the mechanism by which a claim gets scored against the wrong symbol. This block carries no spec-alignment phrase, so nothing fired today.

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

  • names packages/plugin-view/src/ObjectView.tsx → packages/plugin-view/src/ObjectView.tsx — edited by this change

    What was measured. Every reading was taken on the object-view node renderer (packages/plugin-view/src/ObjectView.tsx, registered by plugin-view/src/index.tsx) with schema.objectName / schema.layout as the positive controls of the same schema.KEY query, so each zero is a reading; the repo-wide census of viewTabBar finds the key in no source file outside @object-ui/types (two doc tables listed it as authorable and are corrected here). The spec side was read through the installed pin (@objectstack/spec@17.2.0, ui entry, 117 exported object schemas walked; control keys objectName / columns / navigation / listViews hit): the three spec-modelled keys are optional slots on ListViewSchema and ObjectListViewSchema; the six local keys have no spec slot anywhere.

  • names object-view-unmirrored-keys-7779.test.ts → packages/types/src/__tests__/object-view-unmirrored-keys-7779.test.ts — edited by this change

    ⚠️ Dated note, 2026-09-28 — the value type has since been decided, and listViews is mirrored by reference — objectui#7928. Later in this same release the maintainer's ruling A made ObjectViewSchema.listViews the protocol's own named-view record, by reference: on both faces its value is @objectstack/spec's strict ObjectListViewSchema, and a NamedListView is not assignable to it. The docs have taught that shape since objectui#8255. So "listViews stays unmirrored", "The declaration's value is the local NamedListView", the key "stays in the parity ledger … until the maintainer decides its value type" and the table's "still unmirrored" above no longer hold: the ObjectViewSchema entry has left UnmirroredDeclared. NamedListView stays exported with its 64 declared members. The renderer reads some of them off a named view and leaves the rest unread, and the split is no longer the 21 and 43 this entry counted: objectui#7928 stopped reading the options bag, which the record refuses, and objectui#10758 made the host delegation read a named view's remaining protocol members off the named view. The census in object-view-unmirrored-keys-7779.test.ts pins the current figures. .changeset/7928-listviews-by-reference-fold.md (PR objectui#10821) states what ships; the text above is kept as the reading of this change.

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

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

.changeset/param-dialog-title-fallback-4282.md

  • names ui-action.ts → packages/types/src/ui-action.ts — edited by this change

    title is declared on no action surface in the ecosystem: it is absent from @objectstack/spec's ActionSchema (44 keys walked at spec 17.0.0), from @object-ui/core's ActionDef and its pinned ACTION_DEF_KEYS / SPEC_ACTION_KEYS inventories, and from @object-ui/types' renderer view (ui-action.ts) and crud.ts ActionSchema / BaseSchema. None of the four action renderers — action:button, action:icon, action:group, action:menu — forwards it either. So the right-hand side of that || could not be reached by authored metadata: a fallback that cannot fire, which is the "declared is not enforced" shape objectstack#4075 exists to reduce. Nothing a user hits changes; the line now reads exactly one key, matching the description line directly below it.

.changeset/record-alert-cta-label-i18n-4998.md

.changeset/record-detail-param-dialog-title-5610.md

  • names ui-action.ts → packages/types/src/ui-action.ts — edited by this change

    title is declared on no action surface in the ecosystem: it is absent from @objectstack/spec's ActionSchema (44 keys walked at spec 17.0.0), from @object-ui/core's ActionDef and its pinned ACTION_DEF_KEYS / SPEC_ACTION_KEYS inventories, and from @object-ui/types' renderer view (ui-action.ts) and crud.ts ActionSchema / BaseSchema. None of the four action renderers — action:button, action:icon, action:group, action:menu — forwards it either. So the right-hand side of that || could not be reached by authored metadata: a fallback that cannot fire, which is the "declared is not enforced" shape objectstack#4075 exists to reduce. Nothing a user hits changes; the line now reads exactly one key, matching the description line directly below it.

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

@github-actions

Copy link
Copy Markdown
Contributor

❌ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3563.2 KB 3149.4 KB
Main entry chunk (gzip) 149.3 KB 350 KB
Entry file index-CUM63uDC.js —
Status FAIL —

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.

Which half objected:

Eager-closure half Verdict
Aggregate closure ceiling ❌ over its ceiling
Per-chunk ceilings ❌ over its ceiling
Per-chunk membership (declared packages) ✅ pass
Ceiling sensitivity (headroom) ✅ pass
Ceiling freshness (checkout vs. base branch) ✅ pass

📦 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) 558.78KB 133.92KB
core (index.js) 9.94KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 227.99KB 63.22KB
fields (index.js) 261.01KB 66.28KB
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.35KB 9.18KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
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.58KB 4.90KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.25KB 2.17KB
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.33KB 15.01KB
plugin-charts (index.js) 84.09KB 22.93KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 137.68KB 36.71KB
plugin-designer (index.js) 215.78KB 44.42KB
plugin-detail (index.js) 233.54KB 61.80KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 169.60KB 43.32KB
plugin-gantt (index.js) 171.88KB 42.61KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 31.07KB 9.15KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 90.43KB 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.78KB 2.09KB
sdui-parser (codegen.js) 8.61KB 3.45KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.17KB 2.73KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
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) 22.61KB 7.40KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
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) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.30KB 6.99KB
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

…ne zod 4 copy (objectui#11073)

`pnpm dedupe --check` named exactly one change after the zod move:
fumadocs-mdx's own `zod ^4.4.3` dependency, 4.4.3 -> 4.6.5, which removes the
last zod@4.4.3. Without it `node scripts/check-lockfile-integrity.mjs` reports
"zod gained a physical copy: 2 -> 3" (the Lockfile Integrity Check). Applied
with `pnpm dedupe`, not by hand; the resolution census against the base lock
is now the seven @objectstack/* 17.4.0 -> 17.5.0 and zod 4.4.3 -> 4.6.5,
nothing else.

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

Copy link
Copy Markdown
Contributor

❌ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3563.5 KB 3149.4 KB
Main entry chunk (gzip) 149.3 KB 350 KB
Entry file index-kinSCXlb.js —
Status FAIL —

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.

Which half objected:

Eager-closure half Verdict
Aggregate closure ceiling ❌ over its ceiling
Per-chunk ceilings ❌ over its ceiling
Per-chunk membership (declared packages) ✅ pass
Ceiling sensitivity (headroom) ✅ pass
Ceiling freshness (checkout vs. base branch) ✅ pass

📦 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) 558.78KB 133.92KB
core (index.js) 9.94KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 227.99KB 63.22KB
fields (index.js) 261.01KB 66.28KB
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.35KB 9.18KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
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.58KB 4.90KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.25KB 2.17KB
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.33KB 15.01KB
plugin-charts (index.js) 84.09KB 22.93KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 137.68KB 36.71KB
plugin-designer (index.js) 215.78KB 44.42KB
plugin-detail (index.js) 233.54KB 61.80KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 169.60KB 43.32KB
plugin-gantt (index.js) 171.88KB 42.61KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 31.07KB 9.15KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 90.43KB 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.78KB 2.09KB
sdui-parser (codegen.js) 8.61KB 3.45KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.17KB 2.73KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
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) 22.61KB 7.40KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
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) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.30KB 6.99KB
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

…ectstack/spec 17.5.0's zod ^4.6.1 (objectui#11073)

- imported-defaults-describe-9034: a ZodDefault now answers
  `optin: 'defaulted'` (zod 4.4.3 answered 'optional'). The census asks the
  UNWALKED source node, so "already omissible" counts either rung; the
  corpus figure (5) is unchanged.
- mirror-partial-record-narrowing-8516: zod 4.6 reports a partialRecord's
  out-of-vocabulary key as a non-aborting `unrecognized_keys`, so the
  `GridSchema.columns` union returns that arm's issue alone: the key is
  named at `columns` (in `keys` and the message) instead of inside an
  `invalid_union`. The pin's intent, that the author is shown the key,
  holds.

Claude-Session: https://claude.ai/code/session_01TdiauJaVCHuj45EzZGUxHh
Co-authored-by: Claude <noreply@anthropic.com>
…he published @objectstack/spec 17.5.0 (objectui#11073)

Each re-pin follows the spec's own new answer, or a tripwire's written
instruction for the pin bump; no objectui accept set is decided here.

- detail-view-field-options-10296 + zod-mirror-parity: 17.5.0 requires a
  non-blank `source` on the `visibleWhen` envelope. Both tripwire rows flip
  to refusals, and the spec-version gate SpecEnvelopeAdmitsSourceless, its
  gated WiderThanDeclared entries (DetailViewFieldSchema `options`,
  DetailViewSchema `fields`/`sections`, DetailViewSectionSchema `fields`)
  and their WIDER_ARMS rows are deleted, as the gate's docblock instructed;
  the header figures move 6/7/7 - 5/2/0/0 -> 3/3/3 - 2/1/0/0.
- element-number-arm-10872 + imported-defaults-8317 + imported-defaults.ts
  docblock: ElementDataSourceSchema.filter is the ViewFilterRule array now,
  which reaches no z.lazy, so REBUILT_CLEAN is empty and the boundary hands
  back the spec's own object; the filter rows follow the spec's verdicts.
- imported-defaults-8317 "no member became REQUIRED": zod 4.6's
  `'defaulted'` rung; the strip must turn it into `'optional'`.
- record-highlights-layout-9187: the contract gained requiredPermissions,
  redactFields, enforceFieldSecurity; `layout` did not move.
- calendar-doc-key-set-8830 + calendar-flat-color-allday-8466 +
  plugin-calendar.mdx: CalendarConfigSchema declares `allDayField`; the doc
  fence tracks the SPEC type, so it lists five keys, and the sentences that
  said the spec refuses `allDayField` are corrected.
- spec-object-refinements-7715: checkListViewPageMount is no longer exported;
  its ListView row entry and measurement leave, as its message instructed.

Claude-Session: https://claude.ai/code/session_01TdiauJaVCHuj45EzZGUxHh
Co-authored-by: Claude <noreply@anthropic.com>
@github-actions github-actions Bot added documentation Improvements or additions to documentation package: types tests labels Sep 29, 2026
…onsole patch (objectui#11073)

`patch` on @object-ui/console: the only published artifact whose bytes move
is the console bundle, which inlines its @objectstack/* and zod
devDependencies. No manifest range and no @object-ui/* source API moves;
the @object-ui/types edits are re-read test pins and one comment.

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

Copy link
Copy Markdown
Contributor

❌ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3563.5 KB 3149.4 KB
Main entry chunk (gzip) 149.3 KB 350 KB
Entry file index-kinSCXlb.js —
Status FAIL —

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.

Which half objected:

Eager-closure half Verdict
Aggregate closure ceiling ❌ over its ceiling
Per-chunk ceilings ❌ over its ceiling
Per-chunk membership (declared packages) ✅ pass
Ceiling sensitivity (headroom) ✅ pass
Ceiling freshness (checkout vs. base branch) ✅ pass

📦 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) 558.78KB 133.92KB
core (index.js) 9.94KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 227.99KB 63.22KB
fields (index.js) 261.01KB 66.28KB
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.35KB 9.18KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
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.58KB 4.90KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.25KB 2.17KB
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.33KB 15.01KB
plugin-charts (index.js) 84.09KB 22.93KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 137.68KB 36.71KB
plugin-designer (index.js) 215.78KB 44.42KB
plugin-detail (index.js) 233.54KB 61.80KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 169.60KB 43.32KB
plugin-gantt (index.js) 171.88KB 42.61KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 31.07KB 9.15KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 90.43KB 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.78KB 2.09KB
sdui-parser (codegen.js) 8.61KB 3.45KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.17KB 2.73KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
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) 22.61KB 7.40KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
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) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.30KB 6.99KB
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

…ctui#11073)

Six commits, none touching pnpm-lock.yaml or a manifest; merged so the
patch round measures the tree the merge queue will build.

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

Copy link
Copy Markdown
Contributor

❌ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3563.5 KB 3149.4 KB
Main entry chunk (gzip) 149.3 KB 350 KB
Entry file index-kinSCXlb.js —
Status FAIL —

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.

Which half objected:

Eager-closure half Verdict
Aggregate closure ceiling ❌ over its ceiling
Per-chunk ceilings ❌ over its ceiling
Per-chunk membership (declared packages) ✅ pass
Ceiling sensitivity (headroom) ✅ pass
Ceiling freshness (checkout vs. base branch) ✅ pass

📦 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) 558.78KB 133.92KB
core (index.js) 9.94KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 227.99KB 63.22KB
fields (index.js) 261.01KB 66.28KB
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.35KB 9.18KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
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.58KB 4.90KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.25KB 2.17KB
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.33KB 15.01KB
plugin-charts (index.js) 84.09KB 22.93KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 137.68KB 36.71KB
plugin-designer (index.js) 215.78KB 44.42KB
plugin-detail (index.js) 233.54KB 61.80KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 169.60KB 43.32KB
plugin-gantt (index.js) 171.88KB 42.61KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 31.07KB 9.15KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 90.43KB 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.78KB 2.09KB
sdui-parser (codegen.js) 8.61KB 3.45KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.17KB 2.73KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
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) 22.61KB 7.40KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
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) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.30KB 6.99KB
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

…s terminally, restoring the objectui#9256 / #11022 refusals; DashboardWidgetSchema attaches the spec's two new checks (objectui#11073)

zod 4.6 (forced by @objectstack/spec 17.5.0's zod ^4.6.1) made a strict
object's `unrecognized_keys` non-aborting. A plain `z.union` whose one
non-aborted failing arm is that strict object returns ITS issues alone, so
the widget-slot `metric-card` lost its by-name content-channel refusal and
had its registered `value` reported as unrecognized.

`closedObject` / `closeStrictUnionArms` (node-derivation.ts) are the spec's
own mechanism (its ZodClosedObject marks `unrecognized_keys` continue:false;
not exported, so spelled here), applied only to strict arms of PLAIN unions,
as closed twins: the widgets slot (DashboardComponentSchema), the calendar
selection union (form.zod.ts) and every plain union on the strict authoring
face. Blast radius measured over every objectui union before landing: 29
plain unions with a strict arm, none left open, 1106 probes, 0 accept-set
moves, 187 error-shape moves (each a single arm's `unrecognized_keys`
becoming zod 4.4's `invalid_union` with every arm). Seat ruling Q3 → A.

complex.zod.ts also re-attaches the two object-level checks
@objectstack/spec 17.5.0 added to DashboardWidgetSchema
(checkDashboardWidgetStageOrder, checkDashboardWidgetMetricMeasureArity),
under the objectui#7715 B1 ruling; the census and the parity pin for it
land in the next commit with the rest of the test re-reads.

Claude-Session: https://claude.ai/code/session_01TdiauJaVCHuj45EzZGUxHh
Co-authored-by: Claude <noreply@anthropic.com>
…l refusal can no longer let run (objectui#8355, objectui#10321; objectui#11073)

@objectstack/spec 17.5.0 marks a closed object's unrecognized_keys continue:false, so zod skipped ObjectViewSchema's when-guarded superRefine (checkNamedViewCalendarAliases, checkNamedViewKanbanStrayGroupBy) on exactly the documents it existed for. The document is still refused by the protocol at listViews.KEY.calendar / .kanban, naming the key. The two checks and their helper are removed; the list-view route keeps objectui's pointers. The pins re-read the protocol's refusal. Seat ruling Q2 -> A (objectui#8934 principle), no upstream card.

Claude-Session: https://claude.ai/code/session_01TdiauJaVCHuj45EzZGUxHh
Co-authored-by: Claude <noreply@anthropic.com>
…he retired page view kind, as @objectstack/spec 17.5.0 did (objectui#11073)

The spec retired type: 'page', pageName and the list view's own tabs (ADR-0049). NamedListView declared pageName/tabs as 'declared inert' under objectui#8980, whose premise (the protocol declares them) is falsified; both are ?: never tombstones now with the protocol's prescriptions. The derived ViewType faces already follow the spec; core's UNDRAWABLE_VIEW_KINDS page row was deleted as its own note said it would be once the residual pins were converted, and they are (objectui#8429 now pins the closed state). The plugin-list README record drops page. Seat ruling Q4 -> A.

Claude-Session: https://claude.ai/code/session_01TdiauJaVCHuj45EzZGUxHh
Co-authored-by: Claude <noreply@anthropic.com>
…17.5.0 began exporting under check:spec-symbols (objectui#11073)

Per symbol, measured (seat ruling Q6 -> A):
- core isRefusedTextComparand / textComparandRefusalReason: the spec's are byte-identical ports of core's module, so core re-exports them from @objectstack/spec/data (describeComparand stays local; the spec does not export it). They are 17.5.0-only exports, so @object-ui/core's spec floor rises ^17.3.0 -> ^17.5.0 (core declares no zod).
- components ActionButtonProps / ActionIconProps: the spec's are the AUTHORED props bags; these are the React envelope and were never on the package's published entry, so renamed ActionButtonRendererProps / ActionIconRendererProps (objectui#7265 precedent), reason pinned in a tripwire test.
- plugin-dashboard / plugin-report DatasetTotals: the spec's is the REQUEST side ({ groupings }); these are file-local RESULT groupings, renamed DatasetResultTotals, reason pinned per package.
- plugin-gantt / plugin-map / plugin-timeline / plugin-tree ObjectXProps: React props envelope vs the spec's authored bag, measured unequal, and PUBLISHED exports, so not renamed (a public-name change): ALLOW rows carrying the measured member lists.
@object-ui/types' floors rise to @objectstack/spec ^17.5.0 and zod ^4.6.1 together (Q8): its DashboardWidgetSchema now imports two 17.5.0-only checks. pnpm-lock.yaml moves only those three importer specifiers.

Claude-Session: https://claude.ai/code/session_01TdiauJaVCHuj45EzZGUxHh
Co-authored-by: Claude <noreply@anthropic.com>
…rdWidget checks; the objectui#10916 tripwire is flipped (objectui#11073)

- spec-object-refinements-7715: the DashboardWidgetSchema row names checkDashboardWidgetStageOrder and checkDashboardWidgetMetricMeasureArity as attached, with a parity pin that is objectui#9111's executable criterion (a non-funnel widget with options.stageOrder refused at options.stageOrder with the spec's own message; a funnel accepted on both).
- imported-defaults-8317: the two checks join the named REFINEMENT_EXCEPTIONS.
- report-chart-query-spec-parity: the JoinedReportBlock state pin loses its erased arm and the tripwire row flips to typed, its version row retired, as the tripwire instructed. The published-type burn-down stays on objectui#10940.
- .changeset/7715-mirrors-carry-spec-object-checks.md: a dated note (prose only, frontmatter untouched) on the two sentences 17.5.0 made false.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3569.3 KB 3607.4 KB
Main entry chunk (gzip) 149.5 KB 350 KB
Entry file index-DL-zMq85.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) 559.68KB 134.21KB
core (index.js) 9.94KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 227.08KB 62.96KB
fields (index.js) 261.19KB 66.27KB
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.35KB 9.18KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
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.58KB 4.90KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.25KB 2.17KB
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.17KB 15.06KB
plugin-charts (index.js) 84.09KB 22.93KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 138.73KB 37.05KB
plugin-designer (index.js) 215.78KB 44.42KB
plugin-detail (index.js) 234.78KB 62.36KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 172.30KB 44.19KB
plugin-gantt (index.js) 172.43KB 42.85KB
plugin-grid (index.js) 229.83KB 63.15KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.82KB 28.67KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.04KB 12.21KB
plugin-timeline (index.js) 32.26KB 9.42KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 90.43KB 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.78KB 2.09KB
sdui-parser (codegen.js) 9.45KB 3.76KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.17KB 2.73KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
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) 22.61KB 7.40KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
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) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.82KB 7.15KB
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

@os-zhuang
os-zhuang added this pull request to the merge queue Sep 30, 2026
Merged via the queue into main with commit 81f8498 Sep 30, 2026
46 of 47 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-11073-objectstack-17-5-bump branch September 30, 2026 04:00
huangyiirene pushed a commit that referenced this pull request Sep 30, 2026
…jectui#4795)

Brings in PR #11086 (objectui#11073), which moves the workspace to
@objectstack/spec 17.5.0 and zod 4.6.5. The textual merge is clean; the
CLI importer's lockfile entry still names the 17.4.0 snapshot main no
longer carries, and the next commit regenerates it.

Claude-Session: https://claude.ai/code/session_012UwY3ahMixEFkfTUxMVkYm
Co-authored-by: Claude <noreply@anthropic.com>
huangyiirene pushed a commit that referenced this pull request Sep 30, 2026
…he 17.5.0 snapshot (objectui#4795)

`pnpm install` after merging origin/main: the `packages/cli` importer's
`@objectstack/spec` (`^17.1.0`) now resolves the same
`17.5.0(ai@7.0.65(zod@4.6.5))` snapshot as the rest of the workspace. The
17.4.0 snapshot it named is gone from main since PR #11086, which is what
broke `pnpm install --frozen-lockfile` in the merge group. Generated, not
hand-edited; no manifest moved.

Claude-Session: https://claude.ai/code/session_012UwY3ahMixEFkfTUxMVkYm
Co-authored-by: Claude <noreply@anthropic.com>
This was referenced Sep 30, 2026
huangyiirene pushed a commit that referenced this pull request Sep 30, 2026
…keys

Brings in the @objectstack/spec 17.5.0 resolution (objectui#11073, #11086),
whose ElementDataSourceSchema.filter takes the ViewFilterRule array, so this
branch's pins can be measured on the tree the merge queue builds.
No conflicts; six files auto-merged.

Refs objectui#11070

Claude-Session: https://claude.ai/code/session_012UwY3ahMixEFkfTUxMVkYm
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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

deps: bump objectui's @objectstack/* to 17.5.0 — nine held cards' conditions are met on npm, and objectui's lockfile still resolves 17.4.0

3 participants