Skip to content

feat(tool_call_card): canonical widget Stage 1-4 (:row_and_artifact family)#146

Draft
ty13r wants to merge 2 commits into
mainfrom
claude/phase-41.5-tool-call-card-canonical-widget
Draft

feat(tool_call_card): canonical widget Stage 1-4 (:row_and_artifact family)#146
ty13r wants to merge 2 commits into
mainfrom
claude/phase-41.5-tool-call-card-canonical-widget

Conversation

@ty13r
Copy link
Copy Markdown
Member

@ty13r ty13r commented May 27, 2026

Summary (DRAFT — Pascal-review required)

Phase 41 PR 41.5 — adds :tool_call_card as a NEW canonical widget in the EXISTING :row_and_artifact family. Implements Stage 1-4 of the canonical-widget pipeline; Stage 5 (AshUI Screen DSL adoption) deferred to a follow-on PR after Pascal sign-off.

Marked DRAFT because: this is a Tier-2 substrate gap proposal (new canonical widget). Pascal-review on family aggregation, BEM conventions, and accessibility shape is required before merge.

Implementation (Stage 1-4)

Stage 1 — UnifiedUi catalog + DSL entity:

  • packages/unified_ui/lib/unified_ui/widget_components.ex — register :tool_call_card with family: :row_and_artifact
  • packages/unified_ui/lib/unified_ui/dsl/entities/widget_components.ex — DSL leaf declaration

Stage 2 — UnifiedIUR constructor + validation:

  • packages/unified_iur/lib/unified_iur/widgets/components.extool_call_card/1 constructor; added to @row_artifact_kinds
  • packages/unified_iur/lib/unified_iur/validate.ex:invalid_tool_call_card + :invalid_tool_result_summary validation covering all 14 spec invariants

Stage 3 — LiveUi Phoenix.Component:

  • packages/live_ui/lib/live_ui/widgets/tool_call_card.ex — Phoenix.Component with full canonical contract (required props, state expanded?, event expand_toggled, optional tool_result_summary child)
  • packages/live_ui/lib/live_ui/renderer.ex — dedicated :tool_call_card clause placed above generic fallback

Stage 4 — Adapter routings + family aggregation:

  • lib/ash_ui/rendering/iur_adapter.ex — canonical IUR conversion path
  • lib/ash_ui/rendering/live_ui_adapter.ex — string-HTML fallback for non-LiveView contexts
  • packages/live_ui/lib/live_ui/widgets.ex + new packages/live_ui/lib/live_ui/widgets/row_and_artifact.ex — family aggregation (new file because no :row_and_artifact aggregator existed yet)

Spec ref (ariston-ui)

  • .spec/specs/canonical_widget_tool_call_card.spec.md — all must requirements covered:
    • family_classification (:row_and_artifact)
    • contract (required props + state + event)
    • child_shape (tool_result_summary sub-element)
    • invalid_payloads (14 invariants tested)
    • stage_4_runtime_integration (Phoenix.Component + renderer clause + family aggregation + both adapters + IUR vocab registry + tests at each layer)

Test plan

  • Catalog test asserts family: :row_and_artifact registration
  • IUR constructor: happy path + invalid-payload rejections (14 invariants)
  • LiveUi.Widgets.ToolCallCard render: collapsed / expanded / status variants / paired result / fallback aria
  • Renderer dispatch: :tool_call_card routes through dedicated clause
  • Both adapter dispatch tests
  • aria-controls + aria-expanded linkage (Phoenix.Component + adapter parity)

273 tests pass focused; 74 widget + 86 catalog/validation/adapter via Codex run.

Reviews

  • Codex implementer: 1 round, no WIP, all gates clean.
  • Opus Max independent review (substituting for Codex deep-review per weekly token cap pattern): APPROVE for DRAFT baseline. No P1. 3 P2s fixed inline post-review (status in aria-label, aria-controls linkage in adapter, BEM -- modifier consistency).

Deferred P3 follow-ons

  • Status :failed render variant + child error?: true rendering have minimal assertions; broader coverage in a polish pass.
  • CSS asset file at assets/css/widgets/tool_call_card.css not yet present (spec css_authoring marks as planned; deferred per phase_41_planned_verification exception).
  • paired_result_event_id accepted by both paths but no data-paired-result-event-id hook emitted (downstream pagination_pairing may want this).
  • LiveUi.Widgets.RowAndArtifact aggregator only has ToolCallCard; ThreadCard/ArtifactRow still in LiveUi.Widgets.Data (legacy family: :data). Pascal may want to migrate as a separate alignment commit.

Notes for Pascal

  • Family vocabulary: tool_call_card uses family: :row_and_artifact matching your PresenceDot alignment (a902750). ThreadCard/ArtifactRow still on legacy family: :data — flagging for your call.
  • Adapter vs native render-path parity: live_ui_adapter HTML fallback and LiveUi.Widgets.ToolCallCard now parity-aligned on BEM modifier, accessible name composition, and aria-controls wiring.
  • Stage 5 (AshUI Screen DSL adoption) deferred — will land as a separate small follow-on after this lands and downstream ariston-ui consumption PR opens.

Generated with Claude Code

ty13r and others added 2 commits May 27, 2026 08:49
Co-Authored-By: Codex <codex@openai.com>
Opus Max review P2 fixes:
- aria-label now includes status: "Toggle tool call <name> (<status>) details"
  (both Phoenix.Component and live_ui_adapter HTML paths)
- live_ui_adapter article gains id + button gains aria-controls linkage to
  the details section
- BEM `--` modifier convention applied consistently to live_ui_adapter
  (ash-tool-call-card--<status> and __status-badge--<status>)
- Test assertion updated to use ~s|...| sigil since parentheses now appear
  in the aria-label

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant