feat(sdui): curate the page:*, element:* and action:* families into the public contract - #3069
Merged
Merged
Conversation
…he public contract The AI-authoring vocabulary and the Studio page designer disagreed by thirteen blocks: PUBLIC_BLOCKS carried one page: tag and one element: tag while the designer palette — and @objectstack/spec's page schema — offered the whole families. A block a human can drag in Studio was invisible to a model writing the same page, which is the #3006 state at 10x the scale. Fifteen tags join the contract (42 -> 57), every one shipping a renderer with declared inputs (#3065): page: tabs, card, accordion, section, footer, sidebar element: text, number, button, definition-list, repeater action: button, group, menu, icon Five stay out, each with its reason recorded and guarded: action:bar (record:quick_actions covers the record action strip; the spec blesses the other four), element:image (duplicates the curated `image` — one spelling per concept), and element:record_picker / element:text_input / element:metadata_viewer (mirroring the Studio palette's own PALETTE_EXCLUSIONS, so the two vocabularies stay out for the same reasons rather than by coincidence). The console's reverse-coverage guard now sweeps all four semantic namespaces instead of record: alone — checking only the namespace you just fixed is exactly how the last 22 doubled keys went unnoticed (#3037). A new prop-less allowlist (element:divider, page:section, page:footer, page:sidebar) keeps "declares no inputs" a pinned decision in both directions: those four must stay at zero, everything else curated must declare a surface. Verified by mutation: dropping action:menu from the list fails the sweep with exactly that tag named. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01N4mrr1ihhwnfEHFSWmGoMp
|
The latest updates on your projects. Learn more about Vercel for GitHub. |
Contributor
✅ Console Performance Budget
📦 Bundle Size Report
Size Limits
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part 2 of 2 (#3065 was part 1). The vocabulary decision, kept separate so it's independently revertable.
The gap
The AI-authoring vocabulary and the Studio page designer disagreed by thirteen blocks:
PUBLIC_BLOCKScarried onepage:tag and oneelement:tag while the designer palette — and @objectstack/spec's page schema — offered the whole families. A block a human can drag in Studio was invisible to a model writing the same page: the #3006 state at 10× the scale.Fifteen tags join (42 → 57)
All shipping renderers with declared inputs as of #3065:
page:element:action:element:button(inline ActionDef) andaction:button(declared action by name, visible/enabled predicates) are deliberately both in: distinct semantics, documented at the registration site since #3065.Five stay out — recorded and guarded
action:barrecord:quick_actionscovers the record action strip; the spec blesses the other fourelement:imageimageprimitive — one spelling per conceptelement:record_pickerelement:text_inputelement:metadata_viewerThe three
element:reasons mirror the Studio palette's ownPALETTE_EXCLUSIONSverbatim intent — the two vocabularies now stay out for the same reasons, not coincidentally.Guard generalized
The reverse-coverage sweep now covers all four semantic namespaces (
record,page,element,action) instead ofrecord:alone — checking only the namespace you just fixed is exactly how 22 doubled keys went unnoticed in #3037. Registering any new semantic block now fails CI until it's curated or excluded with a reason.A
PROP_LESS_CURATEDallowlist (element:divider,page:section,page:footer,page:sidebar) pins "declares no inputs" in both directions: those four must stay at zero (they render onlychildren), everything else curated must declare a surface.Verified
Mutation test: dropping
action:menufromPUBLIC_BLOCKSfails the sweep naming exactly that tag. Contract resolves 57/57 in the console. Full suite751 passed | 1 skipped, lint 0 errors, type-check 38/38, changesets included (core minor, console patch).🤖 Generated with Claude Code
https://claude.ai/code/session_01N4mrr1ihhwnfEHFSWmGoMp
Generated by Claude Code