TenantAtlas/specs/269-operationrun-terminal-outcome-feedback/spec.md
Ahmed Darrazi c1f4ebaa05
Some checks failed
PR Fast Feedback / fast-feedback (pull_request) Failing after 1m31s
chore: commit all changes (automated)
2026-05-05 17:20:17 +02:00

237 lines
24 KiB
Markdown

# Feature Specification: OperationRun Terminal Outcome Feedback v1
**Feature Branch**: `269-operationrun-terminal-outcome-feedback`
**Created**: 2026-05-05
**Status**: Ready for implementation
**Input**: Manual promotion from `docs/product/spec-candidates.md` after repo-based verification against the current shell implementation, tests, and roadmap backlog.
## Spec Candidate Check *(mandatory - SPEC-GATE-001)*
- **Problem**: The tenant shell already shows recent terminal `OperationRun` states, but the current surface still collapses successful completion and unresolved follow-up into one generic terminal-update model. Terminal follow-up rows can still read like they are safely dismissible instead of clearly needing review.
- **Today's failure**: A blocked, partial, or failed run can render with the same generic terminal banner framing and `Dismiss` semantics as a no-action-needed success. That weakens the shell's decision-first promise because unresolved work can look like harmless noise.
- **User-visible improvement**: Operators can immediately distinguish `done, no action needed` from `completed, review still needed` in the shell without opening Monitoring first. Successful terminal items stay briefly calm and dismissible, while unresolved follow-up states use explicit acknowledge or review wording.
- **Smallest enterprise-capable version**: tighten the current tenant-shell activity hint only: keep active-state behavior intact, keep canonical links intact, split terminal success from terminal follow-up copy and tertiary actions, and keep acknowledgement browser-session-only.
- **Explicit non-goals**: no new activity tray, no dashboard active-operations card, no new `OperationRun` lifecycle, no new progress contract, no notification-policy rewrite, no persisted acknowledgement state, and no new diagnostics surface.
- **Permanent complexity imported**: one tighter shell-state contract, small copy or action branching in the existing shell helper or view, focused Feature plus browser proof, and one standards-document update.
- **Why now**: repo truth already includes the broader shell activity surface from Spec 268, and the next visible gap is no longer active-work feedback. It is terminal-outcome honesty on the same surface.
- **Why not local**: a one-line copy tweak would not encode the lifecycle-specific action contract, the `success vs follow-up` distinction, or the durable UI guardrail that stops this seam from drifting again.
- **Approval class**: Workflow Compression
- **Red flags triggered**: shared interaction family, shell-level operator surface
- **Score**: Nutzen: 2 | Dringlichkeit: 2 | Scope: 2 | Komplexitaet: 2 | Produktnaehe: 2 | Wiederverwendung: 1 | **Gesamt: 11/12**
- **Decision**: approve
## Spec Scope Fields *(mandatory)*
- **Scope**: tenant
- **Primary Routes**:
- `/admin/t/{tenant}/...` tenant-scoped start and work surfaces that host the shell activity hint
- `/admin/operations` remains the canonical collection drill-through
- `/admin/operations/{run}` remains the canonical detail drill-through
- **Data Ownership**: existing tenant-owned `OperationRun` truth only; no new persisted projection, no new user preference store, and no new queue or notification state
- **RBAC**: current `OperationRun` policies remain authoritative. Non-members or out-of-scope tenant contexts stay deny-as-not-found (`404` semantics through current tenant/admin boundaries). In-scope actors only see terminal states they can already view through the canonical Operations routes.
## Cross-Cutting / Shared Pattern Reuse *(mandatory)*
- **Cross-cutting feature?**: yes
- **Interaction class(es)**: shell status messaging, navigation links, lifecycle-sensitive tertiary actions
- **Systems touched**: `BulkOperationProgress`, `OperationUxPresenter`, `OperationStatusNormalizer`, `OperationRunProgressContract`, `ActiveRuns`, `OperationRunLinks`, `OperationRunUrl`, `OpsUxBrowserEvents`, and `docs/ui/tenantpilot-enterprise-ui-standards.md`
- **Existing pattern(s) to extend**: current shell activity feedback, canonical `View operation` and `Show all operations` links, current progress-contract enforcement, and browser-session collapse behavior
- **Shared contract / presenter / builder / renderer to reuse**: `App\Support\OpsUx\OperationUxPresenter`, `App\Support\OpsUx\OperationStatusNormalizer`, `App\Support\OpsUx\OperationRunProgressContract`, `App\Support\OpsUx\OperationRunUrl`, `App\Support\OpsUx\ActiveRuns`, `App\Support\OpsUx\OpsUxBrowserEvents`, and `App\Support\OperationRunLinks`
- **Why the existing shared path is sufficient or insufficient**: the repo already owns truthful link, status, and progress semantics. What remains open is a narrower shell-level terminal-outcome contract, not a new framework.
- **Allowed deviation and why**: none planned. Keep the refinement local to the existing shell component and its helpers.
- **Consistency impact**: `Hide activity`, `Dismiss` or `Close`, `Acknowledge`, `View operation`, grouped `Review operations`, and the banner helper copy must describe active, successful, and unresolved follow-up states consistently across Feature proof, browser smoke, and the standards document. `Review operations` is the grouped label variant of the same canonical collection link also exposed as `Show all operations`, not a second collection action.
- **Review focus**: verify that unresolved follow-up no longer inherits generic dismiss semantics, that terminal success stays no-action-needed, and that the shell still uses canonical links with no new lifecycle or persistence.
## OperationRun UX Impact *(mandatory)*
- **Touches OperationRun start/completion/link UX?**: yes
- **Shared OperationRun UX contract/layer reused**: existing Ops-UX shell contract through `OperationUxPresenter`, `OperationRunUrl`, `OperationRunLinks`, `OperationRunProgressContract`, and `OpsUxBrowserEvents`
- **Delegated start/completion UX behaviors**: current queued-toast wording, canonical Operations links, current browser event contract, and existing terminal DB-notification lifecycle remain delegated to the shared path
- **Local surface-owned behavior that remains**: terminal success vs follow-up copy, lifecycle-sensitive tertiary action wording, and browser-session-only acknowledge or dismiss behavior on the shell host
- **Queued DB-notification policy**: `N/A` - unchanged
- **Terminal notification path**: unchanged central lifecycle mechanism
- **Exception required?**: none
## Provider Boundary / Platform Core Check *(mandatory)*
N/A - no shared provider or platform-core seam changes. The slice only tightens shell semantics over existing platform-owned `OperationRun` truth.
## UI / Surface Guardrail Impact *(mandatory)*
| Surface / Change | Operator-facing surface change? | Native vs Custom | Shared-Family Relevance | State Layers Touched | Exception Needed? | Low-Impact / `N/A` Note |
|---|---|---|---|---|---|---|
| Tenant shell activity hint | yes | Native Filament + existing Livewire/Blade shell surface | Ops UX lifecycle feedback, canonical run links, browser-session calmness | shell, page, browser-session | no | Tightens terminal outcome semantics only; no new surface family |
## Decision-First Surface Role *(mandatory)*
| Surface | Decision Role | Human-in-the-loop Moment | Immediately Visible for First Decision | On-Demand Detail / Evidence | Why This Is Primary or Why Not | Workflow Alignment | Attention-load Reduction |
|---|---|---|---|---|---|---|---|
| Tenant shell activity hint | Primary Decision Surface | Decide whether the most recent terminal outcome needs no action, acknowledgement, or immediate review | Operation label, lifecycle state, terminal recency, one next-step cue, and one canonical primary action | Full diagnostics, logs, payloads, and evidence stay in Operations collection/detail | Primary because this is the post-start and post-completion surface where operators decide whether to keep working or inspect a run | Follows start-surface workflow, not diagnostics-page storage structure | Prevents unresolved follow-up from blending into harmless completion noise |
## Audience-Aware Disclosure *(mandatory)*
| Surface | Audience Modes In Scope | Decision-First Default-Visible Content | Operator Diagnostics | Support / Raw Evidence | One Dominant Next Action | Hidden / Gated By Default | Duplicate-Truth Prevention |
|---|---|---|---|---|---|---|---|
| Tenant shell activity hint | operator-MSP | Operation label, terminal success or follow-up state, short recency line, concise next-step cue, and canonical primary action | Detailed failure context, run history, and full outcome diagnostics remain on Operations pages | Raw payloads, log details, and support-only evidence stay off the shell | `View operation` for one visible item or `Review operations` when unresolved follow-up is mixed or grouped | Raw and support detail stay diagnostics-only; acknowledge stays browser-session-only | The shell states the next decision once and does not restate full Monitoring prose |
## UI/UX Surface Classification *(mandatory)*
| Surface | Action Surface Class | Surface Type | Likely Next Operator Action | Primary Inspect/Open Model | Row Click | Secondary Actions Placement | Destructive Actions Placement | Canonical Collection Route | Canonical Detail Route | Scope Signals | Canonical Noun | Critical Truth Visible by Default | Exception Type / Justification |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Tenant shell activity hint | Monitoring hint | Activity shell hint | Decide whether to review a just-finished run or keep working | One explicit `View operation` or grouped `Review operations` action | forbidden | One grouped overflow path to `Show all operations` plus one lifecycle-sensitive tertiary action | none | `/admin/operations` in current tenant context | `/admin/operations/{run}` in current tenant context | Current tenant shell context | Operations / Operation | Terminal success vs unresolved follow-up, recency, and the next action | none |
## Operator Surface Contract *(mandatory)*
| Surface | Primary Persona | Decision / Operator Action Supported | Surface Type | Primary Operator Question | Default-visible Information | Diagnostics-only Information | Status Dimensions Used | Mutation Scope | Primary Actions | Dangerous Actions |
|---|---|---|---|---|---|---|---|---|---|---|
| Tenant shell activity hint | Tenant operator | Decide whether a recent terminal outcome is safely complete or still needs review | Start-surface shell hint | Does this run need anything from me now? | Operation label, terminal outcome, recency, concise guidance, and canonical open or review action | Operations detail, logs, and evidence | lifecycle, follow-up-needed, progress-availability | none | `View operation`, `Review operations`, `Show all operations` | none |
**UI Action Matrix**: `N/A - no Filament Resource, RelationManager, or Page action matrix changes are introduced. The shell hint remains a widget-level monitoring hint with one dominant navigation action and one browser-session tertiary affordance.`
## Proportionality Review *(mandatory when structural complexity is introduced)*
- **New source of truth?**: no
- **New persisted entity/table/artifact?**: no
- **New abstraction?**: no
- **New enum/state/reason family?**: no
- **New cross-domain UI framework/taxonomy?**: no
- **Current operator problem**: terminal follow-up still inherits generic dismiss semantics on the shell, which blurs `review needed` with `done, no action needed`.
- **Existing structure is insufficient because**: the current shell already has terminal rows, but its copy and tertiary action rules are still too broad to encode lifecycle-correct operator decisions.
- **Narrowest correct implementation**: refine the existing shell component, helper text, and browser-session tertiary actions only, then document the rule in the standards file.
- **Ownership cost**: small shell branching plus focused Feature and browser coverage.
- **Alternative intentionally rejected**: a copy-only tweak was rejected because it would not define the durable `success vs follow-up` action contract or stop future regression.
- **Release truth**: current-release truth. The repo already ships the shell activity surface; this slice only hardens its terminal semantics.
### Compatibility posture
This feature assumes a pre-production environment.
Backward compatibility, legacy aliases, migration shims, historical fixtures, and compatibility-specific tests are out of scope unless explicitly required by this spec.
Canonical replacement is preferred over preservation.
## Testing / Lane / Runtime Impact *(mandatory)*
- **Test purpose / classification**: Feature plus one required browser smoke for the shell action and overlap contract
- **Validation lane(s)**: fast-feedback, confidence, browser
- **Why this classification and these lanes are sufficient**: Feature coverage proves the lifecycle-specific terminal copy, tertiary actions, and browser-session-only acknowledgement semantics on the current shell host. The browser smoke is the narrowest credible proof that the tightened terminal actions stay reachable without reintroducing obstruction.
- **New or expanded test families**: extend `apps/platform/tests/Feature/OpsUx/ActivityFeedbackSurfaceTest.php`, extend `apps/platform/tests/Feature/OpsUx/BulkOperationProgressDbOnlyTest.php`, and extend `apps/platform/tests/Browser/OpsUx/OperationActivityFeedbackSmokeTest.php`
- **Fixture / helper cost impact**: low to moderate. Reuse current `OperationRun` factories, tenant helpers, and shell smoke helpers; do not add provider-heavy setup or persisted acknowledgement fixtures.
- **Heavy-family visibility / justification**: no heavy-governance family. The browser proof stays explicit and bounded to the shell overlap plus action-label contract.
- **Special surface test profile**: global-context-shell
- **Standard-native relief or required special coverage**: standard Feature coverage is primary; one browser smoke remains required for live shell interaction
- **Reviewer handoff**: reviewers must confirm that successful terminal items stay dismissible, unresolved follow-up uses acknowledge or review semantics, terminal rows never show progressbars, and the shell still reopens on new run-enqueue events.
- **Budget / baseline / trend impact**: small feature-local increase only
- **Escalation needed**: `reject-or-split` if implementation widens into dashboard cards, new notification policy, new persistence, or a second `OperationRun` lifecycle surface
- **Active feature PR close-out entry**: Guardrail / Smoke Coverage
- **Planned validation commands**:
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/OpsUx/ActivityFeedbackSurfaceTest.php tests/Feature/OpsUx/BulkOperationProgressDbOnlyTest.php`
- `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/OpsUx/OperationActivityFeedbackSmokeTest.php`
## User Scenarios & Testing *(mandatory)*
### User Story 1 - Terminal Success Feels Complete, Not Risky (Priority: P1)
As a tenant operator, I need successful terminal runs to stay briefly visible with calm success semantics, so I can see that work finished and dismiss it without confusing it with unresolved follow-up.
**Why this priority**: post-completion trust is the first decision point after work finishes, and it should stay explicitly no-action-needed.
**Independent Test**: seed one recently completed successful run, open a tenant-scoped shell surface, and verify the shell shows success-specific copy, no active progress UI, and `Dismiss` or `Close` semantics during the current 30-second shell-visible success window preserved by `ActiveRuns`.
**Acceptance Scenarios**:
1. **Given** a run completes successfully, **When** the shell refreshes during the current 30-second terminal-success grace window from `ActiveRuns::shellVisibleQueryForTenantId()`, **Then** the shell shows success-specific copy, keeps `View operation` as the canonical primary action, and uses `Dismiss` or `Close` as the tertiary action.
2. **Given** a recent successful terminal item is visible, **When** the shell renders it, **Then** it does not show a determinate or indeterminate progress bar.
---
### User Story 2 - Terminal Follow-Up Stays Explicitly Reviewable (Priority: P1)
As a tenant operator, I need unresolved terminal runs to stay clearly review-worthy on the shell, so I do not treat a failed or partial outcome as safely dismissible noise.
**Why this priority**: unresolved terminal outcomes are the real decision risk in the current shell semantics.
**Independent Test**: seed one failed, partial, or blocked terminal run, open a tenant-scoped shell surface, and verify the shell shows follow-up-specific copy, canonical review or detail navigation, and `Acknowledge` instead of generic dismiss semantics.
**Acceptance Scenarios**:
1. **Given** a run completes with a follow-up-needed outcome, **When** the shell refreshes, **Then** the shell keeps the run visible with follow-up-specific guidance and uses `Acknowledge` as the local tertiary action.
2. **Given** both active work and unresolved terminal follow-up are visible, **When** the shell chooses its grouped primary action, **Then** the grouped action favors review-oriented wording over no-action-needed success wording.
3. **Given** a terminal follow-up item is visible, **When** the shell renders it, **Then** it does not show active-progress UI and does not use `Dismiss` as the tertiary label.
---
### User Story 3 - Acknowledge Stays Browser-Session Only (Priority: P1)
As a tenant operator, I need terminal follow-up acknowledgement to stay local to my current browser session, so the shell can stay calm without inventing a server-side review state.
**Why this priority**: the slice must remain a presentation refinement, not a new workflow system.
**Independent Test**: acknowledge an unresolved terminal item in the current browser session, then trigger a new run-enqueued event and verify the shell reopens without any database-backed acknowledgement state.
**Acceptance Scenarios**:
1. **Given** an unresolved terminal item is visible, **When** the operator clicks `Acknowledge`, **Then** the shell hides that item only for the current browser session.
2. **Given** the shell is hidden or acknowledged in the current browser session, **When** a new run is enqueued for the current tenant, **Then** the shell reopens so the operator does not miss new work.
### Edge Cases
- Successful terminal items must not overwrite unresolved follow-up emphasis when both types are visible in the same shell state.
- Unresolved terminal follow-up must not inherit generic `Dismiss updates` copy when the shell shows a grouped primary action.
- Terminal outcome items must not reintroduce progressbars, indeterminate bars, or fake percentages after completion.
- No tenant context or no `viewAny OperationRun` capability keeps the shell inert and leak-free.
- Browser-session acknowledgement must not mutate the `OperationRun` record or persist across new browser sessions.
- The current 30-second terminal-success grace window from `ActiveRuns::shellVisibleQueryForTenantId()` remains the source of truth unless a later spec deliberately changes it.
## Requirements *(mandatory)*
**Constitution alignment summary**: This feature adds no Graph calls, no new write path, no new `OperationRun` lifecycle, no new notification policy, and no new persistence. It reuses the current shell activity surface, current progress contract, current canonical links, and current browser-session event flow.
### Functional Requirements
- **FR-001**: The shell MUST continue deriving terminal outcome presentation from existing `OperationRun` truth and current shared helpers. It MUST NOT create a second lifecycle, status taxonomy, or persisted shell state.
- **FR-002**: Recent successful terminal items MUST use success-specific shell copy and a no-action-needed posture, keep canonical Operations navigation, and use `Dismiss` or `Close` as the browser-session tertiary action during the current 30-second terminal-success grace window preserved in `ActiveRuns::shellVisibleQueryForTenantId()`.
- **FR-003**: Unresolved terminal follow-up items that still require operator review MUST use follow-up-specific shell copy and `Acknowledge` as the browser-session tertiary action. They MUST NOT reuse generic dismiss semantics.
- **FR-004**: Mixed shell states that include unresolved terminal follow-up MUST preserve review-oriented emphasis in grouped helper copy and primary action wording. Successful completion MUST NOT dominate unresolved follow-up messaging.
- **FR-005**: Terminal success and terminal follow-up items MUST NOT render determinate or indeterminate progress UI after completion.
- **FR-006**: Canonical `View operation`, grouped `Review operations`, and `Show all operations` links MUST remain helper-generated through the existing shared path. `Review operations` is only the grouped label variant of the canonical collection link. The slice MUST NOT introduce raw route strings.
- **FR-007**: Browser-session `Hide activity`, `Dismiss` or `Close`, and `Acknowledge` behavior MUST remain browser-session-only. The implementation MUST NOT persist acknowledgement or dismiss state on the `OperationRun` record or in a new table.
- **FR-008**: A new accepted run in the current browser session MUST reopen the shell if it was previously hidden or acknowledged locally.
- **FR-009**: `docs/ui/tenantpilot-enterprise-ui-standards.md` MUST record the terminal outcome contract for the shell activity hint, including the difference between success dismissal and follow-up acknowledgement semantics.
### Authorization and Safety Requirements
- **AR-001**: Current tenant/admin-plane authorization semantics remain unchanged: out-of-scope tenant access stays deny-as-not-found (`404` semantics) and in-scope visibility continues to reuse server-side `OperationRun` policies.
- **AR-002**: No shell state in this slice may expose a run the actor cannot already reach through the canonical Operations routes.
- **AR-003**: No destructive or mutating action is introduced. Acknowledge and dismiss are browser-session-only presentation controls.
### Non-Functional Requirements
- **NFR-001**: Filament remains v5 on Livewire v4. No panel-provider registration change is allowed, and `apps/platform/bootstrap/providers.php` remains authoritative.
- **NFR-002**: No new panel, no new globally searchable resource, and no new asset registration strategy are allowed.
- **NFR-003**: Polling remains bounded to the current shell host. The slice MUST NOT add a second polling loop or a second active-awareness host surface.
- **NFR-004**: Existing progress-contract and badge semantics remain authoritative. No page-local terminal-status color mapping or progress heuristics may be introduced.
## Deferred Follow-Ups / Explicit Non-Goals
- Tenant dashboard active-operations summary card
- New `OperationRun` progress-contract or counted-progress rollout work
- Phase or composite progress modeling
- A persisted reviewed, investigated, or acknowledged state over terminal follow-up
- Activity tray or inbox v2
- Notification-policy changes for queued or terminal lifecycle events
## Key Entities
- **Terminal success shell item**: a derived, non-persisted shell item for a recently completed successful run that stays briefly visible, conveys no-action-needed completion, and remains locally dismissible.
- **Terminal follow-up shell item**: a derived, non-persisted shell item for a terminal run that still needs operator review and therefore uses acknowledge or review semantics instead of generic dismissal.
- **Browser-session terminal-outcome state**: non-persisted shell-level state that remembers local hide, dismiss, and acknowledge choices only for the current browser session.
## Success Criteria *(mandatory)*
### Measurable Outcomes
- **SC-001**: Focused Feature proof shows a recent successful terminal item with success-specific copy, no active-progress UI, and `Dismiss` or `Close` semantics.
- **SC-002**: Focused Feature proof shows an unresolved terminal follow-up item with review-specific copy and `Acknowledge` semantics instead of generic dismiss wording.
- **SC-003**: Focused Feature proof shows mixed active-plus-follow-up shell states keeping follow-up emphasis in grouped helper copy and grouped primary action wording.
- **SC-004**: The named browser smoke continues to prove that the shell actions remain reachable, collapse or acknowledge behavior stays browser-session-only, and new run-enqueue events reopen the shell.