Repository navigation
refactor(plugins): one authority each for AggregationConfig, ConditionalFormattingRule and ViewType (objectui#6349, batch 7) - #12071
Conversation
…nalFormattingRule and ViewType (objectui#6349, batch 7) Three plugin <-> @object-ui/types rows of the one-authority ledger, each two meanings behind one name. @object-ui/types keeps the general name in all three. - AggregationConfig: the grid's per-group header aggregation (field, type) is renamed GroupAggregationConfig; types' is the query-AST aggregation (function, alias, distinct, separator). The plugin-grid root publishes the new name in place of the old one. - ConditionalFormattingRule: KanbanImpl's module-local alias of KanbanConditionalFormattingRule is deleted; the board spells the kanban rule by its own name. No package entry reached the alias. - ViewType: plugin-list's alias of core's ListViewVisualization (nine arms, without list and detail) is deleted; the switcher and ListView spell ListViewVisualization, and the plugin-list root no longer publishes ViewType. KNOWN_COLLISIONS goes from 19 to 16 rows. Types only: emitted JS is byte-identical. Changesets: plugin-grid and plugin-list minor with breaking notes, plugin-kanban patch. Claude-Session: https://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8 Co-authored-by: Claude <noreply@anthropic.com>
✅ Console Performance Budget
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
Size Limits
|
Contract reviewServed-tier: Inputs: card objectui#6349 (body and all 29 comments, the batch 7 claim ① Derived judgmentsEach accept-set and public-surface change the diff implies, read off the diff and the head tree, with my own census of in-repo readers at base.
Check-runs on this head (the gate verdicts): 43 runs, 40 success, 3 skipped (dependabot, Test (coverage), Test (coverage shard): the expected three), 0 failure. Type Check, Lint, Test shards 1–8 plus the Test aggregate, Test (dist pins), Build & E2E, Build Docs, Doc Snippet Type Check, README Export Check, Changeset Declaration, Changeset Bump Policy, Changeset Fixed Group Check, Changeset Claim Re-read, Changeset Overwrite Report, Governed Surface Queue Guard, Spec Main Shape Gate, Line Citation Gate, Control Byte Scan and Bundle Analysis all read success. The legacy Vercel status is success. The one-authority gate runs under the Test shards; the dev's seven ablation legs (three stale, three fresh, one control, each restore proven) are the non-vacuity evidence, read and not re-run. ② Semver level
③ Boundary flags
Implemented-by: VERDICT: PASS |
Refs #6349 (batch 7)
Clause-②: yes
Batch 7 of the one-authority burn-down, on claim
6088763852(seatdomain:ui#3, sessionhttps://claude.ai/code/session_01CGZy1BGCjdN5cXqL9cnvB8). Three "plugin vs@object-ui/types" rows ofKNOWN_COLLISIONSconverge, so the ledger goes from 19 rows to 16. Each row was two meanings behind one name. In all three,@object-ui/typeskeeps the general name and the plugin side gives up the name. Types and comments only: no runtime behaviour changes, and no emitted JavaScript changes.This PR has no closing keyword. The card stays open for later batches.
What each row was (measured on base
e391f876)The member lists below come from one TypeScript program over each package's BUILT root entry (
exports["."].types), with dist rebuilt for the base tree.AggregationConfig: two meanings, so the plugin side is renamed.packages/types/src/data-protocol.tsfunction(8 arms, incl.array_aggandstring_agg),field?,alias?,distinct?,separator?DriverQueryConfig.aggregations, compiled by@object-ui/core'sQueryASTBuilderquery-ast.tspackages/plugin-grid/src/useGroupedData.tsfield,type(AggregationType, 6 arms)ObjectGridSchema.aggregations)@objectstack/spec17.7.0The two share only
field, and even that differs (field?againstfield). A re-point would retype the grid'stypekey asfunction, which the grid's runtime reads, so it is not a types-only move. The grid's declaration is the narrower meaning. It becomesGroupAggregationConfig, and the plugin-grid root publishes that name in place ofAggregationConfig. The members are unchanged.ConditionalFormattingRule: the plugin side was an alias of a name that already exists. The kanban site wasexport type ConditionalFormattingRule = KanbanConditionalFormattingRuleinKanbanImpl.tsx.@object-ui/typesdeclares bothConditionalFormattingRule(theobject-gridandlist-viewrule) andKanbanConditionalFormattingRule(theobject-kanbanrule). They differ by one member: the grid's rule carries the retiredexpression?: nevertombstone, and the kanban rule does not. So the alias put the kanban meaning behind the grid's name. The kanban meaning already has its specific name, so the alias is deleted and the board spellsKanbanConditionalFormattingRule. The alias had 0 importers. No package entry reachesKanbanImpl.d.ts: a program rooted at the plugin-kanban entry loads 7 of the package's own declaration files, andKanbanImpl.d.tsis not one of them. So the alias published nothing.ViewType: two unions, so the plugin side's alias is deleted.@object-ui/types'ViewTypehas 11 members: the spec's list-view types plus thelistanddetailcategories. plugin-list'sViewTypewas an alias of@object-ui/core'sListViewVisualization, which has 9 members: the same set withoutlistanddetail. The switcher's two total maps (icons and labels) are keyed on the 9-member union. A re-point to the 11-member union would make both maps incomplete, which is a compile error. Filling that gap would need icons and labels forlistanddetail, which is a runtime change. The narrower meaning already has its own name, so the alias is deleted.ViewSwitcher.tsxandListView.tsxspellListViewVisualization, and the plugin-list root no longer publishes aViewType. It had 0 readers through that entry in the repo (control: the same scan of import clauses finds 23 other bindings from that root,ListView×21 among them), and@objectstack/spec17.7.0 has 0 hits.Why no re-point anywhere. Batch 3's rule makes
@object-ui/typesthe only legal authority. In each row the plugin side means something narrower than thetypesname, and both meanings are live. So the rule of batches 4 to 6 applies: rename the narrower side, and keep the general name ontypes. Where the narrower side was only an alias of a name that already exists, the alias goes, and no new name is coined.Published surface, base vs head
This is one TypeScript program per tree over each package's built root entry. Dist was rebuilt for each tree, and every head marker was read in dist before measuring.
Exported name sets:
AggregationConfigout,GroupAggregationConfigin, with identical members;ViewTypeout.Unchanged shapes: types'
AggregationConfig,ConditionalFormattingRule,KanbanConditionalFormattingRuleandViewType(11 members); core'sListViewVisualization(9 members); plugin-list'sViewSwitcherProps, whose members are still typed onListViewVisualization.An external consumer, probed as a virtual file that resolves the packages through
node_modules:import type { AggregationConfig } from '@object-ui/plugin-grid'fails loudly at head with TS2724, which names the replacement: "Did you mean 'GroupAggregationConfig'?";import type { ViewType } from '@object-ui/plugin-list'fails with TS2305;GroupAggregationConfig;ListViewVisualizationfrom@object-ui/core;ViewSwitcherProps['currentView']): 0 diagnostics;@object-ui/types. It reads 0 diagnostics on base and on head;Emitted output: base and head dist differ only in declaration files and their maps:
index,useGroupedData,useServerGrouping;KanbanImpl;index,ListView,ViewSwitcher.No
.jsfile differs in any of the six packages, and types, core and plugin-view dist are byte-identical. So no first-load bytes move.Changesets
6349-batch7-plugin-grid.mdminorAggregationConfig) and its replacement arrives (GroupAggregationConfig). Breaking-change note with the migration.6349-batch7-plugin-list.mdminorViewType). Breaking-change note namingListViewVisualizationfrom@object-ui/core.6349-batch7-plugin-kanban.mdpatch@object-ui/typesis not touched, so it gets no changeset. The grades follow the claim's per-package criterion. ⛔ Nomajor.Docs
packages/plugin-grid/README.mdlists the package's type exports, and it now namesGroupAggregationConfig.check:readme-exportsproves the edit was needed: when the base README is fed against head dist (--readmeoverride), it flagsAggregationConfigat that line aswrong-path, owned by@object-ui/types. No README or docs page names plugin-list'sViewTypeor the kanban alias.Gates
All gates were read at head
ceb7b297f. Heavy runs went throughos-verify-lock.pnpm exec vitest run scripts/__tests__/one-authority-per-exported-name-6273.test.ts: exit 0,Tests 11 passed (11). The ledger has 16 rows.pnpm exec vitest run --maxWorkers=2overpackages/plugin-kanban/,packages/plugin-list/and 31 test files elsewhere that read a touched file's text or path (types, core, app-shell, the console, i18n, react, sdui-parser, calendar, gantt, map, view and scripts): exit 0,Test Files 223 passed (223),Tests 3076 passed (3076).pnpm exec vitest run --maxWorkers=2 packages/plugin-grid/: exit 0,Test Files 197 passed (197),Tests 1851 passed (1851).pnpm --filter @object-ui/PKG type-checkfor plugin-grid, plugin-kanban, plugin-list, plugin-view, core and types, with dist rebuilt and the script names echoed: one chained run, exit 0, 0error TSlines.pnpm type-check:scripts: exit 0.check:doc-snippets: 785 of 785 blocks judged, 0 failed. It ran after its own scoped build.check:readme-exports: OK, with 582 of 582 self-imports real.check:control-bytes,check:test-path-roots,check:changeset-claimsandcheck:pending-changeset-literals;check:icon-record-names(it anchors on the plugin-list switcher'sVIEW_ICONS),check:spec-symbolsandcheck:handler-key-reads;check:new-line-citations, which reports 0 new;check-changeset-no-major;check-changeset-presence, which reads 7 source files of 3 released packages and 3 changesets.pnpm exec eslinton the 8 touched TS files: 0 errors. Two warnings fall on changed lines inListView.tsx, and both are the same rule on the same construct at base (no-explicit-anyon a filter callback,set-state-in-effect). Those lines changed only their type name. The file has 187 warnings at base and 187 at head.git merge-treeagainstmaine391f876is clean.Not run locally:
Reverse verification
Every leg went through
ablation-replacein wrap mode. The predictions were written before any leg ran. Each leg landed on disk: the anchor count went from 1 to 0, the replacement count from 0 to 1, and the blob changed. Each was restored with blob equal to HEAD and an emptygit diff HEAD, which the tool checked and the driver checked again. The gate is a source scan, so no dist leg applies.AggregationConfigrow put backTests 1 failed / 10 passed;no longer collides at:listsuseGroupedData.tsanddata-protocol.tsConditionalFormattingRulerow put backKanbanImpl.tsxandobjectql.tsViewTyperow put backViewSwitcher.tsxandviews.tsGroupAggregationConfig as AggregationConfig(the tempting back-compat shim)AggregationConfig — a NEW colliding name: the plugin-grid barrel (aliasing re-export) anddata-protocol.ts(interface declaration)KanbanImpl.tsxre-declares the aliasConditionalFormattingRule — a NEW colliding name:KanbanImpl.tsx(type declaration) andobjectql.ts(interface declaration)ListViewVisualization as ViewTypeViewType — a NEW colliding name: the plugin-list barrel (aliasing re-export) andviews.ts(type declaration)Tests 11 passed (11)Acceptance notes
GroupAggregationConfigis new on the plugin-grid root. It is the rename target the claim's rule implies for a published site, so this PR does not treat it as an extra export. If the seat reads it otherwise, the claim needs an amendment for it.ViewTypeand does not re-exportListViewVisualization. That name is already published at the@object-ui/coreroot, and a second export site would add nothing.ViewSwitcherProps['currentView']names the same union from this package.ConditionalFormattingRuleas "the contested name". They now say "the bare name", because it is no longer contested. The near-spelling fixtures themselves are unchanged.GroupAggregationConfig, the kanban comment and the switcher comment each say why the general name is not used, so the next author does not restore it.GroupAggregationConfighas the same members as the inline element type ofObjectGridSchema.aggregationsin@object-ui/types(and its zod twin). That is a structural copy, not a name collision under the gate. It is noted here and not filed.Generated by Claude Code