TenantAtlas/specs/164-run-detail-hardening/data-model.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

183 lines
8.5 KiB
Markdown

# Data Model: Operation Run Detail Hierarchy, Deduplication, and Decision Guidance Hardening
## Overview
This feature does not add or change persisted domain entities. It introduces a stricter derived page model for the canonical operation-run detail surface using existing `OperationRun`, artifact-truth, operator-explanation, summary-count, and lifecycle data.
The core design task is to transform an existing run record into a decision-first presentation contract without changing:
- `OperationRun` persistence
- route identity
- RBAC semantics
- status and outcome lifecycle ownership
- type-specific payload availability
## Existing Persistent Entity
### OperationRun
- Purpose: Canonical workspace-owned execution record for operational work tracked in Monitoring.
- Persistent fields used by this feature:
- `id`
- `workspace_id`
- `tenant_id`
- `type`
- `status`
- `outcome`
- `initiator_name`
- `summary_counts`
- `failure_summary`
- `context`
- `created_at`
- `started_at`
- `completed_at`
- Existing relationships used by this feature:
- `workspace`
- `tenant`
- `user`
## Derived View Models
### 1. RunDetailPageModel
Top-level page payload consumed by the enterprise-detail layout and viewer wrapper.
| Field | Type | Source | Notes |
|---|---|---|---|
| `header` | object | Existing `SummaryHeaderData` | Run identity, badges, key facts, existing page-level actions |
| `decisionZone` | object | New derived payload | First-class operator summary immediately after header |
| `supportingGroups` | list<object> | Existing supporting-card inputs regrouped | Replaces or restructures the current dense `Current state` card |
| `mainSections` | list<object> | Existing section builder output | Used for supporting detail and type-specific detail after the decision zone |
| `technicalSections` | list<object> | Existing technical-detail output | Diagnostics-last content such as context JSON |
| `attentionBanners` | list<object> | Existing viewer wrapper helpers | Context mismatch, blocked prerequisite, stale or reconciled lifecycle attention |
## 2. DecisionZoneModel
The primary operator reading block. It must answer: what happened, is the result trustworthy enough to use, and what should happen next.
| Field | Type | Source | Required | Notes |
|---|---|---|---|---|
| `executionState` | badge or labeled fact | `status` plus centralized badge rendering | Yes | Lifecycle state, not result quality |
| `outcome` | badge or labeled fact | `outcome` plus centralized badge rendering | Yes | Execution result, not artifact usability |
| `artifactTruth` | object | `ArtifactTruthPresenter::forOperationRun()` when available | Conditional | Required when the run has artifact-relevant operator meaning |
| `resultMeaning` | string | operator explanation headline or evaluation label | Conditional | Human-readable interpretation of what the result means |
| `resultTrust` | string or badge | operator explanation trust level | Conditional | Confidence or reliability meaning stays distinct from outcome |
| `primaryNextStep` | object | Derived precedence chain | Yes | Exactly one primary next step |
| `compactCounts` | object or null | `SummaryCountsNormalizer` output | Optional | Only when counts add decision value and do not duplicate diagnostics |
| `attentionNote` | string or null | lifecycle or caveat helper | Optional | Short exceptional-state caveat if needed in-zone |
### PrimaryNextStepModel
| Field | Type | Source | Notes |
|---|---|---|---|
| `text` | string | Derived from prioritized guidance sources | Canonical operator action statement |
| `source` | enum-like string | `operator_explanation`, `artifact_truth`, `ops_ux`, `blocked_reason`, `lifecycle_attention` | Debugging and testability only |
| `secondaryGuidance` | list<string> | Non-primary guidance sources | Must not render as equal-priority duplicates |
### Proposed precedence for `primaryNextStep`
1. Operator explanation next action when present
2. Artifact-truth next step when it is more specific than generic run guidance
3. Blocked-execution guidance when outcome is `blocked`
4. Lifecycle guidance when stale or reconciled state requires explicit attention
5. Generic `OperationUxPresenter::surfaceGuidance()`
6. Fallback `No action needed` only when the result is explicitly trustworthy and no follow-up is indicated
## 3. SupportingGroupModel
Semantically grouped supporting context that sits below or beside the decision zone but above diagnostics.
| Group | Purpose | Typical fields |
|---|---|---|
| `guidance` | Secondary operator context that supports the primary next step | coverage statement, contextual caveat, related follow-up links |
| `lifecycle` | Freshness, reconciliation, tenant lifecycle, and contextual caveats | freshness, lifecycle truth, reconciled at, reconciled by |
| `timing` | Operational timestamps and elapsed timing | created, started, completed, elapsed |
| `metadata` | Secondary facts that do not drive the first decision | target scope, initiator, viewer-context notes |
Rules:
- The same semantic fact must not appear in multiple supporting groups unless the representation serves a genuinely different purpose.
- Supporting groups must not restate the same primary next step as the decision zone.
- Supporting groups may explain why the primary next step exists, but not compete with it.
## 4. CountPresentationModel
| Field | Type | Purpose |
|---|---|---|
| `summaryLine` | string or null | Compact operator-facing count hint |
| `primaryFacts` | list<object> | Single main count presentation if counts materially help first-pass understanding |
| `diagnosticFacts` | list<object> | Optional deeper breakdown when the detailed count grid serves investigation |
Rules:
- `primaryFacts` and `diagnosticFacts` must not be identical renderings of the same normalized counts.
- If the detailed count grid remains in main content, the compact summary line must be materially different and lighter-weight.
- If counts are low-signal for the run, both may be omitted.
## 5. TypeSpecificDetailModel
Represents operation-type-specific content that follows the canonical decision summary.
| Operation Type | Existing section examples | Ordering rule |
|---|---|---|
| `baseline_compare` | compare facts, evidence gap details, compare evidence | After decision zone and supporting groups |
| `baseline_capture` | capture evidence | After decision zone and supporting groups |
| verification-capable runs | verification report | After decision zone and supporting groups |
| any run with failures | failures section | After decision zone and supporting groups |
| reconciled runs | lifecycle reconciliation payload | After decision zone and supporting groups |
Rules:
- Type-specific sections may deepen or explain the decision, but they must not replace the canonical summary.
- Raw JSON remains valid only as diagnostics or deep detail.
## 6. DiagnosticSectionModel
Lower-priority technical or investigative information.
| Section | Source | Default posture |
|---|---|---|
| `failures` | `failure_summary` | Visible after decision and supporting context |
| `reconciliation` | `context.reconciliation` | Visible only when relevant; diagnostic |
| `context` | redacted `context` payload | Collapsed by default |
| raw evidence payloads | baseline compare or capture payload arrays | Secondary or collapsible |
Rules:
- Diagnostic sections must remain available for support and investigation.
- Diagnostic sections must never be required to answer the primary operator questions.
## Render Ordering Contract
The surface must obey this order:
1. Attention banners that indicate exceptional context without duplicating neutral page facts
2. Header identity and route-level actions
3. Primary decision zone
4. Supporting semantic groups
5. Type-specific supporting detail
6. Diagnostic and raw context sections
## Validation Rules
- Exactly one primary next-step statement is rendered at top-level priority.
- No identical normalized count block appears more than once in the main content hierarchy.
- `Outcome`, `Artifact truth`, and `Result trust` remain independently visible when the run supplies those semantics.
- Diagnostic JSON or raw technical context cannot appear before the decision zone.
- Type-specific detail cannot render above the canonical decision zone.
## State Notes
There are no new persisted state transitions in this feature.
The relevant page-state modes that must remain representable are:
- completed and trustworthy
- completed with follow-up required
- failed
- blocked
- stale
- reconciled
- artifact unavailable or limited confidence
- type-specific diagnostic-heavy runs