diff --git a/apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php b/apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php index 633f39ab..4aa841fb 100644 --- a/apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php +++ b/apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php @@ -51,171 +51,127 @@
-
-
-
- - {{ $readiness['label'] }} - - - {{ __('localization.review.customer_safe') }} - -
- -
-

- {{ $readiness['question'] }} -

-

- {{ $readiness['reason'] }} -

-
- -
-
-
- {{ __('localization.review.impact') }} -
-

- {{ $readiness['impact'] }} -

+
+
+
+
+ + {{ $readiness['label'] }} + + + {{ __('localization.review.customer_safe') }} +
-
-
- {{ __('localization.review.latest_released_review') }} -
-
- {{ $latest['environment_label'] }} -
-
- {{ __('localization.review.published_date', ['date' => $latest['published_label']]) }} -
-
-
- -
- @if ($readiness['primary_action_url']) - - {{ $readiness['primary_action_label'] }} - - @endif - - @if ($latest['secondary_action_url']) - - {{ $latest['secondary_action_label'] }} - - @endif -
-
-
- -
-
-
-

- {{ __('localization.review.review_consumption_flow') }} -

-

- {{ __('localization.review.review_consumption_flow_description') }} -

-
- -
- @foreach ($readinessFlow as $step) -
-
-
- {{ $step['title'] }} -
- - {{ $step['label'] }} - -
-

- {{ $step['description'] }} -

- @if ($step['is_current']) -
- {{ __('localization.review.current_attention_point') }} -
- @endif -
- @endforeach -
-
-
- -
-
-
-
-

- {{ __('localization.review.review_acknowledgement') }} +
+

+ {{ $readiness['question'] }}

-

- {{ $acknowledgement['reason'] }} -

-
- - {{ $acknowledgement['status_label'] }} - -

- -
-
-
- {{ __('localization.review.impact') }} -
-

- {{ $acknowledgement['impact'] }} +

+ {{ $readiness['reason'] }}

-
-
- {{ __('localization.review.basis') }} +
+
+
+ {{ __('localization.review.impact') }} +
+

+ {{ $readiness['impact'] }} +

-
- @foreach ($acknowledgement['basis'] as $basis) -
- {{ $basis['label'] }} - - {{ $basis['value'] }} - -
- @endforeach +
+
+ {{ __('localization.review.latest_released_review') }} +
+
+ {{ $latest['environment_label'] }} +
+
+ {{ __('localization.review.published_date', ['date' => $latest['published_label']]) }} +
+ +
+ @if ($readiness['primary_action_url']) + + {{ $readiness['primary_action_label'] }} + + @endif + + @if ($latest['secondary_action_url']) + + {{ $latest['secondary_action_label'] }} + + @endif +
+
+ +
+
+
+
+

+ {{ __('localization.review.review_acknowledgement') }} +

+

+ {{ $acknowledgement['reason'] }} +

+
+ + {{ $acknowledgement['status_label'] }} + +
+ +
+
+
+ {{ __('localization.review.impact') }} +
+

+ {{ $acknowledgement['impact'] }} +

+
+ +
+
+ {{ __('localization.review.basis') }} +
+ +
+ @foreach ($acknowledgement['basis'] as $basis) +
+ {{ $basis['label'] }} + + {{ $basis['value'] }} + +
+ @endforeach +
+
+
@if ($acknowledgement['acknowledged_at_label'] || $acknowledgement['acknowledged_by_label'])
@@ -268,86 +224,162 @@ class="mt-2"

@endif
-
-
- -
-
-
-
-

- {{ __('localization.review.findings_needing_attention') }} -

-

- {{ $findingPanel['summary'] }} -

-
- - {{ $findingPanel['status_label'] }} -
+
-
- @foreach ($findingPanel['items'] as $item) -
- {{ $item['label'] }} - - {{ $item['value'] }} - +
+
+
+
+

+ {{ __('localization.review.findings_needing_attention') }} +

+

+ {{ $findingPanel['summary'] }} +

- @endforeach -
-
-
+ + {{ $findingPanel['status_label'] }} + +
-
-
-
-

- {{ __('localization.review.customer_safe_follow_ups') }} -

-
- -
- @forelse ($followUps['entries'] as $followUp) -
-
- {{ $followUp['title'] }} - - {{ $followUp['priority'] }} +
+ @foreach ($findingPanel['items'] as $item) +
+ {{ $item['label'] }} + + {{ $item['value'] }}
-
- {{ $followUp['summary'] }} -
-
- {{ $followUp['proof'] }} · {{ $followUp['next_action'] }} -
-
- @empty -

- {{ $followUps['empty_state'] }} -

- @endforelse + @endforeach +
-
+ -
-
-

- {{ __('localization.review.review_package_index') }} -

-

- {{ __('localization.review.review_package_index_description') }} -

+
+ @php + $currentReadinessStep = collect($readinessFlow)->firstWhere('is_current', true); + @endphp + +
+ +
+
+

+ {{ __('localization.review.review_consumption_flow') }} +

+

+ {{ __('localization.review.review_consumption_flow_description') }} +

+
+ +
+ @if ($currentReadinessStep !== null) +
+
+ {{ __('localization.review.current_attention_point') }} +
+ + {{ $currentReadinessStep['label'] }} + +
+ @endif + + +
+
+
+ +
    + @foreach ($readinessFlow as $step) +
  • +
    +
    +
    + {{ $step['title'] }} +
    +

    + {{ $step['description'] }} +

    +
    +
    + + {{ $step['label'] }} + + @if ($step['is_current']) +
    + {{ __('localization.review.current_attention_point') }} +
    + @endif +
    +
    +
  • + @endforeach +
+
+ +
+
+
+

+ {{ __('localization.review.customer_safe_follow_ups') }} +

+
+ +
+ @forelse ($followUps['entries'] as $followUp) +
+
+ {{ $followUp['title'] }} + + {{ $followUp['priority'] }} + +
+
+ {{ $followUp['summary'] }} +
+
+ {{ $followUp['proof'] }} · {{ $followUp['next_action'] }} +
+
+ @empty +

