Skip to content

feat(types): declare dueLike on the DetailViewField twin (objectui#9738) - #9993

Draft
os-sales wants to merge 1 commit into
mainfrom
claude/issue-9738-duelike-declared-on-twin
Draft

os-sales wants to merge 1 commit into
mainfrom
claude/issue-9738-duelike-declared-on-twin

Conversation

@os-sales

Copy link
Copy Markdown
Collaborator

Fixes #9738

Clause-②: yes

Maintainer ruling, director seat summon 24, 2026-09-18 — letter A, quoted:

dueLike is declared on the published TypeScript twin, so the validator, the type checker, the renderer and the docs say the same thing; the key's meaning — a date / datetime field rendered with due-date semantics — is written once in the declaration

Base for every reading below: edbcf1e7aa17ea85bcc61eb8c3fa657c0a3bdc59, which was origin/main when this branch was cut. Head: 0457692462.

What landed

  • packages/types/src/views.tsDetailViewField gains dueLike?: boolean. The docblock states the rendering effect: both halves of the overdue affordance (the Overdue Nd wording inside the relative face, and text-red-600 on the cell's span), their two different day thresholds, the field-NAME fallback, and that writing false does not suppress that fallback. Every sentence is checked against the tree — see the section below.
  • packages/types/src/zod/views.zod.tsuntouched, and that is a verified reading, not an assumption. DetailViewFieldSchema already declares dueLike: z.boolean().optional().describe(...); the whole defect was that the mirror declared it and the twin did not. Nothing in this branch edits that file.
  • packages/types/src/__tests__/mirror-only-published-keys-9729.test.ts — the pin moves with the measurement; it is ⛔ not "a test that was fixed". See below.
  • packages/types/src/__tests__/zod-mirror-parity.test.ts — the MirroredUndeclared row for views.zod.ts#DetailViewFieldSchema is deleted, and the ledger docstring's two figures are corrected to the values its own sizing pin derives.
  • .changeset/duelike-declared-on-detail-view-field-9738.md@object-ui/types minor.

The widening, measured

1. Member-declaration delta on DetailViewField, comments stripped, base vs head

Instrument: the TypeScript parser, so comments are stripped by construction rather than by a regex — ts.createSourceFile, find the DetailViewField interface declaration, list members.

base edbcf1e7aa  MEMBER_COUNT=13
                 MEMBERS=name,label,type,format,render,value,readonly,visible,span,
                         options,reference_to,reference_field,currency
head 0457692462  MEMBER_COUNT=14
                 MEMBERS=name,label,type,format,render,value,readonly,visible,span,
                         options,reference_to,reference_field,currency,dueLike

Lit control, same instrument, same corpus, both legs: currency is read on base and on head. So the base zero for dueLike is a measured absence, not a dead instrument. Delta: exactly one key.

2. Ablation — a document the twin REFUSED at base and ACCEPTS at head

A throwaway probe file was added to packages/types/src/__tests__/ and the package's own type-check leg run over it. It exists in neither commit; it was deleted before the first git add, and the tree is clean of it.

import type { DetailViewField } from '../views.js';
export const probe: DetailViewField = { name: 'end_date', dueLike: true };
base edbcf1e7aa  tsc -p tsconfig.test.json  -> exit 2
  src/__tests__/zz-ablation-probe-9738.test.ts(3,59): error TS2353: Object literal may
  only specify known properties, and 'dueLike' does not exist in type 'DetailViewField'.

head 0457692462  tsc -p tsconfig.test.json  -> exit 0   (probe removed; the whole leg is green)

Exact code at base: TS2353. That is the same code the card's four-axis analysis named, re-derived here rather than copied.

3. The pin moved WITH the declaration — it was not repaired

mirror-only-published-keys-9729.test.ts carried a @ts-expect-error whose own docblock said it "fails in both directions — if the key stops being refused the directive becomes unused and TypeScript reports it". Declaring the key is exactly that direction, and it fired:

head, before the pin was moved:
  src/__tests__/mirror-only-published-keys-9729.test.ts(190,1): error TS2578: Unused '@ts-expect-error' directive.
  src/__tests__/zod-mirror-parity.test.ts(3756,14): error TS2322: Type '"views.zod.ts#DetailViewFieldSchema"' is not assignable to type 'never'.
  src/__tests__/zod-mirror-parity.test.ts(3777,14): error TS2322: Type '"dueLike"' is not assignable to type 'never'.

Three reds, all of them the instruments reporting the ruling correctly. What replaced the directive keeps the pin discriminating in its new direction:

  • the assignment it guarded now stands on its own, so the twin losing the member again is TS2353 on the same leg;
  • plus an exact Expect< Equal< DetailViewField['dueLike'], boolean OR undefined > > (spelled with a real union in the source; the word is used here because this body eats short angle-bracket-shaped fragments). ⛔ Not weakened to extends: the bare assignment alone would still compile if someone gave DetailViewField an index signature while removing the member — which is precisely the shape ObjectGridSchema has one section up in the same file, where an authored key is absorbed as any. The exact equality separates DECLARED from ABSORBED, and also refuses a widening to any.

⛔ No pin was deleted to get green, and no exact assertion was relaxed.

4. The ledger row, and why the neighbouring row stayed

MirroredUndeclared measures "the zod mirror STATES a key the TypeScript twin does not". Once the twin states it, that pair measures never, so the row is deleted — the ledger's own docblock calls that "the ratchet doing its job, and the only direction this seed may move in". Its sizing pin then reported the docstring figures, derived at test time:

expected { entries: 8, keys: 102 } to deeply equal { entries: 7, keys: 101 }

Corrected to the derived values, per that assertion's own "WHICH SIDE TO CHANGE" instruction (an entry removed ⇒ correct the docstring). ⛔ No key set was edited to satisfy a sentence.

Note the asymmetry with the row directly above it: objectql.zod.ts#ObjectGridSchema stayed after objectui#9739's letter C, because a retirement tombstone is still a stated member. Two rulings, the same day, moving this ledger in opposite directions. A comment left where the deleted row stood says so.

The docblock's factual claims, checked against the tree

PR objectui#9360 was failed for a docblock asserting what the code does not do. Each claim here was verified:

claim where the tree says it
the authored key on a detail-view field reaches the cell DetailSection calls enrichDetailField(field, objectDefField), whose body opens const enriched = { ...viewField };, then renders CellRenderer value=… field=enrichedField
the cell renderer reads the key first, name convention second resolveDueLike in packages/fields/src/index.tsx: const declared = (field as DateFieldMetadata OR DateTimeFieldMetadata OR undefined)?.dueLike; if (declared === true) return true; then the DUE_LIKE_FIELD_NAME regex
false does not suppress the fallback same function — only === true short-circuits; any other value falls through to the name test. content/docs/fields/datetime.mdx says the same ("authoring a neutral name" is the opt-out)
the wording half formatRelativeDate in @object-ui/core: if (diffDays < -1 && options?.dueLike) returns the Overdue Nd phrase
the styling half, on both cells, whatever face isOverdueInstant(date, dueLike) gates text-red-600 in DateCellRenderer's span and in DateTimeCellRenderer's cellClass, outside the per-face branches
the two thresholds differ by a day isOverdueInstant is date < startOfToday; formatRelativeDate gates on diffDays < -1 — so the red starts a day before the wording does
beyond a week the wording stops, the styling does not formatRelativeDate returns the absolute face for diffDays < -7, before the overdue branch; cellClass is computed before any branch

Behaviour is not merely read, it is run: packages/plugin-detail/src/__tests__/DetailSection.dueLikeReachesTheCell-9729.test.tsx draws end_date (a name that deliberately does not match the convention) with and without the key and asserts the drawn wording changes, with a by-value control leg.

What was run

All at head 0457692462, in a dedicated worktree, heavy runs serialised through the shared verify lock.

command result
pnpm --filter @object-ui/types type-check exit 0 — all three legs echoed: tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json. The third is the leg that reads @ts-expect-error.
pnpm exec vitest run packages/types/ (repo root) exit 0Test Files 209 passed (209), Tests 4834 passed (4834)
pnpm exec vitest run over the three renderer suites that read the key exit 0Test Files 3 passed (3), Tests 21 passed (21)
pnpm --filter @object-ui/types lint exit 0298 problems (0 errors, 298 warnings), every warning a pre-existing no-explicit-any; none falls inside the added range
node scripts/check-changeset-presence.mjs exit 0 — "3 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)"
node scripts/check-changeset-no-major.mjs exit 0 — "No changeset declares a major bump"
pnpm check:control-bytes exit 0 — 8061 tracked text files scanned
pnpm check:new-line-citations exit 0 — "0 new citation(s)"
node scripts/check-governed-queue-guard.mjs --test (the four changed paths) NOT GOVERNED — 4 paths checked against 5 governed surfaces, none matched

Lint narrowing, declared. The repo's lint is turbo run lint, i.e. each package's own eslint .; the narrowing run here is that same script for the one package this diff touches. (1) The population is read from eslint's own config resolution, not guessed. (2) --format json over that leg counts 280 files, 0 errors, 298 warnings. (3) Invariance for untouched files: eslint.config.js configures no project / projectService, so type-aware linting is not enabled and this diff cannot move a verdict on a file it does not contain. The full farm is CI's run.

Acceptance notes

Out-of-scope observations, recorded here and in the report, ⛔ not filed and ⛔ not fixed:

  • The in-repo documentation pages content/docs/fields/date.mdx and content/docs/fields/datetime.mdx teach dueLike on object field metadata (DateFieldMetadata / DateTimeFieldMetadata), which was already declared. Neither page documents the detail-view field key this PR declares. That is a gap, not a contradiction, and no page needed editing for this ruling. Noted, not filed — no PR or person is queued to touch those pages. Dedupe words if it is ever wanted: dueLike · detail-view field · docs fields date mdx.
  • resolveDueLike gives dueLike: false no suppressing power — the name convention still wins. That is deliberate and documented on both sides; recorded because the new docblock has to state it, and a reader could otherwise take false for an opt-out.

⛔ This PR does not open the wider question of whether a UI hint like this belongs in @objectstack/spec; the key stays objectui-owned until the protocol claims it. Nothing upstream is touched or proposed.

⛔ This PR does not add, remove or otherwise touch the needs:contract-review label the seat hung on the card, does not leave draft, and does not enqueue. The seat lands it.

This branch was produced in the Claude Code session https://claude.ai/code/session_01UanLVj6xvbS6puBCewLr8L.


Generated by Claude Code

…i#9738)

Maintainer ruling, letter A: the key is declared on the published
TypeScript twin, so the validator, the type checker, the renderer and the
docs say the same thing, and the key's meaning is written once in the
declaration.

- `packages/types/src/views.ts` — `DetailViewField` gains
  `dueLike?: boolean`, with a docblock stating the rendering effect it
  actually has (both halves of the overdue affordance, their different
  day thresholds, and the field-name fallback that `false` does not
  suppress). Every sentence is checked against the tree it describes.
- `packages/types/src/zod/views.zod.ts` — untouched. The mirror already
  declared the key; that was the whole defect.
- `mirror-only-published-keys-9729.test.ts` — the pin MOVES with the
  declaration rather than being repaired. The `@ts-expect-error` that
  recorded the refusal turns unused the moment the twin declares the key
  (`TS2578`), so it is replaced by the assignment it guarded plus an
  exact `Equal` that separates a DECLARED member from one absorbed by an
  index signature. Losing the member again is `TS2353` on the same leg.
- `zod-mirror-parity.test.ts` — the `MirroredUndeclared` row for
  `views.zod.ts#DetailViewFieldSchema` is deleted, which is the only
  direction that ratchet may move in, and the ledger docstring's two
  figures are corrected to the values the sizing pin derives.

Clause-②: yes — the published type's accept set widens by exactly one
key. Measured, not asserted: the interface parses to 13 members at
edbcf1e and 14 at head, the difference being `dueLike`, with
`currency` read by the same instrument on both legs as the lit control;
and a `DetailViewField` literal carrying the key is `TS2353` at
edbcf1e and compiles at head.

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

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 15 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/__tests__/zod-mirror-parity.test.tspackages/types/src/__tests__/zod-mirror-parity.test.ts — edited by this change

    ⚠️ The JUSTIFICATION for that parity clause was retired (objectui#9743); the clause itself stands and did not move. As first written it credited the zod-mirror-parity ratchet with a zero-drift reading for this pair — but at that time the ratchet measured three directions and was structurally blind to the MIRRORED-but-undeclared one (objectui#9711), so a zero from it recorded that it had not looked in that direction, not that nothing was there. objectui#9725 landed the fourth direction, and it covers this pair BY NAME: packages/types/src/__tests__/zod-mirror-parity.test.ts registers objectql.zod.ts#ObjectGanttSchema in both its mirror map and its declaration map; assertionMirroredUndeclaredMatchesLedger requires every registered pair's mirrored-but-undeclared key set to equal that pair's MirroredUndeclared ledger entry — never for a pair the ledger does not name — and assertionNoVacuousMirroredUndeclaredMeasurement refuses a measurement that has degenerated to any. ⛔ Read this pair's verdict off that reconciliation, which re-derives it on every run, rather than off any figure written here; when this paragraph was authored, on 2026-09-18, it required no MirroredUndeclared entry for the pair.

.changeset/5928-classname-style-props-rename.md

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

    Where the non-pair is recorded now. zod-mirror-parity.test.ts keys its existing EXCLUSIONS entry — the mechanism that accounts for every exported const with no TypeScript declaration to mirror, each with its stated reason — to ClassNameStylePropsSchema. Named for its own two keys, the const leaves no like-named declaration for a name-derived pairing to reach for.

.changeset/6051-gantt-flat-config-declared-keys.md

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

    ⚠️ The JUSTIFICATION for that parity clause was retired (objectui#9743) — the same retirement objectui#5903's entry carries, for the same clause and the same reason; the clause itself stands and did not move. As first written it credited the zod-mirror-parity ratchet with a zero-drift reading for this pair, at a time when that ratchet measured three directions and was structurally blind to the MIRRORED-but-undeclared one (objectui#9711), so a zero from it recorded that it had not looked in that direction. objectui#9725 landed the fourth direction, and it covers this pair BY NAME: packages/types/src/__tests__/zod-mirror-parity.test.ts registers objectql.zod.ts#ObjectGanttSchema in both its mirror map and its declaration map; assertionMirroredUndeclaredMatchesLedger reconciles every registered pair's mirrored-but-undeclared key set against that pair's MirroredUndeclared ledger entry — never for a pair the ledger does not name — and assertionNoVacuousMirroredUndeclaredMeasurement refuses a measurement that has degenerated to any. ⛔ Read this pair's verdict off that reconciliation, which re-derives it on every run, rather than off any figure written here; when this paragraph was authored, on 2026-09-18, it required no MirroredUndeclared entry for the pair.

.changeset/6150-undeclared-but-consumed-keys.md

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

    AMENDED, and the amendment ships in this same release. objectui#7804's TreeViewSchema slice gave the key a zod arm after all — a NAMED REFUSAL (handlerKeyRefusal(key, 'runtime-slot', label)), never a shape — because "no mirror entry" is not neutral under BaseSchema.passthrough(): it meant an authored { "type": "tree-view", "onNodeClick": { "action": "toast" } } parsed GREEN, survived the parse, and reached a call site that expects a function. ⇒ the three clauses this bullet used to carry are no longer true of the code shipping beside it. The key is now a MEMBER of TreeViewSchema.shape and an authored value is refused BY NAME at path onNodeClick; it has LEFT zod-mirror-parity.test.ts's RuntimeOnlyDeclared for that file's KnownDrift; and it is no longer "the first pair to sit there without also sitting in UnmirroredDeclared" — draining it emptied that difference, so RuntimeOnlyDeclared is now a SUBSET of UnmirroredDeclared and the union of the two equals UnmirroredDeclared itself. ⛔ objectui#6152's ruling is untouched by any of this: what the key still does not have, and never will, is a z.function() shape — no serialized document could satisfy one.

.changeset/6175-column-state-persistence.md

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

    Nothing is retired. Both spellings remain declared on DataTableSchema; onColumnReorder stays declared and stays unwired, exactly as the RuntimeOnlyDeclared ledger in zod-mirror-parity.test.ts records it. Which of the two survives is a declared-surface ruling that stays open and is deliberately not settled here.

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

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

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

.changeset/6639-objectgrid-title-mirrored.md

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

    The gain is the typed refusal: the mirror's .passthrough() base was already admitting any title unexamined, and it now enforces the declared string. zod-mirror-parity.test.ts's UnmirroredDeclared ledger records the key as worked off — the ledger's first shrink by repair (97 + 1 mirrored + 23 reclassified is what the seeded "121" now means).

.changeset/7287-resolve-title-field-shared-ladder.md

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

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

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

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

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

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

.changeset/7654-floating-chatbot-trigger-icon-tombstone.md

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

    Every other tombstone in this package pairs ?: never with a retirementTombstone() refusal on the Zod twin. There is no twin here to carry one: FloatingChatbotConfig has no Zod mirror at all, and floatingConfig sits in the UnmirroredDeclared ledger (zod-mirror-parity.test.ts, complex.zod.ts#ChatbotSchema). BaseSchema is .passthrough(), so the whole floatingConfig object rides through unvalidated — before this change and after it. Minting a mirror to host a refusal would be the declared-but-UNMIRRORED axis (objectui#6152), a different defect: a key can be mirrored and inert, or unmirrored and live, and fixing one says nothing about the other. This change does not widen into it.

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

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

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

.changeset/8338-retire-toast-action.md

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

    The parity ledgers drain with it, every figure re-derived by zod-mirror-parity.test.ts's own AST and mirror instruments rather than stepped by hand: KnownDrift 42 entries / 64 keys → 41 / 63 (the entry's whole content, so the entry went too — the ledger's first loss by RETIRING a key rather than by moving either face toward the other), and WiderThanDeclared 23 / 36 / 47 arms, split 6 / 30 / 0 / 11 → 22 / 35 / 45, split 6 / 29 / 0 / 10. The pair itself stays registered, so EXPECTED_MIRROR_PAIRS does not move.

.changeset/8572-chatbot-body-retired.md

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

    Why this key and not another. It was the ONE place in this vocabulary where body did not mean "what goes inside this component": zod-mirror-parity.test.ts carried the pair under KnownDrift as "two different meanings of one key", and the same collision was the whole reason chatbot was the single arm of the component union whose output was not assignable to SchemaNode. Both ledger rows move with this change, and the two pins that recorded the old state are INVERTED rather than deleted (see below).

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

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

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

Read the paragraph, not the line: both false halves of the objectui#8617 claim sat in one paragraph, and correcting either alone would have left it asserting the same wrong thing.

If a claim did go false, correct the body. That is precedented and prose-only, frontmatter untouched; check-changeset-overwrite.mjs will report the correction as its own case 2 ("correcting a declaration on purpose … legitimate"), which is the intended shape — one gate asks for the read, the other records the write.

Not covered, stated so nobody reads this as more: a born-false claim that spells no line address at all (objectui#9495 coordinated one by ORDINAL — "a grep finds that member first" — and deciding that means reading what the sentence means), a claim spelled as a symbol or a package rather than a backticked file name, and a file named ambiguously.

Compared the checked-out tree with edbcf1e7a (merge-base with origin/main): 3 file(s) changed outside .changeset/, read against 1203 pending declaration(s) that publish a body (1762 pending in total). · run

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3054.3 KB 3104.5 KB
Main entry chunk (gzip) 145.7 KB 350 KB
Entry file index-CuDuhvNV.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.91KB 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) 254.30KB 66.21KB
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.10KB 14.94KB
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.07KB 8.74KB
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

2 participants