Skip to content

Commit d10f526

Browse files
os-zhuangclaude
andauthored
fix(sdui): the curated contract lists record:line_items, the tag that actually resolves (#3006)
PUBLIC_BLOCKS carried `line_items` — the bare tag. @object-ui/plugin-form registers the block as `record:line_items` with `skipFallback: true`, which exists precisely so the bare name is NOT claimed, so that key never existed and the curated entry could never resolve. Its four siblings in the list are all `record:`-prefixed and plugin-form's own comment says "Register record:line_items"; the bare spelling was a slip. The effect was a block that has shipped all along — a full renderer, a label, five declared inputs — being absent from the public contract, from the JSX type surface, from the generated manifest, and from every kind:'react' page's scope. It read as an unimplemented aspirational entry, which is how it was recorded when #2979 added the contract-coverage guard. With the tag corrected the contract has no gaps left: all 36 curated tags resolve in the console, record:line_items among them with its full inputs. The guard's known-unimplemented list is now empty and stays asserted, so the next entry that cannot resolve surfaces instead of being explained away. Claude-Session: https://claude.ai/code/session_01N4mrr1ihhwnfEHFSWmGoMp Co-authored-by: Claude <noreply@anthropic.com>
1 parent bb563e9 commit d10f526

3 files changed

Lines changed: 42 additions & 7 deletions

File tree

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
---
2+
"@object-ui/core": patch
3+
"@object-ui/console": patch
4+
---
5+
6+
fix(sdui): the curated contract lists `record:line_items`, the tag that actually resolves
7+
8+
`PUBLIC_BLOCKS` carried `line_items` — the bare tag. `@object-ui/plugin-form`
9+
registers the block as `record:line_items` with `skipFallback: true`, which
10+
exists precisely so the bare name is *not* claimed, so that key never existed
11+
and the curated entry could never resolve. Its four siblings in the list are all
12+
`record:`-prefixed, and plugin-form's own comment says "Register
13+
record:line_items"; the bare spelling was a slip.
14+
15+
The effect was a block that has shipped all along — a full renderer, a label,
16+
five declared `inputs` — being absent from the public contract, from the JSX
17+
type surface, from the generated manifest, and from every `kind:'react'` page's
18+
scope. It read as an unimplemented aspirational entry, which is how it was
19+
recorded when objectui#2979 added the contract-coverage guard.
20+
21+
With the tag corrected the contract has no gaps left: all 36 curated tags
22+
resolve in the console, `record:line_items` among them with its full `inputs`.
23+
The guard's known-unimplemented list is now empty and stays asserted, so the
24+
next entry that cannot resolve surfaces instead of being explained away.

apps/console/src/__tests__/public-contract.test.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ const EXPECTED_COVERED = [
5151
'record:highlights',
5252
'record:related_list',
5353
'record:path',
54+
'record:line_items',
5455
'flex',
5556
'grid',
5657
'stack',
@@ -71,13 +72,19 @@ const EXPECTED_COVERED = [
7172
];
7273

7374
/**
74-
* Curated tags with no renderer behind them yet. `PUBLIC_BLOCKS` is documented
75-
* as aspirational-safe (an unregistered tag is skipped), so a gap is allowed —
76-
* but it should be a listed, reviewable gap rather than a silent one, since
77-
* "advertised in the contract, absent at runtime" is what an AI-authored page
78-
* trips over.
75+
* Curated tags with no renderer behind them yet — currently none.
76+
*
77+
* `PUBLIC_BLOCKS` is documented as aspirational-safe (an unregistered tag is
78+
* skipped), so a gap is allowed, but it has to be a listed, reviewable gap
79+
* rather than a silent one: "advertised in the contract, absent at runtime" is
80+
* exactly what an AI-authored page trips over.
81+
*
82+
* The one entry that used to sit here, `line_items`, was not aspirational at
83+
* all — it was a misspelling of `record:line_items`, whose renderer has shipped
84+
* in @object-ui/plugin-form all along. Keeping the list empty is what surfaces
85+
* the next one of those.
7986
*/
80-
const EXPECTED_UNIMPLEMENTED = ['line_items'];
87+
const EXPECTED_UNIMPLEMENTED: string[] = [];
8188

8289
/**
8390
* The curated tags that reach the contract through a PENDING lazy stub in this

packages/core/src/registry/public-blocks.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,11 @@ export const PUBLIC_BLOCKS: readonly string[] = [
4343
'record:highlights',
4444
'record:related_list',
4545
'record:path',
46-
'line_items',
46+
// `record:`-prefixed, like its four siblings above. @object-ui/plugin-form
47+
// registers this one with `skipFallback: true`, so the bare `line_items` key
48+
// it was listed under here never existed — the block has shipped all along
49+
// but could never resolve through the contract (objectui#2953 follow-up).
50+
'record:line_items',
4751
// ── Tier B — layout / content primitives ──────────────────────────────────
4852
'flex',
4953
'grid',

0 commit comments

Comments
 (0)