This repository was archived by the owner on Jul 13, 2026. It is now read-only.
Rewrite component/ to match A2UI v0.9 schema (1/2) - #1
Open
joestump wants to merge 1 commit into
Open
Conversation
The initial scaffold modeled components with a "kind" discriminator and an invented catalog (card/form/input/choice/progress/markdown/stream) — none of that matches the A2UI protocol. A real A2UI document would never route to a renderer. This rewrites component/ against the A2UI v0.9 basic catalog, using the spec's actual wire shape and component types. Wire shape: flat-string discriminator on the field "component" (not "kind"), PascalCase values, children referenced by ID via "child" (single) or "children" (array). Per the v0.9 spec, components arrive as a flat adjacency list keyed by ID; component.Unmarshal decodes a single entry. Catalog: Card, Button, Text, Row, Column, TextField, Modal, Tabs, List. Notable types: - Value distinguishes literal / path-binding / function-call forms, preserves raw JSON for lossless round-trips - ChildrenSpec accepts both static []string and template-object forms (per the v0.9 List/Row/Column spec) - Action and Accessibility kept as json.RawMessage — open shapes we don't want to constrain prematurely - Per-type MarshalJSON re-emits the "component" discriminator Errors are surfaced: malformed JSON, unknown component type, and missing discriminator each return a typed error (ErrUnknownComponent, ErrMissingDiscriminator). No more silent _ = json.Unmarshal swallowing. Tests: table-driven coverage for every catalog entry, error cases, and a nested round-trip (Card -> Column -> Buttons -> Text labels) that exercises the flat adjacency-list pattern. Snippets are sourced from a2ui.org/specification/v0.9-a2ui/ and a2ui.org/reference/components/. examples/hello/sample.json is now a real v0.9 document (updateComponents envelope with a Card containing a Column of Text + Row of Buttons). This PR alone breaks `go build ./...` — render/* still references the old component names (Form, Input, Choice, Progress, Markdown, Stream). Fixing render/* and the a2tea.Render entry-point is Agent 2's job in a stacked follow-up PR. Refs REVIEW.md (issue 2a). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
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 subscribe to this conversation on GitHub.
Already have an account?
Sign in.
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.
Summary
Rewrites the
component/package against the actual A2UI v0.9 basic catalog. Addresses REVIEW.md issue 2a — the initial scaffold's"kind"-discriminated, invented-catalog shape would never route a real A2UI document.Spec verified against:
Wire shape (v0.9, flat-string): discriminator is
"component"(not"kind"), values are PascalCase, children are referenced by ID via"child"(single) or"children"(array). Components are delivered as a flat adjacency list keyed by ID;component.Unmarshaldecodes a single entry — the renderer assembles the tree.Catalog implemented
Matches the 9 types in the brief, drawn from the v0.9 basic catalog:
Cardchild(single ID)Buttonchild(single ID),variant,action(raw JSON, open shape)Texttextis aValue(literal / path / call binding),variantRowchildren(ID array or template),justify,alignColumnTextFieldlabel,value(Value),textFieldType,validationRegexpModalentryPointChild+contentChildTabstabItems[]of{title, child}Listchildren(ID array or template),direction,alignAll nine support
accessibility(raw JSON) andweight.Notable types
Value— distinguishes literal ("John Doe"), path binding ({"path": "/contact/firstName"}), and function-call binding ({"call": "...", "args": {...}}); preserves raw JSON for lossless round-trips.ChildrenSpec— accepts both static["id1", "id2"]and template object{"path": "/employees", "componentId": "employee_card_template"}.Action/Accessibility— kept asjson.RawMessage(open shapes — let renderers/event routers decide).MarshalJSONre-emits the"component"discriminator sojson.Marshal(card)produces a spec-shaped object.Errors
No more silent
_ = json.Unmarshal(...)swallowing.Unmarshalreturns:ErrMissingDiscriminatorwhen"component"is absentErrUnknownComponent(wraps the offending value) for unknown typesfmt.Errorfwrapping the inner decode error for malformed payloads (e.g.Row.children: 42→ "decode Row: …")Tests
component/component_test.go— table-driven, snippets sourced from the A2UI docs (URLs cited inline):Text, both static-array and template-objectListErrUnknownComponentErrMissingDiscriminatorRow.children: 42)Kind*constant to the spec's PascalCase valuego test ./component/...passes;go vet ./component/...clean;gofmt -l component/ examples/clean.sample.json
examples/hello/sample.jsonis now a real v0.9updateComponentsenvelope (Card → Column with greeting Text, subtitle Text, and a Row of OK/Cancel Buttons with Text labels). 11 lines of components inside a 13-line file.KNOWN: this PR alone breaks
go build ./...This is expected and called out by the brief.
render/*(and a small amount ofa2tea.go) still reference the old component names. Specifically,go build ./...frommainof this branch fails with:This is Agent 2's job in PR #2 (stacked on
fix/a2ui-schema). PR #2 will rebuildrender/*against the new catalog, fix thea2tea.Renderentry-point (REVIEW.md issue 2c), wirehuh/v2(REVIEW.md issue 2b), and restore a green full-tree build.Scope kept clean: this PR only touches
component/component.go,component/component_test.go, andexamples/hello/sample.json.Test plan
go test ./component/...passesgo vet ./component/...cleangofmt -l component/ examples/cleancd component && go build .succeedsgo build ./...fails only on the expectedrender/*references (Agent 2)Do not merge before PR #2 lands — the tree won't build.
Refs
REVIEW.mdissue 2a.