Uh oh!
There was an error while loading. Please reload this page.
fix(plugin-detail): derive ReferenceRailEntry from @objectstack/spec and retire the icon key - #5794
Conversation
… retire the icon key ReferenceRailEntry is spec-owned as of @objectstack/spec 17.1.0. The local interface re-declared it with an extra optional icon key that no render path ever read and the spec's $strict ReferenceRailEntrySchema refuses at save. Replace the declaration with a type re-export from @objectstack/spec/ui, stop emitting icon on synthesized reference-rail entries in buildDefaultPageSchema, and burn the collision's DEBT ledger entry in check-spec-symbol-derivation.mjs (regenerated with --ledger). Part of #5494 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E7snar5mwF7qoXJazqKhys
…rement Part of #5494 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01E7snar5mwF7qoXJazqKhys
✅ 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
|
os-sam
commented
Aug 23, 2026
PM review — verified independently, not from the reportI re-derived the load-bearing claims against the tree rather than reading them off the PR body. All four hold. 1. 2. The
Only 3. The type genuinely was not published. Verified rather than assumed: 4. The premise correction is the valuable part of this PR. The card and triage's four-facet block both asserted the renderer "reads and honours" One accuracy caveat, recorded not demandedThe changeset's third bullet is headed "The published TS surface narrows." Per finding 3 that heading overstates reach — the symbol was not in the published surface; only in-repo source importers could ever have hit the error. The sentence under it is properly qualified ("from Gate readingGreen on every gate that is this PR's own. Read by name, never off a rollup:
Generated by Claude Code |
Uh oh!
There was an error while loading. Please reload this page.
Fixes#5494
Implements the maintainer's Option B ruling (2026-08-22, decision-inbox digest, 「接受所有」): objectui drops
iconand derivesReferenceRailEntryfrom the spec. Option C stayed rejected; the ruling's flip condition (real existing usage oficon) did not trigger — stock scan below.Stock scan (ran first — it decides the direction)
Result: no reachable authored usage of
iconon reference-rail entries. The ruling does not flip; Option B proceeds.Populations swept, each with a positive control proving the scanner arrived:
cd4961a68— all 31 files matchingreference_rail|reference-rail|ReferenceRail, plusexamples/(456 authored files incl. the schema-catalog corpus; control:objectName|displayFieldhits 4 files). Zerorecord:reference_railschemas exist in examples at all. The onlyiconwriters found are objectui's own: the local interface declaration andbuildDefaultPageSchema's synthesized entries (both retired here). Theicon: 'check'instrictPayload.test.tsis arelatedoption feedingrecord:related_listtabs, not a rail entry.764dbbc— repo-widegit grepfor the same terms (control:relationshipFieldhits 3 example files): hits only in content docs (component-type lists, noiconadvertising), ADR/audit docs,packages/lint, andpackages/spec. Zero rails inexamples/,skills/, or any template.iconat save and nothing ever rendered it (below), so unreachable stock cannot be depending on a render effect that does not exist.The premise correction worth reading
The card says the renderer "reads and honours"
icon. Measured false — and false at filing: no render path inrecord-reference-rail.tsxhas ever read the key (verified back to the file's first commit,66751896c). The spec's own v18 migration entryui-reference-rail-unknown-keys-refusedmeasured the same, verbatim: "the interface'siconis read by nothing and is refused, not declared". So no functioning affordance retires; what retires is a lying TS declaration plus a synth emission of a key the spec refuses at save. This makes Option B strictly cheaper than the ruling assumed. The runtime accept set does not move —ReferenceRailEntrySchemawas$strictwithouticonbefore and after; validation was already tight, the declaration was lying.Changes
packages/plugin-detail/src/renderers/record-reference-rail.tsx— the hand-writteninterface ReferenceRailEntryis replaced byexport type { ReferenceRailEntry } from '@objectstack/spec/ui'(the gate's sanctioned re-export form). Theicon?: stringmember and the header comment's icon claim go with it.scripts/check-spec-symbol-derivation.mjs— the@object-ui/plugin-detail: ["ReferenceRailEntry"]DEBTentry and its comment block are burned. The ledger is shrink-only;--ledgerregeneration reproduces the remaining block byte-for-byte..changeset/reference-rail-entry-spec-derived.md—minor(breaking-as-minor percheck-changeset-no-major;@object-ui/*fixed group) with the loud migration note the ruling requires: authorediconstops being suggested by the type, never had a render effect, and was already refused at save. Release notes compile from changesets — noreleases/page touched.packages/plugin-detail/src/synth/buildDefaultPageSchema.ts— declared file-surface amendment (bounded in-place fix, all four conditions held): the synthesized reference-rail entries emittedicon: rel.icon, i.e. objectui's own synth was the one live producer of the exact key this ruling retires — same defect class; the correct shape is pinned by the landed ruling and the spec's$strictschema;packages/plugin-detailcarried no other claim (dispatch: lane in-flight zero); covered by the same gate family (plugin-detail tests/type-check, no new verification face). Boundary scan: repo-widegrepshows no other writer oficononto reference-rail entries, and no synth test pins the key (assertions checkentrieslength/objectNameonly). Without this line the "retired" key kept being written into every synthesized rail page — a save-refusal trap for any customize-and-persist flow. Sibling defect at the region level (aside.className, Synthesizedasideregion carriesclassName, whichPageRegionSchemarejects — a Reference Rail page has no persistable spelling #4286) is a different key and remains open — not addressed here.Verification (at
9a13a78f2unless noted)check:spec-symbols— ✅1297 files scanned against 4966 spec export names; 16 declared dialects, 3 untriaged collisions in 1 packages(the 3 are the pre-existing@object-ui/typestrio).cd4961a68), ledger stays burned → gate exit 1:interface ReferenceRailEntry …record-reference-rail.tsx:33 (exported by @objectstack/spec/ui);@object-ui/plugin-detail lists 1 symbol in DEBT that no longer collide — ReferenceRailEntry.error TS2353 … 'icon' does not exist in type '{ objectName; relationshipField; title?; limit?; displayField? }'; green leg (declared keys only) exit 0.4be78c5d0+ the changeset (the only later commit is the changeset .md, outside every test/tsc input): dependency closure built, thenvitest run packages/plugin-detail/— ✅Test Files 93 passed (93) · Tests 866 passed (866);pnpm --filter @object-ui/plugin-detail type-check— ✅ (lock VERDICT command-exit 0). Gate pin testcheck-spec-symbol-derivation.test.ts— ✅ 34/34;type-check:scripts— ✅.9a13a78f2:check:control-bytes✅ ·check:phantom-deps✅ ·check:self-import✅ ·check:esm-specifiers(specifiers leg) ✅ ·check-changeset-fixed✅ ·check-changeset-no-major✅ ·check-changeset-presence✅ ·check:action-forward-parity✅ ·check:i18n-keys✅ ·check:i18n-drift✅.lint: ranpnpm --filter @object-ui/plugin-detail lint+eslint --no-inline-config scripts/check-spec-symbol-derivation.mjs— 0 errors. Invariance for untouched files:eslint.config.jscontains noprojectService/parserOptions.project(no type-aware linting), so this diff cannot move any unlinted file's judgment.check:published-dist: the gate hardcodes a full-workspace turbo build (its own header: "why this gate costs a build"). Ran the targeted equivalent on the one published package this diff touches: plugin-detail's fresh dist (101 files) has 0 test/bench/stories artifacts and 0vitestimports; every other package's dist is a function of sources this diff does not touch....@object-ui/plugin-detail= dependents):ReferenceRailEntryhas zero importers outside the declaring file in the whole tree (git grepat HEAD; the package'sexportsmap exposes only., anddist/index.d.tsnever re-exported it), and no typed caller anywhere writesiconon entries — so no dependent's type-check judgment can move on this narrowing.Build Docsred onmain(Build Docsis red onmain:fsreaches the browser bundle via@objectstack/spec→pg-connection-string#5668, inherited);check-doc-snippet-types/check-eager-closure-budgetrequire built consoles.Out-of-scope findings filed: #5792 (stale parity-test prose citing this card as unsettled), #5793 (spec dependency floors vs 17.1.0-only symbols).
Generated by Claude Code