TenantAtlas/specs/164-run-detail-hardening/plan.md
ahmido 20b6aa6a32 refactor: reduce operation run detail density (#194)
## Summary
- collapse secondary and diagnostic operation-run sections by default to reduce page density
- visually emphasize the primary next step while keeping counts readable but secondary
- keep failures and other actionable detail available without dominating the default reading path

## Testing
- vendor/bin/sail artisan test --compact tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php tests/Feature/Filament/OperationRunEnterpriseDetailPageTest.php tests/Feature/Filament/EnterpriseDetailTemplateRegressionTest.php tests/Feature/Operations/TenantlessOperationRunViewerTest.php
- vendor/bin/sail bin pint --dirty --format agent

Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de>
Reviewed-on: #194
2026-03-26 13:23:52 +00:00

258 lines
19 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Implementation Plan: Operation Run Detail Hierarchy, Deduplication, and Decision Guidance Hardening
**Branch**: `164-run-detail-hardening` | **Date**: 2026-03-26 | **Spec**: `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/164-run-detail-hardening/spec.md`
**Input**: Feature specification from `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/164-run-detail-hardening/spec.md`
## Summary
Harden the canonical operation-run detail page into a decision-first enterprise surface without changing `OperationRun` domain semantics, routing, or authorization. The implementation introduces an explicit primary decision zone, centralizes the leading next step and count presentation, separates supporting context from diagnostics, preserves artifact truth and trust as distinct signals, keeps type-specific detail below the canonical summary layer, and validates the result with focused Pest feature and Livewire coverage.
Key approach: work inside the existing `OperationRunResource::enterpriseDetailPage()` and `TenantlessOperationRunViewer` seams, extend the `EnterpriseDetail` payload shape only where necessary, preserve the current canonical route and permission model, and rely on regrouping and prioritization rather than on new persistence or new screen families.
## Technical Context
**Language/Version**: PHP 8.4, Laravel 12, Blade views, Alpine via Filament v5 / Livewire v4
**Primary Dependencies**: Filament v5, Livewire v4, Pest v4, Laravel Sail, existing `OperationRunResource`, `TenantlessOperationRunViewer`, `EnterpriseDetailBuilder`, `ArtifactTruthPresenter`, `OperationUxPresenter`, and `SummaryCountsNormalizer`
**Storage**: PostgreSQL with existing `operation_runs` JSONB-backed `context`, `summary_counts`, and `failure_summary`; no schema change planned
**Testing**: Pest feature tests, Livewire page tests, and existing enterprise-detail unit coverage run through Sail
**Target Platform**: Laravel web application in Sail locally and containerized Linux deployment in staging and production
**Project Type**: Laravel monolith web application
**Performance Goals**: Keep canonical run detail DB-only at render and poll time, preserve 510 second operator scanability above the fold, avoid additional render-time data loading or external calls, and keep type-specific sections progressively reachable without layout thrash
**Constraints**: No new tables or domain models, no route changes, no RBAC drift, no Graph/render side effects, no semantic collapse between execution status and artifact truth, no duplicate primary next-step surface, and no new global Filament assets
**Scale/Scope**: One canonical operator-facing detail page with existing type-specific extensions, a small set of builder and Blade seams, and focused regression coverage across completed, partial, failed, stale or reconciled, and artifact-limited runs
## Constitution Check
*GATE: Passed before Phase 0 research. Re-checked after Phase 1 design and still passing.*
| Principle | Status | Notes |
|-----------|--------|-------|
| Inventory-first | Pass | No inventory or snapshot ownership semantics change; this is a presentation hardening slice only |
| Read/write separation | Pass | No new mutation path is introduced; the surface remains read-only |
| Graph contract path | Pass | No new Graph calls or registry changes; render stays DB-only |
| Deterministic capabilities | Pass | No new capability derivation or role logic |
| RBAC-UX planes and 404 vs 403 | Pass | Canonical `/admin/operations/{run}` behavior remains policy-driven and tenant-safe |
| Workspace isolation | Pass | No workspace-context broadening; canonical viewer stays workspace-member gated |
| Tenant isolation | Pass | Tenant-linked related context and follow-up links remain entitlement-checked |
| Destructive confirmation | Pass | No new destructive action; any existing destructive-like action remains under existing confirmation rules |
| Global search safety | Pass | No searchability or global-search behavior changes |
| Run observability | Pass | Existing `OperationRun` lifecycle, monitoring role, and DB-only render contract remain unchanged |
| Ops-UX 3-surface feedback | Pass | No toast, progress, or terminal notification behavior changes |
| Ops-UX lifecycle ownership | Pass | `status` and `outcome` remain service-owned; this feature is display-only |
| Ops-UX summary counts | Pass | Counts continue to come from `OperationSummaryKeys::all()`-backed normalization; display dedupe only |
| Ops-UX guards | Pass | Existing lifecycle guards remain intact; new tests focus on decision-surface regressions |
| Data minimization | Pass | No new raw payload exposure; diagnostics remain secondary and redaction behavior stays in place |
| Badge semantics (BADGE-001) | Pass | Status, outcome, trust, and artifact-truth badges remain centralized through existing badge systems |
| UI naming (UI-NAMING-001) | Pass | Domain-first vocabulary remains `Outcome`, `Artifact truth`, `Result trust`, `Next step`, and related operator wording |
| Operator surfaces (OPSURF-001) | Pass | The feature explicitly strengthens operator-first default-visible content and pushes diagnostics later |
| Filament Action Surface Contract | Pass | No action inventory expansion; only hierarchy and grouping change on an existing detail page |
| Filament UX-001 | Pass with documented variance | The page remains a custom enterprise detail view rather than a stock infolist layout, but still satisfies the sectioned, operator-first intent |
| Filament v5 / Livewire v4 compliance | Pass | The work remains inside the current Filament v5 + Livewire v4 stack |
| Provider registration location | Pass | No panel/provider changes; Laravel 11+ provider registration stays in `bootstrap/providers.php` |
| Global-search hard rule | Pass | No resource search changes are proposed |
| Asset strategy | Pass | No new panel assets or published views required; existing Blade/Tailwind/Filament primitives are sufficient |
## Phase 0 Research
Research outcomes are captured in `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/164-run-detail-hardening/research.md`.
Key decisions:
- Introduce an explicit decision-zone section rather than trying to repurpose the header or the existing sidebar as the sole operator summary.
- Derive one canonical primary next step from existing explanation and guidance sources, with a defined precedence and explicit secondary-guidance fallback.
- Centralize counts into one primary presentation and move any extra count detail into diagnostics-only or purposefully different surfaces.
- Treat lifecycle attention as contextual supporting information or a banner-level exception, not as a duplicated fact across multiple equal-priority zones.
- Preserve type-specific sections, but force them below the generic decision and supporting layers.
- Keep raw payloads, JSON, detailed failures, and reconciliation evidence available through technical or diagnostic sections without deleting them.
## Phase 1 Design
Design artifacts are created under `/Users/ahmeddarrazi/Documents/projects/TenantAtlas/specs/164-run-detail-hardening/`:
- `data-model.md`: derived run-detail view model and section-order contract
- `contracts/operation-run-detail-page.openapi.yaml`: internal page-contract schema for the canonical run detail surface and its structured payload
- `quickstart.md`: focused verification workflow for manual and automated validation
Design decisions:
- No schema migration is required; the design uses existing `OperationRun`, `ArtifactTruthPresenter`, `OperationUxPresenter`, and `EnterpriseDetail` data.
- The main implementation seam remains `OperationRunResource::enterpriseDetailPage()` plus the `EnterpriseDetail` Blade layout and supporting-card rendering.
- The design introduces a first-class decision zone and explicit supporting groups, rather than relying on a single dense supporting facts card.
- The design formalizes one primary next-step slot, one primary count slot, and a diagnostics-last ordering contract.
- Regression coverage expands around hierarchy, duplication, special-state clarity, and coexistence with baseline-compare and other type-specific detail.
## Project Structure
### Documentation (this feature)
```text
specs/164-run-detail-hardening/
├── spec.md
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
│ └── operation-run-detail-page.openapi.yaml
├── checklists/
│ └── requirements.md
└── tasks.md
```
### Source Code (repository root)
```text
app/
├── Filament/
│ ├── Pages/
│ │ └── Operations/
│ │ └── TenantlessOperationRunViewer.php
│ └── Resources/
│ └── OperationRunResource.php
├── Support/
│ ├── OpsUx/
│ │ ├── OperationUxPresenter.php
│ │ └── SummaryCountsNormalizer.php
│ └── Ui/
│ ├── EnterpriseDetail/
│ │ ├── EnterpriseDetailBuilder.php
│ │ ├── EnterpriseDetailPageData.php
│ │ └── EnterpriseDetailSectionFactory.php
│ └── GovernanceArtifactTruth/
│ └── ArtifactTruthPresenter.php
resources/
└── views/
└── filament/
├── infolists/
│ └── entries/
│ ├── enterprise-detail/
│ │ ├── header.blade.php
│ │ ├── layout.blade.php
│ │ ├── section-items.blade.php
│ │ ├── supporting-card.blade.php
│ │ └── technical-detail.blade.php
│ └── governance-artifact-truth.blade.php
└── pages/
└── operations/
└── tenantless-operation-run-viewer.blade.php
tests/
├── Feature/
│ ├── Filament/
│ │ ├── OperationRunBaselineTruthSurfaceTest.php
│ │ └── OperationRunEnterpriseDetailPageTest.php
│ └── Operations/
│ └── TenantlessOperationRunViewerTest.php
└── Unit/
└── Support/
└── Ui/
└── EnterpriseDetail/
└── EnterpriseDetailBuilderTest.php
```
**Structure Decision**: Standard Laravel monolith. The change is concentrated in one canonical page composer, one viewer wrapper, a small enterprise-detail presentation layer, and focused Pest coverage. No new base directories or architectural layers are required.
## Implementation Strategy
### Phase A — Introduce A First-Class Decision Zone
**Goal**: Add an explicit, top-priority decision summary that answers outcome, artifact truth, trust, and the one primary next step without relying on the dense supporting card.
| Step | File | Change |
|------|------|--------|
| A.1 | `app/Filament/Resources/OperationRunResource.php` | Refactor `enterpriseDetailPage()` to assemble a first-class decision-zone payload before generic sections and supporting cards |
| A.2 | `app/Support/Ui/EnterpriseDetail/EnterpriseDetailBuilder.php` and `app/Support/Ui/EnterpriseDetail/EnterpriseDetailPageData.php` | Extend the enterprise-detail payload contract so the builder can carry an explicit decision zone and grouped supporting content end-to-end |
| A.3 | `app/Support/Ui/EnterpriseDetail/EnterpriseDetailSectionFactory.php` | Add or refine helpers needed to construct decision-zone and grouped-support payloads without page-local array drift |
| A.4 | `resources/views/filament/infolists/entries/enterprise-detail/layout.blade.php` | Render the decision zone immediately after the header and before the main grid |
| A.5 | `resources/views/filament/infolists/entries/governance-artifact-truth.blade.php` or a new dedicated decision-zone partial | Reuse existing artifact-truth semantics without duplicating the same top-level meaning elsewhere |
### Phase B — Canonicalize Primary Next Step And Count Placement
**Goal**: Remove semantically duplicated next-step and count presentations while preserving deeper diagnostic value.
| Step | File | Change |
|------|------|--------|
| B.1 | `app/Filament/Resources/OperationRunResource.php` | Define a single primary-next-step resolution order across operator explanation, artifact truth, blocked guidance, and `OperationUxPresenter` |
| B.2 | `app/Filament/Resources/OperationRunResource.php` | Remove duplicate count blocks and keep one primary count surface plus optional diagnostics-only detail |
| B.3 | `app/Support/OpsUx/OperationUxPresenter.php` and existing helpers if needed | Keep guidance sourcing centralized rather than inventing page-local text rules |
| B.4 | Relevant enterprise-detail partials | Ensure the same next-step statement is not rendered in both decision and supporting zones |
### Phase C — Rebuild Supporting Context As Semantic Groups
**Goal**: Replace the current fact-dump sidebar with grouped supporting context for guidance, lifecycle caveats, timing, and secondary metadata.
| Step | File | Change |
|------|------|--------|
| C.1 | `app/Filament/Resources/OperationRunResource.php` | Split the existing `Current state` card into semantically grouped cards or grouped payload sections |
| C.2 | `resources/views/filament/infolists/entries/enterprise-detail/supporting-card.blade.php` | Support richer grouping or presentation treatment if the current generic fact card is insufficient |
| C.3 | `app/Filament/Pages/Operations/TenantlessOperationRunViewer.php` | Keep mismatch, blocked, and lifecycle banners as contextual attention surfaces only where they add non-duplicative value |
| C.4 | `resources/views/filament/pages/operations/tenantless-operation-run-viewer.blade.php` | Preserve banner-before-detail ordering while avoiding redundant repetition of the same lifecycle message inside neutral summary facts |
### Phase D — Preserve Type-Specific Detail And Diagnostics-Last Ordering
**Goal**: Keep baseline compare, baseline capture, verification, failure, reconciliation, and raw context sections available but clearly lower in the reading order.
| Step | File | Change |
|------|------|--------|
| D.1 | `app/Filament/Resources/OperationRunResource.php` | Reorder type-specific sections below the canonical decision and supporting layers |
| D.2 | `resources/views/filament/infolists/entries/enterprise-detail/technical-detail.blade.php` | Keep technical detail progressive and collapsed where appropriate |
| D.3 | Existing type-specific partials and JSON sections | Preserve data availability while ensuring raw payloads do not compete with the primary decision zone |
### Phase E — Regression Protection And Focused Validation
**Goal**: Lock the new hierarchy into tests and preserve route, RBAC, and semantic non-regression.
| Step | File | Change |
|------|------|--------|
| E.1 | `tests/Feature/Filament/OperationRunEnterpriseDetailPageTest.php` | Add hierarchy, count-deduplication, next-step singularity, diagnostics-order, and required scenario-matrix assertions |
| E.2 | `tests/Feature/Filament/OperationRunBaselineTruthSurfaceTest.php` | Protect the distinction between outcome, artifact truth, trust, and next action on artifact-heavy runs, including summary-versus-expansion non-duplication |
| E.3 | `tests/Feature/Operations/TenantlessOperationRunViewerTest.php` | Preserve banner behavior, canonical view accessibility, and positive or negative tenant-safe related-context and diagnostic-visibility semantics |
| E.4 | `tests/Unit/Support/Ui/EnterpriseDetail/EnterpriseDetailBuilderTest.php` | Extend payload-shape assertions if the builder gains decision-zone or grouped-supporting semantics |
| E.5 | `vendor/bin/sail bin pint --dirty --format agent` and focused Pest runs | Required formatting and targeted verification before task completion |
## Key Design Decisions
### D-001 — Decision summary must be explicit, not inferred from header plus sidebar
The current page spreads the meaning across header badges, a run-summary section, artifact truth, and the dense `Current state` card. A dedicated decision zone creates one predictable operator reading path without changing the underlying domain semantics.
### D-002 — One primary next step needs a deterministic precedence rule
The current page can expose `Artifact next step`, `Next step`, and lifecycle guidance at the same level. The design resolves one primary next-step slot first and demotes all other guidance to secondary context.
### D-003 — Counts should exist once as a decision aid and optionally again only as diagnostics
The current page can show counts in the main sections and in the supporting card. The design keeps one operator-facing count summary and treats any deeper count grid as diagnostics-only when genuinely useful.
### D-004 — Lifecycle attention belongs in contextual emphasis, not in repeated fact rows
Blocked, stale, and reconciled states are important, but they should appear as clear contextual attention surfaces or grouped caveats instead of as duplicate headline facts in multiple page regions.
### D-005 — Type-specific sections remain important, but only after the generic decision layer
Baseline compare, baseline capture, verification, and similar operation-type detail should deepen the operator understanding after the page has already answered the generic triage questions.
## Risk Assessment
| Risk | Impact | Likelihood | Mitigation |
|------|--------|------------|------------|
| Decision-zone refactor unintentionally hides useful diagnostics | Medium | Medium | Use progressive disclosure and keep raw sections intact below the primary summary |
| Next-step consolidation oversimplifies special cases | Medium | Medium | Use explicit precedence plus preserved secondary guidance rather than dropping alternative guidance |
| Count deduplication removes meaningful drill-down context | Medium | Low | Keep one diagnostics-only detailed count surface when it has a different purpose |
| Artifact truth and outcome become visually merged | High | Low | Preserve separate labels, badges, and assertions in both the plan and tests |
| Type-specific sections drift upward and reintroduce hierarchy noise | Medium | Medium | Lock ordering in feature tests and keep type-specific sections appended after canonical summary layers |
## Test Strategy
- Extend existing canonical run-detail feature coverage instead of creating a brand-new test architecture.
- Add scenario coverage for completed success, completed with follow-up or partial, failed, blocked, stale or reconciled, and artifact-limited runs.
- Add explicit assertions for no duplicate next-step statement at equal priority and no duplicate main-content count block.
- Add explicit assertions that the decision-zone artifact-truth summary is not simply restated by a later artifact-truth section.
- Preserve canonical-view non-regression: tenant-safe access, positive or negative related-context and diagnostic-visibility semantics, 404 versus 403 behavior, and no render-time external calls.
- Keep Livewire v4-compatible page tests for the canonical viewer and Pest feature tests for rendered ordering and section presence.
## Complexity Tracking
No constitution violations or justified complexity exceptions were identified.