Skip to content

fix(plugin-kanban,plugin-timeline,plugin-detail): refuse a non-positive row cap before it reaches $top (objectui#9925) - #10001

Merged
os-tesla merged 3 commits into
mainfrom
claude/issue-9925-three-more-limit-read-points
Sep 19, 2026
Merged

os-tesla merged 3 commits into
mainfrom
claude/issue-9925-three-more-limit-read-points

Conversation

@os-tesla

@os-tesla os-tesla commented Sep 19, 2026

Copy link
Copy Markdown
Collaborator

Part of #9925

⚠️ Part of, not a closing keyword — deliberately. The card names three blocks. Two of them
are repaired here. The third, record:line_items, does not live where the card says it does,
lies outside this PR's declared file face, and sits inside a package another seat has claimed.
It is reported below and left untouched. A third block in the face, which the card did not name,
is repaired here. The dispatch asked for a closing keyword; the standard clause says a merge
that leaves half the card undone must not close it, and this body follows the clause. Named in the
seat report as a conflict rather than resolved silently.

1. The derived site list — the population, by CONCEPT, and the reading that produced it

The card's list of three was not taken on trust. Derived on this branch's base 1ed2e69fa by
sweeping the concept (a row cap spent into $top through a nullish fallback), not one identifier:

git grep -nE '\?\?\s*[A-Za-z_]*(LIMIT|Limit|limit|SIZE|Size|PAGE)' -- 'packages/*/src/**'
git grep -n '\$top' -- 'packages/plugin-*/src/**'
git grep -nE 'schema\.limit|limit \?\?' -- 'packages/plugin-detail/src/**'
read point spelling on the base reachable? this PR
object-kanbanpackages/plugin-kanban/src/ObjectKanban.tsx $top: schema.limit ?? DEFAULT_KANBAN_LIMIT yes, both entrances repaired
object-timelinepackages/plugin-timeline/src/ObjectTimeline.tsx $top: schema.limit ?? DEFAULT_TIMELINE_LIMIT yes, both entrances repaired
record:reference_railpackages/plugin-detail/src/renderers/record-reference-rail.tsx $top: entry.limit ?? 3 yes — ReferenceRailEntrySchema.limit is authorable and declared positive repaired (⭐ NOT on the card)
record:related_listpackages/plugin-detail/src/renderers/record-related-list.tsx typeof schema.limit === 'number' && schema.limit > 0 already refuses rejected on the record
record:historypackages/plugin-detail/src/renderers/record-history.tsx Number(... ?? 50) || 50, then $top: Math.max(1, limit) already refuses (floors) rejected on the record
record:activitypackages/plugin-detail/src/renderers/record-activity.tsx $top: Math.max(1, pageSize) + 1 already refuses (floors) rejected on the record
record:line_itemspackages/plugin-form/src/LineItemsPanel.tsx $top: schema.limit ?? DEFAULT_LINE_ITEMS_LIMIT yes, same shape out of face — stop-and-report

⭐ The card's third site is real, and it is not where anyone would look

The claim's grep of packages/plugin-detail/src was correct to come back empty. record:line_items
is registered and implemented in packages/plugin-form, not plugin-detail:
ComponentRegistry.register('line_items', LineItemsPanelRenderer, ...) in
packages/plugin-form/src/index.tsx, and the renderer's own header says
"LineItemsPanel — the record:line_items component". Its cap read is
$top: schema.limit ?? DEFAULT_LINE_ITEMS_LIMIT, identical in shape to the two the card measured.
So the site is unread, not absent — and it is outside this PR's declared file face
(packages/plugin-kanban/src/**, packages/plugin-timeline/src/**, packages/plugin-detail/src/**,
.changeset/*). packages/plugin-form is also the face objectui#9884 is claimed against, so
touching it here would collide with in-flight work. ⛔ Not repaired here; reported.

⭐ The face did contain a site the card did not name

record:reference_rail spends each entry's preview-row cap through the same ?? DEFAULT shape, and
its limit is authorable metadata the spec declares positive
(ReferenceRailEntrySchema.limit = z.number().int().positive().optional(), described there as "the
$top of the one query this entry issues"). The card asked for the population rather than the first
site; this is what the population turned out to be inside the fence.

2. What objectui#9853 and objectui#9897 ACTUALLY landed — ⛔ there is no shared helper

Read from the commits themselves before anything was copied.

card commit files it touched
objectui#9853 31d34cb44 packages/plugin-grid/src/ObjectGrid.tsx + one pin + one changeset
objectui#9897 f5e2fcb4a packages/plugin-list/src/ListView.tsx + one pin + one changeset

Neither landed an importable helper. Each landed a file-local trio inside its own
component file: a predicate (isUsablePageSize), a resolver (resolvePageSize) and a conditional
diagnostic (describeNonPositivePageSize / describeRefusedPageSize), plus one useEffect keyed
on the declaration that emits the diagnostic through console.warn. ListView re-declared the
shape rather than importing ObjectGrid's. savedViewLimit in @object-ui/core's
element-data-source.ts is the lowering layer — objectui#9928's subject — and is not a
read-point resolver.

This PR therefore repeats the same file-local trio once per package, which is the family's actual
precedent and the only option inside the declared face (a shared home would be @object-ui/core,
which is out of face here). The duplication is called out under "Acceptance notes".

3. drop / clamp / refuse — the answer taken, and why, from the code

Three different answers exist in this tree, and the card's own sibling warns they are not
interchangeable. Established from the code rather than from the card:

  • clamp is what record:history and record:activity already do (Math.max(1, limit)). It
    keeps the query alive but silently turns an authored 0 into a window of 1 — a number the author
    never wrote, with nothing said.
  • refuse loudly is what objectui#9853 and objectui#9897 chose for a renderer, in their own
    words: throwing "would take out the whole subtree for a declaration the flat path already
    tolerated, which is a worse outcome than the defect."
  • drop silently is the pre-existing defect's quieter half.

All three sites here are renderers inside a page subtree, and one of them (record:reference_rail)
is documented as degrading silently by design — a failed entry renders an em dash rather than
blanking the rail. So a throw is worse here than at either sibling, and a silent substitution is
least observable here. ⇒ fail-soft refusal plus one loud, conditional, deduped diagnostic,
the sibling answer, adopted because this code says it carries, not because the card says so.

⛔ Not a spec change from this side — the declaration half is objectstack#19046.

4. Both entrances, which is why the repair is at the read point

Each block reads one key. Two authoring shapes fill it:

  1. a dataSource binding lowers a named view's pagination.pageSize into schema.limit
    (OBJECT_KANBAN_DATA_SOURCE = { filter: true, limit: 'limit' },
    OBJECT_TIMELINE_DATA_SOURCE = { filter: true, sort: true, limit: 'limit' });
  2. a block with no binding at all carries the authored limit straight through.

A repair at the lowering layer closes only the first. Every refusal assertion in the two block pins
is therefore run twice, once per entrance, and the two are asserted in separate describe
blocks so a failure says which entrance broke.

5. The pins, and the ablation — red leg and green leg

Three pin files, 56 assertions. Each refusal row is the relation (a refused value does not reach
$top; the site's own default does), never a literal, and each is paired with a control that must
NOT fire: a legitimate 7 reaches $top unchanged at every site, an absent limit stays silent,
and the rest of the binding still arrives when its page size is refused.

RED leg — ablated from the committed fix, through ablation-replace.mjs

Each leg asserts on disk that the anchor hit exactly once, that the blob hash moved, and after the
run that the blob equals HEAD's and git diff HEAD is empty. ⛔ No exit code was read as evidence
of restore.

ablation what was mutated result
kanban resolver isUsableRowLimit(authored) ? authored : fallback restored to authored ?? fallback 9 failed / 10 passed (19) — every refusal row on both entrances; all controls held
timeline resolver same 9 failed / 11 passed (20)
rail resolver same 7 failed / 9 passed (16, before the dedupe row landed)
kanban diagnostic describeRefusedRowLimit forced to always return null 4 failed / 15 passed — the three naming rows plus the fires-once row
kanban diagnostic key effect deps [schema.limit, schema.objectName] widened to [schema] 1 failed / 18 passed — only the fires-once row
rail dedupe memory the per-(object, value) Set check removed 1 failed / 16 passed — only the neighbour-arrives row

Blob evidence, one example: 124648549d91 -> 315011d04520 on mutation, -> 124648549d91 on
restore, equal to HEAD, git diff HEAD empty.

⚠️ No build is in this loop, and that is a property of the harness rather than an omission: the
root vitest config aliases every @object-ui/* specifier to that package's src, and each pin
imports its subject by a relative path inside its own package. Nothing resolves through dist,
so a stale build cannot make an ablation falsely green here.

GREEN leg

At cebc39270, tree clean: 3 files passed, 56 tests passed.

6. Verification

what command result
affected packages, whole suites pnpm exec vitest run packages/plugin-kanban/ packages/plugin-timeline/ packages/plugin-detail/ 276 files / 2604 tests passed
typecheck, incl. test programs per-package type-check over the three (tsc --noEmit && tsc -p tsconfig.test.json) Done, exit 0
dependency closure build pnpm --workspace-concurrency=2 --filter 'PKG^...' run build over the three exit 0
changeset declaration node scripts/check-changeset-presence.mjs "3 source file(s) of 3 released package(s) changed, and this change declares 1 changeset(s)"
control bytes pnpm check:control-bytes OK, 8065 tracked text files scanned
line citations pnpm check:new-line-citations 0 new cross-file line-address citations
governed surface node scripts/check-governed-queue-guard.mjs --test ... NOT GOVERNED — 7 paths, none matched

Lint is a declared narrowing, not the repo-wide run. eslint over the six changed files:
0 errors, and on the one file re-measured with inline directives honoured, 10 warnings — all
pre-existing rule classes (no-explicit-any, one react-hooks/exhaustive-deps on a fetch effect
this PR did not touch). The three pieces of evidence:

  1. the governed population, read from ESLint's own ignore configuration via
    ESLint#isPathIgnored over git ls-files, not guessed: 5156 files of 8150 tracked;
  2. the count actually linted, from --format json: 6;
  3. invariance for the other 5150: this repository configures no type-aware linting — no
    parserOptions.project and no projectService anywhere in eslint.config.js — so no edit in
    this diff can move the verdict on a file the diff does not contain.

⛔ The repo-wide pnpm lint (turbo run lint) is CI's run and was not taken here.

The objectui#7322 pin, re-pointed at unchanged strength (commit 28a24f50e)

packages/types/src/__tests__/object-kanban-group-by-limit-7322.test.ts holds a source-text
pin
that reads ObjectKanban.tsx off disk and toContains the exact $top expression. This
PR's repair retires that spelling, so the pin went red on Test (shard 4/4) — correctly: it was
doing the job it was built for. The pin's own docblock says what it holds ("Line numbers drift
and live in the docblocks' prose only; the READ is the fact"
), and the fact — schema.limit
lowered into the query's top-level $top — survives this change intact. So READ_TEXT.limit is
re-pointed, ⛔ not deleted, skipped, loosened or weakened: same file, same reader, same key,
one toContain, DECLARED still toHaveLength(2), and a string the retired ?? form cannot
satisfy. Two ablation legs were run and both go red (the retired spelling restored; a deliberate
typo in the new constant), so the re-pointed pin is not vacuous.

The two declaration docblocks the failing assertion names — "as the exact text the docblocks
cite", i.e. packages/types/src/objectql.ts and packages/types/src/zod/objectql.zod.ts — carry
the same re-spelling, because leaving them behind would make that sentence false with nothing
checking the disagreement.

⭐ Their stale cross-file address ObjectKanban.tsx:264 was removed, not re-pointed.
AGENTS.md commandment #11 bans a cross-file path:line outright and directs exactly this
opportunistic repair ("when you touch a file anyway, fix the cross-file line addresses inside
it"); re-pointing would have minted a fresh instance of the banned form, and
check:new-line-citations reads 0 citations added by this branch. The claiming seat's
dispatch had asked for a re-point and is withdrawn on this point — see the ratification on
objectui#9925.

Seat content-verification on 28a24f50e vs origin/main, taken 2026-09-19T08:38Z: new expression in the
reader 0 → 1; retired expression 1 → 0; the three groupBy READ_TEXT controls and
DEFAULT_LIMIT_TEXT unmoved at 1 / 1 / 2 / 1 on both refs; cross-file :264 addresses
2 → 0.

Acceptance notes

⛔ Nothing below is filed as an issue by this PR; it is recorded for the seat to route.

  • record:line_items — a real, reachable instance of this exact defect, left untouched.
    packages/plugin-form/src/LineItemsPanel.tsx spells $top: schema.limit ?? DEFAULT_LINE_ITEMS_LIMIT
    with DEFAULT_LINE_ITEMS_LIMIT = 500. Out of this PR's face, and plugin-form is objectui#9884's
    claimed face. This is the half objectui#9925 keeps, which is why this body says Part of.
    Dedupe words: record-line-items limit zero $top · LineItemsPanel nullish limit ·
    plugin-form row cap non-positive.
  • Three file-local copies of one four-function shape now exist across five packages
    (ObjectGrid, ListView, and the three here). Noted, not filed: a shared home would be
    @object-ui/core, which is out of face for this card and is objectui#9928's package; the right
    moment to extract it is when that card lands and the family stops moving. Whoever picks that up
    reads all five call sites.
  • No default literal was changed. Each site keeps the window it already documented
    (100 / 100 / 3). Whether those belong next to ObjectGrid's three and ListView's one is the
    same product question those two cards handed back, and it is not answered here.
  • ⛔ CORRECTED, and now filed: objectui#10005. This note previously read "record:history and
    record:activity answer this class by clamping, not refusing … an authored 0 there still
    becomes a window of 1 in silence." Both halves are wrong, measured on origin/main at 2026-09-19T08:17Z:
    record:activity does not clamp at all — normalizeLimit
    (packages/plugin-detail/src/renderers/recordActivityFeed.ts:565-:567) already refuses every
    non-positive and non-finite value and falls back to DEFAULT_ACTIVITY_LIMIT = 20, which is this
    PR's own shape minus the warning, and it is pinned at
    renderers/__tests__/recordActivityFeed.test.ts:431-:436. And an authored 0 does not become
    1 in either renderer: record:history's Number(…) || 50
    (renderers/record-history.tsx:76) catches 0 as falsy and yields 50.
    The defect is real but narrower and in record:history alone: a negative is truthy, survives
    the ||, and Math.max(1, limit) at :85 repairs it into $top: 1; a non-integer survives
    both and reaches the adapter as a fractional $top (2.5$top: 2.5). A usable cap (10)
    passes through unchanged on both, which is the control that makes those readings readings.
    Filed as objectui#10005 rather than left here, because "which answer does the family keep" is a
    decision and this note's stated carrier — "the next PR in this family that touches
    plugin-detail" — names no actual PR or person.
  • Three internal docblocks elsewhere still cite the spelling this PR retires, and no PR carries
    them.
    After this PR, $top: schema.limit ?? DEFAULT_KANBAN_LIMIT exists nowhere in
    packages/plugin-kanban/src/ObjectKanban.tsx, but it is still quoted as the renderer's read at
    packages/plugin-kanban/src/index.tsx:426 and :570 and at
    packages/app-shell/src/views/metadata-admin/previews/block-config.ts:237 (readings taken on
    origin/main at 2026-09-19T08:17Z). They are prose, not pins, so nothing turns red. They are fenced
    out of this PR deliberately: block-config.ts:232 names its own source-text pin
    (__tests__/block-config.test.ts), so editing that comment carries a redness risk this PR has
    no reason to take, and none of the three is one of the three filing classes. The two declaration
    docblocks the objectui#7322 pin actually names — packages/types/src/objectql.ts:3717 and
    packages/types/src/zod/objectql.zod.ts:2096 — ARE in this PR, because the pin's assertion
    message is "as the exact text the docblocks cite" and leaving them behind would make that
    sentence false with nothing checking it. Carrier for the remaining three: none named.
    .changeset/7322-object-kanban-group-by-limit.md:15 and
    .changeset/7772-page-block-kanban-group-by-control.md:28 quote it too and are ⛔ out of reach —
    a changeset records what its own change did at the time and is not retroactively rewritten.

🤖 Generated with Claude Code

https://claude.ai/code/session_018HrVaotisyhgmot9o2MLRq


Generated by Claude Code


Generated by Claude Code

…ve row cap before it reaches `$top`

Three read points spelled their row cap `?? DEFAULT`. `??` rejects only `null`
and `undefined`, so a value `@objectstack/spec` declares refused (every one of
these members is `z.number().int().positive()`) was not nullish and survived as
a real fetch window: `$top: 0` left for the adapter, the block asked the server
for nothing, and the empty board / rail / card named no cause.

All three now go through one resolver per site, mirroring the shape objectui#9853
landed on `ObjectGrid` and objectui#9897 repeated on `ListView` — one resolver at
every entry is what keeps the answer single. Fail-soft: the value is dropped, the
site's own default is used, and one conditional, deduped `console.warn` names the
block, the object and the value.

The repair is at the READ POINT because each block has two entrances into one
key: a `dataSource` binding lowers a named view's `pagination.pageSize` into
`schema.limit`, and a block with no binding at all carries the authored `limit`
straight through. A repair at the lowering layer closes only the first.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HrVaotisyhgmot9o2MLRq
…a neighbour arriving

The dedupe claim is not the effect's dependency key: adding a second entry
changes the declaration, the effect re-runs and walks the list again, and
without a per-(object, value) memory the untouched entry is named twice. The
row ablates against removing that memory.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HrVaotisyhgmot9o2MLRq
@github-actions

github-actions Bot commented Sep 19, 2026

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 2 address(es) in this pull request's own prose name a tree it replaced

Each was read from a tree this change itself moves, so a reader who follows it lands somewhere else. ⛔ Nothing here blocks and nothing here says the sentence is false — the question asked is arithmetic: does this diff move the line that number points at?

  • in this body, packages/types/src/zod/objectql.zod.ts:2096 — this change rewrites packages/types/src/zod/objectql.zod.ts:2096

    packages/types/src/zod/objectql.zod.ts:2096 — ARE in this PR, because the pin's assertion

  • in this body, packages/types/src/objectql.ts:3717 — this change rewrites packages/types/src/objectql.ts:3717

    docblocks the objectui#7322 pin actually names — packages/types/src/objectql.ts:3717 and

The repair is not to correct the number. Changing :246 to :274 is true today and born false again on the next insertion — objectui#9509 states that before anything else. Bind the number to the tree it was read from (`:246` at `b8a006883d`, `:274` at this head), which cannot re-stale because each number names its own tree; or state a rule instead of a coordinate, the way objectui#9495 replaced a file count with "every file in git diff --name-only against the merge base".

⚠️ 33 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/5903-objectgantt-declared-keys.md

  • names packages/types/src/objectql.tspackages/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.tspackages/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.

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

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

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

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

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

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

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

  • names zod/objectql.zod.tspackages/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.tspackages/types/src/zod/objectql.zod.ts — edited by this change

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

.changeset/7322-object-kanban-component-props.md

  • names ObjectKanban.tsxpackages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    Inside ObjectKanban.tsx, three schema-key reads drop their as any: titleField (two sites, now honest because the object-kanban arm declares it) and cardFields / cardTitle (already declared; the casts were redundant). (schema as any).navigation staysnavigation is declared on neither face, so removing the cast would change nothing but the spelling of an index-signature read.

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

  • names objectql.tspackages/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.tspackages/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/plugin-kanban/src/ObjectKanban.tsxpackages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    What was measured, on this branch's base (53ded82b). packages/plugin-kanban/src/ObjectKanban.tsx reads schema.groupBy at thirteen sites (lane materialisation at :601 / :625 / :640, card moves at :747 / :865, and their effect deps) and schema.limit at two (:264, $top: schema.limit ?? DEFAULT_KANBAN_LIMIT, and the effect deps at :291). groupField has ZERO read sites anywhere under packages/plugin-kanban/ — against a control of those thirteen groupBy reads in the same query, so the zero is a reading, not a blind grep. Yet the declaration REQUIRED groupField and declared neither groupBy nor limit. Measured from source: the documented, tested, working shape — { type: 'object-kanban', objectName, groupBy, limit } — failed ObjectKanbanSchema.safeParse and safeValidateSchema on the missing groupField, and only ever reached the renderer through BaseSchema's [key: string]: any and .passthrough(), admitted unexamined. An author who followed the declaration wrote groupField and got a board that grouped nothing, with no diagnostic on either face.

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

  • names zod/objectql.zod.tspackages/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.tspackages/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.tspackages/types/src/zod/objectql.zod.ts — edited by this change

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

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

  • names packages/types/src/objectql.tspackages/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 (objectui#6939, 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/7712-kanban-calendar-filter-input.md

  • names ObjectKanban.tsxpackages/plugin-kanban/src/ObjectKanban.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/7772-page-block-kanban-group-by-control.md

  • names ObjectKanban.tsxpackages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    What was measured, on this branch's base (0c8dbc49). BLOCK_CONFIG['object-kanban'] offered exactly four controls — objectName / groupField / titleField / cardFields. ObjectKanbanSchema.groupBy is REQUIRED on both published faces (objectql.ts:2765 groupBy: string, no ?; objectql.zod.ts:1001 groupBy: z.string(), no .optional()) and had no control at all, while groupField — the only control able to set grouping — has been a retirementTombstone() on the Zod face and ?: never on the TS face since objectui#7322. ObjectKanban.tsx reads schema.groupBy at thirteen sites and groupField at zero (control: those same thirteen hits in the one query, so the zero is a reading).

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

  • names ObjectKanban.tsxpackages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    The object-kanban renderer never read it: groupField has ZERO hits anywhere under packages/plugin-kanban/, against a control of thirteen schema.groupBy read sites in ObjectKanban.tsx from the same query — so the zero is a reading, not a blind grep. The write was inert; the board grouped by groupBy and groupField rode along unread.

.changeset/7780-object-kanban-record-source.md

  • names packages/plugin-kanban/src/ObjectKanban.tsxpackages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    packages/plugin-kanban/src/ObjectKanban.tsx resolves a board's rows in four steps: the pre-fetched data PROP a parent passes (hasExternalData), then bind through useDataScope(schema.bind), then the inline ROW ARRAY on schema.data, and only then a fetch keyed by schema.objectNamerawData = (hasExternalData ? externalData : undefined) || boundData || schema.data || fetchedData, with the fetch itself gated on schema.objectName && !boundData && !schema.data. Every objectName read is guarded. Both published faces nevertheless REQUIRED objectName, so a bind-only or data-only board — one that renders correctly today — was refused by the shipped validator and could not be annotated with its own type.

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

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

    The four plain objectql.ts node faces declare the nine handler keys their registered renderers read (objectui#7804, 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.tspackages/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.

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

  • names objectql.zod.tspackages/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.tspackages/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/8174-kanban-calendar-filter-sort.md

  • names ObjectKanban.tsxpackages/plugin-kanban/src/ObjectKanban.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/8478-describe-line-addresses.md

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

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

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

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

  • names packages/types/src/objectql.tspackages/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.tspackages/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.tspackages/types/src/zod/objectql.zod.ts — edited by this change

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

.changeset/8827-kanban-empty-state-settled.md

  • names ObjectKanban.tsxpackages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    A genuinely empty board still paints DataEmptyState. The reverse regression — "gating on a truthy definition would leave those boards empty forever", named in ObjectKanban.tsx itself — is what the settle contract exists to prevent, and every exit settles: the query succeeding, the query throwing, no readable source, the non-fetch record sources (external, bound and inline data are settled from the first frame), and the schema-only kanban-ui entry, which has no ObjectKanban and therefore no provider and so takes the context's settled default. Lanes, headers, counts and drop targets keep rendering while the rows are in flight; only the claim is withheld.

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

  • names packages/types/src/objectql.tspackages/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.tspackages/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.tspackages/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.tspackages/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.tspackages/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.tspackages/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.

  • names ObjectKanban.tsxpackages/plugin-kanban/src/ObjectKanban.tsx — edited by this change

    What a lane-less board does, measured rather than assumed. Every schema.groupBy read in ObjectKanban.tsx is a guarded early-return, so the board degrades instead of breaking: with no lane key and no columns it renders an empty board; with bare-string columns it draws those lanes, titled by the raw strings; card moves are inert (persistCardMove and the move callback both open if (!groupBy) return). ⚠️ Every lane-less board holds zero cardsbucketCardsIntoColumns returns before distributing records when there is no lane key — so omitting groupBy is not a way to configure a board, it is a board that groups by nothing.

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

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

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

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

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

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

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

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

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

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

  • names zod/objectql.zod.tspackages/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.tspackages/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.tspackages/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/reference-rail-entry-spec-derived.md

  • names record-reference-rail.tsxpackages/plugin-detail/src/renderers/record-reference-rail.tsx — edited by this change

    ReferenceRailEntry is owned by @objectstack/spec as of 17.1.0. The hand-written interface in record-reference-rail.tsx is replaced by a re-export of the spec's ReferenceRailEntry (derived from ReferenceRailEntrySchema, $strict over { objectName, relationshipField, title?, limit?, displayField? }), and buildDefaultPageSchema no longer emits icon on the reference-rail entries it synthesizes.

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

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3054.7 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-BC-TaDW7.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.69KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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) 26.08KB 7.56KB
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) 545.92KB 130.72KB
core (index.js) 8.94KB 3.59KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 216.90KB 60.15KB
fields (index.js) 249.62KB 63.02KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.22KB 2.26KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.83KB 10.95KB
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) 2.53KB 0.85KB
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.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
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) 14.81KB 3.63KB
plugin-calendar (index.js) 49.92KB 14.22KB
plugin-charts (index.js) 71.73KB 20.08KB
plugin-chatbot (index.js) 195.35KB 46.52KB
plugin-dashboard (index.js) 132.96KB 35.17KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 255.18KB 66.49KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 137.49KB 34.64KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 213.44KB 58.21KB
plugin-kanban (index.js) 48.71KB 15.17KB
plugin-list (index.js) 113.42KB 27.95KB
plugin-map (index.js) 21.48KB 6.99KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.41KB 11.93KB
plugin-timeline (index.js) 30.68KB 8.95KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 85.05KB 21.01KB
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.66KB 3.50KB
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) 109.04KB 36.08KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.38KB 1.98KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.74KB 2.54KB
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.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 15.71KB 5.30KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
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.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
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) 14.04KB 5.36KB
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

…ing this PR ships

objectui#9925 moved this board's row cap from `$top: schema.limit ??
DEFAULT_KANBAN_LIMIT` to `$top: resolveRowLimit(schema.limit,
DEFAULT_KANBAN_LIMIT)`, and the source-text pin in
`object-kanban-group-by-limit-7322.test.ts` still held the retired spelling.
That is the one red check on this branch, and the pin is doing exactly the job
it was built to do.

The pin states its own contract: line numbers live in the docblocks' prose and
the READ is the fact. The read survived — same file, same named `query`
object, same `schema.limit`, still lowered into the query's top-level `$top` —
and only the spelling moved, because `??` rejects `null` and `undefined` and
nothing else, so an authored `limit: 0` rode through as a real fetch window on
a key `@objectstack/spec` declares a positive integer. So the constant moves to
the new spelling at unchanged strength: one `toContain`, same reader, same key,
and a string the retired `??` form cannot satisfy.

The two declaration docblocks the failing assertion names — "as the exact text
the docblocks cite" — move with it. Leaving them behind would make the
assertion's own stated semantic false with nothing checking the disagreement.

Both of those also carried a cross-file `ObjectKanban.tsx:264` address, already
measured as drifted twice. Per commandment #11 a cross-file `path:line` is the
banned form, so these are REMOVED and the citation left to the quoted
expression beside them — the same repair objectui#8478 recorded for this exact
address ("rewritten to cite the same fact by identifier/behavior instead of by
file:line, which survives a line renumbering that a bare address would not").
The differential gate reads zero new citations before and after.

The renderer's own cross-reference is restated true: what keeping the read
inline preserves is the READ the pin reads out of the named `query` object,
not the retired spelling.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018HrVaotisyhgmot9o2MLRq
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3054.7 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-BC-TaDW7.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.69KB 6.21KB
app-shell (runtime-config.js) 20.68KB 7.36KB
app-shell (types.js) 0.01KB 0.04KB
app-shell (urlParams.js) 10.06KB 3.86KB
auth (ActiveOrganizationStorage.js) 25.05KB 9.16KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.18KB 10.59KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.65KB 2.22KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.41KB 1.23KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.21KB 10.80KB
auth (createAuthenticatedFetch.js) 8.46KB 3.43KB
auth (index.js) 3.19KB 1.44KB
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) 26.08KB 7.56KB
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) 545.92KB 130.72KB
core (index.js) 8.94KB 3.59KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 216.90KB 60.15KB
fields (index.js) 249.62KB 63.02KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 1.22KB 0.64KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.22KB 2.26KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 32.15KB 10.49KB
i18n (useDisplayLocale.js) 2.85KB 1.45KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 38.83KB 10.95KB
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) 2.53KB 0.85KB
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.52KB 4.88KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.24KB 2.16KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.39KB 3.10KB
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) 14.81KB 3.63KB
plugin-calendar (index.js) 49.92KB 14.22KB
plugin-charts (index.js) 71.73KB 20.08KB
plugin-chatbot (index.js) 195.35KB 46.52KB
plugin-dashboard (index.js) 132.96KB 35.17KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 255.18KB 66.49KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 137.49KB 34.64KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 213.44KB 58.21KB
plugin-kanban (index.js) 48.71KB 15.17KB
plugin-list (index.js) 113.42KB 27.95KB
plugin-map (index.js) 21.48KB 6.99KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 43.41KB 11.93KB
plugin-timeline (index.js) 30.68KB 8.95KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 85.05KB 21.01KB
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.66KB 3.50KB
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) 109.04KB 36.08KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.63KB 2.18KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.38KB 1.98KB
sdui-parser (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.74KB 2.54KB
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.66KB 1.82KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 15.71KB 5.30KB
types (ai.js) 4.11KB 2.06KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 2.87KB 1.00KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 2.93KB 1.49KB
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.25KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 4.73KB 2.28KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 0.20KB 0.18KB
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) 14.04KB 5.36KB
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

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants