You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
feat(core): say which column identity key won, out loud (#3104 PR3) (#3124)
Closes the battle opened in #3104. PR1 (#3119) put the canonicalizing fold at
ingestion; PR2 (#3122) converged all 22 read sites onto columnIdentity(). This
is the audible half.
A column carrying two identity keys that DISAGREE now logs a one-time dev-mode
warning naming which key won and what to change. The fold making the two halves
agree is what stops the bug, but silently rewriting `name` to match `field`
also hides that the producer is emitting a contradiction. The renderer
recovering is not the same as the metadata being right, so the recovery says so.
Deliberately narrow:
- Only contradictions. `{name:'stage'}` is legacy, not conflicting — stamped
without noise.
- Warn once per (identity, conflicting spelling). Columns are re-normalized on
every render, and a warning that floods the console is one that gets muted.
Keyed by the pair rather than the identity alone, so a column carrying two
different stale spellings reports both.
- Silent under NODE_ENV=production, and the fold still runs there.
No lint rule, and that is a measured decision. #3104 asked for
no-restricted-syntax on `.field ?? .name` to be evaluated on its false-positive
rate first. With the family at zero, all 12 remaining scanner hits are
legitimate — a syntactic rule cannot tell a two-layer join from a dual read,
because the distinction is what the keys MEAN in that layer, not how the
expression is spelled. Adopting it would mean 12 inline disables on correct
code, which trains the next author to reach for the disable. The ratchet carries
a verdict and a why per site instead. The evaluation is written into its header.
Ledger item resolved with no change needed: #3104 flagged ListColumn for
disposition under objectstack#4115 (spec-named symbols must be imports, not
declarations). ListColumnSchema is already a by-reference re-export of
@objectstack/spec/ui, and spec-subschema-parity.test.ts already pins it by
reference identity — the only check that distinguishes a re-export from a
faithful fork. Already compliant.
Verified: M5 (drop the warn call) turns 4 of the new tests red.
vitest core+list+grid+detail+tree+view+types -> 188 files / 2663 tests green
vitest app-shell -> 250 files / 2089 tests green
turbo type-check, eslint -> green
Refs: objectstack#4115, #3090 (playbook), #3119 (PR1), #3122 (PR2)
Claude-Session: https://claude.ai/code/session_01C2pdPmf2yZSd4wFDs1NHY5
Co-authored-by: Claude <noreply@anthropic.com>
0 commit comments