+ {{ $followUps['empty_state'] }} +

+ @endforelse +
+
- {{ $this->table }} -
+
+
+

+ {{ __('localization.review.review_package_index') }} +

+

+ {{ __('localization.review.review_package_index_description') }} +

+
+ + {{ $this->table }} +
+
@endif - -
- - {{ __('localization.review.accepted_risk_records') }} - - -
- @forelse ($acceptedRisks['entries'] as $risk) -
-
- {{ $risk['title'] }} - - {{ $risk['state_label'] }} - -
-
- {{ $risk['summary'] }} -
-
- @empty -

- {{ $acceptedRisks['empty_state'] }} -

- @endforelse -
-
diff --git a/apps/platform/tests/Browser/Spec344CustomerReviewWorkspaceDensitySmokeTest.php b/apps/platform/tests/Browser/Spec344CustomerReviewWorkspaceDensitySmokeTest.php new file mode 100644 index 00000000..0b6c75ff --- /dev/null +++ b/apps/platform/tests/Browser/Spec344CustomerReviewWorkspaceDensitySmokeTest.php @@ -0,0 +1,131 @@ +browser()->timeout(60_000); + +beforeEach(function (): void { + Storage::fake('exports'); +}); + +it('Spec344 smokes the customer review workspace hierarchy and density changes', function (): void { + [$user, $environment] = createUserWithTenant(role: 'owner', workspaceRole: 'manager'); + $environment->forceFill(['name' => 'Spec344 Browser Workspace'])->save(); + + $snapshot = seedEnvironmentReviewEvidence($environment, findingCount: 0, driftCount: 0); + spec344BrowserCreatePublishedReview($environment, $user, $snapshot); + + spec344AuthenticateBrowser($this, $user, $environment); + + $page = visit(CustomerReviewWorkspace::environmentFilterUrl($environment)) + ->resize(1236, 900) + ->waitForText(__('localization.review.review_acknowledgement')) + ->assertSee(__('localization.review.review_consumption_flow')) + ->assertNoJavaScriptErrors() + ->assertNoConsoleLogs(); + + $page->assertScript('document.querySelector("[data-testid=\"customer-review-readiness-flow\"]")?.open === false', true); + $page->assertScript( + '(() => { const ack = document.querySelector("[data-testid=\"customer-review-acknowledgement-card\"]"); const flow = document.querySelector("[data-testid=\"customer-review-readiness-flow\"]"); if (!ack || !flow) return false; return ack.getBoundingClientRect().top < flow.getBoundingClientRect().top; })()', + true, + ); + + $page->script('window.scrollTo(0, 0);'); + $page->screenshot(true, spec344BrowserScreenshotName('01-operator-summary')); + spec344CopyBrowserScreenshot('01-operator-summary'); + + $page->script('document.querySelector("[data-testid=\"customer-review-acknowledgement-card\"]")?.scrollIntoView({ block: "start" });'); + $page->screenshot(true, spec344BrowserScreenshotName('02-acknowledgement-prominent')); + spec344CopyBrowserScreenshot('02-acknowledgement-prominent'); + + $page->script('document.querySelector("[data-testid=\"customer-review-readiness-flow\"]")?.scrollIntoView({ block: "start" });'); + $page->assertScript('document.querySelector("[data-testid=\"customer-review-readiness-flow\"]")?.open === false', true); + $page->screenshot(true, spec344BrowserScreenshotName('03-supporting-details-demoted')); + spec344CopyBrowserScreenshot('03-supporting-details-demoted'); + + $page->script('document.querySelector("[data-testid=\"customer-review-diagnostics\"]")?.scrollIntoView({ block: "start" });'); + $page->assertScript('document.querySelector("[data-testid=\"customer-review-diagnostics\"]")?.open === false', true); + $page->screenshot(true, spec344BrowserScreenshotName('04-diagnostics-collapsed')); + spec344CopyBrowserScreenshot('04-diagnostics-collapsed'); + + $page->script("document.documentElement.classList.add('dark');"); + $page->script('window.scrollTo(0, 0);'); + $page->assertScript('document.documentElement.classList.contains("dark")', true); + $page->screenshot(true, spec344BrowserScreenshotName('05-dark-mode')); + spec344CopyBrowserScreenshot('05-dark-mode'); +}); + +function spec344BrowserScreenshotName(string $name): string +{ + return 'spec344-customer-review-workspace-'.$name; +} + +function spec344CopyBrowserScreenshot(string $name): void +{ + $filename = spec344BrowserScreenshotName($name).'.png'; + $source = base_path('tests/Browser/Screenshots/'.$filename); + $targetDirectory = repo_path('specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots'); + + if (! is_dir($targetDirectory)) { + @mkdir($targetDirectory, 0755, true); + } + + if (! is_file($source)) { + $source = \Pest\Browser\Support\Screenshot::path($filename); + } + + for ($attempt = 0; $attempt < 10 && ! is_file($source); $attempt++) { + usleep(100_000); + clearstatcache(true, $source); + } + + if (is_file($source) && is_dir($targetDirectory) && is_writable($targetDirectory)) { + @copy($source, $targetDirectory.DIRECTORY_SEPARATOR.$name.'.png'); + } +} + +function spec344AuthenticateBrowser(mixed $test, User $user, ManagedEnvironment $environment): void +{ + $workspaceId = (int) $environment->workspace_id; + + $test->actingAs($user)->withSession([ + WorkspaceContext::SESSION_KEY => $workspaceId, + WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY => [ + (string) $workspaceId => (int) $environment->getKey(), + ], + ]); + + session()->put(WorkspaceContext::SESSION_KEY, $workspaceId); + session()->put(WorkspaceContext::LAST_ENVIRONMENT_IDS_SESSION_KEY, [ + (string) $workspaceId => (int) $environment->getKey(), + ]); + + setAdminPanelContext($environment); +} + +function spec344BrowserCreatePublishedReview(ManagedEnvironment $environment, User $user, EvidenceSnapshot $snapshot): EnvironmentReview +{ + $review = composeEnvironmentReviewForTest($environment, $user, $snapshot); + + $review->forceFill([ + 'status' => EnvironmentReviewStatus::Published->value, + 'generated_at' => now(), + 'published_at' => now(), + 'published_by_user_id' => (int) $user->getKey(), + ])->save(); + + return $review->refresh(); +} + diff --git a/apps/platform/tests/Feature/Filament/Spec344CustomerReviewWorkspaceDensityTest.php b/apps/platform/tests/Feature/Filament/Spec344CustomerReviewWorkspaceDensityTest.php new file mode 100644 index 00000000..b0ad1576 --- /dev/null +++ b/apps/platform/tests/Feature/Filament/Spec344CustomerReviewWorkspaceDensityTest.php @@ -0,0 +1,108 @@ +create(['name' => 'Spec344 Operator Summary']); + [$user, $environment] = createUserWithTenant(tenant: $environment, role: 'owner', workspaceRole: 'manager'); + + $snapshot = seedEnvironmentReviewEvidence($environment, findingCount: 0, driftCount: 0); + spec344CreatePublishedReview($environment, $user, $snapshot); + + $this->actingAs($user); + setAdminPanelContext(); + session()->put(WorkspaceContext::SESSION_KEY, (int) $environment->workspace_id); + + $component = Livewire::actingAs($user)->test(CustomerReviewWorkspace::class) + ->assertSee(__('localization.review.review_acknowledgement')); + + $html = $component->html(); + + expect($html)->toContain('data-testid="customer-review-operator-summary"') + ->and($html)->toContain('data-testid="customer-review-supporting-details"'); + + $operatorSummaryStart = strpos($html, 'data-testid="customer-review-operator-summary"'); + $supportingDetailsStart = strpos($html, 'data-testid="customer-review-supporting-details"'); + + expect($operatorSummaryStart)->not->toBeFalse() + ->and($supportingDetailsStart)->not->toBeFalse() + ->and($operatorSummaryStart)->toBeLessThan($supportingDetailsStart); + + $operatorSummaryHtml = substr($html, $operatorSummaryStart, $supportingDetailsStart - $operatorSummaryStart); + + expect($operatorSummaryHtml)->toContain('data-testid="customer-review-decision-card"') + ->and($operatorSummaryHtml)->toContain('data-testid="customer-review-acknowledgement-card"') + ->and($operatorSummaryHtml)->toContain('data-testid="customer-review-findings-summary"'); + + $acknowledgementCardPosition = strpos($html, 'data-testid="customer-review-acknowledgement-card"'); + $readinessFlowPosition = strpos($html, 'data-testid="customer-review-readiness-flow"'); + + expect($acknowledgementCardPosition)->not->toBeFalse() + ->and($readinessFlowPosition)->not->toBeFalse() + ->and($acknowledgementCardPosition)->toBeLessThan($readinessFlowPosition); + + expect($html)->toContain('data-testid="customer-review-diagnostics"') + ->and($html)->not->toContain('data-testid="customer-review-diagnostics" open'); +}); + +it('shows the environment filter chip when environment_id is present', function (): void { + $environment = ManagedEnvironment::factory()->create(['name' => 'Spec344 Environment Filter']); + [$user, $environment] = createUserWithTenant(tenant: $environment, role: 'owner', workspaceRole: 'manager'); + + $snapshot = seedEnvironmentReviewEvidence($environment, findingCount: 0, driftCount: 0); + spec344CreatePublishedReview($environment, $user, $snapshot); + + $this->actingAs($user) + ->withSession([WorkspaceContext::SESSION_KEY => (int) $environment->workspace_id]) + ->get(CustomerReviewWorkspace::environmentFilterUrl($environment)) + ->assertOk() + ->assertSee('Environment filter:') + ->assertSee('Spec344 Environment Filter') + ->assertDontSee('/admin/t', false) + ->assertDontSee('tenant_id=', false); +}); + +it('disables the acknowledgement action when the actor lacks acknowledge permissions', function (): void { + $environment = ManagedEnvironment::factory()->create(['name' => 'Spec344 Ack Disabled']); + [$publisher, $environment] = createUserWithTenant(tenant: $environment, role: 'owner', workspaceRole: 'manager'); + [$actor] = createUserWithTenant(tenant: $environment, role: 'readonly'); + + $snapshot = seedEnvironmentReviewEvidence($environment, findingCount: 0, driftCount: 0); + spec344CreatePublishedReview($environment, $publisher, $snapshot); + + $this->actingAs($actor); + setAdminPanelContext(); + session()->put(WorkspaceContext::SESSION_KEY, (int) $environment->workspace_id); + + $component = Livewire::actingAs($actor)->test(CustomerReviewWorkspace::class); + $payload = $component->instance()->latestReviewConsumptionPayload(); + + expect(data_get($payload, 'acknowledgement.action_name'))->toBe('acknowledgeReview') + ->and(data_get($payload, 'acknowledgement.action_disabled'))->toBeTrue(); +}); + +function spec344CreatePublishedReview(ManagedEnvironment $environment, User $user, EvidenceSnapshot $snapshot): EnvironmentReview +{ + $review = composeEnvironmentReviewForTest($environment, $user, $snapshot); + + $review->forceFill([ + 'status' => EnvironmentReviewStatus::Published->value, + 'generated_at' => now(), + 'published_at' => now(), + 'published_by_user_id' => (int) $user->getKey(), + ])->save(); + + return $review->refresh(); +} diff --git a/docs/ui-ux-enterprise-audit/page-reports/ui-006-customer-review-workspace.md b/docs/ui-ux-enterprise-audit/page-reports/ui-006-customer-review-workspace.md index 470dba72..69052d5c 100644 --- a/docs/ui-ux-enterprise-audit/page-reports/ui-006-customer-review-workspace.md +++ b/docs/ui-ux-enterprise-audit/page-reports/ui-006-customer-review-workspace.md @@ -15,9 +15,11 @@ ## First Five Seconds This is the most important customer-safe productization candidate. The page should answer what the customer can trust, what changed, what risks are accepted, which evidence supports the state, and what should happen next. +Spec 344 tightens the hierarchy so the Operator Summary (decision + acknowledgement + findings signal) comes first, while the review consumption flow and proof panels remain available as supporting details. + ## Productization Review -- Decision-first: strong candidate, needs final target hierarchy. +- Decision-first: improved by explicit Operator Summary-first hierarchy. - Evidence-first: must anchor all claims to review/evidence artifacts. - Context: workspace-level customer view. - Customer/auditor safety: primary concern. @@ -35,14 +37,14 @@ ## Scores | IA | Density | User Clarity | Sellability | Disclosure | Hierarchy | DS Fit | A11y | Responsive | Components | UX Writing | Perf | | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | ---: | -| 3 | 3 | 3 | 5 | 3 | 3 | 4 | 3 | 3 | 4 | 3 | 4 | +| 3 | 4 | 4 | 5 | 3 | 4 | 4 | 3 | 3 | 4 | 3 | 4 | ## Top Issues 1. Acknowledgement copy must remain customer-safe and explicitly non-legal (no compliance certification semantics). 2. Evidence and accepted-risk meaning should be visible without raw diagnostics. -3. Requires individual target mockup, not only cleanup. +3. Sidebar proof panels can still compete visually with the main decision flow; keep them secondary and avoid duplicating “ready/available” signals at equal weight. ## Target Direction -P0 individual target mockup and follow-up implementation wave. This page is a core sellability surface. +Spec 344 implements the first density/hierarchy polish wave. If the surface still feels too dense after real operator use, follow up with a targeted mockup and a second, narrower polish pass rather than adding new workflow surfaces. diff --git a/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/01-operator-summary.png b/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/01-operator-summary.png new file mode 100644 index 00000000..fe6208bb Binary files /dev/null and b/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/01-operator-summary.png differ diff --git a/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/02-acknowledgement-prominent.png b/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/02-acknowledgement-prominent.png new file mode 100644 index 00000000..92eeb0f5 Binary files /dev/null and b/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/02-acknowledgement-prominent.png differ diff --git a/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/03-supporting-details-demoted.png b/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/03-supporting-details-demoted.png new file mode 100644 index 00000000..be03c126 Binary files /dev/null and b/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/03-supporting-details-demoted.png differ diff --git a/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/04-diagnostics-collapsed.png b/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/04-diagnostics-collapsed.png new file mode 100644 index 00000000..be03c126 Binary files /dev/null and b/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/04-diagnostics-collapsed.png differ diff --git a/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/05-dark-mode.png b/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/05-dark-mode.png new file mode 100644 index 00000000..80363f50 Binary files /dev/null and b/specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/05-dark-mode.png differ diff --git a/specs/344-customer-review-workspace-density-audience-polish/checklists/requirements.md b/specs/344-customer-review-workspace-density-audience-polish/checklists/requirements.md new file mode 100644 index 00000000..ac9aa768 --- /dev/null +++ b/specs/344-customer-review-workspace-density-audience-polish/checklists/requirements.md @@ -0,0 +1,48 @@ +# Specification Quality Checklist: Spec 344 - Customer Review Workspace Density & Audience Mode Polish + +**Purpose**: Validate Spec 344 preparation completeness before implementation. +**Created**: 2026-06-01 +**Feature**: `specs/344-customer-review-workspace-density-audience-polish/spec.md` + +## Candidate Selection Gate + +- [x] CHK001 The selected candidate is directly provided by the user as Spec 344 (follow-up after Specs 342–343). +- [x] CHK002 The candidate aligns with current roadmap direction: customer-safe review consumption and operator workflow maturity on UI-038 (no portal/framework rewrite). +- [x] CHK003 No existing `specs/344-*` package or `344-*` branch was found before this prep. +- [x] CHK004 Related specs were checked for completed-spec signals and are treated as context only (337, 342, 343). +- [x] CHK005 Close alternatives are deferred rather than hidden scope (governance inbox follow-through, localization adoption, provider readiness, PSA handoff). +- [x] CHK006 Scope is narrowed to one strategic surface (`/admin/reviews/workspace`) and UI-only hierarchy changes. + +## Content Quality + +- [x] CHK007 `spec.md` defines problem, user value, functional requirements, non-goals, acceptance criteria, assumptions, risks, and open questions. +- [x] CHK008 `plan.md` lists likely affected repo surfaces and preserves repo-truth-first execution. +- [x] CHK009 `tasks.md` is ordered into small phases with explicit test/browser/screenshot/validation tasks. +- [x] CHK010 No unresolved template placeholders remain in `spec.md`, `plan.md`, or `tasks.md`. + +## Constitution And Scope + +- [x] CHK011 Proportionality review is present and explicitly rejects new persistence, new status families, and new frameworks. +- [x] CHK012 Workspace/environment isolation boundaries and deny-as-not-found posture are preserved (no authorization weakening). +- [x] CHK013 UI Surface Impact and UI/Productization Coverage are completed for UI-038 (strategic surface). +- [x] CHK014 Filament v5 / Livewire v4 posture, panel provider location, destructive-action confirmation rules, asset strategy, and testing plan are explicit. + +## Plan Quality + +- [x] CHK015 Plan sequencing is baseline inventory → hierarchy refactor → keep Spec 343 semantics → tests/browser → UI audit artifact decision. +- [x] CHK016 Deployment/ops impact is explicit (no env/migrations/queues/scheduler/assets expected). +- [x] CHK017 No Graph/provider calls during UI render are enforced by plan constraints. + +## Task Quality + +- [x] CHK018 Tasks include concrete repo surfaces and avoid inventing new runtime paths beyond UI-038 touch points. +- [x] CHK019 Tasks include Feature/Livewire tests and one bounded Browser smoke (strategic surface). +- [x] CHK020 Tasks include screenshot artifacts and “unreachable state” handling without faking backend truth. +- [x] CHK021 Tasks explicitly forbid new domain model/persistence and forbid rewriting completed specs. + +## Spec Readiness Gate + +- [x] CHK022 `spec.md`, `plan.md`, and `tasks.md` exist. +- [x] CHK023 Open questions do not block safe implementation. +- [x] CHK024 Scope is bounded enough for a later implementation loop. +- [x] CHK025 Result: ready for implementation loop. diff --git a/specs/344-customer-review-workspace-density-audience-polish/plan.md b/specs/344-customer-review-workspace-density-audience-polish/plan.md new file mode 100644 index 00000000..ea467da1 --- /dev/null +++ b/specs/344-customer-review-workspace-density-audience-polish/plan.md @@ -0,0 +1,96 @@ +# Implementation Plan: Spec 344 - Customer Review Workspace Density & Audience Mode Polish + +**Branch**: `344-customer-review-workspace-density-audience-polish` | **Date**: 2026-06-01 | **Spec**: `specs/344-customer-review-workspace-density-audience-polish/spec.md` +**Input**: User-provided Spec 344 draft (Codex attachment `pasted-text.txt`) + repo truth from Specs 337, 342, 343. + +## Summary + +Improve the Customer Review Workspace (UI-038) as a daily MSP/operator surface by reducing density and restoring decision hierarchy: + +1) **Operator Summary first**: shareability + acknowledgement + primary next action + risk/findings signal. +2) **Supporting details second**: evidence/proof path + review pack state + accepted risks + diagnostics + package index. + +This slice is UI/productization polish only: + +- preserve all semantics from Specs 342–343 +- no new persistence or status families +- no new routes or navigation changes +- no Graph/provider calls during render + +## Technical Context + +- **Language/Version**: PHP 8.4.15, Laravel 12.x. +- **UI**: Filament v5 + Livewire v4 (no Livewire v3 APIs). +- **Panel providers**: remain registered in `apps/platform/bootstrap/providers.php` (no changes expected). +- **Storage**: PostgreSQL (no migrations expected). +- **Testing**: Pest Feature/Livewire tests + one bounded Pest Browser smoke test for this strategic surface. +- **Assets**: no new global assets expected; prefer Filament primitives and Tailwind utilities already in the stack. + +## UI / Surface Guardrail Plan + +- **Guardrail scope**: material change to an existing strategic customer-safe review surface (UI-038). +- **Primary surface**: + - `apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php` + - `apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php` +- **New/changed surface elements**: + - explicit “Operator Summary” zone (layout + grouping) + - reordering so acknowledgement sits inside the primary decision area when required + - de-duplication and compression of “ready/available/no action needed” signals +- **Disclosure defaults**: diagnostics remain collapsed/secondary and capability-gated (`support_diagnostics.view`). +- **One primary next action**: preserve exactly one dominant next action in the Operator Summary; demote secondary navigation/inspect links. +- **UI audit artifacts**: decide post-diff whether `docs/ui-ux-enterprise-audit/page-reports/ui-006-customer-review-workspace.md` needs updating; route inventory entry (UI-038) should remain stable. + +## Repo-Truth-First Execution Rule + +Before any refactor, confirm the current runtime surface inventory: + +- which cards/sections exist today and what they mean (no invented semantics) +- where acknowledgement, accepted-risk, evidence path, review pack status, disclosure rules, and diagnostics currently render +- which sections are redundant “green noise” vs required evidence/proof state + +## Implementation Phases + +### Phase 1 — Baseline Inventory + Before/After Proof + +- Capture baseline screenshots for the current hierarchy (pre-change). +- Record a short inventory note in the PR description (later), not as a new framework or test snapshot. + +### Phase 2 — Layout/Hiearchy Refactor (UI-only) + +- Implement the two-layer structure: Operator Summary vs Supporting Details. +- Move acknowledgement into the Operator Summary hierarchy when required. +- Group or demote readiness-only cards so they do not compete with the pending action. +- Preserve environment filter semantics and visibility (local page filter, not global context). +- Preserve customer-safe wording and avoid “legal/compliance certification” phrasing. + +### Phase 3 — Preserve Spec 343 Semantics + +- Acknowledgement remains: + - capability-gated + - confirmation-gated + - auditable + - behavior-identical (only placement changes) + +### Phase 4 — Tests (Pest) + +- Keep Spec 343 tests passing; update only assertions that intentionally depend on hierarchy markers. +- Add Spec 344 Feature/Livewire tests focusing on: + - Operator Summary markers exist + - acknowledgement action visibility in the primary zone when required + - diagnostics remain capability-gated and collapsed/secondary + - environment filter remains visible and page-local +- Add one Spec 344 Browser smoke to prove scan-first hierarchy + screenshots. + +### Phase 5 — UI Coverage Artifacts (post-diff decision) + +- If the layout materially changes what the UI-006 page report describes, update: + - `docs/ui-ux-enterprise-audit/page-reports/ui-006-customer-review-workspace.md` +- Otherwise record a concise “no update needed” note in the active feature PR close-out entry. + +## Deployment / Ops Impact + +- **Env vars**: none. +- **Migrations**: none expected. +- **Queues/scheduler**: none. +- **Storage/volumes**: none. +- **Filament assets**: not expected; if any registered assets are introduced, include `cd apps/platform && php artisan filament:assets` in deployment/release steps. diff --git a/specs/344-customer-review-workspace-density-audience-polish/spec.md b/specs/344-customer-review-workspace-density-audience-polish/spec.md new file mode 100644 index 00000000..d7739dc6 --- /dev/null +++ b/specs/344-customer-review-workspace-density-audience-polish/spec.md @@ -0,0 +1,195 @@ +# Feature Specification: Spec 344 - Customer Review Workspace Density & Audience Mode Polish + +**Feature Branch**: `344-customer-review-workspace-density-audience-polish` +**Created**: 2026-06-01 +**Status**: Draft +**Type**: Productization / UX hierarchy / MSP operator workflow polish +**Runtime posture**: UI/productization polish only. Preserve Spec 343 acknowledgement behavior and Customer Review Workspace semantics. Do not introduce new domain models, persisted truth, or status families unless repo truth proves a minimal derived view state is unavoidable (derived-only, not persisted). +**Input**: User-provided Spec 344 draft (Codex attachment `pasted-text.txt`) + repo truth from Specs 337, 342, 343 + current `CustomerReviewWorkspace` UI. + +## Spec Candidate Check *(mandatory — SPEC-GATE-001)* + +- **Problem**: The Customer Review Workspace (UI-038) is now functionally strong (Specs 342–343), but visually dense. Operator decision state, customer-safe sharing state, acknowledgement state, evidence path, review pack state, accepted-risk state, disclosure rules, diagnostics, and package index compete at equal weight. +- **Today's failure**: An operator must scan too many regions before answering the first questions: “Is this review shareable?”, “What action is required now?”, “Is anything risky or blocking?”, “Where is the evidence/proof path?”, “What details can I inspect if needed?” +- **User-visible improvement**: The first screen becomes scan-first and decision-first: one Operator Summary zone with shareability + acknowledgement + primary next action + risk/findings signal, and a clear Supporting Details layer for proof/diagnostics/index. +- **Smallest enterprise-capable version**: Refactor only the existing `/admin/reviews/workspace` layout and hierarchy. Preserve all existing truth sources and actions; change ordering, grouping, and repetition only. +- **Explicit non-goals**: No new customer portal, no new persisted view state, no new domain model, no new review pack format, no new evidence generation, no new accepted-risk lifecycle semantics, no new OperationRun types, no new navigation/shell redesign, no localization project, no “legal sign-off” semantics. +- **Permanent complexity imported**: Targeted UI refactor on one page + small presenter extraction only if needed to prevent duplicated logic, plus focused Feature/Livewire tests and one bounded Browser smoke + screenshots. No migrations, no packages, no new global UI framework. +- **Why now**: Spec 343 added acknowledgement and tightened accepted-risk visibility; the page is v1-usable but now too dense for daily MSP/operator workflows. Productization polish improves operator velocity and reduces false calmness by making the next action unavoidable. +- **Why not local**: Small cosmetic changes cannot fix the decision hierarchy problem; this must be an intentional “Operator Summary first” re-layout to prevent drift and duplicated truth across cards. +- **Approval class**: Workflow Compression. +- **Red flags triggered**: Customer-safe strategic surface changes and risk of “false calmness” if hierarchy is wrong. Defense: preserve truth sources and semantics; keep diagnostics/proof as supporting details; require browser screenshots + targeted tests. +- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexität: 1 | Produktnähe: 2 | Wiederverwendung: 1 | **Gesamt: 10/12** +- **Decision**: approve. + +## Candidate Source And Completed-Spec Guardrail + +- **Candidate source**: Directly user-provided as “Spec 344 — Customer Review Workspace Density & Audience Mode Polish” as the next slice after Spec 343. +- **Completed-spec check**: No `specs/344-*` package existed before this prep. Related Specs 337, 342, and 343 contain completed-task, validation, and/or close-out signals and are treated as historical context only (do not rewrite or normalize them). +- **Roadmap alignment**: Stays inside the “Customer Review Workspace v1 completion / productization” lane by improving operator decision hierarchy and customer-safe disclosure without creating a parallel customer portal. +- **Close alternatives deferred**: + - Decision-based Governance Inbox follow-through (separate strategic workflow surface; defer to keep this slice UI-only on UI-038). + - Customer-facing localization adoption (needs stable hierarchy first). + - Provider readiness / monitoring maturity (unrelated). + - External support desk / PSA handoff (unrelated). + +## Spec Scope Fields *(mandatory)* + +- **Scope**: workspace hub (existing strategic surface UI-038) with page-level `environment_id` filter. +- **Primary Routes**: + - `/admin/reviews/workspace` (Customer Review Workspace) +- **Data Ownership**: no new persistence; no migrations. +- **RBAC**: + - Preserve existing membership + capability gates for view and for acknowledgement write (Spec 343). + - Diagnostics remain capability-gated (`support_diagnostics.view`). + +## UI Surface Impact *(mandatory — UI-COV-001)* + +- [ ] No UI surface impact +- [x] Existing page changed +- [ ] New page/route added +- [ ] Navigation changed +- [ ] Filament panel/provider surface changed +- [ ] New modal/drawer/wizard/action added +- [x] New table/form/state added +- [x] Customer-facing surface changed +- [ ] Dangerous action changed +- [x] Status/evidence/review presentation changed +- [x] Workspace/environment context presentation changed + +## UI/Productization Coverage *(mandatory)* + +- **Route/page/surface**: `/admin/reviews/workspace` (`apps/platform/app/Filament/Pages/Reviews/CustomerReviewWorkspace.php` + `apps/platform/resources/views/filament/pages/reviews/customer-review-workspace.blade.php`) +- **Current page archetype**: `docs/ui-ux-enterprise-audit/route-inventory.md` → UI-038 (Strategic Surface, repo-verified) +- **Design depth**: Strategic Surface (operator/MSP surface that produces customer-safe output) +- **Repo-truth level**: repo-verified surface; no new truth sources +- **Existing pattern reused**: Spec 342 decision-first hierarchy + Spec 343 acknowledgement card/action + existing customer-safe disclosure + existing evidence/proof layout primitives +- **New pattern required**: none; only regrouping and de-duplication + one explicit “Operator Summary” layer marker +- **Screenshot required**: yes (`specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/`) +- **Customer-safe review required**: yes (copy + disclosure + prevent false “ready/available” duplication) +- **Dangerous-action review required**: no (no new destructive/high-impact actions; acknowledgement remains confirmed + capability-gated per Spec 343) +- **Coverage artifacts**: decide post-diff whether `docs/ui-ux-enterprise-audit/page-reports/ui-006-customer-review-workspace.md` needs an update; route inventory entry should remain stable. + +## Cross-Cutting / Shared Pattern Reuse *(mandatory)* + +- **Cross-cutting feature?**: yes. +- **Interaction classes**: status messaging, action hierarchy, proof/evidence disclosure, diagnostics collapse, accepted-risk summary. +- **Shared paths reused**: + - Existing customer-safe disclosure language and copy discipline from Specs 342–343 (no legal/compliance certification wording). + - Existing badge/status primitives (no ad-hoc “ready/available” duplication). + - Existing acknowledgement action semantics from Spec 343 (capability + confirmation + audit). +- **Deviations**: none intended. If a new presenter/state helper is introduced to reduce duplicated UI logic, it must remain page-local and derived-only. + +## OperationRun UX Impact *(mandatory)* + +N/A - no OperationRun creation/completion/dedupe semantics are introduced or changed in this slice. + +## Provider Boundary / Platform Core Check *(mandatory)* + +N/A - no provider/platform shared boundary is changed. + +## Proportionality Review *(mandatory when structural complexity is introduced)* + +- **New source of truth?**: no. +- **New persisted entity/table/artifact?**: no. +- **New abstraction?**: no new framework. Optional: extract a page-local derived “summary view state” helper only if it reduces duplicated truth and keeps copy/status consistent. +- **New enum/status family?**: no. All displayed states remain derived from existing review/pack/evidence/acknowledgement/accepted-risk truth. +- **Alternative intentionally rejected**: audience-mode toggle framework, separate customer portal page, new review readiness engine, new accepted-risk workflow surface. + +## Testing / Lane / Runtime Impact *(mandatory for runtime behavior changes)* + +- **Test purpose / classification**: Feature/Livewire for action visibility + RBAC + disclosure defaults; Browser for scan-first hierarchy and “acknowledgement is visible before supporting details” on a strategic surface. +- **Validation lane(s)**: confidence + browser. +- **Planned validation commands** (later implementation): + - `cd apps/platform && ./vendor/bin/sail artisan test tests/Feature/Filament/Spec343CustomerReviewAttestationAcceptedRiskTest.php --compact` + - `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec343CustomerReviewAttestationAcceptedRiskSmokeTest.php --compact` + - `cd apps/platform && ./vendor/bin/sail artisan test tests/Feature/Filament/Spec344CustomerReviewWorkspaceDensityTest.php --compact` + - `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec344CustomerReviewWorkspaceDensitySmokeTest.php --compact` + - `cd apps/platform && ./vendor/bin/sail pint --dirty` + - `git diff --check` + +## User Scenarios & Testing *(mandatory)* + +### User Story 1 — Understand the main decision quickly (Priority: P1) + +An MSP/operator opens Customer Review Workspace and immediately sees shareability status, acknowledgement status, and the one primary next action without scanning multiple equal-weight cards. + +**Independent proof**: browser smoke + screenshots showing the Operator Summary zone in realistic fixtures. + +### User Story 2 — Acknowledgement appears before supporting details (Priority: P1) + +If acknowledgement is required, it appears in the primary decision area (or directly beneath it) and never below secondary proof/flow sections. + +**Independent proof**: Livewire test asserts acknowledgement action is present and visible in the Operator Summary; browser smoke confirms hierarchy. + +### User Story 3 — Supporting details remain available but secondary (Priority: P2) + +Evidence path, review pack state, accepted-risk detail lists, disclosure rules, diagnostics, and the package index remain accessible but are visually secondary and/or progressively disclosed. + +**Independent proof**: browser smoke shows details as secondary/collapsed; Livewire test confirms diagnostics remain capability-gated. + +## Functional Requirements + +- **FR-001**: The page must have two clear layers: + 1) **Operator Summary** (decision + acknowledgement + risks/findings + primary next action) + 2) **Supporting Details** (proof/evidence path + pack state + accepted risks + diagnostics + index) +- **FR-002**: Acknowledgement must appear in (1) when required. +- **FR-003**: Repetitive “ready/available/no action needed” blocks must be reduced, grouped, or demoted so they do not compete with the true pending action. +- **FR-004**: Accepted-risk and findings signals must not be duplicated in multiple equal-weight regions without distinct purpose. +- **FR-005**: Diagnostics remain collapsed/secondary by default and capability-gated. +- **FR-006**: Environment filter remains a local page filter and stays visible; no new “topbar-as-filter” guidance is introduced. + +## Non-Functional Requirements + +- Page render remains DB-only: no Graph/provider calls during UI render. +- Preserve Filament v5 + Livewire v4.0+ compliance. +- Keep panel provider registration unchanged in `apps/platform/bootstrap/providers.php`. +- Avoid new frontend assets; if any asset registration becomes necessary, document `php artisan filament:assets`. + +## Out Of Scope + +- No new portal routes, no audience-mode toggle framework, no new persisted preferences. +- No new review readiness engine, no new accepted-risk workflow surface, no lifecycle or taxonomy rewrite. +- No changes to acknowledgement semantics introduced by Spec 343 (capability/confirmation/audit behavior stays intact). + +## Acceptance Criteria + +- [ ] AC-001 Operator Summary answers (in order): shareability, acknowledgement, primary next action, blockers/risks, and latest review context. +- [ ] AC-002 If acknowledgement is required, the action is visible before supporting details (no scroll needed). +- [ ] AC-003 Duplicate “ready/available/no action needed” cards are reduced or grouped so the pending action stands out. +- [ ] AC-004 Evidence path remains visible but secondary; diagnostics remain collapsed/secondary. +- [ ] AC-005 Environment filter remains visible and local; the page does not imply global context. +- [ ] AC-006 Spec 343 acknowledgement behavior is preserved end-to-end. +- [ ] AC-007 Tests pass (targeted Spec 343 + Spec 344 feature + browser lanes). + +## Success Criteria + +- An operator can answer “what do I do now?” within a few seconds on first load. +- Customer-safe claims remain truthful and do not become “green noise”. +- Supporting proof paths remain accessible without competing as primary decision content. + +## Assumptions + +- The current strategic surface remains `UI-038 /admin/reviews/workspace` and uses the existing page class + Blade view. +- Spec 343 acknowledgement is already repo-real and covered by targeted tests. +- No additional backend truth is needed to improve hierarchy (UI-only slice). + +## Open Questions + +- OQ-001: Should the “Supporting Details” layer be purely collapsed-by-default, or should it remain visible but visually demoted? (Decision belongs to implementation with screenshots; either is acceptable if diagnostics remain secondary.) + +## Spec Artifacts *(required for this package)* + +- `specs/344-customer-review-workspace-density-audience-polish/spec.md` +- `specs/344-customer-review-workspace-density-audience-polish/plan.md` +- `specs/344-customer-review-workspace-density-audience-polish/tasks.md` +- `specs/344-customer-review-workspace-density-audience-polish/checklists/requirements.md` +- `specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/` + +## Follow-Up Spec Candidates + +- Decision-based Governance Inbox follow-through (separate surface; keep numbering flexible). +- Customer Review External Portal v1 (separate customer-facing surface, not the operator workspace). +- Customer Review Mode Toggle (only if one page cannot serve operator vs customer-summary needs). +- Review Package Index productization (timeline/history focus). +- Accepted Risk lifecycle detail surface (only if accepted-risk records need their own workflow). diff --git a/specs/344-customer-review-workspace-density-audience-polish/tasks.md b/specs/344-customer-review-workspace-density-audience-polish/tasks.md new file mode 100644 index 00000000..143817aa --- /dev/null +++ b/specs/344-customer-review-workspace-density-audience-polish/tasks.md @@ -0,0 +1,78 @@ +# Tasks: Spec 344 - Customer Review Workspace Density & Audience Mode Polish + +**Branch**: `344-customer-review-workspace-density-audience-polish` | **Date**: 2026-06-01 +**Spec**: `specs/344-customer-review-workspace-density-audience-polish/spec.md` +**Plan**: `specs/344-customer-review-workspace-density-audience-polish/plan.md` + +## Test Governance (TEST-GOV-001) + +- **Test purpose / classification**: Feature/Livewire + Browser (strategic surface UI-038). +- **Validation lanes**: confidence + browser. +- **Why sufficient**: this slice changes scan-first hierarchy on a strategic surface; browser proof is required while Feature/Livewire tests protect RBAC + disclosure defaults + action availability. + +## Phase 0 — Guardrails + Baseline + +- [x] T010 Confirm this slice is UI-only: no persistence, no new status family, no new routes. +- [x] T011 Capture representative screenshots for UI-038 hierarchy under `specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/` (pre-change baseline optional; post-change required). +- [x] T012 Re-read Specs 342–343 close-out signals to avoid reopening semantics and to preserve acknowledgement behavior. + +## Phase 1 — Repo-Truth Inventory (before code changes) + +- [x] T020 Inventory current visible regions/cards on Customer Review Workspace and identify: + - which regions are true blockers vs redundant “green noise” + - which regions are operator decision vs supporting proof vs diagnostics/support +- [x] T021 Record the intended before/after hierarchy in the PR description (later) and keep the change bounded to UI-038. + +## Phase 2 — UI Refactor (Customer Review Workspace) + +- [x] T030 Implement an explicit **Operator Summary** zone on `/admin/reviews/workspace`. +- [x] T031 Move acknowledgement (Spec 343) into the primary decision hierarchy when required (no behavior change; placement only). +- [x] T032 Reduce or group duplicate “ready/available/no action needed” blocks so pending actions dominate. +- [x] T033 Keep Evidence Path visible but secondary; avoid competing primary card weight. +- [x] T034 Keep diagnostics collapsed/secondary and capability-gated (`support_diagnostics.view`). +- [x] T035 Keep `environment_id` filter visible and page-local; avoid “topbar as filter” copy or implied global context. + +## Phase 3 — Feature/Livewire Tests (Pest) + +- [x] T040 Add `apps/platform/tests/Feature/Filament/Spec344CustomerReviewWorkspaceDensityTest.php` covering: + - Operator Summary markers present + - acknowledgement action visible in the summary zone when required (and disabled when unauthorized) + - diagnostics remain capability-gated and not default-prominent + - environment filter visibility and canonical query behavior +- [x] T041 Keep Spec 343 tests passing; update only assertions that intentionally depend on hierarchy markers. + +## Phase 4 — Browser Smoke + Screenshots + +- [x] T050 Add `apps/platform/tests/Browser/Spec344CustomerReviewWorkspaceDensitySmokeTest.php` proving: + - Operator Summary is first-screen + - acknowledgement appears before supporting details when required + - diagnostics are collapsed/secondary by default +- [x] T051 Capture screenshots under `specs/344-customer-review-workspace-density-audience-polish/artifacts/screenshots/`: + - `01-operator-summary.png` + - `02-acknowledgement-prominent.png` + - `03-supporting-details-demoted.png` + - `04-diagnostics-collapsed.png` + - `05-dark-mode.png` (if practical) +- [x] T052 If a screenshot state is unreachable, document why in the spec package instead of inventing backend truth. + +## Phase 5 — UI Coverage Artifacts (post-diff decision) + +- [x] T060 Decide whether `docs/ui-ux-enterprise-audit/page-reports/ui-006-customer-review-workspace.md` requires an update due to hierarchy changes. +- [x] T061 If required, update that page report; otherwise record a concise “no update needed” note in the active feature PR close-out entry. + +## Phase 6 — Validation + +- [x] T070 Run: + - `cd apps/platform && ./vendor/bin/sail artisan test tests/Feature/Filament/Spec343CustomerReviewAttestationAcceptedRiskTest.php --compact` + - `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec343CustomerReviewAttestationAcceptedRiskSmokeTest.php --compact` + - `cd apps/platform && ./vendor/bin/sail artisan test tests/Feature/Filament/Spec344CustomerReviewWorkspaceDensityTest.php --compact` + - `cd apps/platform && ./vendor/bin/sail php vendor/bin/pest tests/Browser/Spec344CustomerReviewWorkspaceDensitySmokeTest.php --compact` + - `cd apps/platform && ./vendor/bin/sail pint --dirty` + - `git diff --check` + +## Explicit Non-Goals + +- [x] NT001 Do not introduce a new domain model, new persisted view state, or new status family. +- [x] NT002 Do not change acknowledgement semantics (capability/confirmation/audit) from Spec 343. +- [x] NT003 Do not add a customer portal, audience-mode toggle framework, or new navigation shell. +- [x] NT004 Do not add new global frontend assets unless explicitly justified and documented.