Uh oh!
There was an error while loading. Please reload this page.
fix(plugin-dashboard): name and adjudicate ObjectDataTable's authored column-override reads - #6590
Conversation
… column-override reads `enrich()` handed `buildFieldMeta` six values taken off the AUTHORED column. Five of them — `format`, `options`, `referenceTo`, `currency`, `decimals` — are declared by neither `TableColumn` nor its `TableColumnSchema` zod mirror. Three arrived through `(col as any)`; the other two through the column bag's `[key: string]: any`, which answers `any` just as loudly without the tell. Those reads now go through `AuthoredColumnOverrides`: a local holds type with a written verdict and an owning card per key, plus a DERIVED `?: never` band over the rest of the `FieldMeta` override vocabulary, so a seventh member is refused by default instead of admitted by silence. Nothing published is declared or retired — `packages/types` is untouched. The new suite is the per-key evidence the open ruling needs: it MEASURES, at run time, that `currency` and `options` separate two otherwise identical columns while `decimals` and `referenceTo` reach no reader at all, each zero paired with a live control built the same way. Part of #6425 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011SfZeFWrhGLHmfq61xbz4q
…uns on The two existing band pins act on assignment INTO `AuthoredColumnOverrides`. `enrich` never assigns a banded source — it READS `authored.currency` and friends off the keyhole. That read is where the enforcement lands: the keyhole carries no index signature, so an unadjudicated key is TS2339 at the read, where the pre-fix code answered `any` twice over — through `(col as any)` and through `NormalizedColumn`'s `[key: string]: any`. Measured: with the directive in place `tsc -p tsconfig.test.json` is green, so the directive is USED; an unused one is TS2578, as the band ablation showed. Paired with a positive control on an adjudicated key in the same shape. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011SfZeFWrhGLHmfq61xbz4q
… not the authored type `plugin-grid`'s sibling band derives from its AUTHORED column type (`Exclude<keyof ListColumn, …>`). This one cannot, and the reason is worth writing down before someone "aligns" the two: `NormalizedColumn` carries `[key: string]: any`, so `keyof` it is `string | number` — measured, a band built on it accepts `'totallyMadeUpKey'` as a member and therefore bans nothing. Also states the cost that choice carries rather than leaving it to be found: a candidate key outside `FieldMeta` cannot land in the band, and is refused instead by the keyhole having no index signature (TS2339 at the read site). Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011SfZeFWrhGLHmfq61xbz4q
os-support-ai
commented
Aug 26, 2026
ACCEPT on the diff at Both ⛔ exclusions heldThree files: the changeset, This seat's re-dispatch instruction was wrong, and following it would have destroyed workI told you the branch had no work and to re-cut with Confirmed in this PR's history: commit This is the second agent to hit this in the same batch; #6458's reported it independently. The instruction is defective and the emptiness check needs a local-worktree leg. That is on this seat, and it is going into the seat's standing patrol text so the next re-dispatch template carries it. It also means a statement this seat made earlier — that the killed agents' work was unrecoverable — was false. It was inferred from a remote-branch reading and asserted about local disk that was never checked. Two of the three worktrees survived the restart with work in them. "Part of #6425", not "Fixes" — and you were right to override the orderMy order said to open with The sting is that this seat filed #6584 an hour earlier recording precisely that failure — "a card that closes on The band question, answered better than it was askedI asked whether So the band derives from ⭐ And you wrote the bound into the source docblock specifically so a later agent does not "align" this band to The per-key table splits three ways, not two
The sharpest finding, and the one the ruling most needs: You stated no recommendation, per the order. Correct: this is the evidence the maintainer's ruling needs, and it is materially better evidence for being three-way rather than the two-way split the card assumed. Measurement discipline
Both ablations predicted their direction first, including the subtle one: removing the derived band should turn exactly two directives Your independent re-confirmation of the seven surviving casts in Generated by Claude Code |
✅ 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
|
Uh oh!
There was an error while loading. Please reload this page.
Part of #6425
Part of, not a closing keyword.#6425's real subject is theper-key declare-or-retire ruling, and this PR explicitly does not settle it — the
dispatch order and the claim comment both say the ruling stays open for a maintainer.
A closing keyword here would silently close the card on merge and drop the open ruling
out of every
is:openinbox filter. This PR is the prerequisite that makes that rulingcheap; the card stays open for it.
packages/types/is untouched. Nothing published is declared, and nothing is retired.What changed
ObjectDataTable.enrich()handedbuildFieldMetasix values read off the authoredcolumn. Five —
format,options,referenceTo,currency,decimals— are declaredby neither
TableColumnnor itsTableColumnSchemazod mirror (re-measured on thistree: the mirror declares
header,accessorKey,className,cellClassName,width,minWidth,align,fixed,type,sortable,filterable,resizable,editable,cell— none of the five). Three arrived through(col as any); the other two throughNormalizedColumn's[key: string]: any, which answersanyjust as loudly withoutthe tell.
Those reads now go through
AuthoredColumnOverrides— a local keyhole carrying a writtenverdict and an owning card per held key, plus a derived
?: neverband over the restof the override vocabulary. This is the read-side counterpart to
EnrichedColumn, theemit-side fence already in this file from #6373.
The per-key evidence the open ruling needs
Re-measured on this tree, not carried over from the card body.
formattype,format,options,referenceTo…", and itsobject-data-tableexample authors threeformatcolumns.ObjectDataTable.cells.test.tsxrenders$150,000/60%from it.buildFieldMeta(recordFields.tsx:152) →renderFieldValue's currency / percent / date branches (:187–:196),isNumericFieldMeta(:163, which decidesalign),resolveCellRendererTypecol.format)optionsbuildFieldMeta(:131, with the per-option translation pass) →SelectCellRendererviafield.optionsTechnology→Overriddencol.options)referenceTofieldMeta.referenceTo(:125) and handed to the renderer asfield, butLookupField/ the lookup cell readreference_toorreference(LookupField.tsx:256), neverreferenceTo.computeLookupExpandbuilds$expandfrom the object schema's field types, not from this key.(col as any)currencybuildFieldMeta(:153) →renderFieldValue'sformatCurrency(...)(:194), which takesfieldMeta.currencyahead of both the symbol inferred fromformatand the ADR-0053 tenant defaultcurrency: 'EUR'renders€where the control renders$(col as any)decimals:154(overrides.decimals ?? meta?.decimals ?? meta?.scale) and then read by nobody: zero.decimalsproperty reads across@object-ui/fields,@object-ui/i18n,@object-ui/components.NumberCellRendererreadsscale,PercentCellRendererreadsprecision, and the percent branch counts digits in the format string.(col as any)Every zero above is paired with a positive control in the same query shape. The
static zeros (
.decimals,referenceTo) come from greps that do return hits for.scaleand.precisionin the same trees — so the query fires. The runtime zeros sitnext to a live pair built by the identical harness:
decimalsagainstcurrency,referenceToagainstoptions, two columns over equal values where only the overridecan separate them.
The finding most likely to matter to the ruling:
referenceToanddecimalsare notinert because the concept is unused — they are inert because of a spelling mismatch
with what the consumers actually read (
reference_to/reference, andscale/precision). Declaring either onTableColumnas spelled would publish a promise thatcurrently does nothing. That is a different decision from declaring
format, and thistable exists so it can be made separately. ⛔ No recommendation is stated here — this is
what was measured.
Why the band derives from the vocabulary, not from the authored type
plugin-grid's sibling band (RetiredListColumnKey, #6461) is an Exclude overkeyof ListColumn— derived from its authored column type. This one is an Excludeover
keyof FieldMeta, the override vocabulary, and that difference is forced, notstylistic:
NormalizedColumncarries[key: string]: any, sokeyofit is the openstring | number. Measured on this program — a band built on it accepts'totallyMadeUpKey'as a member, and would therefore ban nothing at all.The cost of that choice is stated in the docblock rather than left to be discovered: a
candidate key outside
FieldMetacan never land in the band. It is refused by theother half of the keyhole instead —
AuthoredColumnOverridesdeclares no indexsignature, so reading an unadjudicated key is
TS2339at the read site, which is themechanism
enrichactually runs on. Both halves are pinned by the suite.Reverse verification — direction predicted first, then measured
Ablation A — remove the derived band. Predicted: exactly the two band-pinned
@ts-expect-errordirectives turnTS2578unused; the excess-property one does not,because freshness is different machinery. Observed exactly that:
Ablation B — restore the pre-fix
(col as any)expression from the merge-base.Predicted: the type half goes red, and the runtime half stays green, because this
change is behaviour-neutral by design. Observed exactly that —
TS2305on both typeimports plus all three directives unused, while the runtime suite reported
Test Files 2 passed (2) / Tests 12 passed (12). The runtime half staying green underablation is the behaviour-neutrality evidence: the per-key liveness measurements are
identical before and after the fix.
Both ablations confirmed the mutation on disk by grep count and by
git hash-objectagainst the
HEADblob before reading any result, restored from a trap viagit checkout HEAD --naming the file by absolute path, and proved the restore bygit diff HEADbeing empty and the worktree blob hashing equal to theHEADblob.Gates — each verdict from the gate's own output, exit code captured before any pipe
Union run at
26a8f64de, the final commit, with a clean tree.@object-ui/plugin-dashboardtype-check(tsc --noEmitthentsc -p tsconfig.test.json)vitest run packages/plugin-dashboard/(repo root)Test Files 82 passed (82)/Tests 774 passed (774)@object-ui/plugin-dashboardlint✖ 398 problems (0 errors, 398 warnings)— warnings are the package's pre-existingno-explicit-anybandcheck-changeset-presence✅ 2 source file(s) of 1 released package(s) changed, and this change declares 1 changeset(s)— empty frontmatter, "the explicit exemption and a complete answer to this gate"check-control-bytes✅ OK (scanned 5445 tracked text file(s))check-vi-mock-specifiers✅ OKcheck-readme-exports✅ OK (… 0 unbuilt …)check-phantom-dependencies✅ Every in-scope import is declared by the package that publishes it.check-readme-exportsfirst refused to judge — its population-collapse self-guard fired("the population COLLAPSED -- this run proves nothing", 25 of 40 packages unbuilt). That
is NOT MEASURED, not green. A full
pnpm buildwas run and the gate re-run to get thereal verdict above.
The type gate is a real measurement, not a green
tsc.tsconfig.test.jsonincludessrc/**/*.test.tsx, andtsc --listFilesconfirms the new suite is a program input (1hit, 1897 files total) — so the four
@ts-expect-errordirectives are genuinely checked,and an unused one would be
TS2578, as both ablations demonstrate.Changeset
.changeset/6425-objectdatatable-column-holds.mdwith empty frontmatter — declared asreleasing nothing, which is objectui's way of saying "no published behaviour change"
(this repo has no
skip-changesetlabel).check-changeset-presenceaccepts it as acomplete answer rather than a missing changeset. No behaviour claim is invented.
Scope
Touched:
packages/plugin-dashboard/and one changeset. Not touched:packages/types/(neither
data-display.ts, its zod mirror, nor the parity fixtures), andpackages/plugin-grid/src/ObjectGrid.tsx, which is #6458's.mainat6a7893d57: the unlock comment on#6425 states that after #6461"the
anyhole is closed" inObjectGrid.tsx. That istrue of the emit signature only. The read side there is untouched — 7
(col as any).reads remain, at
:1815format,:1840/:1841options,:1846appearance,:1925prefix,:1951essential,:3418fitContent. Recorded here because thepattern this PR converges on is a fence on the emit side; the analogous read-side seam
in
plugin-gridis still open and belongs to that package's card, not to this one.Generated by Claude Code