Skip to content

docs(plugin-kanban): stop naming which face declares which kanban key (objectui#9726) - #9740

Merged
os-sales merged 3 commits into
mainfrom
claude/issue-9726-objectkanban-docblock-tense
Sep 17, 2026
Merged

os-sales merged 3 commits into
mainfrom
claude/issue-9726-objectkanban-docblock-tense

Conversation

@os-sales

@os-sales os-sales commented Sep 17, 2026

Copy link
Copy Markdown
Collaborator

Fixes #9726

Clause-②: no

Session for this work: https://claude.ai/code/session_01UanLVj6xvbS6puBCewLr8L (written as prose, because an edited body loses the link form of the footer).

Repair shape — decided in one line before either site was touched

DELETE the per-key declaration inventory rather than re-date it. A source comment publishes nothing and freezes no reading, so the dated-reading construction objectui#9713 needs for a .changeset body protects nothing here; the inventory restates what tsc already answers off ObjectKanbanSchema (AGENTS.md #9 — leave the count to the instrument), and its measured half-life in this tree is hours (timeline below), so a re-dated restatement only schedules the next rot.

⛔ What is NOT deleted: each site keeps a dated, past-tense retirement notice naming what it used to claim and when each half went false. That is how the two claims that are still true survive instead of being swept out with the three that are not.

⚠️ The pending changeset is the opposite case and takes the opposite shape: it publishes verbatim, it already dates itself, so its correction is a dated note in its own register and ⛔ never a silent overwrite.

Per-key verdict, re-derived on this branch base 580e5dd94

⚠️ Instrument, stated because a lit control certifies the instrument and not the question:

  • DOMAIN — the brace-balanced block of ObjectKanbanSchema in each published face (packages/types/src/objectql.ts and its zod/objectql.zod.ts twin), extracted per symbol. ⛔ Not a grep over the file: the indentation is shared by every schema there, so a file-wide grep answers about the FILE.
  • PREDICATE — a property line at the block's member indentation. Docblock lines are skipped by construction, so a key-shaped token inside prose or a string cannot satisfy it. A key is (interface, name), and this reads exactly that pair.
key objectql.ts objectql.zod.ts the docblocks said verdict
columns :3672 declared :2087 declared rides the index signature false
filter :3750 declared :2103 declared 「as filter always has」 false
cardTitle :3786 declared :2129 declared reached through the index signature false
swimlaneField ABSENT ABSENT rides the index signature still true
grouping ABSENT ABSENT rides the index signature still true
  • [LIT CTRL] same instrument, same corpus: objectName (:3420 / :2071) and groupBy (:3525 / :2081) are FOUND ⇒ a declared key is visible to it.
  • [ABSENT CTRL] same call: a nonsense key zzNoSuchKeyEver reads ABSENT in both blocks ⇒ the two ABSENT rows are a verdict, not a dark instrument. Two zeros on one instrument would have been a broken instrument.
  • Second reading, second instrument: BaseSchema still carries [key: string]: any (packages/types/src/base.ts:523), so the two surviving rows have a live mechanism behind them.
  • KanbanSchema is gone from packages/types/src/: a grep for its exported declaration returns 0, exit 1, with a [LIT CTRL] on the same instrument and corpus — the same grep for ObjectKanbanSchema returns 2 hits, exit 0.

Timeline — ⭐ the claims are three different defects, not one

The repository was deepened (git fetch --deepen=800; the checkout is shallow, and a log -S on a shallow tree answers 0 without meaning it). Every ancestry leg below is git merge-base --is-ancestor with a control leg at least as deep on the same target, both exit codes read.

claim written went false class
site 1 「both declared arms」 4fa0eb9c4 2026-09-10T00:34Z (objectui#8308) adf581278 2026-09-10T09:59Z (objectui#8802) ROTTED after 9h25m
site 1 「cardTitle … through the index signature」 4fa0eb9c4 2026-09-10T00:34Z 78a9c6744 2026-09-17T18:36Z (objectui#9606) ROTTED after 7d18h
site 2 「as filter always has」 adf581278 2026-09-10T09:59Z (objectui#8802) ee4d19f6c 2026-09-09T07:51Z (objectui#8174) — 26h08m EARLIER BORN FALSE
site 3 「exactly as filter does」 (the navigation read site) adf581278 2026-09-10T09:59Z — the same commit same declaration, same 26h08m BORN FALSE
site 2 columns rides the index signature adf581278 2026-09-10T09:59Z 8693b8569 2026-09-10T16:32Z (objectui#8913) ROTTED after 6h33m
site 2 cardTitle rides the index signature adf581278 2026-09-10T09:59Z 78a9c6744 2026-09-17T18:36Z ROTTED after 7d09h
site 2 swimlaneField, grouping adf581278 2026-09-10T09:59Z still true
the pending entry's 「thirteen」 6ca6e12a7 2026-09-06 nothing — it was one short on its own measurement date BORN FALSE

⇒ this is what decided the shape. The shortest-lived rotted claim was false 6 hours 33 minutes after it was written, by a pull request that was in flight while it was being authored. A re-dated inventory would be a promise to lose the same race again.

Site 3 — the third copy, repaired in place

The navigation read site in the same file said the key rides BaseSchema's index signature 「exactly as filter does」. That is the site-2 sentence a third time, written in the same commit, false for the same reason. It is the card's own defect class in the card's own declared file, the repair shape was already fixed, no other branch holds this file, and it adds no verification surface — so it is repaired here rather than filed, with the comparison retired and the reason dated. Everything else in that comment was re-measured and stands: navigation is absent from ObjectKanbanSchema's member list and from BaseSchema's, so the index-signature claim about navigation itself is true.

The pending copy — ⚠️ the count was still downstream

.changeset/7322-object-kanban-component-props.md:39-40 still carried 「reads thirteen keys off schema」 and 「the two TOGETHER cover twelve」, undated, in a body that otherwise dates every reading. That entry publishes verbatim into the CHANGELOG at the next release, so this is the card's own mechanism one step downstream, with a closing window.

A second instrument, built so it does not have the defect the first one had. The earlier census scoped by identifier NAME and so conflated the component's schema prop with resolveKanbanTitleField's same-named parameter. This one scopes by binding:

  • DOMAINObjectKanban.tsx with comment spans AND string/template literals blanked by the repo's own scanner (scripts/js-comment-mask.mjs, scanSource), so a key-shaped token in prose or in a string cannot be read as a property access.
  • PREDICATE — a distinct property name reached off the identifier schema where that identifier is the component's prop; the one shadowing binding in the file is excluded by region, and the two keys the resolver reads are re-admitted only because the component measurably hands it its own schema (2 call sites).
reading today (09121e4ee) at the entry's own date (6ca6e12a7)
direct reads off the prop 12 14
resolveKanbanTitleField(schema) call sites 2 0 (the resolver did not exist yet)
union — what the component reaches off its own schema 14 14
  • [LIT CTRL] objectName and groupBy are in the set ⇒ real reads are visible.
  • [ABSENT CTRL] a minted name is not in the set; and highlightFields, a property read in this same file off a DIFFERENT receiver, is not in the set although its token is present in the masked source ⇒ the instrument discriminates by receiver, not by name.
  • [SHADOW CTRL] the same census without the region exclusion still totals 14, but cardTitle / titleField enter it from the shadowed binding ⇒ the exclusion is doing work, and the earlier census got the right total by the wrong route.

「thirteen」 was one short on its own measurement date: the entry's bullet list omits navigation, which the entry's own 「Casts this removes」 section names as a read ((schema as any).navigation then, schema.navigation now — the cast spelling is why a -S search for the dotted form dates it later). Born false, ⛔ not rotted.

Disposition — ⛔ the new number is NOT written in. The lead sentence now names WHERE the read set is derived (the bullet list that follows it, which is the set), and both cardinals are retired by a dated note in the register the entry already uses. A cardinal in a body that publishes verbatim is derived once and never again. ⛔ The bullets themselves are left exactly as measured on 2026-09-06 — adding navigation to them would silently rewrite a dated reading, which is the thing objectui#9713 rules against. ⚠️ The nearby 「it drops four declared reads」 is left alone deliberately: it is anchored to the bullet that enumerates those four, one line above it, so it is not an undated free-floating cardinal.

Two byte-level proofs

Frontmatter untouched (check-changeset-overwrite.mjs's documented case 2):

block 580e5dd94 worktree
frontmatter fence block (42 bytes) bf9e59f9… bf9e59f9…identical
whole file [LIT CTRL] 9f62b265… 2a495ab9…differs, so the hash is not stuck

The gate agrees on its own terms: declared at base: @object-ui/plugin-kanban: minor · declares now: @object-ui/plugin-kanban: minor.

Nothing executable moved in ObjectKanban.tsx: the code-only projection (comments removed by the repo's own scanner, blank lines dropped, trailing space normalised) is 639 lines, sha256 fd6b7487…, identical at 580e5dd94 and at this head, while the raw files differ [LIT CTRL] and the projection is non-vacuous [CTRL] (it contains the navigation read line itself). ⚠️ Recorded because the first projection of this proof reported a false alarm: stripComments keeps every newline, so changing the NUMBER of comment lines moves the projection's length without moving any code. The length reading was the wrong projection, not a moved byte.

Gates on head 09121e4ee — exit code captured to disk before any pipe

gate exit verdict line
pnpm --filter @object-ui/plugin-kanban type-check 0 tsc --noEmit && tsc -p tsconfig.test.json, both legs clean (dependency closure rebuilt first, so the compile-time suite judged real .d.ts output)
pnpm exec vitest run packages/plugin-kanban/ (repo-root form, per AGENTS.md) 0 Test Files 57 passed (57) · Tests 365 passed (365)
node scripts/check-changeset-overwrite.mjs 0 report-only; case 2, declaration unchanged either side
node scripts/check-changeset-presence.mjs 0 declares 1 changeset(s) — EMPTY frontmatter, the gate's own named exemption
pnpm check:changeset-claims 0 report-only: 8 pending entries describe a file this change touches. All eight describe BEHAVIOUR, and the proof above shows no executable byte moved, so none of them is falsified by this change
pnpm check:pending-changeset-literals 0 No test source names a pending changeset
pnpm check:control-bytes 0 OK (scanned 7827 tracked text file(s); skipped 85 binary), plus a direct control-byte scan of both changed files (zero hits)
pnpm check:new-line-citations 0 VERDICT new-cross-file-line-citations: 0 new citation(s)
node scripts/check-governed-queue-guard.mjs --test (all three changed paths) 0 NOT GOVERNED — 3 path(s) checked against 5 governed surface(s); none matched
pnpm exec eslint on the changed paths 0 30 pre-existing warnings in ObjectKanban.tsx, 0 errors, none on a touched line; the other 2 are File ignored because no matching configuration was supplied for the two .md paths

Both heavy runs went through the shared verify lock (OS_VERIFY_LOCK_SLOT=objectui-9726), each printing VERDICT command-exit 0; the second build waited 3m21s behind another holder. The working tree was byte-identical to 09121e4ee when they ran (git status empty). The repo-wide pnpm lint and the full suite are CI's.

Serial constraint — re-taken against the live branches before this write

.changeset/7322-object-kanban-component-props.md and packages/plugin-kanban/src/ObjectKanban.tsx appear on nobody else's list. Merge-queue pull requests objectui#9734 (plugin-detail + three other changesets) and objectui#9735 (plugin-detail, plugin-grid, types tests + its own changeset) were read file by file; cards objectui#9629 and objectui#9365 have no open pull request yet, and their local branches were read directly — objectui#9629 holds packages/types/src/objectql.ts, .changeset/8801-*, .changeset/9629-* and a types test; objectui#9365 holds packages/types/src/base.ts and a components test. Disjoint at file level. ⛔ Release pull request objectui#5400 was not touched, and neither were the other pending entries that name ObjectKanban.tsx.

Why no new test

After the repair there is no per-key claim left in any of the three sites to pin, and a census that forbade one from coming back would redden on the retirement notices that quote them. The pins this file already owes are unchanged and green: the objectui#8308 source census masks comments, so a comment edit is invisible to it (its two anchors, the KanbanTitleFieldSource declaration and the resolveKanbanTitleField definition, are untouched).

Out of scope, noted and ⛔ not filed

  • packages/types/src/objectql.ts's cardTitle docblock records that the zod-mirror-parity ratchet does not hold the optionality agreement between the two faces, naming objectui#9711 — already the live sibling card objectui#9729's surface. Carrier: objectui#9729.

Generated by Claude Code

Two docblocks in `ObjectKanban.tsx` asserted in the present tense which
published face declares which key. Measured per key against the block of
`ObjectKanbanSchema` extracted per symbol from both faces, three of the
five they name are declared today (`columns`, `filter`, `cardTitle`) and
two still ride `BaseSchema`'s index signature (`swimlaneField`,
`grouping`).

Repair shape: DELETE the per-key declaration inventory rather than
re-date it. A source comment publishes nothing and freezes no reading, so
there is nothing a dated construction protects; the inventory restates
what `tsc` already answers off `ObjectKanbanSchema`, and its measured
half-life in this tree is hours, not releases.

Each site keeps a dated, past-tense retirement notice naming what it used
to claim and when each half went false, so the two claims that are still
true are not swept away with the three that are not.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UanLVj6xvbS6puBCewLr8L
…ng nothing

`scripts/check-changeset-presence.mjs` scores any edit under a released
package's `src/` as owing a declaration, comment-only included. This is
the empty-frontmatter form the gate names as its explicit exemption: no
published behaviour moves.

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

github-actions Bot commented Sep 17, 2026

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 8 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/7322-object-kanban-group-by-limit.md

  • 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/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/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/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/8990-object-kanban-groupby-optional.md

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

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 claim that was born false (a changeset this change adds is excluded by construction), a claim spelled as a symbol or a package rather than a backticked file name, and a file named ambiguously.

Compared the checked-out tree with 07e14d62a (merge-base with origin/main): 1 file(s) changed outside .changeset/, read against 1131 pending declaration(s) that publish a body (1645 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3049.2 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-DnyzLIkC.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.93KB 130.69KB
core (index.js) 8.94KB 3.59KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 215.98KB 59.97KB
fields (index.js) 249.27KB 62.92KB
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) 4.39KB 1.66KB
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.49KB 19.99KB
plugin-chatbot (index.js) 195.34KB 46.51KB
plugin-dashboard (index.js) 131.44KB 34.65KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 253.29KB 65.88KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.71KB 34.16KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 212.64KB 57.91KB
plugin-kanban (index.js) 48.10KB 14.94KB
plugin-list (index.js) 112.73KB 27.69KB
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.07KB 8.74KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 85.04KB 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) 104.82KB 34.67KB
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 (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
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) 14.82KB 4.99KB
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

… entry, and the third copy of the filter comparison

The count this PR removed from the docblock was still pending one step
downstream, in `.changeset/7322-object-kanban-component-props.md`, which
publishes verbatim into the CHANGELOG at the next release. Re-measured by
binding -- property reads off the component's own `schema` prop, with
`resolveKanbanTitleField`'s same-named parameter excluded by region -- the
read set is 14 today and was 14 at that entry's own measurement commit
`6ca6e12a7`: its bullet list omits `navigation`, which its own "Casts this
removes" section names as a read. So "thirteen" was one short when it was
written, not rotted afterwards. It is not replaced with 14; both cardinals
are retired with a dated note in the register the entry already uses.

The entry's frontmatter is byte-identical to the merge-base (sha256 over the
fence block, with the whole-file hash as the lit control that the hash is not
stuck). Prose only.

Same commit repairs a third copy of the born-false comparison inside
`ObjectKanban.tsx`: the `navigation` read site said this key rides
`BaseSchema`'s index signature "exactly as `filter` does", written in the
same commit as the site-2 sentence and false for the same reason.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3049.2 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-DnyzLIkC.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.93KB 130.69KB
core (index.js) 8.94KB 3.59KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 215.98KB 59.97KB
fields (index.js) 249.27KB 62.92KB
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) 4.39KB 1.66KB
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.49KB 19.99KB
plugin-chatbot (index.js) 195.34KB 46.51KB
plugin-dashboard (index.js) 131.44KB 34.65KB
plugin-designer (index.js) 215.94KB 44.33KB
plugin-detail (index.js) 253.29KB 65.88KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 136.71KB 34.16KB
plugin-gantt (index.js) 167.62KB 41.26KB
plugin-grid (index.js) 212.64KB 57.91KB
plugin-kanban (index.js) 48.10KB 14.94KB
plugin-list (index.js) 112.73KB 27.69KB
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.07KB 8.74KB
plugin-tree (index.js) 10.58KB 3.72KB
plugin-view (index.js) 85.04KB 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) 104.82KB 34.67KB
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 (codegen.js) 6.58KB 2.74KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 5.66KB 2.50KB
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) 14.82KB 4.99KB
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

@os-sales
os-sales marked this pull request as ready for review September 17, 2026 23:15
@os-sales
os-sales added this pull request to the merge queue Sep 17, 2026
Merged via the queue into main with commit e89aae3 Sep 17, 2026
38 checks passed
@os-sales
os-sales deleted the claude/issue-9726-objectkanban-docblock-tense branch September 17, 2026 23:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

2 participants