feat(live_session_card): composite canonical widget Stage 1-4 (:workflow_progress_and_status family)#147
Draft
ty13r wants to merge 2 commits into
Draft
Conversation
…e 41.8)
Wires the most complex Phase 41 widget through all four pipeline stages
(IUR constructor → UnifiedUI catalog/DSL → LiveUI renderer → AshUI
iur_adapter + live_ui_adapter) plus two new test modules and boundary
assertions in eight existing test files.
Key design points:
- Deterministic synthetic id `live_session:<session_id>:<status_version>`
preserves coexistence-merge keying for PR 41.10 without coupling.
- Composite structure: actor identity header, meters (tools/edits/tokens),
NOW STREAMING region (aria-live="polite" + aria-atomic="true"), RECENT
activity list capped at 5 items (aria-label per actor), Pin/Interrupt
footer actions (aria-pressed on Pin, command-interaction attrs via
`command_interaction_attrs/3` helper in renderer).
- IUR validation: uuid_string? + datetime_like? + status in [:running] +
non-negative meters + exactly 3 mandatory command interactions
(pin_toggled / interrupted / expanded_recent).
- Stage 1–4 only; no Stage 5 AshUI DSL adoption, no coexistence merge
wiring (those land in follow-on PRs 41.9/41.10).
Gates: mix compile --warnings-as-errors EXIT=0 /
mix test (269 tests, 0 failures) EXIT=0 /
mix format --check-formatted on all 20 modified files EXIT=0
Co-Authored-By: Codex GPT-5.5 Pro xhigh <noreply@openai.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Opus Max review P2 fixes: - adapter Pin button aria-label now flips Pin↔Unpin with @Pinned? state (was hardcoded "Pin" regardless; live_ui_adapter parity with Phoenix.Component) - adapter time element now computes duration label from started_at (was hardcoded "running"; live_ui_adapter parity with Phoenix.Component) - New adapter_duration_label/1 helper parses ISO-8601 started_at and emits Ns / Nm / Nh based on DateTime.utc_now diff 🤖 Generated with [Claude Code](https://claude.com/claude-code) 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 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.
Summary (DRAFT — Pascal-review required)
Phase 41 PR 41.8 — adds
:live_session_cardas a NEW COMPOSITE canonical widget in family:workflow_progress_and_status. Stage 1-4 of the canonical-widget pipeline; Stage 5 (AshUI Screen DSL adoption) and PR 41.10 coexistence merge wiring deferred.This is the centerpiece of Phase 41's chat surface — the only collapsed view for actively-running bound sessions. Composite shape with meters + NOW STREAMING + RECENT list + Pin/Interrupt actions.
Implementation
Stage 1 — UnifiedUi catalog + DSL entity:
packages/unified_ui/lib/unified_ui/widget_components.ex— register:live_session_cardwithfamily: :workflow_progress_and_statuspackages/unified_ui/lib/unified_ui/dsl/entities/widget_components.ex— DSL leafStage 2 — UnifiedIUR constructor + validation:
packages/unified_iur/lib/unified_iur/widgets/components.ex—live_session_card/1constructor; deterministic synthetic idlive_session:<session_id>:<status_version>enforcedpackages/unified_iur/lib/unified_iur/validate.ex—:invalid_live_session_cardwith full coverage (uuid format, non-blank, status forced:running, status_version int, meters non-negative int, started_at, recent_events ≤5 cap, per-event shape, pinned? bool, actions)Stage 3 — LiveUi Phoenix.Component:
packages/live_ui/lib/live_ui/widgets/live_session_card.ex— composite component witharia-live="polite"+aria-atomic="true"on NOW STREAMING area,aria-pressedreflectingpinned?on Pin button,<ol aria-label>for recent events,role="status"badge,<time datetime>with liveduration_label/1packages/live_ui/lib/live_ui/renderer.ex— dedicated:live_session_cardclause placed before generic fallbackStage 4 — Adapter routings + family aggregation:
lib/ash_ui/rendering/iur_adapter.ex— canonical IUR path;element_id_for_kind(:live_session_card, ...)constructs synthetic id consistently with constructorlib/ash_ui/rendering/live_ui_adapter.ex— string-HTML fallback with parity-aligned aria-label state + duration label (portingadapter_duration_label/1)packages/live_ui/lib/live_ui/widgets/workflow_progress_and_status.ex—LiveSessionCardadded to@modulesSpec ref (ariston-ui)
.spec/specs/canonical_widget_live_session_card.spec.mdSpec ↔ implementation reconciliation needed (Pascal): spec lists props as
session_handle, nestedmetersmap,expanded?state. Implementation matches the orchestrator brief: flat meter fields (tools_count/edits_count/tokens_consumed), action eventspin_toggled/interrupted/expanded_recent, nosession_handle. The brief contract is the working model for Phase 41; recommend amending the spec rather than re-shaping the widget.Test plan
pinned?269 tests, 0 failures (8 widget + 6 IUR + 50 adapter + existing).
Reviews
Deferred P3 follow-ons
assets/css/widgets/live_session_card.cssnot present (DRAFT acceptable).timeelement'sdatetimeattribute uses raw started_at without ISO-8601 normalization.tokens_consumedcardinality not bounded — operator-display sanity caps for Pascal to decide.Notes for Pascal
:workflow_progress_and_status(afterworkflow_progress_status_card). Both follow same nested-attribute pattern (attributes.live_session.*vsattributes.subject.*). Composite is cleanly bounded.IURComponents.live_session_card/1), adapter (element_id_for_kind/2), and validator (validate.ex) all construct/check identically.Generated with Claude Code