Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 3m45s
Implemented the first version of review output resolve actions. Included a ReviewOutputResolveActionMapper, commands to seed browser fixtures, updated CustomerReviewWorkspace, EnvironmentReviewResource, UI enforcement, and related views. Also added extensive unit, feature, and browser tests, and updated the design coverage matrix.
17 KiB
17 KiB
Implementation Plan: Spec 351 - Review Output Resolve Actions v1
Branch: 351-review-output-resolve-actions-v1 | Date: 2026-06-03 | Spec: specs/351-review-output-resolve-actions-v1/spec.md
Input: Direct user-provided Spec 351 draft plus repo truth from the current review-output guidance path and existing review lifecycle actions.
Summary
Productize Spec 350's review-output-first contract into one bounded review-output resolve-action layer that can surface a real next step where the repo already supports one:
- choose the strongest safe next action
- explain why it is recommended
- execute it only through existing source-owned Filament actions and services
- degrade honestly to navigation or disclosure when execution is unavailable
This slice stays review-output-only and touches only the current review-output consumers:
CustomerReviewWorkspace- Environment Review detail
It must not:
- broaden into provider readiness, governance inbox, or dashboard reuse
- invent a new workflow engine or action runtime
- create fake remediation or fake draft discovery
- add persistence, schema, or new lifecycle states
Technical Context
- Language/Version: PHP 8.4.15, Laravel 12.52.x
- Primary Dependencies: Filament 5.2.x, Livewire 4.1.x, Pest 4, Tailwind CSS 4
- Storage: PostgreSQL; no schema change expected
- Testing: Pest Unit + Feature/Livewire + one bounded Browser smoke
- Validation Lanes: fast-feedback + confidence + browser
- Target Platform:
apps/platformLaravel monolith, Sail-first locally - Project Type: server-rendered Filament web application
- Performance Goals: derived-only action selection, no new remote calls during render, no new queue family, no duplicate lifecycle dispatch
- Constraints: no fake executable actions, no direct service calls from Blade, no duplicate primary CTAs on detail, no provider/dashboard scope growth
- Scale/Scope: one deterministic mapper, one review-output adapter integration, one workspace-side executable action bridge, one non-duplicative detail alignment
UI / Surface Guardrail Plan
- Guardrail scope: changed strategic workspace surface plus changed review-detail guidance semantics
- Affected routes/pages/actions/states/navigation/panel/provider surfaces:
/admin/reviews/workspace- existing Environment Review detail route(s)
- existing workspace-mounted page actions and Environment Review header lifecycle actions
- No-impact class, if applicable: N/A
- Native vs custom classification summary: native Filament page/resource surfaces plus existing custom Blade rendering
- Shared-family relevance: review-output guidance, lifecycle actions, evidence/proof follow-up links
- State layers in scope: page, detail, URL-query, derived action-state envelope
- Audience modes in scope: operator-MSP, manager, readonly reviewer, customer-workspace detail context
- Decision/diagnostic/raw hierarchy plan: dominant next action first; limitations and evidence second; technical detail third
- Raw/support gating plan: unchanged; raw/support detail stays on source-owned surfaces
- One-primary-action / duplicate-truth control: workspace gets one dominant resolve action; detail aligns to one dominant lifecycle action without creating a second equal-weight rail
- Handling modes by drift class or surface: review-mandatory
- Repository-signal treatment: review-mandatory because the slice makes high-impact review actions more visible
- Special surface test profiles:
global-context-shell+shared-detail-family - Required tests or manual smoke: Unit + Feature + one bounded Browser smoke
- Exception path and spread control: if workspace execution requires more than mounting source-owned Filament actions, stop and keep the action as fallback navigation/disclosure
- Active feature PR close-out entry: Guardrail / Confirmation / Smoke Coverage
- UI/Productization coverage decision: update
ui-006andui-040only; no new route archetype or registry row is required - Coverage artifacts to update:
docs/ui-ux-enterprise-audit/page-reports/ui-006-customer-review-workspace.md,docs/ui-ux-enterprise-audit/page-reports/ui-040-environment-review-detail.md - No-impact rationale: N/A
- Navigation / Filament provider-panel handling: no route or provider change
- Screenshot or page-report need: yes; this is a first-screen CTA trust change on existing strategic surfaces
Shared Pattern & System Fit
- Cross-cutting feature marker: yes
- Systems touched:
App\Support\ReviewPacks\ReviewPackOutputResolutionGuidanceApp\Support\ResolutionGuidance\ResolutionActionApp\Support\ResolutionGuidance\ResolutionCaseApp\Support\ResolutionGuidance\Adapters\ReviewPackOutputResolutionAdapterApp\Filament\Pages\Reviews\CustomerReviewWorkspaceApp\Filament\Resources\EnvironmentReviewResourceApp\Filament\Resources\EnvironmentReviewResource\Pages\ViewEnvironmentReviewApp\Support\Ui\GovernanceActions\GovernanceActionCatalog
- Shared abstractions reused:
- current review-output readiness derivation
- existing
ResolutionCase/ResolutionActioncontract - existing Filament page-action mounting pattern on
CustomerReviewWorkspace - existing lifecycle actions and services on
ViewEnvironmentReview - current scoped route helpers and
OperationRunLinks
- New abstraction introduced? why?: yes, one
ReviewOutputResolveActionMapperis required because the repo has multiple real action sources and fallbacks, but current review-output guidance remains link-first and not execution-aware - Why the existing abstraction was sufficient or insufficient: Spec 350 standardized the case shape, but not the deterministic ranking of real resolve actions or the surface-safe execution bridge for those actions
- Bounded deviation / spread control: any action execution metadata added to
ResolutionActionmust stay optional, review-output-only, and derived-only
OperationRun UX Impact
- Touches OperationRun start/completion/link UX?: yes, indirectly
- Central contract reused:
EnvironmentReviewService::refresh()EnvironmentReviewLifecycleService::createNextReview()- existing
OperationRunLinks
- Delegated UX behaviors: queueing, dedupe, run creation, and notifications remain owned by the current services and shared UX paths
- Surface-owned behavior kept local: action ranking, explanation text, and honest fallback selection
- Queued DB-notification policy: unchanged
- Terminal notification path: unchanged
- Exception path: none
Provider Boundary & Portability Fit
N/A - the slice stays on review, evidence, pack, and operation surfaces only.
Current Repo Truth Summary
ReviewPackOutputResolutionGuidancealready derives rich output state, limitation, and link/disclosure copy fromReviewPackOutputReadiness.ReviewPackOutputResolutionAdapteralready wraps that guidance intoResolutionCase, but today it can only promote safe navigation/download/disclosure actions.ViewEnvironmentReviewalready exposes repo-real lifecycle actions:refresh_reviewbacked byEnvironmentReviewService::refresh()publish_reviewbacked byEnvironmentReviewLifecycleService::publish()create_next_reviewbacked byEnvironmentReviewLifecycleService::createNextReview()
create_next_reviewis capability-gated and audited, but it is not currently confirmation-gated even though it mutates review lifecycle state and starts the next review cycle.EnvironmentReviewLifecycleService::createNextReview()supersedes the published review and returns a mutable successor review; the repo has no generic workspace-level "open existing draft review" helper unless a concrete target review is already known.CustomerReviewWorkspacealready mounts real Filament page actions from custom Blade viamountAction()and includes<x-filament-actions::modals />, so workspace-side execution of bounded actions is feasible without inventing a second runtime.- Environment Review detail already has dominant header lifecycle actions, and customer-workspace detail mode intentionally suppresses repeated action rails inside the guidance card.
EvidenceSnapshotResource\Pages\ViewEvidenceSnapshotalready exposesrefresh_evidenceas a repo-real action, but review-output surfaces currently only link to evidence detail rather than executing evidence refresh directly.CustomerReviewWorkspaceis viewable by readonly actors, so executable resolve actions on the workspace must be capability-aware and honest when unavailable.
Implementation Approach
Phase 0 - Repo Truth Gate
- Re-read
spec.md,plan.md,tasks.md,repo-truth-map.md,contracts/review-output-resolve-action-map.md, andchecklists/requirements.md. - Re-verify:
apps/platform/app/Support/ReviewPacks/ReviewPackOutputResolutionGuidance.phpapps/platform/app/Support/ResolutionGuidance/Adapters/ReviewPackOutputResolutionAdapter.phpapps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.phpapps/platform/app/Filament/Resources/EnvironmentReviewResource.phpapps/platform/app/Filament/Resources/EnvironmentReviewResource/Pages/ViewEnvironmentReview.phpapps/platform/app/Services/EnvironmentReviews/EnvironmentReviewService.phpapps/platform/app/Services/EnvironmentReviews/EnvironmentReviewLifecycleService.phpapps/platform/app/Filament/Resources/EvidenceSnapshotResource/Pages/ViewEvidenceSnapshot.php
- Keep the repo-truth docs current if the narrowest safe action map changes during implementation.
Phase 1 - Tests First
- Add
apps/platform/tests/Unit/ResolutionGuidance/Spec351ReviewOutputResolveActionMapperTest.php. - Cover deterministic selection for:
- published blocked review with known successor review
- published blocked review without known successor review
- published blocked review without safe executable action
- mutable review with stale/missing evidence
- ready mutable review
- internal-only / PII / export-not-ready / no-action fallback
- Add workspace/detail feature tests:
apps/platform/tests/Feature/Filament/Spec351CustomerReviewWorkspaceResolveActionTest.phpapps/platform/tests/Feature/EnvironmentReview/Spec351EnvironmentReviewResolveActionTest.php
- Add one browser smoke:
apps/platform/tests/Browser/Spec351ReviewOutputResolveActionsSmokeTest.php, covering at least one blocked path and one ready-state path
- Reuse Spec 347/349/350 coverage instead of duplicating readiness/output assertions wholesale.
Phase 2 - Core Mapper And Contract Extension
- Create
apps/platform/app/Support/ResolutionGuidance/ReviewOutputResolveActionMapper.php. - Feed it:
- the current
EnvironmentReview - current review-output guidance/readiness truth
- known linked targets such as evidence, review detail, operation proof, download URL
- surface context (
customer_review_workspace,environment_review_detail,environment_review_detail.customer_workspace) - actor/capability availability where action execution must differ by viewer
- the current
- Deterministic ranking order:
- known successor review navigation when a concrete target exists
create_next_reviewfor blocked/limited published reviewsrefresh_reviewfor mutable reviews with stale or incomplete inputspublish_reviewfor ready mutable reviews- evidence/proof/disclosure fallback when no safe execution path exists
- Extend
ResolutionActiononly if needed so a case can carry missing source-owned execution-routing metadata such asaction_nameandexecution_surface, while reusing existingdisabled_reason, capability, confirmation, audit-event, andOperationRunmetadata. - Make the mapper the canonical selector of
resolution_case.primary_actionandsecondary_actionsfor the two in-scope surfaces.ReviewPackOutputResolutionGuidanceremains the source for readiness, limitations, and explanatory copy; its raw action fields are compatibility data and must not drive CTA ranking on workspace or detail. - Keep the contract derived-only and request-scoped.
Phase 3 - Workspace-Side Source-Owned Action Execution
- Add or reuse
CustomerReviewWorkspacepage actions for:refresh_reviewpublish_reviewcreate_next_review
- Reuse existing services,
GovernanceActionCatalogwhere already repo-real,UiEnforcement, capability checks, notifications, and audit behavior. - Mount those actions from the workspace decision card via
mountAction()and existing Filament modals. - Do not call lifecycle services directly from Blade.
- If a current actor or surface cannot safely execute the dominant action, downgrade to the strongest truthful navigation/disclosure fallback instead of showing a fake enabled button.
- If
create_next_reviewbecomes a dominant workspace CTA, addrequiresConfirmation()to the source-owned action before exposing it as executable; otherwise degrade it to truthful navigation/disclosure fallback. No exception path is allowed for executable use.
Phase 4 - Adapter Integration And Workspace Behavior
- Update
ReviewPackOutputResolutionAdapterso the dominant action comes from the new mapper while preserving current case/title/reason/impact/source/evidence data. - Preserve current findings and accepted-risk follow-up overrides on
CustomerReviewWorkspace; those remain higher-priority than the base review-output case. - Render exactly one dominant primary CTA in the workspace decision card and move all other mapped actions into a clearly secondary supporting-action group.
- Keep current technical details and grouped limitations disclosure intact unless a narrower improvement is required for clarity.
- Keep the review-consumption flow on the workspace as a supporting reference below the primary decision surfaces instead of a peer decision card.
- Do not regress qualified download wording or honest internal-only wording.
Phase 5 - Environment Review Detail Alignment
- Align
EnvironmentReviewResource::outputGuidanceState()to the same resolve-action semantics. - Preserve current
customer_workspacedetail-mode suppression and context note. - In normal detail mode, do not create two equal-weight primary action rails when the header already carries the same lifecycle action.
- Satisfy the detail requirement by aligning the guidance card
next stepsemantics and copy to the existing dominant header action. Do not move lifecycle CTA ownership out ofViewEnvironmentReviewin this slice. - Only offer successor-review-open navigation on detail when a concrete successor review target is actually known.
Phase 6 - Copy, Audit, And Browser Proof
- Update only the required copy keys in:
apps/platform/lang/en/localization.phpapps/platform/lang/de/localization.php
- Clarify acknowledgement copy so it never implies acknowledgement alone makes an output customer-ready.
- Split the workspace review-pack state presentation into package-exists, internal-export, and customer-sharing semantics without adding new persistence or workflow state.
- If repo truth keeps the current labels (
Create next review,Refresh review) instead of the user-draft wording (Create next review draft,Refresh review inputs), document that decision in the implementation close-out. - Update:
docs/ui-ux-enterprise-audit/page-reports/ui-006-customer-review-workspace.mddocs/ui-ux-enterprise-audit/page-reports/ui-040-environment-review-detail.md
- Capture screenshots under
specs/351-review-output-resolve-actions-v1/artifacts/screenshots/. - When a persistent ready-path demo is needed in local/testing, seed it via a bounded Artisan browser-fixture command instead of mutating product code or widening browser smoke scope.
Phase 7 - Validation And Close-Out
- Run focused Spec 351 Unit, Feature, and Browser coverage.
- Re-run filtered regressions for Specs 347, 349, 350, and
CustomerReviewWorkspace. - Run
pint --dirtyandgit diff --check. - Report any out-of-scope failures separately without widening implementation scope.
Validation Plan
cd apps/platform
./vendor/bin/sail artisan test tests/Unit/ResolutionGuidance/Spec351ReviewOutputResolveActionMapperTest.php --compact
./vendor/bin/sail artisan test tests/Feature/Filament/Spec351CustomerReviewWorkspaceResolveActionTest.php tests/Feature/EnvironmentReview/Spec351EnvironmentReviewResolveActionTest.php --compact
./vendor/bin/sail artisan test tests/Feature/Console/TenantpilotSeedReviewOutputBrowserFixtureCommandTest.php --compact
./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec351ReviewOutputResolveActionsSmokeTest.php --compact
./vendor/bin/sail artisan tenantpilot:review-output:seed-browser-fixture --no-interaction
./vendor/bin/sail artisan test --compact --filter=Spec347
./vendor/bin/sail artisan test --compact --filter=Spec349
./vendor/bin/sail artisan test --compact --filter=Spec350
./vendor/bin/sail artisan test --compact --filter=CustomerReviewWorkspace
./vendor/bin/sail pint --dirty
git diff --check
Deployment Impact
- Env vars: none expected
- Migrations: none
- Queues / scheduler: no new queue family; existing review refresh / next-review queue behavior reused
- Storage: none
- Assets: no new Filament asset registration expected;
filament:assetsis not newly required by this slice - Panel providers / global search: unchanged; Filament v5 / Livewire v4 posture remains, and provider registration stays in
apps/platform/bootstrap/providers.php