# Implementation Plan: OperationRun Activity Feedback v1 **Branch**: `268-operationrun-activity-feedback` | **Date**: 2026-05-03 | **Spec**: [spec.md](./spec.md) **Input**: Feature specification from `/specs/268-operationrun-activity-feedback/spec.md` ## Summary This plan prepares one bounded Ops-UX slice over the repo's existing `OperationRun` truth. The implementation path is to refactor the current tenant-shell activity widget so it becomes non-obstructive, honest about active progress, and capable of showing a brief terminal-success or unresolved terminal follow-up handoff in the same surface, then record the durable shell guardrail in `docs/ui/tenantpilot-enterprise-ui-standards.md`. The slice must stay on current `OperationRun` truth, current start toasts, current Operations drill-through pages, and current badge/link helpers with no new persistence, no new lifecycle, no new notification policy, no new active-awareness host surface, and no tray/inbox expansion. Filament remains on Livewire v4, no panel-provider registration changes are required (`apps/platform/bootstrap/providers.php` remains authoritative), no globally searchable resource is added, and no asset registration change is expected. ## Inherited Baseline / Explicit Delta ### Inherited baseline - `OperationRun` already provides the execution-truth model and current tenant/workspace scoping. - `OperationUxPresenter`, `OperationStatusNormalizer`, `OperationRunLinks`, and `OperationRunUrl` already provide truthful run guidance, badge semantics, and canonical links. - `BulkOperationProgress` plus the current poller already provide tenant-shell activity surfacing, albeit in an obstructive floating form. - `OperationRunLinkContractGuardTest` and the current Ops-UX Feature tests already enforce parts of the link and host-surface contract. ### Explicit delta in this plan - narrow the current `BulkOperationProgress` shell contract to one bounded activity surface and end its obstructive overlay behavior - keep progress treatment honest and constitution-safe, including no fake active progress after terminal transition - add a brief terminal-success handoff and unresolved terminal follow-up visibility on the same surface - add browser-session hide/dismiss/acknowledge behavior without introducing persistence - update `docs/ui/tenantpilot-enterprise-ui-standards.md` with the durable shell activity-feedback guardrail ## Technical Context **Language/Version**: PHP 8.4, Laravel 12, Filament v5, Livewire v4 **Primary Dependencies**: current Ops-UX support classes, native Filament widgets/Blade, current badge infrastructure, Pest v4 **Storage**: PostgreSQL via existing `operation_runs`; browser-session state only for allowed collapse behavior; no new DB storage **Testing**: Pest Feature coverage plus one required browser smoke **Validation Lanes**: fast-feedback, confidence, browser **Target Platform**: existing Laravel monolith in `apps/platform`, admin/operator plane only **Project Type**: Web application (Laravel monolith with Filament) **Performance Goals**: bounded shell/start-surface rendering, no new query families beyond current run reads, no duplicate polling loops, and max-three item presentation on the shell host **Constraints**: no new persistence, no new lifecycle/state family, no new notification policy, no tray v2, and no panel/provider/asset changes **Scale/Scope**: one current host surface, one standards update, one browser-session calmness rule ## Likely Affected Repo Surfaces - `apps/platform/app/Support/OpsUx/OperationUxPresenter.php` - `apps/platform/app/Support/OpsUx/OperationStatusNormalizer.php` - `apps/platform/app/Support/OpsUx/OperationRunUrl.php` - `apps/platform/app/Support/OperationRunLinks.php` - `apps/platform/app/Support/OpsUx/ActiveRuns.php` - `apps/platform/app/Livewire/BulkOperationProgress.php` - `apps/platform/resources/views/livewire/bulk-operation-progress.blade.php` - `apps/platform/resources/views/livewire/bulk-operation-progress-wrapper.blade.php` - `apps/platform/app/Providers/Filament/TenantPanelProvider.php` - `apps/platform/app/Filament/Pages/Monitoring/Operations.php` (inherited tenant-prefilter precedence seam) - `apps/platform/public/js/tenantpilot/ops-ux-progress-widget-poller.js` - `apps/platform/tests/Feature/OpsUx/...` - `apps/platform/tests/Feature/Guards/OperationRunLinkContractGuardTest.php` - `apps/platform/tests/Feature/Monitoring/MonitoringPageStateContractTest.php` (inherited state-contract coverage) - `apps/platform/tests/Browser/OpsUx/...` - `docs/ui/tenantpilot-enterprise-ui-standards.md` ## UI / Filament & Livewire Fit - Keep the changed shell host Filament-native. It may remain a Livewire shell entrypoint, but the refactor should stay local to the existing shell component and views instead of introducing a second host surface. - The shell host stays decision-first. It shows at most three visible items, one dominant `View operation` action per item, one canonical overflow path, and only the minimum run state needed for the next operator decision. - Monitoring collection/detail pages remain diagnostics-first drill-through targets. The shell must not re-state their evidence-heavy content. - Browser-session hide/dismiss/acknowledge stays local to the current browser session and does not create a server-side acknowledgement model. - Keep custom markup narrow and standards-aligned. Avoid page-local progress bar colors, host-specific card systems, fake percentages, or percentage text. - No new asset registration, panel configuration, or provider registration change is planned. ## RBAC / Policy Fit - Existing `OperationRun` policies remain the first and only visibility gate. - The tenant shell host derives rows only after tenant context and policy filtering. - The shell overflow path must preserve the selected tenant as the initial `tenant_id` contextual prefilter on the canonical Operations page; restored session filters may narrow inside that tenant scope but must not broaden beyond it. - Tenant/admin plane behavior stays unchanged: no cross-plane expansion and no new authorization surface. - No new mutation or retry action is introduced, so current confirmation/authorization behavior stays on existing start surfaces and run detail pages. ## Audit / Logging Fit - Existing queued toasts and terminal DB notifications remain authoritative and unchanged. - Existing run audit/Monitoring behavior remains the only audit trail. No new page-view audit stream is introduced. - Because the slice changes presentation only, `OperationRun.status` / `OperationRun.outcome` ownership remains service-owned and unchanged. ## Data & Query Fit - The shell host continues to derive rows from current-tenant `OperationRun` truth, limits visible presentation to three items, and uses overflow navigation for the rest. - Determinate progress must derive from truthful run-owned counts only while the run is active. If a run becomes terminal, the shell switches to terminal-success or terminal-follow-up semantics instead of reusing the active progress UI. - Hide, dismiss, and acknowledge state remain browser-session scoped and must not be persisted in the database or on the run record. ## UI / Surface Guardrail Plan - **Guardrail scope**: changed surfaces - **Native vs custom classification summary**: native Filament plus a bounded local shell refactor - **Shared-family relevance**: Ops UX start feedback, canonical run links - **State layers in scope**: shell, page, browser-session - **Audience modes in scope**: operator-MSP - **Decision/diagnostic/raw hierarchy plan**: decision-first on the shell host, diagnostics-first on Operations collection/detail - **Raw/support gating plan**: raw/support evidence stays on the existing diagnostics surfaces only - **One-primary-action / duplicate-truth control**: each shell item keeps one dominant `View operation` action, overflow navigation stays collection-only, the tertiary affordance is lifecycle-sensitive, and the shell does not duplicate detail-surface diagnostics - **Handling modes by drift class or surface**: review-mandatory - **Repository-signal treatment**: review-mandatory - **Special surface test profiles**: global-context-shell - **Required tests**: functional-core, state-contract, named-browser-smoke - **Exception path and spread control**: none planned; any attempt to add host-specific run-state cards or persisted hide semantics resolves as `reject-or-split` - **Active feature PR close-out entry**: Guardrail / Smoke Coverage ## Shared Pattern & System Fit - **Cross-cutting feature marker**: yes - **Systems touched**: current shell hint, canonical run links, current run guidance, current activity poller, UI standards - **Shared abstractions reused**: `OperationUxPresenter`, `OperationStatusNormalizer`, `OperationRunLinks`, `OperationRunUrl`, `ActiveRuns`, `OpsUxBrowserEvents`, current badge infrastructure - **New abstraction introduced? why?**: none planned by default; keep the change local to the existing shell component unless a tiny helper is strictly needed for readability - **Why the existing abstraction was sufficient or insufficient**: the repo already owns truthful state and links; the missing piece is a constitution-aligned shell contract, not a new framework - **Bounded deviation / spread control**: do not create a multi-profile registry, strategy system, or separate persisted activity model ## OperationRun UX Impact - **Touches OperationRun start/completion/link UX?**: yes, for start-surface follow-through, terminal handoff, and drill-through links only - **Central contract reused**: current Ops-UX start contract via `OperationUxPresenter`, `OperationRunLinks`, `OperationRunUrl`, and `OpsUxBrowserEvents` - **Delegated UX behaviors**: queued toast wording, canonical view/collection links, current browser-event dispatch, and existing terminal DB notifications remain delegated to the shared contract - **Surface-owned behavior kept local**: bounded shell layout, brief terminal-success/follow-up visibility, and browser-session hide/dismiss/acknowledge only - **Queued DB-notification policy**: `N/A` - unchanged - **Terminal notification path**: unchanged central lifecycle mechanism - **Exception path**: none ## Provider Boundary & Portability Fit - **Shared provider/platform boundary touched?**: no - **Provider-owned seams**: `N/A` - **Platform-core seams**: existing `OperationRun` truth, links, and operator vocabulary only - **Neutral platform terms / contracts preserved**: `Operation`, `View operation`, `Show all operations`, `queued`, `running`, `active` - **Retained provider-specific semantics and why**: none - **Bounded extraction or follow-up path**: none ## Constitution Check *GATE: Must pass before implementation begins and again before merge.* - Inventory-first: PASS. The slice is fully derived from existing `OperationRun` truth. - Read/write separation: PASS. No new write path or retry surface is introduced. - Graph contract path: PASS. No Graph/provider interaction is added. - Deterministic capabilities: PASS. Existing `OperationRun` policies remain authoritative. - RBAC-UX: PASS. No plane expansion; tenant/admin visibility stays on current guards and deny-as-not-found semantics. - Run observability: PASS. Existing start contract, terminal notifications, and Monitoring ownership remain unchanged while the shell adds only a bounded terminal handoff. - Ops-UX lifecycle: PASS. No change to service-owned status/outcome transitions or `summary_counts` semantics. - Data minimization: PASS. Hosts stay compact and do not surface raw evidence by default. - Test governance: PASS. Proof stays bounded to Feature plus one named browser smoke for the overlap contract. - Proportionality / no premature abstraction: PASS. The default implementation stays local to the existing shell host and standards doc. - Persisted truth / behavioral state: PASS. No new table, no new lifecycle, no new persisted hide/dismiss/acknowledge state. - Shared pattern first / UI semantics / Filament-native UI: PASS. Existing helpers and badge semantics stay central, and the shell host moves closer to the existing Ops-UX contract. - Provider boundary: PASS. No provider/platform seam changes. - Filament/Laravel panel safety: PASS. Filament v5 stays on Livewire v4, provider registration remains in `apps/platform/bootstrap/providers.php`, and no new assets are planned. **Gate evaluation**: PASS. ## Test Governance Check - **Test purpose / classification by changed surface**: Feature for shell behavior; one required browser smoke for the overlap/non-obstruction contract - **Affected validation lanes**: fast-feedback, confidence, browser - **Why this lane mix is the narrowest sufficient proof**: Feature coverage proves real tenant context, active plus bounded terminal visibility, links, lifecycle-sensitive tertiary copy, and progress rules on the current shell host; browser proof is reserved for the one contract that depends on real clickability/layout - **Narrowest proving command(s)**: - `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Feature/OpsUx/BulkOperationProgressDbOnlyTest.php tests/Feature/OpsUx/ProgressWidgetOverflowTest.php tests/Feature/OpsUx/ActivityFeedbackSurfaceTest.php tests/Feature/Guards/OperationRunLinkContractGuardTest.php` - `export PATH="/bin:/usr/bin:/usr/local/bin:$PATH" && cd apps/platform && ./vendor/bin/sail artisan test --compact tests/Browser/OpsUx/OperationActivityFeedbackSmokeTest.php` - **Fixture / helper / factory / seed / context cost risks**: moderate; reuse current operation-run factories and tenant helpers instead of introducing new provider-heavy defaults or persistence fixtures - **Expensive defaults or shared helper growth introduced?**: no - **Heavy-family additions, promotions, or visibility changes**: none - **Surface-class relief / special coverage rule**: `global-context-shell` - **Closing validation and reviewer handoff**: reviewers should rerun the focused commands above, then manually verify that the shell hint no longer covers row-level actions on a page with active runs. They should also review the standards-doc update for canonical link/progress rules. - **Budget / baseline / trend follow-up**: none expected beyond a small feature-local increase - **Review-stop questions**: did the shell stay bounded, did terminal success/follow-up remain truthful, did it remain non-obstructive, did any raw route strings reappear, and did hide/dismiss/acknowledge stay browser-session-only? - **Escalation path**: `reject-or-split` for any persisted hide model, activity center expansion, or notification-policy change - **Active feature PR close-out entry**: Guardrail / Smoke Coverage - **Why no dedicated follow-up spec is needed**: this package already carries the standards-doc guardrail for the chosen v1 slice; larger tray/lifecycle topics remain explicit follow-up specs rather than hidden work here. ## Project Structure ### Documentation (this feature) ```text specs/268-operationrun-activity-feedback/ ├── spec.md ├── plan.md ├── tasks.md └── checklists/ └── requirements.md ``` This preparation package intentionally stays on the core artifacts plus the readiness checklist. The repo already contains the relevant Ops-UX truth, current host surfaces, and adjacent tests, so no extra research, data-model, or contract package is required for a bounded implementation handoff. ### Source Code (expected implementation surfaces) ```text apps/platform/app/Livewire/BulkOperationProgress.php apps/platform/resources/views/livewire/bulk-operation-progress.blade.php apps/platform/resources/views/livewire/bulk-operation-progress-wrapper.blade.php apps/platform/app/Providers/Filament/TenantPanelProvider.php apps/platform/public/js/tenantpilot/ops-ux-progress-widget-poller.js apps/platform/tests/Feature/OpsUx/... apps/platform/tests/Feature/Guards/OperationRunLinkContractGuardTest.php apps/platform/tests/Browser/OpsUx/... docs/ui/tenantpilot-enterprise-ui-standards.md ``` **Structure Decision**: keep the implementation local to the existing Ops-UX Livewire shell seams. Do not introduce a new multi-host activity framework in this slice. ## Data / Migration Implications - No migration or new table is planned. - No new persisted user preference is allowed. - No new cache layer, backfill, or asset/deploy step should be required for v1. ## Rollout Considerations - Filament remains v5 on Livewire v4. No panel-provider change is required, and provider registration remains in `apps/platform/bootstrap/providers.php`. - No global search change is required because the slice changes widgets/shell feedback, not resources. - No destructive action is added. Existing start/retry surfaces remain the only mutation owners. - No new asset registration is expected. ## Risk Controls - Reject any implementation that introduces a new `OperationRun` lifecycle, persisted hide model, or persistent acknowledgement workflow. - Reject any implementation that widens the slice into tray v2, notification policy changes, or any new host-surface migration beyond the current global active-ops shell widget. - Reject any implementation that keeps or reintroduces a fixed overlay that covers page actions. - Reject any implementation that uses fake progress percentages, percentage text, terminal runs in the shell, or raw route strings. ## Implementation Phases ### Phase 0 - Confirm Current Ops-UX Truth - Verify the current shell host, current link helpers, and current overlap/regression tests. ### Phase 1 - Encode The Shell Activity Contract - Keep the shell query and rendering derived from current `OperationRun` truth only. - Keep active, terminal-success, and terminal-follow-up semantics bounded to the same shell host. ### Phase 2 - Migrate The Shell Hint - End the obstructive floating-overlay behavior while keeping bounded polling. ### Phase 3 - Record The Guardrail And Calmness Rules - Update the UI standards doc with canonical link, bounded terminal-success/follow-up scope, progress, and hide/dismiss/acknowledge rules. ### Phase 4 - Harden Browser-Session Calmness And Validation - Add browser-session hide/dismiss/acknowledge only for allowed informational items. - Run the focused test suite and browser smoke. ## Proportionality Review - **Current operator problem**: the repo has truthful run-state helpers, but the current shell hint is obstructive and does not encode the active-only, honest-progress contract clearly. - **Existing structure is insufficient because**: the current shell implementation leaves key Ops-UX rules implicit and therefore easy to regress even if the underlying run truth is correct. - **Narrowest correct implementation**: refactor the existing shell component and views locally, keep the query active-only, add browser-session calmness, and update the standards doc. - **Ownership cost created**: one browser-session calmness rule and focused test/doc updates. - **Alternative intentionally rejected**: a shell-only CSS adjustment was rejected because it would not encode the active-only and honest-progress rules or leave a durable guardrail for future work. - **Release truth**: current-release truth. The repo already owns the active-ops widget and the Ops-UX constitution; this slice aligns the current shell to that truth.