Skip to content

feat(core)!: retire the bare-string globalFilters[].options lift (objectui#4356) - #10930

Merged
objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-4356-retire-shorthand-lift
Sep 29, 2026
Merged

objectstack-fleet[bot] merged 6 commits into
mainfrom
claude/issue-4356-retire-shorthand-lift

Conversation

@objectstack-fleet

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

Copy link
Copy Markdown
Contributor

Fixes #4356

Clause-②: yes — published runtime behaviour is removed (the bare-string lift, and the exported resetDashboardFilterWarnings if it retires with its memo), per the execution parameters in 5511028727.

The claim's "if" resolved to stays: the memo survives (it now dedupes the dropped-member warning, see "The audible-skip question"), so resetDashboardFilterWarnings keeps its job and its export; the changeset names no removed export.

Final head a890654027a69911412efbcb146e326da8476256. Commits on this branch since the branch point 733fd5ac6: bc4ea976e (the retirement), 98623a24d (rework round 1: W1–W3), e0647486b (patch round 2: W5), the two merges of origin/main (1daf7edf7 at 29c76e573, a1058f90e at 2eaf5be27), and a89065402 (W4, the dated note). Implemented in session session_012UwY3ahMixEFkfTUxMVkYm.

What changed

Phase 2 of objectui#4356 — the runtime bare-string globalFilters[].options lift retires.

  • packages/core/src/utils/dashboard-filters.ts — in normalizeFilterOptions, the non-object arm no longer pushes { value: String(o), label: String(o) }. A member that is not an object (string, number, boolean) yields NO option: a shorthand-only filter resolves with no options, a mixed array keeps only its object members. The nullish / value-less skips are unchanged. The Phase 1 deprecation warning (warnShorthandOptions, whose text said "Still lifted here") is deleted; a dev-mode, once-per-filter warnDroppedShorthandOptions names the filter, the dropped members and the rewrite, and promises no lift. The DashboardFilterDef.options JSDoc, the normalizeFilterOptions docblock, the memo docblock and the resetDashboardFilterWarnings docblock stop describing a lift. No lift, alias, fallback or migration is added anywhere.
  • packages/core/src/utils/__tests__/dashboard-filters.test.ts — every lift-pinning test is flipped to pin the new contract (red-first, quoted under Tests): normalizes options: spec {value,label} objects AND bare-string shorthand became normalizes spec {value,label} objects, and DROPS a bare-string member rather than lifting it; the [#4356] describe is retired: dropped, not lifted — a shorthand-only filter yields no options; a mixed array keeps only its object members; a number and a boolean are dropped too; warn ONCE across renders while dropping on every render; a different filter warns separately; canonical { value, label } options and an I18nLabel map are untouched and silent; resetDashboardFilterWarnings re-arms the memo. The stale Phase 1 header above the block is removed (W3).
  • content/docs/guide/dashboard-filters.md — the "Deprecated: … still lifted by the runtime" callout became false and now reads "Not accepted": refused at publish, no longer lifted, a bare-string member yields no option, rewrite "X" as { "value": "X", "label": "X" }. No fenced block changed.
  • packages/types/src/zod/complex.zod.ts — the JSDoc of the exported GlobalFilterSchema said the runtime "still LIFTS a stored bare-string option on read"; that sentence ships in @object-ui/types' emitted declarations and is corrected in place. Outside the claim's original surface; accepted by the seat's addendum, see "Deviations".
  • packages/plugin-dashboard/README.md (W1, ships in that package's files) — the globalFilters example's options comment no longer says a stored bare string "is still lifted at runtime, and warns"; it says NOT accepted, the runtime no longer lifts it (objectui#4356), a bare member yields no option, a dev-mode warning names it, rewrite each X as { "value": X, "label": X }.
  • Three test docblocks state the retirement instead of the lift (W2): packages/types/src/__tests__/dashboard-global-filters-spec-binding.test.ts, packages/types/src/__tests__/report-chart-query-spec-parity.test.ts (its header docblock only — nothing near objectui#10916's JoinedReportBlock pin, which PR test(types): the JoinedReportBlock pin compiles on the installed spec and on spec main, and trips at the bump (objectui#10916) #10934 rewrote and this branch has merged), packages/plugin-dashboard/src/__tests__/DashboardRenderer.filters.test.tsx. A fourth (W5), packages/plugin-dashboard/src/__tests__/DashboardFilterBar.i18nLabel.test.tsx, no longer says the shorthand "is deprecated and now warns" nor names the renamed lift pin; it names the current DROP pin. No assertion moved in any of the four.
  • .changeset/retire-options-shorthand-lift-4356.md — @object-ui/core: minor, opening with the ruled wording: "bare-string globalFilters[].options is no longer lifted; use { value, label } objects, the spec's form". Never major (AGENTS.md §9 version policy: the break is stated in the body, the bump stays minor); check-changeset-no-major exit 0.
  • .changeset/7759-dashboard-header-global-filters-spec.md (W4) — a dated note appended, nothing else touched. That pending entry says "The runtime is unchanged too: @object-ui/core still converts a STORED bare-string option into a pair when it reads the document, and logs a deprecation warning. That conversion keeps its own retirement schedule (objectstack#7917)." — a sentence this PR makes false in the same release. The note (PR docs(changeset): date-note six pending entries that PRs #10793, #10802 and #10821 made false (objectui#10877) #10891 form, dated 2026-09-29) says which sentences no longer hold and what ships. Authorised by the maintainer's ruling of 2026-09-29, option 「Allow the appended note (Recommended)」, recorded on the card as 5883360525; the option reads, verbatim: "You allow developers to append dated correction notes to pending .changeset files (appended only, no existing line or frontmatter edited). The feat(core)!: retire the bare-string globalFilters[].options lift (objectui#4356) #10930 developer adds the W4 note inside that PR, then it merges main, gets a final review, and merges." Measured: 16 insertions, 0 deletions; frontmatter md5 ac1bfd0472c0d0b981d923c32d435f18 before and after; whole-file md5 94edd5855709afe137f9184c630f298c → 5c8f0508bed5ed6f5b76254bb74d622d; 0 angle-bracket characters; diff against origin/main shows only the appended block.

Untouched on purpose: examples/schema-catalog/test/plugin-dashboard-global-filters-spec.test.ts (the GlobalFilterSchema catalog guardrail from PR #4601 — the positive control; its docblock narrates history and spec facts only, and stays true); the assertions of the two packages/types tests that pin the SPEC's refusal of options: ['EMEA'] (rejection pins, not lift pins); @objectstack/spec; content/docs/releases/**; skills/** (no file there becomes false — measured below).

Rulings executed

The audible-skip question — governing text found

The dispatch asked whether any governing text requires the post-removal skip to be audible. What was read, verbatim:

  • objectstack AGENTS.md, "Degradation log levels — warn vs error": "Functional degradation → warn / info. A screen is missing, a trigger is not armed, a capability is not enabled … The system is visibly smaller than it should be, and the next person to use the missing thing finds out." and "prefer failing to falling back, and when you must fall back, say what was lost." — A select filter whose members were all bare strings now renders with an empty option list (DashboardFilterBar: const authored = def.options?.length ? def.options : (dynamicOptions ?? [])): visibly smaller, functional, warn-level — and "say what was lost" is the operative sentence.
  • objectstack docs/adr/0078-no-silently-inert-metadata.md, §4 "Loud-not-silent at the runtime seam": "Where the runtime skips an inert instance … it emits a dev-mode diagnostic at registration rather than swallowing it silently. This is the only layer that is authoring-tool-agnostic". The ADR's completeness gate (§1) is about Zod-VALID instances and a bare string is Zod-invalid, but §4 is exactly the case here: a STORED dashboard is the one document no author-time gate re-reads.
  • objectui AGENTS.md: no clause on audibility; #0.1 (contract-first, no lenient fallback) is honoured — a diagnostic is not a fallback, and nothing is lifted.
  • The module's own convention, same file: buildFilterCondition — "anything else → skipped with a console warning, never silently downgraded"; buildWidgetScopedFilter skips an unknown default field "with a console warning instead of emitting a query".

Conclusion: yes, at warn, dev-mode, deduped — the smallest audible path consistent with the ruling. Implemented as warnDroppedShorthandOptions: same isDev() gate and memo key as Phase 1 (no per-render flood), new sentence (DROPPED, "no longer lifted", the rewrite), no lift. Consequence: the memo and therefore resetDashboardFilterWarnings stay. The contract review (5866198610) judged this RIGHT; dev-only rather than always-on is the same review's answer for this PR.

Measurements against the dispatch's mechanism assumptions

  1. Lift live on origin/main 733fd5ac6 — confirmed: the else arm pushed { value: String(o), label: String(o) } and called warnShorthandOptions for EVERY non-nullish primitive. Pinned now in drops EVERY non-object member — a number and a boolean, not only a string.
  2. resetDashboardFilterWarnings — git grep repo-wide: importers are dashboard-filters.test.ts only (plus a packages/core/CHANGELOG.md paragraph); it clears only warnedShorthandOptions. The inference "with the memo gone it has no job" is falsified by (4): the memo does not go. It stays, with a docblock saying why.
  3. Fixture recount, repo-wide over every file containing globalFilters (tests included; positive control: the same matcher found the callout it was meant to find): lift-pinning bare-string members existed only in dashboard-filters.test.ts — six members across five tests (the dispatch's list lacked the bare 'lost' of the mixed-array test; the director's "three" and the dispatch's "five" were both stale). All six retired or flipped. The two packages/types occurrences pin the spec's REFUSAL and keep their assertions.
  4. Skip audibility — see the section above.
  5. Teaching sites — swept at the final head with git grep -n -i -E 'lift' -- ':!**/CHANGELOG.md' ':!content/docs/releases/**' ':!pnpm-lock.yaml' | grep -i -E 'shorthand|bare[- ]string|4356' over the whole tracked tree (a superset of every package's files[], content/docs, skills/, examples/): 20 hits on bc4ea976e with packages/plugin-dashboard/README.md's "still lifted at runtime" line as the found positive control; 18 on a89065402 — every hit either states the retirement (this PR's changeset, source, docs and test text) or is the unrelated data-array shorthand in plugin-grid / plugin-map. The first-round sweep's option|filter post-filter is what hid the README line (W1) and the i18nLabel comment (W5); the rework sweep has no post-filter. When the sweep runs on a ref, the ref prefix is stripped before the second grep — this branch's name contains both "shorthand" and "lift". Three other sites author options: ['…'] on select FIELDS (form / object field schemas: content/docs/guide/expressions.md, content/docs/guide/schema-playground.md, skills/objectui/guides/project-setup.md) — a different contract, out of this card, untouched; the governed skills/** file does not become false.
  6. Release — packages/core/package.json is 17.6.0; .changeset/config.json has @object-ui/core in the fixed group; a minor changeset makes the next release ≥ 17.7.0; release PR chore: release packages #5400 is open (not touched).
  7. Pending changesets — swept on the merged tree (2326 pending entries) with git grep -n -i -E 'normalizeFilterOptions|bare[- ]string|shorthand|lift' -- '.changeset/*.md' filtered to option / globalFilters / 4356 / 7917 context: exactly ONE pending sentence this PR makes false, the 7759 paragraph quoted above (W4). Its earlier sentence "the bare-string option shorthand (options: ['EMEA']) is refused with invalid_type" stays true. Every other hit is a different contract (export-options bare array, object-map / gantt data arrays, kanban columns, picklist / field options, widget shorthand). The nine entries the changeset-claim-re-read comment 5865883972 lists were re-read: none says anything about the options lift; all still true.

Merges of main

No rebase, no amend, no force-push at any point; every push was a plain git push.

Tests

Red-first (at bc4ea976e, the new pins against the UNTOUCHED source, pnpm exec vitest run packages/core/src/utils/__tests__/dashboard-filters.test.ts, exit 1):

× normalizes spec {value,label} objects, and DROPS a bare-string member rather than lifting it (objectui#4356)
× DROPS a bare string: a shorthand-only filter resolves with no `options`, and says so
× keeps ONLY the object members of a MIXED array, and names only the dropped ones
× drops EVERY non-object member — a number and a boolean, not only a string
× warns ONCE per offending filter across repeated renders, and drops on every one of them
AssertionError: expected [ …(2) ] to be undefined
AssertionError: expected [ Array(2) ] to deeply equal [ { value: 'won', label: 'Won' } ]
AssertionError: expected [ { value: '42', label: '42' }, …(2) ] to deeply equal [ { value: 'gold', label: 'Gold' } ]
 Test Files  1 failed (1)
      Tests  5 failed | 44 passed (49)

The three that stayed green on the old code are the ones the block labels as non-discriminating (different-filter memo, canonical silence, memo reset). Green after the source change, same command: Tests 49 passed (49).

Final head a89065402, one pnpm exec vitest run from the repo root under the shared verify lock over packages/core/ plus the two packages/types global-filter tests and the two plugin-dashboard dashboard-filter tests this PR touched: Test Files 188 passed (188) · Tests 3725 passed | 27 skipped (3752), exit 0. The changeset script tests (check-changeset-{presence,no-major,fixed,overwrite,claims}, check-pending-changeset-literals, changeset-polarity-census): Test Files 7 passed (7) · Tests 292 passed (292), exit 0.

Consumer sweep at bc4ea976e (resolveDashboardFilterDefs consumers re-derived by git grep: core, types, plugin-dashboard, plugin-designer, app-shell, examples/schema-catalog), exit 0: packages/core 182 files / 3643 tests; packages/plugin-dashboard 147 / 1346 (6 pre-existing skips); packages/types 3 / 58; packages/plugin-designer (DashboardDesignPage.presetAlias) 1 / 4; packages/app-shell (DashboardWidgetInspector.test.tsx) 1 / 19; examples/schema-catalog (the guardrail) 1 / 9 — totals 335 passed (335) · 5073 passed | 6 skipped (5079). No consumer fixture asserted the old lift. The code has not changed since that head (every later commit is prose or a merge), and the final-head run above re-covers core, types and the touched plugin-dashboard tests.

Gates on the final head a89065402 (hand-derived from root package.json and .github/workflows/; exit codes captured before any pipe)

gate exit note
pnpm --filter '@object-ui/core^...' build then pnpm --filter @object-ui/core build 0 / 0 dependency closure first, so the type-checks read rebuilt declarations
pnpm --filter @object-ui/core type-check · pnpm --filter @object-ui/types type-check 0 / 0
pnpm --filter @object-ui/core lint · pnpm --filter @object-ui/types lint 0 / 0 0 errors; the warnings are pre-existing no-explicit-any — on the touched files the as any counts equal the base (2 / 10 / 0), unchanged since bc4ea976e
vitest packages/core/ + the four touched dashboard-filter tests (under the lock) 0 188 files, 3725 passed, 27 skipped
vitest changeset script tests ×7 0 292 passed
node scripts/check-changeset-presence.mjs 0 11 files changed vs merge-base 2eaf5be27, 7 published source files of 3 released packages, 1 changeset added
node scripts/check-changeset-no-major.mjs · check-changeset-fixed.mjs · check-changeset-claims.mjs · check-changeset-overwrite.mjs 0 ×4 claims and overwrite are report-only; the W4 append is overwrite's documented "correcting a declaration on purpose" case
pnpm check:pending-changeset-literals 0 "No test source names a pending changeset"
node scripts/check-control-bytes.mjs 0 9331 tracked text files
node scripts/check-new-cross-file-line-citations.mjs 0 0 new citations (the W4 note cites by quoted sentence)
node scripts/check-governed-queue-guard.mjs --test (every touched path) 0 NOT GOVERNED
pnpm check:doc-fences · check:doc-types · check:doc-example-ids · check:spec-symbols · node scripts/check-doc-links.mjs · check:test-path-roots · check:vi-mock-specifiers · check:phantom-deps 0 ×8 measured at bc4ea976e / 98623a24d; the files they read have not changed since
pnpm check:doc-snippets · pnpm check:readme-exports 2 / 1 NOT MEASURED locally — both PRECONDITION NOT MET (unbuilt packages); CI's Doc Snippet Type Check and README Exports are the readings. The docs hunk changes no fenced block; the README hunk is a JSON comment with no import binding

Not run locally, CI-owned: repo-wide pnpm lint, pnpm test, pnpm type-check (the public type face is unchanged — no export added or removed, no signature changed; emitted declarations differ in JSDoc text only), pnpm check, the i18n gates, plugin-dashboard's own type-check (comment-only hunks in two test files).

Deviations

  • packages/types/src/zod/complex.zod.ts was outside claim 5865368364's original file surface; edited under the bounded in-place-fix exemption (same defect class; mechanical; no other open PR on the file; inside core's type-checked closure) and accepted by the seat's addendum 5865980488. The later addenda 5866223135, 5866346457, 5866480991 added the W1–W5 files and the 7759 changeset.
  • The first-round teaching sweep under-reported (W1, W5) because of its option|filter post-filter; corrected above.
  • The W4 append was first refused by the auto-mode classifier ("Modify Shared Resources", record 5866443287), held and not re-routed; it landed only after the maintainer's 2026-09-29 ruling.

Acceptance notes


Generated by Claude Code

…bjectui#4356)

`normalizeFilterOptions` no longer lifts a non-object `options` member to a
`{ value, label }` pair: the member yields no option, a shorthand-only filter
resolves with no `options`, and a mixed array keeps only its object members.
The Phase 1 deprecation warning (PR #4601), whose text promised the lift, goes
with the arm; a dev-mode, once-per-filter warning names the dropped members
and the rewrite instead (ADR-0078 section 4), so `resetDashboardFilterWarnings`
keeps its memo and stays exported.

Rulings: objectstack#7917 「7917 ②」 (2026-08-12) and 「objectstack#7917
不考虑现有数据」 (2026-09-02). The docs callout and the `GlobalFilterSchema`
docblock in @object-ui/types stop describing the lift. Changeset: core minor.

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

github-actions Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

changeset-claim-re-read

⚠️ 9 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/6939-kanban-column-cards.md

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

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

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

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

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

.changeset/7703-chatbot-dark-keys-retired.md

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

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

.changeset/8114-detail-tab-activity-timeline.md

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

    README.md ships in this package's files, so the example went out in every tarball. DetailTabs renders a tab's content through ANGLE-BRACKETS(SchemaRenderer schema={toRenderableSchema(tab.content)} /), which makes content.type an SDUI node position judged by the component registry — so a reader copying the tab got the registry's Unknown component type panel (OBJUI-001) where the timeline should be. Same shape as the line-chart widget in plugin-dashboard/README.md (objectui#7896's census; fixed by objectui#7951) and the fourth known instance.

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

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

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

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

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

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

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

    The remaining 6 addresses (zod/complex.zod.ts) stayed out of scope for this PR and returned to the queue rather than riding this PR's scope — the card did not close here.

.changeset/8801-object-kanban-allow-collapse-retired.md

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

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

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

@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3096.0 KB 3104.5 KB
Main entry chunk (gzip) 148.6 KB 350 KB
Entry file index-2BDgfYvV.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.58KB 6.17KB
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) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.70KB 2.23KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 557.59KB 133.60KB
core (index.js) 9.93KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 226.44KB 63.00KB
fields (index.js) 261.01KB 66.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.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.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 51.96KB 14.83KB
plugin-charts (index.js) 83.99KB 22.86KB
plugin-chatbot (index.js) 197.67KB 46.90KB
plugin-dashboard (index.js) 136.93KB 36.48KB
plugin-designer (index.js) 215.03KB 44.21KB
plugin-detail (index.js) 233.48KB 61.79KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 161.21KB 41.41KB
plugin-gantt (index.js) 170.35KB 42.19KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.17KB 12.20KB
plugin-timeline (index.js) 31.00KB 9.09KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 88.55KB 22.21KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 119.16KB 39.05KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.22KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 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.26KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.27KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Spec Main Shape Gate is red on this head (bc4ea976e5), and the red is not this PR's. From the domain:spec @ objectui seat, session session_012UwY3ahMixEFkfTUxMVkYm.

The at-tier contract review of this head is in progress.

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: bc4ea976e5e142ffbeb4583326298fc58eaf69ba
Local-runs: none

Inputs: card #4356 (body and all 16 comments, the os-dev-report 5865928783 and the claim addendum 5865980488 included), PR #10930 (body, file list, net diff origin/main 733fd5ac6...bc4ea976e, five files, +197/-148), the check-runs on the head (read 2026-09-28T08:17Z). Governing text read at current HEAD: objectui AGENTS.md (#0.1, #11, §9 版本号策略, the changeset-presence rule), objectstack AGENTS.md ("Degradation log levels", Post-Task Checklist item 3), docs/adr/0078-no-silently-inert-metadata.md §4. Read-only git only (git grep / git show / git diff on the fetched ref); nothing built, run or re-run.

① Derived judgments

Right.

  1. Accept-set narrowing (runtime). resolveDashboardFilterDefs → normalizeFilterOptions: a globalFilters[].options[] member that is not an object (string, number, boolean) used to be lifted to { value: String(o), label: String(o) } and now yields no option — a shorthand-only filter resolves with options undefined, a mixed array keeps only its object members. The nullish and value-less skips are unchanged. The runtime now reads the document exactly as GlobalFilterSchema does: one strict contract, no renderer dialect beside it (objectui AGENTS.md #0.1). This is the end state the rulings named — 「7917 ②」 (2026-08-12) and 「objectstack#7917 不考虑现有数据」 (2026-09-02, director release 5511028727). No lift, alias, fallback or migration is added. RIGHT.
  2. Whole arm, not the string case. Numbers and booleans, which Phase 1 also lifted through String(o), are dropped too and pinned (drops EVERY non-object member); the warning spells "42" and 42 distinguishably. They were never spec-valid. RIGHT.
  3. Public export surface of @object-ui/core unchanged. packages/core/src/index.ts re-exports ./utils/dashboard-filters.js; the module's export lines are identical between base and head (DashboardFilterDef, DateRangeValue, DATE_RANGE_PRESETS, resetDashboardFilterWarnings, resolveDashboardFilterDefs, dashboardFilterVariableDefs, buildFilterCondition, buildWidgetScopedFilter). resetDashboardFilterWarnings keeps a job — the memo it clears now dedupes the dropped-member warning — so the dispatch's conditional ("if it retires with its memo") resolved to "stays", and the changeset says so. No signature moved; normalizeFilterOptions is module-private. RIGHT.
  4. The skip is audible, at the right level, and is not a fallback. warnDroppedShorthandOptions: dev-mode, once per filter per session (same memo key discipline as Phase 1), names the filter, the dropped members and the { value, label } rewrite, and promises no lift — the negative pin not.toContain('lifted here') guards the sentence. Governing text supports it: objectstack AGENTS.md "Degradation log levels" puts a functional degradation (a visibly emptier select) at warn and says "when you must fall back, say what was lost"; ADR-0078 §4 asks the runtime seam to emit a dev-mode diagnostic where it skips rather than swallow it. A diagnostic is not a lenient fallback, so #0.1 is intact. RIGHT.
  5. @object-ui/types. GlobalFilterSchema JSDoc corrected in place; the schema itself is untouched, so the emitted declaration changes in comment text only. The { preset } alias (liftLegacyGlobalFilterDefault) is left on its own retirement window and the docblock now says so. RIGHT.
  6. Docs callout (content/docs/guide/dashboard-filters.md) flipped from "Deprecated … still lifted" to "Not accepted … no longer lifts … yields no option … rewrite". No fenced block changed. RIGHT.
  7. Pins. Five DROP pins reported red-first against the untouched source and green after; the once-memo, different-filter, canonical-silence (honestly labelled vacuous) and reset pins are retained. The diff matches the report. RIGHT.

Wrong.

  • W1 — a shipped README still promises the lift (verdict-carrying). packages/plugin-dashboard/README.md, the globalFilters example's options comment, at the head: 「The bare-string shorthand (["EMEA", …]) is deprecated: a STORED one is still lifted at runtime, and warns (objectui#4356).」 README.md is in that package's files, so it ships in the npm tarball and is the package page. This diff makes the sentence false and leaves the file untouched (byte-identical to main). It is the Phase-0 teaching site the survey named (5276031321, then rewritten by PR fix(core): bare-string filter options — docs/examples stop teaching it, runtime lift warns (#4356) #4601 to the current text) — known to this card's thread. It is the same defect class the dev repaired in complex.zod.ts under the in-place-fix exemption, and the seat's addendum 5865980488 states the rule in so many words: 「A published text that the change makes false is fixed in the same PR.」 The PR body's assumption-5 sweep claims packages/plugin-dashboard/README.md was covered by the pattern shorthand|still lifted|is lifted and yielded nothing beyond the callout; the line matches both shorthand and still lifted, so that measurement claim is falsified. WRONG.
  • W2 — three in-repo test docblocks now state a lift that does not exist. packages/types/src/__tests__/dashboard-global-filters-spec-binding.test.ts (「NOT a runtime removal. normalizeFilterOptions … still lifts a bare string for STORED documents … The runtime half is filed separately.」), packages/types/src/__tests__/report-chart-query-spec-parity.test.ts (「⚠️ Retired at the SCHEMA only. normalizeFilterOptions … still lifts a stored bare-string option on read, with its deprecation warning」), packages/plugin-dashboard/src/__tests__/DashboardRenderer.filters.test.tsx (「… which pins normalizeFilterOptions lifting it」). The PR body judged the two types tests "still true": their assertions are (they pin the spec's refusal), their prose is not. Not published; secondary. WRONG.
  • W3 — a stale header inside the PR's own hunk. packages/core/src/utils/__tests__/dashboard-filters.test.ts at the head carries both rule lines back to back: the Phase-1 「normalizeFilterOptions accepts a bare-string globalFilters[].options shorthand that @objectstack/spec rejects at publish #4356 — the bare-string options shorthand is DEPRECATED and says so.」 directly above the new 「normalizeFilterOptions accepts a bare-string globalFilters[].options shorthand that @objectstack/spec rejects at publish #4356 — … RETIRED: dropped, not lifted.」 The file the PR rewrote to stop describing the lift still opens the block by describing it. Secondary. WRONG.

None of W1–W3 is code, a test assertion, a type or a changeset shape; each is a prose edit. They are what stands between this head and PASS.

② Semver level

  • Changeset .changeset/retire-options-shorthand-lift-4356.md: '@object-ui/core': minor. RIGHT under objectui AGENTS.md §9 版本号策略: objectui's own breaking changes are declared minor with the break stated in the body, major is reserved for the objectstack cross-major sync and is mechanically refused (check-changeset-no-major). The body states the break, the FROM → TO mapping ('EMEA' → { value: 'EMEA', label: 'EMEA' }) and the one-line rewrite, which is what objectstack AGENTS.md Post-Task item 3 requires of a breaking changeset; the opening sentence is the director's ruled wording verbatim. @object-ui/core is 17.6.0 in the fixed group, so minor publishes at ≥ 17.7.0 and never as a 17.6.x patch — as ruled. skip-changeset is correctly not used.
  • Clause-②: yes — RIGHT: published runtime behaviour is removed, so yes, and yes takes at least minor, which is satisfied. No arm is written; Post-Task item 3 allows at most one, so none is a legal spelling. Were one written, the accurate arm for a shrinking accept-set is (narrowing) — observation, not a fault. The line's conditional sub-clause about resetDashboardFilterWarnings resolved to "stays" and the changeset names no removed export: consistent.
  • @object-ui/types is not named in the changeset though its emitted declaration text changes. Fixed group bumps together, the hunk is JSDoc only with no type moved, and the presence and fixed-group gates accepted it. Acceptable; the fix for W2 adds test-file hunks in packages/types and packages/plugin-dashboard, which the same one-changeset shape already covered here — re-read the presence gate's verdict on the new head rather than assume.
  • Gate verdicts on the head: Changeset Bump Policy, Changeset Claim Re-read, Changeset Declaration, Changeset Fixed Group Check, Changeset Overwrite Report — all success.

③ Boundary flags

deviations in the os-dev-report 5865928783.

  1. packages/types/src/zod/complex.zod.ts outside the claimed surface — answered: accepted. The seat amended the claim's file surface in 5865980488, and on this reading the four conditions hold (JSDoc-only hunk, same class as the in-scope docblocks, inside core's type-check closure, no other open PR on the file per the seat's file-list read). Note that the rule the seat wrote to accept it is the rule W1 fails.
  2. check:doc-snippets not measured locally — answered: closed by CI. "Doc Snippet Type Check" is success on the head; the docs hunk has no fenced block.
  3. Assumption 2 falsified (the reset export stays) — answered: confirmed by the base/head export comparison in ①.3; Clause-② line and changeset are consistent with it.
  4. Assumption 3 recount (six bare-string fixtures in five tests) — answered: consistent with the diff (one fixture in each of four tests, two in the different-filter test); every one flipped or retired; the two packages/types occurrences are spec-refusal pins and are correctly untouched as assertions — their docblocks are W2.

open_questions.

  1. Audible skip — option A (dev-mode, deduped warning; memo and resetDashboardFilterWarnings stay) vs B (silent skip, delete the export). Answered: A, on the governing text already cited in ①.4; no escalation needed — the text answers it, and the module's own sibling skips (buildFilterCondition's unknown preset, buildWidgetScopedFilter's unknown field) already warn rather than swallow.
  2. Dev-only vs always-on — answered: A for this PR. It matches the Phase-1 gate it replaces and the actionKeys.ts precedent the module cites, and a removal card is not the place to introduce production console output. B is a one-line product decision for the maintainer; it does not block this PR and needs no ruling to land it — the seat may file it as its own card if wanted. Not escalated as blocking.

out_of_scope_findings. Select-FIELD options: ['…'] sites are a different contract — agreed, correctly untouched. CHANGELOGs narrating the lift as history — agreed, published record; the PR body's citation "AGENTS.md #11" for that point is mis-numbered (objectui #11 is the cite-by-content rule) — cosmetic, PR body only.

Check-runs on the head (43 runs at the reading above): 39 success; 3 skipped — Test (coverage), Test (coverage shard), matrix-conditional, and dependabot, not a dependabot PR; 1 failure — Spec Main Shape Gate. That gate compiles objectui against @objectstack/spec built from objectstack main (this run: dcd3bceaa068). Its annotation attributes the red to packages/types/src/__tests__/report-chart-query-spec-parity.test.ts, the true satisfies IsUnknown pin on SpecJoinedReportBlock ("TS1360: Type 'true' does not satisfy the expected type 'false'"): the spec has typed that schema upstream and the pin's own text calls this flip "the instruction: re-run the triage and burn it down". This PR leaves that file byte-identical to main; the workflow's own header says its subject is cross-repo drift, not the pull request's diff; and its run history shows every run on every branch and every merge-queue build in the visible window red on the same commit (a claude/issue-10916-joined-report-block-pin branch is already in flight). It is requirable and not required. Reported as it stands: not caused by this diff, and not this record's to clear.

Remedy for the FAIL, bounded: (a) rewrite the two README comment lines to the "not accepted / no longer lifted / a bare-string member yields no option / rewrite as { value, label }" sentence; (b) correct the three test docblocks in W2; (c) delete the stale Phase-1 header line in W3; (d) re-run the teaching sweep with an alternation-capable pattern (git grep -i -E) and quote its hits in the PR body; (e) push, and a new record is rendered on the new head. No code, assertion or changeset change is expected.

Implemented-by: claude/issue-4356-retire-shorthand-lift
Reviewed-by: session_012UwY3ahMixEFkfTUxMVkYm

VERDICT: FAIL

…the README and three test docblocks (objectui#4356)

Rework round 1 after contract review 5866198610 on bc4ea97 — prose only,
no assertion, type, changeset level or Clause-② moves:

- packages/plugin-dashboard/README.md (ships in `files`): the globalFilters
  example's options comment no longer says a stored bare string "is still
  lifted at runtime, and warns"; it says not accepted, no longer lifted, a
  bare member yields no option, a dev-mode warning names it, rewrite X as
  { value: X, label: X }.
- packages/types/src/__tests__/dashboard-global-filters-spec-binding.test.ts,
  packages/types/src/__tests__/report-chart-query-spec-parity.test.ts (its
  header docblock only) and packages/plugin-dashboard/src/__tests__/
  DashboardRenderer.filters.test.tsx: docblocks that stated the lift now
  state the retirement.
- packages/core/src/utils/__tests__/dashboard-filters.test.ts: the stale
  Phase 1 "DEPRECATED and says so" header above the RETIRED one is removed.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_012UwY3ahMixEFkfTUxMVkYm
@github-actions github-actions Bot added documentation Improvements or additions to documentation plugin labels Sep 28, 2026
@github-actions

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3096.0 KB 3104.5 KB
Main entry chunk (gzip) 148.6 KB 350 KB
Entry file index-2BDgfYvV.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.58KB 6.17KB
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) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.70KB 2.23KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 557.59KB 133.60KB
core (index.js) 9.93KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 226.44KB 63.00KB
fields (index.js) 261.01KB 66.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.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.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 51.96KB 14.83KB
plugin-charts (index.js) 83.99KB 22.86KB
plugin-chatbot (index.js) 197.67KB 46.90KB
plugin-dashboard (index.js) 136.93KB 36.48KB
plugin-designer (index.js) 215.03KB 44.21KB
plugin-detail (index.js) 233.48KB 61.79KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 161.21KB 41.41KB
plugin-gantt (index.js) 170.35KB 42.19KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.17KB 12.20KB
plugin-timeline (index.js) 31.00KB 9.09KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 88.55KB 22.21KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 119.16KB 39.05KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.22KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 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.26KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.27KB 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

…he retired mixed-array lift (objectui#4356)

Patch round 2 (W5, claim addendum 5866480991), comment only: the '(e) leaves
plain-string labels and options exactly as authored' case said the bare-string
shorthand "is deprecated and now warns" and that "the mixed-array lift has its
own pin" named `names ONLY the bare members of a MIXED array`, asserting a
lifted `{ value: 'lost', label: 'lost' }`. The shorthand is retired — a bare
member yields no option — and the pin is now `keeps ONLY the object members of
a MIXED array, and names only the dropped ones`. No assertion moves.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3096.0 KB 3104.5 KB
Main entry chunk (gzip) 148.6 KB 350 KB
Entry file index-2BDgfYvV.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.58KB 6.17KB
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) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.70KB 2.23KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 557.59KB 133.60KB
core (index.js) 9.93KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 226.44KB 63.00KB
fields (index.js) 261.01KB 66.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.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.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 51.96KB 14.83KB
plugin-charts (index.js) 83.99KB 22.86KB
plugin-chatbot (index.js) 197.67KB 46.90KB
plugin-dashboard (index.js) 136.93KB 36.48KB
plugin-designer (index.js) 215.03KB 44.21KB
plugin-detail (index.js) 233.48KB 61.79KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 161.21KB 41.41KB
plugin-gantt (index.js) 170.35KB 42.19KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.17KB 12.20KB
plugin-timeline (index.js) 31.00KB 9.09KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 88.55KB 22.21KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 119.16KB 39.05KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.22KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 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.26KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.27KB 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

…o claude/issue-4356-retire-shorthand-lift

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 329 chunks) 3096.0 KB 3104.5 KB
Main entry chunk (gzip) 148.6 KB 350 KB
Entry file index-2BDgfYvV.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.58KB 6.17KB
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) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.15KB 5.39KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.70KB 2.23KB
auth (SocialSignInButtons.js) 9.61KB 3.89KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 557.59KB 133.60KB
core (index.js) 9.93KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 226.44KB 63.00KB
fields (index.js) 261.01KB 66.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.34KB 9.17KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.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.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 51.96KB 14.83KB
plugin-charts (index.js) 83.99KB 22.86KB
plugin-chatbot (index.js) 197.67KB 46.90KB
plugin-dashboard (index.js) 136.93KB 36.48KB
plugin-designer (index.js) 215.03KB 44.21KB
plugin-detail (index.js) 233.48KB 61.79KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 161.21KB 41.41KB
plugin-gantt (index.js) 170.35KB 42.19KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.17KB 12.20KB
plugin-timeline (index.js) 31.00KB 9.09KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 88.55KB 22.21KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 119.16KB 39.05KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.22KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 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.26KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 17.15KB 6.32KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.27KB 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

This was referenced Sep 28, 2026
…nce this PR made false (objectui#4356)

W4 (claim addendum 5866346457), authorised by the maintainer's 2026-09-29
ruling 「Allow the appended note (Recommended)」 (card comment 5883360525): a
dated note in the PR #10891 form is appended to
.changeset/7759-dashboard-header-global-filters-spec.md, whose pending
paragraph "The runtime is unchanged too: @object-ui/core still converts a
STORED bare-string option into a pair when it reads the document, and logs a
deprecation warning" would publish in the same release as this PR's "no longer
lifted" entry. Append only: frontmatter byte-identical, 16 insertions, 0
deletions, no existing line edited.

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

Copy link
Copy Markdown
Contributor

✅ Console Performance Budget

Metric Value Budget
Eager closure (gzip, 330 chunks) 3105.5 KB 3149.4 KB
Main entry chunk (gzip) 149.4 KB 350 KB
Entry file index-pKfO7ATe.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.72KB 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) 27.95KB 10.04KB
auth (AuthContext.js) 0.31KB 0.24KB
auth (AuthGuard.js) 2.07KB 1.00KB
auth (AuthProvider.js) 40.22KB 10.61KB
auth (AuthShell.js) 3.49KB 1.40KB
auth (ForgotPasswordForm.js) 12.21KB 3.45KB
auth (LoginForm.js) 18.17KB 5.40KB
auth (PreviewBanner.js) 0.90KB 0.50KB
auth (RegisterForm.js) 6.72KB 2.24KB
auth (SocialSignInButtons.js) 9.70KB 3.93KB
auth (UserMenu.js) 3.39KB 1.21KB
auth (auth-gate-events.js) 1.29KB 0.66KB
auth (authStyles.js) 5.04KB 1.72KB
auth (createAuthClient.js) 40.70KB 10.94KB
auth (createAuthenticatedFetch.js) 8.52KB 3.45KB
auth (index.js) 3.63KB 1.64KB
auth (invitation-status.js) 1.22KB 0.70KB
auth (org-roles.js) 6.66KB 2.78KB
auth (phone-identifier.js) 1.11KB 0.66KB
auth (types.js) 0.59KB 0.35KB
auth (useAuth.js) 5.30KB 1.02KB
auth (useWorkspaceAdminStatus.js) 11.08KB 4.58KB
collaboration (CommentThread.js) 27.13KB 7.95KB
collaboration (LiveCursors.js) 3.17KB 1.27KB
collaboration (PresenceAvatars.js) 6.49KB 2.64KB
collaboration (PresenceProvider.js) 2.79KB 1.13KB
collaboration (index.js) 1.68KB 0.73KB
collaboration (useCollaborationTranslation.js) 6.05KB 2.52KB
collaboration (useCommentSearch.js) 1.98KB 0.88KB
collaboration (useConflictResolution.js) 7.75KB 1.86KB
collaboration (useMentionNotifications.js) 1.81KB 0.68KB
collaboration (usePresence.js) 6.33KB 1.84KB
collaboration (useRealtimeSubscription.js) 7.91KB 2.01KB
components (index.js) 558.92KB 133.97KB
core (index.js) 9.93KB 3.94KB
create-plugin (index.js) 27.94KB 9.51KB
data-objectstack (index.js) 227.62KB 63.16KB
fields (index.js) 261.01KB 66.28KB
i18n (LocalizationContext.js) 1.76KB 0.96KB
i18n (builtinAggregateLabels.js) 0.86KB 0.49KB
i18n (currency.js) 2.59KB 1.22KB
i18n (fallbackInterpolation.js) 6.25KB 2.77KB
i18n (i18n.js) 8.87KB 3.64KB
i18n (index.js) 5.24KB 2.27KB
i18n (pickLocalized.js) 9.86KB 3.95KB
i18n (provider.js) 39.40KB 12.91KB
i18n (translateFn.js) 0.20KB 0.18KB
i18n (useDisplayLocale.js) 3.52KB 1.76KB
i18n (useObjectLabel.js) 34.35KB 9.18KB
i18n (useSafeTranslation.js) 5.60KB 2.33KB
layout (index.js) 39.32KB 11.09KB
mobile (MobileProvider.js) 0.92KB 0.49KB
mobile (ResponsiveContainer.js) 0.94KB 0.38KB
mobile (breakpoints.js) 1.51KB 0.70KB
mobile (createOfflineDataSource.js) 5.61KB 1.75KB
mobile (index.js) 1.99KB 0.87KB
mobile (offlineQueue.js) 3.91KB 1.35KB
mobile (pwa.js) 0.97KB 0.49KB
mobile (serviceWorker.js) 1.48KB 0.62KB
mobile (serviceWorkerSource.js) 3.41KB 1.48KB
mobile (useBreakpoint.js) 1.54KB 0.65KB
mobile (useGesture.js) 6.96KB 1.98KB
mobile (useOfflineSync.js) 1.99KB 0.72KB
mobile (usePullToRefresh.js) 6.62KB 2.45KB
mobile (useResponsive.js) 0.72KB 0.42KB
mobile (useSpecGesture.js) 5.52KB 2.10KB
mobile (useTouchTarget.js) 1.01KB 0.54KB
permissions (MePermissionsProvider.js) 13.53KB 4.89KB
permissions (PermissionContext.js) 0.31KB 0.25KB
permissions (PermissionGuard.js) 0.89KB 0.45KB
permissions (PermissionProvider.js) 6.25KB 2.17KB
permissions (discardProofCache.js) 1.04KB 0.55KB
permissions (evaluator.js) 8.33KB 3.07KB
permissions (index.js) 0.93KB 0.41KB
permissions (store.js) 0.91KB 0.42KB
permissions (useFieldPermissions.js) 1.28KB 0.53KB
permissions (usePermissions.js) 4.83KB 2.27KB
plugin-ai (index.js) 16.01KB 3.93KB
plugin-calendar (index.js) 52.02KB 14.87KB
plugin-charts (index.js) 84.09KB 22.93KB
plugin-chatbot (index.js) 198.22KB 46.97KB
plugin-dashboard (index.js) 137.56KB 36.67KB
plugin-designer (index.js) 215.78KB 44.42KB
plugin-detail (index.js) 233.49KB 61.79KB
plugin-editor (index.js) 2.23KB 1.05KB
plugin-form (index.js) 163.08KB 42.10KB
plugin-gantt (index.js) 170.35KB 42.19KB
plugin-grid (index.js) 228.33KB 62.59KB
plugin-kanban (index.js) 48.43KB 15.11KB
plugin-list (index.js) 115.86KB 28.64KB
plugin-map (index.js) 22.90KB 7.62KB
plugin-markdown (index.js) 13.88KB 4.80KB
plugin-report (index.js) 44.17KB 12.20KB
plugin-timeline (index.js) 31.07KB 9.15KB
plugin-tree (index.js) 11.21KB 3.89KB
plugin-view (index.js) 89.59KB 22.47KB
providers (DataSourceProvider.js) 0.75KB 0.39KB
providers (MetadataProvider.js) 1.37KB 0.59KB
providers (ThemeProvider.js) 1.90KB 0.85KB
providers (UploadProvider.js) 11.81KB 3.58KB
providers (index.js) 0.45KB 0.23KB
providers (types.js) 0.01KB 0.04KB
react-runtime (index.js) 5.62KB 2.34KB
react (LazyPluginLoader.js) 4.47KB 1.63KB
react (SchemaRenderer.js) 119.16KB 39.05KB
react (data-invalidation.js) 5.05KB 2.08KB
react (index.js) 4.03KB 1.86KB
react (schema-input.js) 4.25KB 2.04KB
react (spec-input.js) 0.20KB 0.18KB
sdui-parser (body-dialect.js) 4.78KB 2.09KB
sdui-parser (codegen.js) 7.50KB 3.05KB
sdui-parser (dashboard-widget-options.js) 3.08KB 1.30KB
sdui-parser (index.js) 6.16KB 2.71KB
sdui-parser (input-type.js) 2.84KB 1.40KB
sdui-parser (kanban-quick-add.js) 3.89KB 1.87KB
sdui-parser (parse.js) 25.28KB 7.80KB
sdui-parser (provenance.js) 3.84KB 1.90KB
sdui-parser (types.js) 0.28KB 0.23KB
sdui-parser (validate.js) 18.27KB 6.22KB
types (ai.js) 4.39KB 2.17KB
types (api-types.js) 0.20KB 0.18KB
types (app.js) 3.83KB 1.49KB
types (base.js) 0.20KB 0.18KB
types (blocks.js) 0.20KB 0.18KB
types (complex.js) 3.19KB 1.62KB
types (crud.js) 0.20KB 0.18KB
types (dashboard-filter-alias.js) 6.23KB 2.74KB
types (data-display.js) 3.75KB 1.85KB
types (data-protocol.js) 0.20KB 0.19KB
types (data.js) 0.20KB 0.18KB
types (designer.js) 1.85KB 0.85KB
types (disclosure.js) 0.20KB 0.18KB
types (error-code.js) 1.54KB 0.88KB
types (expression.js) 0.20KB 0.18KB
types (feedback.js) 0.20KB 0.18KB
types (field-types.js) 0.20KB 0.18KB
types (form.js) 0.20KB 0.18KB
types (http-inflight.js) 8.87KB 3.73KB
types (http-retry.js) 4.32KB 2.02KB
types (icon-key-migration.js) 4.26KB 1.63KB
types (index.js) 4.74KB 2.26KB
types (layout.js) 0.20KB 0.18KB
types (managed-by.js) 0.19KB 0.18KB
types (mobile.js) 5.00KB 2.39KB
types (navigation.js) 0.20KB 0.18KB
types (objectql.js) 0.20KB 0.18KB
types (overlay.js) 0.20KB 0.18KB
types (permissions.js) 2.52KB 1.31KB
types (plugin-scope.js) 0.20KB 0.18KB
types (record-components.js) 0.20KB 0.19KB
types (record-semantics.js) 1.28KB 0.67KB
types (registry.js) 0.20KB 0.18KB
types (reports.js) 0.20KB 0.18KB
types (select-option.js) 0.20KB 0.19KB
types (spec-report.js) 5.05KB 1.93KB
types (spec-ui-namespace.js) 0.20KB 0.19KB
types (strict-authoring-face.js) 19.30KB 6.99KB
types (system-fields.js) 3.33KB 1.54KB
types (theme.js) 6.28KB 2.87KB
types (ui-action.js) 8.11KB 3.32KB
types (views.js) 0.20KB 0.18KB
types (widget.js) 0.20KB 0.18KB

Size Limits

  • ✅ Core packages should be < 50KB gzipped
  • ✅ Component packages should be < 100KB gzipped
  • ⚠️ Plugin packages should be < 150KB gzipped

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: a890654027a69911412efbcb146e326da8476256
Local-runs: none

Inputs: card #4356 (body and all 25 comments — the rulings 5264143301 「7917 ②」, 5511028727 (director release) and 5883360525 (W4 append); claim 5865368364 and its addenda 5865980488, 5866223135, 5866346457, 5866480991; the six os-dev-reports 5865928783, 5866362802, 5866443287, 5866532227, 5866654956, 5883501541), PR #10930 (body, the 11-file list — identical to the diff's, all 8 comments including the earlier record 5866198610 FAIL on bc4ea976e and the changeset-claim-re-read 5865883972, and the net diff origin/main 2eaf5be27...a89065402, +237/−171), and the check-runs on the head. Governing text read at current HEAD: objectui AGENTS.md (#0.1, #9, #11, §9 版本号策略, the changeset-presence rule, the dispatched-PR draft rule), objectstack AGENTS.md ("Degradation log levels", Post-Task Checklist item 3, the packages/*/CHANGELOG.md row), objectstack docs/adr/0078-no-silently-inert-metadata.md §4; objectui docs/adr/** holds no ADR on this surface. Read-only git only — the branch fetched into a review ref of its own, then git diff / git show / git grep / git merge-base on it; nothing built, run or re-run.

① Derived judgments

Accept-set and public-surface changes the diff implies, each judged.

  1. Runtime accept-set — @object-ui/core normalizeFilterOptions (module-private, reached through the exported resolveDashboardFilterDefs). A globalFilters[].options[] member that is not an object — string, number or boolean — used to yield { value: String(o), label: String(o) } under a deprecation warning; on this head it yields nothing and is recorded for one warning. Nullish members and value-less objects are skipped exactly as before; object members normalize as before (value stringified, label carried through as a string or an I18nLabel map). So a shorthand-only filter resolves with options undefined and a mixed array keeps only its object members; the accept-set shrinks to the spec's object arm. RIGHT — this is the end state 「7917 ②」 named and the director release 5511028727 dispatched under 「objectstack#7917 不考虑现有数据」: no lift, alias, fallback or migration entry anywhere (#0.1). Retiring the WHOLE non-object arm rather than the string case is right too — Phase 1 lifted every primitive through String(o), so a string-only removal would have left a number/boolean dialect; pinned by drops EVERY non-object member. Observation, not a fault and not this card's: the object arm still fills a missing label with String(value) while the spec refuses a label-less option (the pending 7759 entry states that refusal). That tolerance predates this card and the card, the director release and the changeset all name the bare-string lift only; it is the same #0.1 class and can be its own card.
  2. The dev-mode warning. warnShorthandOptions (whose text promised "Still lifted here") is deleted — no residue of the name anywhere on the head — and warnDroppedShorthandOptions replaces it: the same isDev() gate (NODE_ENV !== 'production'), the same warnedShorthandOptions memo keyed on filter name plus the spelled members (strings JSON-quoted, other primitives String()ed, so "42" and 42 do not collide), one console.warn through warnDateFilter per offending filter per session that names the filter, the dropped members, says DROPPED and "no longer lifted (objectui#4356)", prints the { value, label } rewrite and promises no lift (the negative pin not.toContain('lifted here') guards that). RIGHT: a select rendering with an empty option list is a functional degradation, which objectstack AGENTS.md "Degradation log levels" puts at warn with "when you must fall back, say what was lost"; ADR-0078 §4 asks the runtime seam to emit a dev-mode diagnostic where it skips rather than swallow; the module's own sibling skips (buildFilterCondition, buildWidgetScopedFilter) already warn. A diagnostic is not a lenient fallback, so #0.1 is intact; the memo protects the per-render path. Consequence: the memo and resetDashboardFilterWarnings stay, and the changeset says so.
  3. Public export surface of @object-ui/core — unchanged. packages/core/src/index.ts re-exports ./utils/dashboard-filters.js; the module's export lines are identical by content between base and head (DashboardFilterDef, DateRangeValue, DATE_RANGE_PRESETS, resetDashboardFilterWarnings, resolveDashboardFilterDefs, dashboardFilterVariableDefs, buildFilterCondition, buildWidgetScopedFilter). No signature moved. The emitted declarations change in JSDoc text only (DashboardFilterDef.options, the memo and resetDashboardFilterWarnings docblocks now describe the drop, not a lift). RIGHT; the dispatch's conditional ("if it retires with its memo") resolved to "stays", and the PR body and changeset both say so.
  4. GlobalFilterSchema docblock (packages/types/src/zod/complex.zod.ts, +11/−12, comment only). The "still LIFTS a stored bare-string option on read" paragraph is replaced by "no longer lifts … the SCHEMA and the READ PATH now refuse the same spelling"; the { preset } paragraph now reads as "the split options has now left behind", still pointing at liftLegacyGlobalFilterDefault in ../dashboard-filter-alias.ts, which is present on the head, so that sentence stays true. The schema itself is untouched; the text ships in @object-ui/types' emitted declarations. RIGHT. Outside the claim's original surface — accepted by addendum 5865980488; ③ below.
  5. The docs guide (content/docs/guide/dashboard-filters.md). The callout flipped from "Deprecated … still lifted … scheduled for removal" to "Not accepted … refused by GlobalFilterSchema at publish, and the runtime no longer lifts it either … a bare-string member yields no option … in development a single console.warn names the filter and the dropped members … Rewrite each string X as { "value": "X", "label": "X" }". Every sentence is true of the head; no other line of the guide names the shorthand; no fenced block changed (Doc Snippet Type Check success). RIGHT.
  6. The README (packages/plugin-dashboard/README.md, in that package's files, so it ships). The globalFilters example's comment now reads NOT accepted / the runtime no longer lifts it (objectui#4356) / a bare member yields no option / a dev-mode warning names it / rewrite each X as { "value": X, "label": X }; the example's options array is already the pair form. True of the head; README Export Check success. RIGHT.
  7. Four test docblocks, comment only, no assertion moved (each hunk read): dashboard-global-filters-spec-binding.test.ts ("This card was the TYPE half only. The runtime half followed …"), report-chart-query-spec-parity.test.ts header ("Retired at the SCHEMA first, and since objectui#4356 at the READ PATH too"; nothing near the JoinedReportBlock pin, which arrived from main through the 1daf7edf7 merge), DashboardRenderer.filters.test.tsx ("no longer lifted by normalizeFilterOptions either"), DashboardFilterBar.i18nLabel.test.tsx (names the pin keeps ONLY the object members of a MIXED array, and names only the dropped ones, which exists verbatim in dashboard-filters.test.ts on the head). RIGHT.
  8. Pins in dashboard-filters.test.ts. The top-level lift pin now expects toBeUndefined(); the [#4356] block pins the drop (shorthand-only → no options; mixed → object members only, the warning naming only the dropped; a number and a boolean dropped; once across renders while dropping on every render; a different filter warns separately; canonical options and an I18nLabel map silent and intact; resetDashboardFilterWarnings re-arms). The old lift pin names ONLY the bare members of a MIXED array is gone, replaced by the DROP pin the i18nLabel comment now cites. The block's own header carries one rule line. Red-first output is quoted in the PR body against the untouched source. RIGHT.

Teaching sweep, re-derived read-only on the head — git grep -n -i -E 'lift' over the tracked tree with CHANGELOGs, content/docs/releases/** and the lockfile excluded, post-filtered shorthand|bare[- ]string|4356, the review ref's prefix stripped first: 18 hits. Thirteen are this PR's own changesets, source, docs, README and test text, all stating the retirement; five are the unrelated data-array shorthand in plugin-grid / plugin-map. None is false. skills/**, packages/core/README.md, content/docs/plugins/plugin-dashboard.mdx and the schema-catalog plugin-dashboard entries carry no bare-string globalFilters teaching.

W1–W5 of record 5866198610 and the seat's addenda, on this head:

  • W1 (README promising the lift) — RESOLVED. The two comment lines are rewritten (+4/−2); 「still lifted at runtime, and warns」 is absent from the head.
  • W2 (three test docblocks stating a lift) — RESOLVED. All three hunks are in the diff (+6/−5, +5/−4, +5/−5), prose only.
  • W3 (stale Phase-1 header in dashboard-filters.test.ts) — RESOLVED. The block opens with the single 「RETIRED: dropped, not lifted」 line; 「DEPRECATED and says so」 is absent from the head.
  • W4 (pending 7759 changeset made false) — RESOLVED, under ruling 5883360525; judged in ②.
  • W5 (DashboardFilterBar.i18nLabel.test.tsx comment) — RESOLVED. A +6/−6 comment-only hunk naming the current DROP pin.

② Semver level

  • .changeset/retire-options-shorthand-lift-4356.md — '@object-ui/core': minor. RIGHT under objectui AGENTS.md §9 版本号策略: an objectui break ships as minor with the break stated in the body, major is reserved for the objectstack cross-major sync and is refused mechanically (Changeset Bump Policy success). The body states the break in its first bold sentence, the FROM → TO ('EMEA' used to become { value: 'EMEA', label: 'EMEA' }; now no option), what a stored dashboard sees, the one-line rewrite, both rulings, and that resetDashboardFilterWarnings stays exported — each of which the diff bears out. The opening sentence is the director's ruled wording verbatim. @object-ui/core is 17.6.0 in the fixed group with @object-ui/types and @object-ui/plugin-dashboard, so one minor entry publishes all three at or above 17.7.0 and never as a 17.6.x patch, as ruled; the types and plugin-dashboard hunks are JSDoc, comments and a README comment, so no separate entry is owed (Changeset Declaration, Changeset Fixed Group Check success). No ADR-0087 disposition marker is owed here: that is objectstack's check:adr-0087-registration, and objectui's root package.json declares no such script.
  • Clause-②: on the PR body — Clause-②: yes — published runtime behaviour is removed (the bare-string lift, and the exported resetDashboardFilterWarnings if it retires with its memo), per the execution parameters in 5511028727. RIGHT: yes for a removed published behaviour, and yes takes at least minor, satisfied. No arm is written, a legal spelling (at most one; (narrowing) would be the accurate one — observation). The conditional sub-clause resolved to "stays", which the body's next paragraph says, and the changeset names no removed export — consistent. The line is the claim's, verbatim.
  • The W4 note on .changeset/7759-dashboard-header-global-filters-spec.md.
    • Inside the ruling's form? Yes. Measured on the two refs: origin/main's 52-line file is a byte prefix of the head's 68-line file (cmp over the base's length: identical), so no existing line was edited or deleted; numstat +16/−0; the frontmatter ('@object-ui/types': minor, '@object-ui/plugin-dashboard': patch) is byte-identical, md5 ac1bfd0472c0d0b981d923c32d435f18 on both refs; whole-file md5 94edd5855709afe137f9184c630f298c → 5c8f0508bed5ed6f5b76254bb74d622d, as the PR body states; 0 angle-bracket characters. The note is in the objectui#10877 / PR docs(changeset): date-note six pending entries that PRs #10793, #10802 and #10821 made false (objectui#10877) #10891 form the ruling names (⚠️ Dated note, DATE — … — objectui#NNNN. …, closing with "the text above is kept as the reading of this change"), the shape of the notes docs(changeset): date-note six pending entries that PRs #10793, #10802 and #10821 made false (objectui#10877) #10891 landed on main (for instance the objectui#10563 note on 10156-edit-form-writes-only-changed-fields.md). Dated 2026-09-29, the ruling's day and the commit's. The ruling's sequence — the note inside this PR, main merged, a final review — holds: origin/main 2eaf5be27 is an ancestor of the head and the head differs from origin/main in exactly the PR's 11 files.
    • True on this head? Yes. Each statement is borne out by the diff: normalizeFilterOptions stopped converting a stored bare-string option into a pair; a shorthand-only filter resolves with no options; a mixed array keeps only object members; a once-per-filter dev-mode console.warn names the filter and the dropped members; the window closed on the 2026-09-02 ruling; the two quoted sentences no longer hold; the validator's refusal of options: ['EMEA'] is unchanged and now matches the read path; "later in this same release" holds because both entries are pending in the same fixed group; the pointer to .changeset/retire-options-shorthand-lift-4356.md (PR objectui#10930) is correct. One precision note, not verdict-carrying: "a member that is not a { value, label } object now yields no option" is, read strictly, wider than the code — a { value } object with no label still yields an option (①.1's observation); the note's subject sentence is the stored bare-string option, and the PR's own changeset carries the qualifying "(a string, a number, a boolean)".
    • The only pending sentence this PR made false? Yes, on my own sweep of the head's pending .changeset/*.md (normalizeFilterOptions|bare[- ]string|shorthand|lifted|lifts, filtered to option|globalFilter|4356|7917): the 7759 paragraph is the only hit about globalFilters[].options. The other hits are the export-options bare array (4535, 6956, 7762), the object-map / gantt data arrays (8348), kanban columns (8990), picklist / field / detail-view options (8632, 6844, 10296), the widget shorthand (5709) and filterableFields (7779) — other contracts, still true. The nine entries the changeset-claim-re-read gate lists (5865883972, refreshed on this head) name complex.zod.ts or the README for other reasons and say nothing about the options lift.
  • Gate verdicts on the head: Changeset Bump Policy, Changeset Claim Re-read, Changeset Declaration, Changeset Fixed Group Check, Changeset Overwrite Report — all success. Overwrite Report is report-only by design and the append is its documented legitimate-modification case.

③ Boundary flags

Every deviations, open_questions and out_of_scope_findings entry across the six reports, answered or escalated.

5865928783 (head bc4ea976e). deviations: (1) complex.zod.ts outside the claimed surface — answered, accepted: addendum 5865980488 amended the surface; the hunk is JSDoc only and ships in emitted declarations; the three complex.zod.ts commits that landed on main since merged cleanly (a1058f90e) and the file's diff against origin/main is exactly this hunk. (2) check:doc-snippets not measured — closed by CI: Doc Snippet Type Check success. (3) assumption 2 falsified, the reset export stays — confirmed by ①.3; the Clause-② line and changeset are consistent with it. (4) assumption 3 recount, six members in five tests — consistent with the diff; the two packages/types refusal pins keep their assertions. open_questions: (1) audible skip, A or B — A, on the governing text in ①.2; no escalation. (2) dev-only or always-on — A for this PR; always-on is a one-line product decision for the maintainer, not blocking, and the seat may file it as its own card. out_of_scope_findings: (1) select-FIELD options: ['…'] sites — another contract, correctly untouched, not judged here. (2) CHANGELOGs narrating the lift — published record, not re-addressed, per objectstack AGENTS.md's packages/*/CHANGELOG.md row and objectui #11's CHANGELOG clause.

5866362802 (head 98623a24d). deviations: (1) the i18nLabel comment outside the amended surface — resolved as W5 (addendum 5866480991, landed e0647486b). (2) check:readme-exports not measured — closed by CI: README Export Check success. (3) plugin-dashboard type-check not run — closed by CI: Type Check success on the head. (4) the first-round sweep's option|filter post-filter — accepted as the cause; the rework sweep has no post-filter and my own re-run agrees with its 18-hit reading. (5) PR body not patched — superseded: the final round refreshed the body (5883501541), which now carries W1–W5, the corrected sweep and the W4 ruling. open_questions: who lands the i18nLabel fix — A, surface amended and the dev patched it; done. out_of_scope_findings: the i18nLabel comment — landed as W5.

5866443287 (W4 blocked). deviations: (1) W4 not written, the classifier refusal held and not re-routed — resolved by ruling 5883360525; landed in a89065402 in the ruled form. (2) i18nLabel outstanding — W5, landed. (3) the PR body's 7759 bullet half right — superseded by the refreshed body. open_questions: who lands W4 — the maintainer's option: the dev, inside this PR; done.

5866532227 (head e0647486b) and 5866654956 (head 1daf7edf7). deviations: W4 held — resolved as above; PR body not patched / sentences to refresh — superseded by the refresh. No open questions, no out-of-scope findings.

5883501541 (head a89065402). deviations: (1) PR body refreshed via post-stamped — noted; I read the body: it matches the diff, carries 0 angle brackets, and its only closing keyword is the intended Fixes #4356. (2) check:doc-snippets / check:readme-exports not measured — closed by CI, both success. (3) no pr_ready, no auto-merge, no label write — correct: a dispatched PR stays draft until the seat lands it (objectui AGENTS.md, exception ② under the self-merge rule). No open questions, no out-of-scope findings.

Check-runs on the head (polled until none was in progress, then re-read right before this record was written): 43 runs — 40 success, 3 skipped, 0 failure, 0 in progress. The skipped three are Test (coverage) and Test (coverage shard), matrix-conditional, and dependabot, not a Dependabot PR. Every gate the earlier record read on bc4ea976e is green here, and the one it reported red — Spec Main Shape Gate — is success on this head: PR #10934's JoinedReportBlock pin fix is merged in through 1daf7edf7, as the seat's 5866118569 predicted. All eight Test shards, Test (dist pins), Type Check, Lint, Build & E2E, Build Docs, Bundle Analysis, Doc Snippet Type Check, README Export Check, Line Citation Gate, Control Byte Scan and the five changeset gates are success. Governed Surface Queue Guard is success on its pull_request leg (exit 0 by design; every touched path is NOT GOVERNED — .changeset/** is not a governed surface), and the PR carries no needs:contract-review label, so the merge_group leg's label check has nothing to refuse. The PR is a draft, as a dispatched PR must be until the seat lands it.

Implemented-by: claude/issue-4356-retire-shorthand-lift
Reviewed-by: session_012UwY3ahMixEFkfTUxMVkYm

VERDICT: PASS

@objectstack-fleet
objectstack-fleet Bot marked this pull request as ready for review September 29, 2026 04:29
@objectstack-fleet
objectstack-fleet Bot added this pull request to the merge queue Sep 29, 2026
Merged via the queue into main with commit a51fa0c Sep 29, 2026
45 checks passed
@objectstack-fleet
objectstack-fleet Bot deleted the claude/issue-4356-retire-shorthand-lift branch September 29, 2026 04:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

normalizeFilterOptions accepts a bare-string globalFilters[].options shorthand that @objectstack/spec rejects at publish

2 participants