feat(propose_new_doc_card): canonical widget Stage 1-4 (:layer_shell_and_callout family — new)#148
Merged
ty13r merged 3 commits intoMay 29, 2026
Conversation
…_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>
…bute
Opus Max review P2: aria-controls references @seed_id; when collapsed via
:if={@seed_expanded?}, the target node is removed from DOM, leaving a
dangling aria-controls reference. ARIA disclosure pattern recommends the
target exist with the hidden attribute.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
ty13r
added a commit
that referenced
this pull request
May 29, 2026
…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>
…and_callout) Phase31DocsConformanceTest asserts each AshUI.WidgetComponents.kinds() name appears in the user guide. propose_new_doc_card was added as a canonical widget in Phase 41.6 but not documented in UG-0003, causing a net-new conformance regression on PR #148. Added propose_new_doc_card to the Layer shell and callout family table row and added a descriptive paragraph covering its key props (target_path, title, body_md_preview, status, actor_handle, expanded?) and canonical interactions (accept, reject, preview, body_toggled, conversation_seed_toggled). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
ty13r
added a commit
that referenced
this pull request
May 29, 2026
…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>
ty13r
added a commit
that referenced
this pull request
May 29, 2026
…allout sibling to propose_new_doc_card) (#149) * feat(propose_new_doc_card): add canonical widget for Phase 41 propose_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> * feat(widget): add :escalation_card canonical widget to :layer_shell_and_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> * fix(escalation_card): P1 layer_callout_kinds assertion + P2 unified_ui 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> * docs(conformance): add propose+escalation_card to UG-0003; fix Phase31PackageBoundaryTest 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> * fix(format): remove extra blank line in unified_iur components 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> --------- 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.6 — adds
:propose_new_doc_cardas a NEW canonical widget in family:layer_shell_and_callout(NEW family — this PR creates the aggregator). Stage 1-4 of the canonical-widget pipeline; Stage 5 (AshUI Screen DSL adoption) deferred.Renders the
:propose_new_docSessionEvent emitted bypropose_new_project_documentMCP (shipped in PR 41.3afeat(phase-41.3a)).Implementation
Stage 1 — UnifiedUi catalog + DSL entity + DSL pipeline + verifier:
packages/unified_ui/lib/unified_ui/widget_components.ex— register:propose_new_doc_cardwithfamily: :layer_shell_and_calloutpackages/unified_ui/lib/unified_ui/dsl/entities/widget_components.ex— DSL leafpackages/unified_ui/lib/unified_ui/compiler/pipeline.ex+dsl/node.ex+dsl/verifiers/validate_widget_components.ex— lowering + verifier wiringStage 2 — UnifiedIUR constructor + validation:
packages/unified_iur/lib/unified_iur/widgets/components.ex—propose_new_doc_card/1constructor +@layer_callout_kindspackages/unified_iur/lib/unified_iur/validate.ex—:invalid_propose_new_doc_cardvalidationpackages/unified_iur/lib/unified_iur/fixtures.ex— fixture coverageStage 3 — LiveUi Phoenix.Component:
packages/live_ui/lib/live_ui/widgets/propose_new_doc_card.ex— Phoenix.Component withlive-ui-*BEM, full aria coverage (aria-controls + aria-expanded + descriptive labels), Accept/Reject/Preview actionspackages/live_ui/lib/live_ui/renderer.ex— dedicated:propose_new_doc_cardclause placed above generic fallbackStage 4 — Adapter routings + NEW family aggregator:
lib/ash_ui/rendering/iur_adapter.ex— canonical IUR pathlib/ash_ui/rendering/live_ui_adapter.ex— string-HTML fallbackpackages/live_ui/lib/live_ui/widgets/layer_shell_and_callout.ex— NEW family aggregator (Codex created this file because:layer_shell_and_calloutdidn't exist as an aggregator yet; will be extended in PR 41.7 withescalation_card)Spec ref (ariston-ui)
.spec/specs/canonical_widget_propose_new_doc_card.spec.mdSpec ↔ shipped payload reconciliation needed (Pascal): spec contract uses
proposed_path/proposed_title/rationale/proposed_kind/decision. Implementation usestarget_path/title/body_md_preview/conversation_seed_md/statusto match the Phase 41.3a SessionEvent payload (lib/ariston_ui/mcp/tools/propose_new_project_document.ex:80-88,107-111) that's already shipped. Recommend amending the spec to match the working payload — the SessionEvent ships those exact field names and any rename would ripple back through PRs 41.3a/3b.Test plan
:pending/ preview link / aria-expanded + aria-controls linkagefamily: :layer_shell_and_callouthiddenattribute when collapsed (post-Opus-review fix)97/97 tests pass on changed files; 117 total pass across the widget surface.
Reviews
Deferred P3 follow-ons
status: :archivedadded to widget enum — not in spec; aligns with Phase 41.3a lifecycle. Pascal to confirm.assets/css/widgets/propose_new_doc_card.cssnot present (DRAFT acceptable).Notes for Pascal
:layer_shell_and_calloutfamily aggregator atpackages/live_ui/lib/live_ui/widgets/layer_shell_and_callout.ex. PR 41.7 (escalation_card) will extend this aggregator with its widget.:expanded?and:seed_expanded?state lives in the consuming LiveView, not the widget. Widget emitsbody_toggledandconversation_seed_toggledevents; consumer flips state.Generated with Claude Code