Skip to content

feat(live_session_card): composite canonical widget Stage 1-4 (:workflow_progress_and_status family)#147

Merged
ty13r merged 4 commits into
mainfrom
claude/phase-41.8-live-session-card-canonical-widget
May 29, 2026
Merged

feat(live_session_card): composite canonical widget Stage 1-4 (:workflow_progress_and_status family)#147
ty13r merged 4 commits into
mainfrom
claude/phase-41.8-live-session-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.8 — adds :live_session_card as 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_card with family: :workflow_progress_and_status
  • packages/unified_ui/lib/unified_ui/dsl/entities/widget_components.ex — DSL leaf

Stage 2 — UnifiedIUR constructor + validation:

  • packages/unified_iur/lib/unified_iur/widgets/components.exlive_session_card/1 constructor; deterministic synthetic id live_session:<session_id>:<status_version> enforced
  • packages/unified_iur/lib/unified_iur/validate.ex:invalid_live_session_card with 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 with aria-live="polite" + aria-atomic="true" on NOW STREAMING area, aria-pressed reflecting pinned? on Pin button, <ol aria-label> for recent events, role="status" badge, <time datetime> with live duration_label/1
  • packages/live_ui/lib/live_ui/renderer.ex — dedicated :live_session_card clause placed before generic fallback

Stage 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 constructor
  • lib/ash_ui/rendering/live_ui_adapter.ex — string-HTML fallback with parity-aligned aria-label state + duration label (porting adapter_duration_label/1)
  • packages/live_ui/lib/live_ui/widgets/workflow_progress_and_status.exLiveSessionCard added to @modules

Spec ref (ariston-ui)

  • .spec/specs/canonical_widget_live_session_card.spec.md
  • ADR-0044 §"PR 8 — live_session_card"

Spec ↔ implementation reconciliation needed (Pascal): spec lists props as session_handle, nested meters map, expanded? state. Implementation matches the orchestrator brief: flat meter fields (tools_count/edits_count/tokens_consumed), action events pin_toggled/interrupted/expanded_recent, no session_handle. The brief contract is the working model for Phase 41; recommend amending the spec rather than re-shaping the widget.

Test plan

  • IUR constructor: happy path + invalid-payload rejections (14+ invariants)
  • Deterministic synthetic id: constructor + adapter + validator three-way consistency
  • LiveUi.Widgets.LiveSessionCard render: status badge / meters / NOW STREAMING with aria-live / RECENT list capped at 5 / Pin aria-pressed / Interrupt actions
  • Both adapter dispatch tests (canonical IUR path + string-HTML fallback)
  • aria-label parity: Phoenix.Component + adapter both flip Pin↔Unpin with pinned?
  • Duration label parity: both compute from started_at

269 tests, 0 failures (8 widget + 6 IUR + 50 adapter + existing).

Reviews

  • Codex implementer: 1 round, no WIP. 20 source files, 1593 insertions.
  • Opus Max independent review: APPROVE for DRAFT. No P1. 2 P2s fixed inline post-review (adapter Pin aria-label state + adapter duration label).

Deferred P3 follow-ons

  • CSS asset at assets/css/widgets/live_session_card.css not present (DRAFT acceptable).
  • Adapter time element's datetime attribute uses raw started_at without ISO-8601 normalization.
  • tokens_consumed cardinality not bounded — operator-display sanity caps for Pascal to decide.

Notes for Pascal

  • Composite-widget pattern: second composite in :workflow_progress_and_status (after workflow_progress_status_card). Both follow same nested-attribute pattern (attributes.live_session.* vs attributes.subject.*). Composite is cleanly bounded.
  • Deterministic synthetic id is the key correctness invariant for PR 41.10's coexistence merge — constructor (IURComponents.live_session_card/1), adapter (element_id_for_kind/2), and validator (validate.ex) all construct/check identically.
  • Spec ↔ implementation drift — see above. Recommend amending spec to match working model.

Generated with Claude Code

ty13r added a commit that referenced this pull request May 29, 2026
…ss_and_status)

Phase31DocsConformanceTest asserts each AshUI.WidgetComponents.kinds() name
appears in the user guide. live_session_card was added as a canonical widget
in Phase 41.8 but not documented in UG-0003, causing a net-new conformance
regression on PR #147.

Added live_session_card to the Workflow, progress, and status family table
row and added a descriptive paragraph covering its key props (session_id,
actor_handle, status, status_version, tools_count, edits_count,
tokens_consumed, started_at, now_streaming, recent_events, pinned?) and
canonical interactions (pin_toggled, interrupted, expanded_recent).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ty13r and others added 4 commits May 28, 2026 22:51
…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>
…-existing coverage gaps

Adds a Components.live_session_card/1 reference fixture to the canonical
components--accessibility_and_safety fixture in UnifiedIUR.Fixtures.
Uses an ISO 8601 string for started_at rather than a DateTime struct
so the reference snapshot_map walk does not hit an Enumerable error.

Also adds the three fixtures missing on main (collection_picker, thread_card,
composer_query_preview) so this branch does not carry pre-existing coverage
redness into its PR gate.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…ss_and_status)

Phase31DocsConformanceTest asserts each AshUI.WidgetComponents.kinds() name
appears in the user guide. live_session_card was added as a canonical widget
in Phase 41.8 but not documented in UG-0003, causing a net-new conformance
regression on PR #147.

Added live_session_card to the Workflow, progress, and status family table
row and added a descriptive paragraph covering its key props (session_id,
actor_handle, status, status_version, tools_count, edits_count,
tokens_consumed, started_at, now_streaming, recent_events, pinned?) and
canonical interactions (pin_toggled, interrupted, expanded_recent).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
@ty13r ty13r force-pushed the claude/phase-41.8-live-session-card-canonical-widget branch from 6b35023 to c89355b Compare May 29, 2026 03:52
@ty13r ty13r marked this pull request as ready for review May 29, 2026 04:11
@ty13r ty13r merged commit 21d2b17 into main May 29, 2026
8 checks passed
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