From 93173fa7b4c2cee19aef5df8d5aed4e3a10004ed Mon Sep 17 00:00:00 2001 From: Claude Date: Sat, 29 Aug 2026 04:10:51 +0000 Subject: [PATCH] refactor(plugin-grid): dismantle the emit-side fitContent cast, re-point the 6458 control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Maintainer ruling 2026-08-29 (option 甲) completes its declare branch: with `TableColumn` declaring `fitContent` since PR #6673, the `(col as any).fitContent` read in `ObjectGrid`'s grouped-width pass loses its cast. What that buys is measured rather than assumed: nothing at the type level. The receiver is `any` either way — `applyColumnChrome` is `(col: any)`, so `orderedColumns` is `any[]` and the loop widens it a second time. The TypeScript checker reports `isAny=true` for the receiver both before and after the cast, against a control in the same query shape that reports a non-`any` type. The load-bearing half is the guard. `columnReadBoundary-6458.test.ts` used that cast as anti-vacuity control 3 — its only proof that the scanner can find a real cast in the real file at real scale — and that control's own comment requires it to be re-pointed at another real cast and never deleted. Its scanner hard-coded the receiver to `col`, and the dismantling left zero `col` casts outside the guarded region, so the receiver becomes a parameter (defaulting to `col`, leaving every bound assertion unchanged) and the anchor moves to `(schema as any).hideRowHeightToggle`. That anchor is picked on a principle, not merely moved: a deliberately held non-authoring key (objectui#5091) that `gridNonAuthorKeys.test.tsx` independently pins, so it cannot expire silently the way `fitContent` just did. Control 2 gains assertions pinning that the receiver parameter is honoured, so the bound assertions' `col` scoping cannot quietly become a fiction. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01CRJge11jso9TpXRWFt1Z49 --- .changeset/6424-dismantle-fitcontent-cast.md | 30 ++++++ packages/plugin-grid/src/ObjectGrid.tsx | 12 ++- .../__tests__/columnReadBoundary-6458.test.ts | 95 +++++++++++++++---- 3 files changed, 118 insertions(+), 19 deletions(-) create mode 100644 .changeset/6424-dismantle-fitcontent-cast.md diff --git a/.changeset/6424-dismantle-fitcontent-cast.md b/.changeset/6424-dismantle-fitcontent-cast.md new file mode 100644 index 0000000000..d4ab6e2d57 --- /dev/null +++ b/.changeset/6424-dismantle-fitcontent-cast.md @@ -0,0 +1,30 @@ +--- +--- + +No published behaviour changes: the emit-side `(col as any).fitContent` cast in +`ObjectGrid`'s grouped-width pass is dismantled, and the guard that observed it is +re-pointed rather than deleted (objectui#6424, maintainer ruling 2026-08-29, option +甲). + +`TableColumn` declares `fitContent` since PR #6673, so the ruling's declare branch +completes with the cast removed. ⚠️ The narrowness of what that buys is measured, not +assumed: the cast was already worth **zero** type safety, because the receiver is `any` +either way — `applyColumnChrome` is `(col: any)`, so `orderedColumns` is `any[]` and the +loop widens it a second time. The TypeScript checker reports `isAny=true` for the +receiver both before and after the cast, against a control in the same query shape that +reports a non-`any` type. Removing it changed no emit type and no rendered output. + +The load-bearing half is the guard. `columnReadBoundary-6458.test.ts` used that cast as +its anti-vacuity control 3 — the one control proving its scanner can find a real cast in +the real file at real scale — and that control's own comment requires it to be re-pointed +at another real cast and never deleted. Its scanner had the receiver hard-coded to `col`, +and dismantling left the file with zero `col` casts outside the guarded region, so the +receiver becomes a parameter (defaulting to `col`, so every bound assertion is unchanged) +and the anchor moves to `(schema as any).hideRowHeightToggle`. + +That anchor is chosen on a principle rather than merely moved: it is a deliberately held +non-authoring key (objectui#5091) that is independently pinned by +`gridNonAuthorKeys.test.tsx`, so it cannot expire silently the way `fitContent` just did — +retiring it turns that guard red in the same run. Control 2 gains a pair of assertions +pinning that the new receiver parameter is honoured rather than ignored, so the bound +assertions' scoping to `col` cannot quietly become a fiction. diff --git a/packages/plugin-grid/src/ObjectGrid.tsx b/packages/plugin-grid/src/ObjectGrid.tsx index 0e314c331c..0988ddca0a 100644 --- a/packages/plugin-grid/src/ObjectGrid.tsx +++ b/packages/plugin-grid/src/ObjectGrid.tsx @@ -3672,7 +3672,17 @@ export const ObjectGrid: React.FC = ({ // `fitContent` columns (row actions) hug their content — leave them out so // they aren't pinned to the 80px char-estimate floor and clipped in // grouped mode the same way they were in the flat list. - if ((col as any).fitContent) continue; + // + // Read WITHOUT a cast since objectui#6424 (maintainer ruling 2026-08-29, + // option 甲): `TableColumn` declares `fitContent` now, so the key this + // renderer honours is the key the published type admits. ⚠️ Read the + // narrowness of that claim: the cast was already buying ZERO type safety + // here, because `col` is `any` either way — `applyColumnChrome` is + // `(col: any)`, so `orderedColumns` is `any[]` and the loop above widens it + // a second time. This read is unchecked for that reason, not for want of a + // declaration, and typing it is the separate question the `as any[]` on the + // loop belongs to (objectui#6459). Removing the cast changed no type. + if (col.fitContent) continue; let maxLen = String(col.header ?? '').length; for (const row of data.slice(0, 50)) { const v = row?.[key]; diff --git a/packages/plugin-grid/src/__tests__/columnReadBoundary-6458.test.ts b/packages/plugin-grid/src/__tests__/columnReadBoundary-6458.test.ts index 4f5ef3b7c8..d38291b71b 100644 --- a/packages/plugin-grid/src/__tests__/columnReadBoundary-6458.test.ts +++ b/packages/plugin-grid/src/__tests__/columnReadBoundary-6458.test.ts @@ -72,7 +72,11 @@ * answer is known; * 3. the regex proved able to find a cast read in THIS REAL FILE, at real * scale — necessarily from OUTSIDE the guarded region, since inside it - * the whole point is that there is nothing left to find. + * the whole point is that there is nothing left to find. Its anchor is a + * cast on a DIFFERENT receiver than the bound assertions scan for, which + * is why the scanner takes the receiver as a parameter — objectui#6424 + * dismantled the `col` cast this control used to observe, and the file has + * no other `col` cast outside the region to move to. */ import { describe, it, expect } from 'vitest'; @@ -97,9 +101,12 @@ const gridSource = readFileSync(GRID_SOURCE, 'utf8'); /** * The bounds of the `ListColumn` branch of `generateColumns()`. The scan is * scoped to it on purpose: `col` names a DIFFERENT thing further down the file - * (a generated column, in the grouped-width pass), and a cast read there is a - * separate question owned by objectui#6424 — pulling it in here would make this - * guard fail for a reason it has no verdict on. + * (a generated column, in the grouped-width pass), and what is read off it + * there is a separate question owned by objectui#6424 — pulling it in here + * would make this guard fail for a reason it has no verdict on. That read went + * through `(col as any).fitContent` until objectui#6424's 2026-08-29 ruling + * dismantled the cast; the READ is unchanged and still outside this guard's + * remit, and the emitted column it reads is still not the authored input. */ const REGION_START = '(cols as ListColumn[])'; const REGION_END = '// String array format - enrich with objectDef field metadata'; @@ -108,11 +115,22 @@ const REGION_END = '// String array format - enrich with objectDef field metadat * Any cast spelling, not just `as any` — `(col as unknown as X).k` and * `(col as ListColumn & { k })` would dodge a narrower pattern while doing the * same thing. + * + * The RECEIVER is a parameter (objectui#6424). It was hard-coded to `col` while + * anti-vacuity control 3's anchor happened to be a `col` cast; the 2026-08-29 + * ruling dismantled that cast and left the file with ZERO `col` casts outside + * the guarded region, so the control had to re-point at a cast on a different + * receiver — which a hard-coded pattern cannot express. ⚠️ The parameter is the + * WHOLE of that change and it defaults to `col`: every BOUND assertion below + * still scans for `col`, over the same region, and still means exactly what it + * meant. Control 2 pins that the parameter is honoured rather than ignored, so + * this cannot quietly become a pattern that matches any receiver at all. */ -const CAST_READ = /\(\s*col\s+as\s+[^)]*\)\s*\.\s*([A-Za-z_$][\w$]*)/g; +const castReadRe = (receiver: string) => + new RegExp(String.raw`\(\s*${receiver}\s+as\s+[^)]*\)\s*\.\s*([A-Za-z_$][\w$]*)`, 'g'); -function castReadKeys(source: string): string[] { - return [...source.matchAll(CAST_READ)].map((m) => m[1]); +function castReadKeys(source: string, receiver = 'col'): string[] { + return [...source.matchAll(castReadRe(receiver))].map((m) => m[1]); } function guardedRegion(): string { @@ -133,6 +151,30 @@ const DECLARED_KEYS = Object.keys( */ const RETIRED_UNDECLARED_READS = ['format', 'options', 'appearance', 'essential']; +/** + * Anti-vacuity control 3's anchor in the REAL file — re-pointed by objectui#6424 + * (maintainer ruling 2026-08-29), which dismantled the `(col as any).fitContent` + * read in the grouped-width pass that used to serve as it. Per this control's + * own standing instruction the control was RE-POINTED, never deleted. + * + * Why this cast and not one of the twelve others outside the region: it is the + * only kind here that cannot expire SILENTLY. `hideRowHeightToggle` is a + * deliberately held non-authoring key (objectui#5091) — a host-written switch + * that `ComponentPropsMap['object-grid']`'s `strictObject` refuses by name, so + * `(schema as any)` is the only way to read it and the cast is load-bearing + * rather than incidental — and it is INDEPENDENTLY PINNED by + * `gridNonAuthorKeys.test.tsx`, in that file's key table and in a behavioural + * test. If it is ever retired, that guard goes red in the same run and names it, + * instead of leaving this control to fail alone against a stale anchor. + * + * ⭐ That is precisely the failure the previous anchor had, and the reason this + * one is chosen on a different principle rather than merely moved: `fitContent` + * was nothing else's premise, so dismantling it broke this control with no other + * signal — the silent-expiry shape this card family keeps recording. + */ +const CONTROL_RECEIVER = 'schema'; +const CONTROL_KEY = 'hideRowHeightToggle'; + describe('objectui#6458 — the read boundary of ObjectGrid.generateColumns()', () => { it('the scan region is anchored — both bounds present exactly once', () => { // Anti-vacuity control 1. Every "no such key" claim below is worthless if @@ -151,21 +193,38 @@ describe('objectui#6458 — the read boundary of ObjectGrid.generateColumns()', expect(castReadKeys('const x = (col as any).someKey;')).toEqual(['someKey']); expect(castReadKeys('const y = (col as unknown as Foo).other;')).toEqual(['other']); expect(castReadKeys('const z = col.declaredKey;')).toEqual([]); + // …and the RECEIVER parameter is HONOURED rather than ignored. Without this + // pair, `castReadRe` could degrade into a pattern that matches any receiver + // whatsoever: control 3 below would still pass, and the two bound + // assertions' scoping to `col` would silently become a fiction that admits + // every cast in the region. Both directions asserted, so neither a stuck + // receiver nor an ignored one survives. + expect(castReadKeys('const w = (schema as any).someKey;')).toEqual([]); + expect(castReadKeys('const w = (schema as any).someKey;', 'schema')).toEqual(['someKey']); }); it('the scanner finds a cast read in the REAL file, outside the guarded region', () => { - // Anti-vacuity control 3, and the one that had to move. It used to draw its - // control from INSIDE the region — which worked only while the region still - // contained cast reads to find. Now that the region's correct answer is - // zero, a control drawn from inside it would be the very thing it is meant - // to rule out. So it is drawn from the grouped-width pass further down the - // file, where `(col as any).fitContent` iterates EMITTED columns rather - // than the authored input (objectui#6424's question, deliberately outside - // this guard). If that read is ever retired too, this control must be - // re-pointed at another real cast — never deleted, and never re-pointed - // back inside the region. + // Anti-vacuity control 3, and the one that has now had to move twice. It + // first drew its control from INSIDE the region — which worked only while + // the region still contained cast reads to find. Now that the region's + // correct answer is zero, a control drawn from inside it would be the very + // thing it is meant to rule out. It then drew on `(col as any).fitContent` + // in the grouped-width pass, until objectui#6424's 2026-08-29 ruling + // dismantled that cast; measured on that ref, the file then had ZERO `col` + // casts anywhere outside the region, so the anchor moved to a different + // RECEIVER (see CONTROL_RECEIVER above) rather than being deleted. + // ⛔ If this anchor is ever retired too, re-point it at another real cast — + // never delete this control, and never re-point it back inside the region. const outside = gridSource.slice(gridSource.indexOf(REGION_END)); - expect(castReadKeys(outside)).toContain('fitContent'); + expect( + castReadKeys(outside, CONTROL_RECEIVER), + `Anti-vacuity control 3 has lost its anchor: no \`(${CONTROL_RECEIVER} as ...).` + + `${CONTROL_KEY}\` cast read remains outside the guarded region, so this scanner ` + + 'is no longer proved able to find anything at real scale — and every "no such ' + + 'key" claim in this file becomes a green no-op. ⛔ Re-point this control at ' + + 'another real cast in this file; never delete it, and never re-point it back ' + + 'inside the region (objectui#6458).' + ).toContain(CONTROL_KEY); }); it('⭐ no key `ListColumn` DECLARES is read through a cast', () => {