feat(escalation_card): canonical widget Stage 1-4 (:layer_shell_and_callout sibling to propose_new_doc_card)#149
Merged
Conversation
ty13r
added a commit
that referenced
this pull request
May 29, 2026
…1PackageBoundaryTest Phase31DocsConformanceTest asserts each AshUI.WidgetComponents.kinds() name appears in UG-0003. Both propose_new_doc_card and escalation_card were missing, causing net-new conformance regressions on PR #149. Phase31PackageBoundaryTest layer_shell_and_callout families assertion lacked :escalation_card. The code legitimately adds it; this is a correct test-list update, not test weakening. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…_new_doc SessionEvents Full 4-stage canonical widget pipeline for :propose_new_doc_card in the :layer_shell_and_callout family, supporting pending/accepted/rejected/archived status, accept/reject/preview actions, body expansion, and conversation seed collapsible slot. Stage 1 (catalog): widget_components.ex entry with family/summary/aliases Stage 2 (DSL): dsl/entities/widget_components.ex leaf entity with all attrs Stage 3 (IUR): components.ex constructor + validate.ex + fixture coverage Stage 4 (LiveUI): ProposeNewDocCard Phoenix.Component, layer_shell_and_callout aggregation, renderer.ex clause, iur_adapter.ex routing, live_ui_adapter.ex fallback markup Fixture coverage: propose_new_doc_card added to components--accessibility_and_safety fixture; 6 pre-existing missing-kind failures (collection_picker, thread_card, composer_query_preview) are unrelated to this PR. DRAFT: spec contract discrepancy — canonical_widget_propose_new_doc_card.spec.md uses proposed_path/proposed_title/rationale/proposed_kind/decision but this implementation follows Phase 41 SessionEvent payload shape (target_path/title/ body_md_preview/status). Pascal review required before merge. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…nd_callout family Extends the family aggregator from PR 41.6 with EscalationCard — a severity-bearing inline callout for :escalation_raised SessionEvents. Stage 1-4 pipeline: - family aggregator: add LiveUi.Widgets.EscalationCard to @modules - unified_iur: escalation_card/1 constructor + @escalation_severities [:p1,:p2,:p3] + put_escalation_interactions (acknowledge + route_to_rail defaults) - unified_iur validate: :invalid_escalation_card guidance + validate_escalation_shape/1 (required target_project_id/text/severity; optional string + optional severity checks) - unified_iur fixtures: coverage entry with p2 severity - live_ui renderer: native :escalation_card clause before generic fallback; escalation_attributes/1 + escalation_action_attrs/2 helpers - iur_adapter: base_attributes(:escalation_card) + escalation_card_opts/1 - live_ui_adapter: generate_heex("escalation_card") with BEM classes, severity modifier, acknowledged? aria-label flip Tests: 25 unit (live_ui + unified_iur widgets) + 204 rendering (0 failures). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…i threading + pre-existing coverage gaps P1: append :escalation_card to the layer_callout_kinds() assertion in components_test.exs — the code had it in @layer_callout_kinds but the test assertion still ended at :propose_new_doc_card. P2: thread escalation_card into unified_ui as a resource-authorable widget, mirroring what propose_new_doc_card (#148) did: - widget_components.ex catalog entry (:layer_shell_and_callout family) - dsl/entities/widget_components.ex: leaf(:escalation_card) with all required/optional fields (target_project_id, text, severity, etc.) - dsl/node.ex: 10 new fields in @type t(), defstruct, and summary/1 - dsl/verifiers/validate_widget_components.ex: validate_node/1 clause with @escalation_severities + optional field checks - compiler/pipeline.ex: :escalation_card arm calling Widgets.Components.escalation_card via common_opts Test updates (all asserting correct runtime values, not weakening): - unified_iur components_test: layer_callout_kinds list includes :escalation_card - unified_ui catalog/operational/phase_2/advanced_widget_families tests: kinds lists updated to include :escalation_card - compiler lowering test: escalation_card DSL node + lowering assertions Also adds 3 pre-existing coverage gaps (collection_picker, thread_card, composer_query_preview) to unified_iur/fixtures.ex so this branch does not carry main redness. Result: unified_iur 196 tests 0 failures; unified_ui 162 tests 29 failures (identical to the 29 pre-existing failures on #148 baseline). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
…1PackageBoundaryTest Phase31DocsConformanceTest asserts each AshUI.WidgetComponents.kinds() name appears in UG-0003. Both propose_new_doc_card and escalation_card were missing, causing net-new conformance regressions on PR #149. Phase31PackageBoundaryTest layer_shell_and_callout families assertion lacked :escalation_card. The code legitimately adds it; this is a correct test-list update, not test weakening. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ca80983 to
6b23a90
Compare
Trailing double blank line before normalize_query_preview_state!/1 fails mix format --check-formatted in the unified_iur package. Co-Authored-By: Claude Sonnet 4.6 <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.7 — adds
:escalation_cardas a NEW canonical widget in family:layer_shell_and_callout. Sibling of 41.6 — extends the family aggregator created in PR ash_ui#148. Stage 1-4 of the canonical-widget pipeline; Stage 5 deferred.This PR is based on the 41.6 branch (
claude/phase-41.6-propose-new-doc-card-canonical-widget). When 41.6 lands, 41.7 rebases naturally. Review the diff against 41.6 (not main) for 41.7-specific changes only.Renders the
:escalation_raisedSessionEvent emitted byescalate_to_teamMCP (shipped in PR 41.3a).Implementation
Stage 1 — UnifiedUi catalog + DSL:
packages/unified_ui/lib/unified_ui/widget_components.ex— register:escalation_cardwithfamily: :layer_shell_and_calloutStage 2 — UnifiedIUR:
packages/unified_iur/lib/unified_iur/widgets/components.ex—escalation_card/1constructor; added to@layer_callout_kinds;@escalation_severities = [:p1, :p2, :p3]packages/unified_iur/lib/unified_iur/validate.ex—validate_escalation_shape/1rejecting blank/invalid severity/missing requiredpackages/unified_iur/lib/unified_iur/fixtures.ex— fixture coverage with:p2severityStage 3 — LiveUi Phoenix.Component:
packages/live_ui/lib/live_ui/widgets/escalation_card.ex—role="alert",aria-labelledbyto title, severity-aware action button aria-labels, acknowledged state cleanly hides actions + shows status textpackages/live_ui/lib/live_ui/renderer.ex— dedicated:escalation_cardclause +escalation_attributes/escalation_action_attrshelpersStage 4 — Adapters + family aggregator extension:
lib/ash_ui/rendering/iur_adapter.ex— canonical IUR conversion +escalation_card_opts/1lib/ash_ui/rendering/live_ui_adapter.ex— string-HTML fallback with BEM--<severity>modifier +acknowledged?flip on aria-labelpackages/live_ui/lib/live_ui/widgets/layer_shell_and_callout.ex—EscalationCardADDED to@modules(existingProposeNewDocCardfrom 41.6 untouched)Spec ref (ariston-ui)
.spec/specs/canonical_widget_escalation_card.spec.mdSpec vs shipped payload reconciliations (4 items in P3 below — same pattern as 41.6's reconciliation).
Test plan
:invalid_escalation_carderrors for each invariant25 unit tests + 204 rendering tests pass.
Reviews
Deferred P3 follow-ons (Pascal review)
evidencefield reconciliation — spec requiresevidence: [{ref, anchor}]and validation; shipped widget usesescalate_to_teamMCP payload (no evidence field). Same pattern Pascal accepted for 41.6's spec-vs-payload trade.--severity-infix — spec wants.ash-escalation-card--severity-p1; shipped emits.ash-escalation-card--p1. Matches 41.6's.ash-propose-new-doc-card--{status}convention.assets/css/widgets/escalation_card.cssnot present (spec marks "planned").title/actor_handle— spec lists both required; shipped uses hardcoded "Escalation" + optional actor_handle (matchesescalate_to_teampayload reality).Notes for Pascal
:layer_shell_and_calloutfamily now holds 2 widgets (propose_new_doc_cardfrom 41.6 +escalation_cardfrom 41.7). Aggregator extension is additive — no 41.6 churn.Generated with Claude Code