Filed unassigned by the dev seat implementing the @objectstack/spec 17.1.0 pin bump (#5328, branch claude/issue-5328-spec-pin-17-1-0). Not claiming — resolving it requires a contract call the pin-bump card cannot make.
What was measured
@objectstack/spec@17.1.0 newly exports ReferenceRailEntry (and ReferenceRailEntrySchema) from @objectstack/spec/ui. It is absent from 17.0.0 — grep -rl ReferenceRailEntry node_modules/@objectstack/spec/dist/ returns nothing on 17.0.0 and hits dist/ui/index.js on 17.1.0.
objectui declares its own interface ReferenceRailEntry at packages/plugin-detail/src/renderers/record-reference-rail.tsx:33, so check:spec-symbols (scripts/check-spec-symbol-derivation.mjs) now fails: a spec-named symbol is hand-written rather than derived.
Counter-probe that this is the bump: the gate exits 0 on origin/main (2524e7450) with the 17.0.0 lockfile, 1 with only pnpm-lock.yaml moved to 17.1.0.
The part that is not mechanical
The two declarations are not the same shape, and the difference is contract-bearing:
| key | spec 17.1.0 ReferenceRailEntrySchema | objectui local |
|---|
objectName | ✅ required | ✅ required |
relationshipField | ✅ required | ✅ required |
title | ✅ optional | ✅ optional |
limit | ✅ optional | ✅ optional |
displayField | ✅ optional | ✅ optional |
icon | ❌ not declared | ✅ optional, and read by the renderer |
The spec's object is z.core.$strict. An author who writes icon on a reference-rail entry is therefore refused at save, while objectui's renderer reads and honours it — the "preview-works / save-refuses" trap #5328 was filed about, arriving here as a real instance rather than a hypothetical.
So the gate's three mechanical remedies all beg the question:
- import / derive from the spec — drops
icon from the type and breaks the renderer's read of it; that is a decision to retire an objectui-side affordance. - rename to a declared dialect (
ObjectUiLocalReferenceRailEntry) — records the divergence as deliberate and keeps icon unsaveable, i.e. decides the opposite way. Also renames a symbol @object-ui/plugin-detail exports. ALLOW entry — asserts "deliberately differs", a judgement nobody has actually made.
What is needed
A ruling on icon: either objectui drops it and derives the type from the spec, or icon is proposed upstream for ReferenceRailEntrySchema, or the divergence is formalised as a named dialect. Whichever way it goes, the local declaration should stop sitting under the spec's own symbol name.
Recorded meanwhile in the DEBT ledger of scripts/check-spec-symbol-derivation.mjs (regenerated with its own --ledger flag), which is shrink-only and ratcheted, so the entry fails the gate as soon as the collision is resolved.
Refs: #5328 (the pin bump that surfaced it) · objectstack#4115 (the ledger's umbrella card).
Filed unassigned by the dev seat implementing the
@objectstack/spec17.1.0 pin bump (#5328, branchclaude/issue-5328-spec-pin-17-1-0). Not claiming — resolving it requires a contract call the pin-bump card cannot make.What was measured
@objectstack/spec@17.1.0newly exportsReferenceRailEntry(andReferenceRailEntrySchema) from@objectstack/spec/ui. It is absent from 17.0.0 —grep -rl ReferenceRailEntry node_modules/@objectstack/spec/dist/returns nothing on 17.0.0 and hitsdist/ui/index.json 17.1.0.objectui declares its own
interface ReferenceRailEntryatpackages/plugin-detail/src/renderers/record-reference-rail.tsx:33, socheck:spec-symbols(scripts/check-spec-symbol-derivation.mjs) now fails: a spec-named symbol is hand-written rather than derived.Counter-probe that this is the bump: the gate exits 0 on
origin/main(2524e7450) with the 17.0.0 lockfile, 1 with onlypnpm-lock.yamlmoved to 17.1.0.The part that is not mechanical
The two declarations are not the same shape, and the difference is contract-bearing:
ReferenceRailEntrySchemaobjectNamerelationshipFieldtitlelimitdisplayFieldiconThe spec's object is
z.core.$strict. An author who writesiconon a reference-rail entry is therefore refused at save, while objectui's renderer reads and honours it — the "preview-works / save-refuses" trap #5328 was filed about, arriving here as a real instance rather than a hypothetical.So the gate's three mechanical remedies all beg the question:
iconfrom the type and breaks the renderer's read of it; that is a decision to retire an objectui-side affordance.ObjectUiLocalReferenceRailEntry) — records the divergence as deliberate and keepsiconunsaveable, i.e. decides the opposite way. Also renames a symbol@object-ui/plugin-detailexports.ALLOWentry — asserts "deliberately differs", a judgement nobody has actually made.What is needed
A ruling on
icon: either objectui drops it and derives the type from the spec, oriconis proposed upstream forReferenceRailEntrySchema, or the divergence is formalised as a named dialect. Whichever way it goes, the local declaration should stop sitting under the spec's own symbol name.Recorded meanwhile in the
DEBTledger ofscripts/check-spec-symbol-derivation.mjs(regenerated with its own--ledgerflag), which is shrink-only and ratcheted, so the entry fails the gate as soon as the collision is resolved.Refs: #5328 (the pin bump that surfaced it) · objectstack#4115 (the ledger's umbrella card).