Repository navigation
feat(types)!: retire object-grid's resizableColumns on both faces and stop ObjectGrid reading it (part of objectui#6152, round 7) - #11955
Conversation
…d stop ObjectGrid reading it objectui#6152 round 7, the four strokes the seat scoped once @objectstack/spec 17.7.0 refused the key in the object-grid row: - ObjectGridSchema.resizableColumns is `?: never` on the interface; - the flat zod ObjectGridSchema declares it as a retirementTombstone() whose message names properties.resizable; - ObjectGrid reads `resizable` alone (the `?? schema.resizableColumns` fallback is dropped), and the registration's `resizable` description stops naming the old spelling; - the UnmirroredDeclared entry leaves the parity ledger (4 entries / 5 keys), with every pinned prose figure and its history sentence moved. The round-6 pin that read "is NOT mirrored" is flipped into the retired assertion; a round-7 pin file covers the protocol precondition, the mirror, every authored door and the TS face, and a plugin-grid pin counts the column resize handles. Claude-Session: https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw Co-authored-by: Claude <noreply@anthropic.com>
…nown instead of any The pin writes the retired spelling on purpose, so it needs a cast; a cast through `unknown` to ObjectGridSchema does that without adding an explicit `any` (the only lint warning the round's diff added). Claude-Session: https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgw 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. Which half objected:
📦 Bundle Size Report
Size Limits
|
|
Generated by Claude Code |
Contract reviewServed-tier: PR objectui#11955, round 7 of card objectui#6152 (draft, not ready, no auto-merge). Inputs, and nothing else: the card body and all 54 comments (the scope comments 5957903936, 5958557260, 6020652401 and 6029312212; the claim 6056162668; the dev report 6057365466; the round-6 report 5957803718 and its ACCEPT 5958245046 for the stop condition this round releases), the PR body, its 10-file list, the net diff against ① Derived judgmentsPublished TypeScript face (
Zod accept sets (
Renderer (
Test-only ledger moves (no published face):
Corpus and docs:
File surface against the claim 6056162668: every one of the 8 named files is touched and inside scope; the two new pin files ( ② Semver level
③ Boundary flagsDev-declared deviations (report 6057365466), each answered:
Check-runs on this head, at the final poll, all 43 completed: 39 success, 3 skipped (Test coverage, Test coverage shard, dependabot — the expected skips) and 1 failure, Noted, not flagged:
Escalations: none. No maintainer decision is needed for this head to land. Implemented-by: VERDICT: PASS Rendered 2026-10-08T10:12Z · a read-only contract review of PR objectui#11955 on the head named above; the newest record naming this head governs, and any push after it voids it. Generated by Claude Code |
…ssue-6152-resizable-columns-retire
✅ 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: PR objectui#11955, round 7 of card objectui#6152 (draft, not ready, no auto-merge, head repo is the base repo). This head is a base merge: ① Derived judgments
② Semver levelUnchanged from ③ Boundary flagsCheck-runs on Bundle Analysis. Conclusion Dev-declared deviation (base-merge report Superseded from the earlier record: its deviation (f), that Noted, not flagged:
Implemented-by: VERDICT: PASS Rendered 2026-10-08T10:56Z · a read-only contract review of PR objectui#11955 on the head named above; the newest record naming this head governs, and any push after it voids it. Generated by Claude Code |
Part of #6152 (round 7)
The card stays open for its later rounds, which triage booked as separate PRs: the 17.7.0 member moves (
operations,conditionalFormatting,filter) andObjectCalendarSchema.calendar's.passthrough(). Neither is in this PR.Clause-②: no
This round narrows and widens nothing. It retires
object-grid'sresizableColumns, which@objectstack/spec17.7.0 already refuses, so it owes one at-tier contract review before the queue.What changed: the four strokes the seat scoped
The seat answered (card comment
5957903936) thatresizableis canonical andresizableColumnsretires with no window, once the spec half was installable.@objectstack/spec17.7.0 retired the key inComponentPropsMap['object-grid'](objectstack#21445), and objectui resolves 17.7.0 since objectui#11717.ObjectGridSchema.resizableColumnsis?: never, following the package's convention for a retired member (thedefaultSortprecedent on the same interface). The@deprecatedtag points atresizable, which isproperties.resizableon an authored node.ObjectGridSchemain@object-ui/types/zoddeclaresresizableColumns: retirementTombstone(...). Its one-string message, theOBJECT_GRID_RESIZABLE_COLUMNS_RETIREDconstant beside the objectui#11068 constants, namesproperties.resizable. It sits next todefaultSort's tombstone. Theobject-viewtableslot keeps its own refusal, which.extends over this member, just as it does for the five keys objectui#11068 retired on the grid.ObjectGridhandsDataTableresizableColumns: schema.resizable ?? true. The?? schema.resizableColumnsfallback is gone. Theobject-gridregistration'sresizableinput description no longer calls the old spelling a fallback. The registration's header comment now namesresizableColumnsbesidedefaultSortas a spelling that left by tombstone, not by exemption.objectql.zod.ts#ObjectGridSchemaentry leavesUnmirroredDeclared. Its one key was retired, and a tombstone is a mirrored member, so the entry went with it, asPaginationSchema's did. The entry's docblock is rewritten as the departed-entry comment its neighbours use and keeps the entry's history. Every pinned prose figure moved and gained its history sentence: the header bullet, the split's SPEC-DERIVED line, the totals line and its narrative, both ledger docstrings, and the cross-ledger union sentence. The objectui#7279, finding(types): zod-mirror-parity's three LEDGER entry counts are still hand-written prose — the half of #6141 that #7433's scope deliberately left behind #7733, finding(types): zod-mirror-parity's header says KnownDrift holds 62 keys; two instruments measure 63 — wrong since objectui#7664, and the sibling half of #7733 #8222 and finding(types): zod-mirror-parity's two ledger docstrings say UnmirroredDeclared records 94 keys; two instruments measure 87 — unmoved since objectui#7779, and outside every pin in the file #8243 pins derive the new figures and are green:UnmirroredDeclared4 entries / 5 keys, 2 / 3 spec-derived and 2 / 2 local, with a union of 9. NoKnownDrift,RuntimeOnlyDeclared,WiderThanDeclaredorMirroredUndeclaredrow moved.SPEC_DERIVED_PAIRSkeepsObjectGridSchema, because its membership comes from the mirror's spec references, which did not change.What moves for a reader of the published packages
{ "type": "object-grid", "properties": { "resizableColumns": false } }and the flat spelling on the node were already refused by name before this change, through the spec row andflatPropRefusals. That holds on the tolerant face, the strict face andsafeValidateSchema, and the round-7 pin re-measures all three.@object-ui/types. The TypeScript member now refuses any value. The exported flatObjectGridSchemamirror refuses the key at the key withinvalid_type, whereBaseSchema's.passthrough()used to keep it unexamined.@object-ui/plugin-grid. A grid node that still carriesresizableColumnsgets the default, resizable columns.resizableColumns: falseno longer removes the resize handles. A tree-scoped search found no producer that writes the key on anobject-grid(see Measurements)..changeset/6152-resizable-columns-retired.mdbumps@object-ui/typesand@object-ui/plugin-gridminor(the fixed group's version policy) and states the break.Measurements before editing (the dispatch's mechanism assumptions)
H1, the sites: held, on base
19a7348, which is the dispatch'sf1781beplus one app-shell commit. The one renderer read is the?? schema.resizableColumnsfallback inObjectGrid. The registration names the spelling in theresizableinput's description and in the header comment. The flat mirror did not carry the key, and thetableslot refused it by name.H2, the install surface already refuses it: held on the installed
@objectstack/spec17.7.0.ComponentPropsMap['object-grid'].safeParse({ resizableColumns: true })fails withinvalid_typeatresizableColumnsand the retired-key message namingresizable. The lit control{ resizable: true }parses, and the strictness control (an unknown key) fails withunrecognized_keys. So the local tombstone refuses nothing the installed protocol accepts. The round-7 pin re-reads this against the installed package.H3, the pins that flip: partly held. The round-6 test "
resizableColumnsis NOT mirrored: its route is open, and the parity ledger keeps it" flips in place into the retired assertion: the key is a member, andtrueandfalseare each refused at the key. Two other pins do not flip, because they pin thetableslot's own refusal, which this round leaves standing:table.navigationandtable.resizableColumnsstay withheld, refused by name";object-view-slot-key-lists.test.ts'saliasrow.Their docstrings now record that the grid itself tombstones the key since round 7. No assertion was deleted.
Fixture sweep, by the rule's consumer radius (the whole repository). Zero tracked JSON, Markdown or MDX documents write
resizableColumnson anobject-grid; a control search forresizablefinds 11. The one consumer test that writes the key past the type is plugin-view's table-relay test, which writes it to prove it is withheld; it is green.DataTableSchema.resizableColumnsis a different block's own key and is untouched, as the claim requires.Tests and gates
Run from the worktree root with repo-relative paths. Every build, suite, type-check and ablation went through
os-verify-lock.sh. Each exit code was captured before any pipe.Build.
turbo run build --concurrency=2overcheck-doc-snippet-types --build-filter:Tasks: 35 successful, 35 total. The dist was checked after the build:packages/types/dist/objectql.d.tscarriesresizableColumns?: never;resizableColumns: e.resizable ?? !0and has 0 hits for the old fallback.Type-checks, both scripts echoed in the log, exit 0, 0
error TS:pnpm --filter @object-ui/types type-check(tsc --noEmit && tsc -p tsconfig.examples.json && tsc -p tsconfig.test.json);pnpm --filter @object-ui/plugin-grid type-check(tsc --noEmit && tsc -p tsconfig.test.json).--listFilesOnlyshows both test projects include the touched and new test files.Suites, with
--maxWorkers=2:vitest run packages/types/:Test Files 360 passed (360),Tests 9624 passed (9624).vitest run packages/plugin-grid/ apps/console/src/__tests__/registry-inputs-spec-parity.test.ts:Test Files 195 passed (195),Tests 2077 passed (2077). A verbose re-run of the two named files read 255 console-parity tests and the 4 new grid tests, each passing.ObjectView.tableSlotRelay-10976.test.tsx: 7 passed.Gates at the final head
06db65a6, all exit 0:check-changeset-presence("9 source file(s) of 2 released package(s) changed, and this change declares 1 changeset(s)"),changeset:check,check:changeset-claims("No pending changeset names a file this change touches"; a search of pending changesets forresizableColumnsand for ledger figures also found nothing),check:pending-changeset-literals;check:new-line-citations("0 new citation(s)"),check:control-bytes,check:spec-symbols,check:test-path-roots,check:unreferenced-sources,check:handler-key-reads,check:vi-mock-specifiers,check-type-check-coverage("43/43");check-governed-queue-guard --testover the 10 paths: NOT GOVERNED.Doc and skill gates, run on the built closure at
4a1feb41, all exit 0:check:skill-examples;check:doc-types;check:doc-snippets("784 of 784 block(s) judged, 0 failed");check:doc-examples;check:readme-exports;check:component-surface-parity(report-only);check:prompt-keys;check:designer-field-key-parity.06db65a6changes only the plugin-grid pin's cast, which no doc gate reads.Lint, a declared narrowing.
eslint --no-inline-config --format jsonjudged all 9 changed TS files and ignored none: 1 error and 261 warnings. No message sits on an added line once the pin'sanywas replaced by a cast throughunknown(06db65a6). The one error is the inline-disabledreact-hooks/static-componentsline inObjectGrid's empty-state icon, which this diff does not touch. Invariance:eslint.config.jsdeclares noparserOptions.projectorprojectService(no type-aware linting), so this diff cannot move a verdict in an untouched file. The repo-widepnpm lintis CI's.Reverse verification
Predictions were written to scratch before each run. Each mutation ran through objectstack's
scripts/ablation-replace.mjs(wrap mode) on committed HEAD06db65a6, inside a harness with atraprestore on absolute paths. Every leg was restored and proven: blob equal to the HEAD blob,git diff HEAD0 bytes, porcelain 0 lines. No leg needed a dist step: every subject resolves to source through relative imports.A1, put the renderer's fallback read back (anchor x1 to x0, blob
2ec85adbtoed7482d6). The plugin-grid pin read1 failed | 3 passed, exactly the predicted row: "resizableColumns: falsealone is not read",expected +0 to be 2.A2, delete the mirror's tombstone member (blob
59edcee7toece13ddb).tsc -p tsconfig.test.jsonexited 2 with exactly oneTS2322,"objectql.zod.ts#ObjectGridSchema"not assignable tonever, atassertionUnmirroredMatchesLedger.4 failed | 159 passed, as predicted: the three mirror rows of the round-7 pin and the flipped round-6 test. Every authored-door and slot row stayed green, and so didobject-view-slot-key-listsand the parity runtime pins.A3, re-declare the TypeScript member as
boolean(blobb1d0a398to1caaa5d4).tsc -p tsconfig.test.jsonexited 2 with the three predicted errors:TS2578, the round-7@ts-expect-errornow unused;TS2344atassertionResizableColumnsIsRetiredOnTheInterface;TS2322atassertionDriftMatchesLedger(the mirror'sneveragainst a declaredboolean).The first A3 attempt timed out in the lock queue (exit 99) before
tscran. Its restore was proven, and it was re-run under the same slot.NOT MEASURED
check:sdui-registration-pins. It weighs registrations in a built console, and this diff adds and removes no registration; only one input's description text changed.pnpm testfarm and the repo-widepnpm lint. Both are CI's.resizableColumnstoObjectGrid(the tree-scoped search above), andObjectViewwithholds it by construction.Acceptance notes
zod-mirror-parity.test.ts's paragraph listing which cross-ledger figures are pinned spelled their values as digits (13, both8s). Those digits had gone stale before this round, while the pinned ones moved. Because this round moves the same figures, the paragraph now names them by role, not by digit.apps/console'sregistry-inputs-spec-parity.test.tscomment on the harvestedobject-grid.resizableColumnsrow ends "Retiring the renderer's own read of the old spelling is objectui#6152's." That read is retired here, so the sentence is now history. It is outside this round's surface and was left as is. Carrier: the next PR that touches that file.content/docs/plugins/plugin-view.mdx,packages/plugin-view/README.mdand theObjectViewrelay comment still callresizableColumnsa legacy alias thetableslot withholds (writeresizable). That stays true, because the slot's own refusal is unchanged.Deviations, declared
Claude-SessionplusCo-authored-by: Claude), not the harness reminder's model-named line.Session:
https://claude.ai/code/session_01DBZ9bntPZ7VKyQNtJeNsgwGenerated by Claude Code