# 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.