# Implementation Plan: Operations Auto-Refresh Pass **Branch**: `[123-operations-auto-refresh]` | **Date**: 2026-03-08 | **Spec**: [spec.md](./spec.md) **Input**: Feature specification from `/specs/123-operations-auto-refresh/spec.md` **Note**: This plan is filled in by the `/speckit.plan` workflow. ## Summary Add conditional auto-refresh to the canonical tenantless operation run viewer and intentionally reusable tenant-scoped review pack card surfaces by reusing existing product polling patterns instead of inventing new infrastructure. The run viewer will stay aligned with the shared run-detail polling helper and its existing hidden-tab / modal-open safeguards, while the embedded review pack widget will emit a simple `10s` Livewire polling interval only when the latest review pack is in an active generation state. ## Technical Context **Language/Version**: PHP 8.4 runtime target on Laravel 12 code conventions; Composer constraint `php:^8.2` **Primary Dependencies**: Laravel 12, Filament v5.2.1, Livewire v4, Pest v4, Laravel Sail **Storage**: PostgreSQL primary app database **Testing**: Pest feature tests run through `vendor/bin/sail artisan test --compact` **Target Platform**: Web application rendered through Filament panels on Laravel Sail / containerized deployment **Project Type**: Single Laravel web application **Performance Goals**: Active monitoring surfaces should refresh automatically without manual input while avoiding unnecessary polling once work is terminal **Constraints**: Preserve DB-only render behavior for monitoring surfaces; no WebSockets, no new backend events, no global polling rewrite, no polling on terminal states **Scale/Scope**: Two existing UI surfaces, no schema changes, no dependency changes, targeted regression coverage only ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* - **Inventory-first**: PASS — no inventory or snapshot semantics change. - **Read/write separation**: PASS — no new write workflow is introduced; only passive refresh behavior changes. - **Graph contract path**: PASS — no Graph calls or contract registry changes are involved. - **Deterministic capabilities**: PASS — no capability derivation changes. - **RBAC-UX plane separation**: PASS — `/admin/operations/{run}` remains a canonical Monitoring route and the intentionally reusable tenant-scoped review widget remains tenant-plane only on every host surface, with existing authorization rules unchanged. - **Workspace isolation**: PASS — the tenantless operation viewer continues to rely on existing workspace membership checks and referenced-tenant entitlement checks for tenant-bound runs. - **Destructive confirmations**: PASS — no new destructive actions are added. - **Global search safety**: PASS — feature does not touch global search. - **Tenant isolation**: PASS — review pack polling remains tenant-scoped and uses existing access checks. - **Run observability**: PASS — existing `OperationRun` records remain the sole source for operation progress; no new run type or lifecycle mutation path is introduced. - **Ops-UX 3-surface feedback**: PASS — queued toast, progress surfaces, and terminal notification behavior are unchanged. - **Ops-UX lifecycle ownership**: PASS — this feature reads run state only; `OperationRunService` remains the only lifecycle transition owner. - **Ops-UX summary counts**: PASS — unchanged. - **Ops-UX guards**: PASS — existing helper guard coverage is reused and extended where needed. - **Ops-UX system runs**: PASS — unchanged. - **Automation / idempotency**: PASS — unchanged. - **Data minimization / safe logging**: PASS — unchanged. - **Badge semantics (BADGE-001)**: PASS — existing badge mappings stay centralized; polling only re-renders them. - **Filament Action Surface Contract**: PASS WITH EXEMPTION — affected surfaces change passive refresh behavior only, not action definitions. - **Filament UX-001**: PASS WITH EXEMPTION — no layout or information-architecture changes are introduced. - **Livewire v4.0+ compliance**: PASS — Filament v5 / Livewire v4 stack remains unchanged. - **Provider registration location**: PASS — no panel-provider changes; Laravel 12 keeps providers in `bootstrap/providers.php`. ## Phase 0 — Research Summary Research findings are recorded in [research.md](./research.md). - Reuse `App\Support\OpsUx\RunDetailPolling::interval()` for tenantless run detail behavior instead of introducing a second run-detail polling policy. - Preserve the existing run-detail suppression guards for hidden browser tabs and mounted Filament actions. - Treat review-pack `queued` and `generating` as the only active widget states; `ready`, `failed`, `expired`, and empty state are terminal/non-polling. - Attach review-pack polling at the widget Blade root using the same `pollingInterval` → `wire:poll.{interval}` pattern already used by lightweight dashboard widgets. - Extend existing Pest coverage rather than building new test infrastructure. ## Phase 1 — Design & Contracts ### Data Model Design details are recorded in [data-model.md](./data-model.md). Key design points: - No schema changes are required. - `OperationRun` remains the source of truth for run-detail polling decisions. - `ReviewPack` remains the source of truth for review-pack-card polling decisions. - Polling state is derived view state (`interval string | null`), not persisted state. ### Contracts Internal UI behavior contracts are recorded in [contracts/polling-contracts.yaml](./contracts/polling-contracts.yaml). Contract scope: - Tenantless operation run viewer at `/admin/operations/{run}` - Intentionally reusable tenant-scoped embedded `TenantReviewPackCard` widget surfaces (component-scoped; no standalone route is owned by the widget itself) ### Quickstart Implementation and verification steps are recorded in [quickstart.md](./quickstart.md). ### Post-Design Constitution Re-check - **Inventory-first**: PASS — no data-ownership boundary changes. - **Read/write separation**: PASS — polling remains read-only. - **Graph contract path**: PASS — no remote integrations added. - **RBAC-UX**: PASS — existing 404/403 behavior and capability checks remain authoritative. - **Workspace isolation**: PASS — tenantless run viewer continues to authorize against the run workspace and referenced tenant scope when the run is tenant-bound. - **Tenant isolation**: PASS — review-pack-card polling is based on the current tenant’s latest pack only. - **Run observability**: PASS — `OperationRun` reuse remains intact; no inline work added to render surfaces. - **Ops-UX lifecycle ownership**: PASS — plan introduces no direct `status` / `outcome` mutation path. - **BADGE-001**: PASS — no new badge semantics introduced. - **Filament Action Surface Contract**: PASS WITH EXEMPTION — no action-surface mutation. - **UX-001**: PASS WITH EXEMPTION — no layout change required for passive refresh. ## Project Structure ### Documentation (this feature) ```text specs/123-operations-auto-refresh/ ├── plan.md ├── research.md ├── data-model.md ├── quickstart.md ├── contracts/ │ └── polling-contracts.yaml └── tasks.md ``` ### Source Code (repository root) ```text app/ ├── Filament/ │ ├── Pages/Operations/TenantlessOperationRunViewer.php │ ├── Resources/OperationRunResource.php │ └── Widgets/ │ ├── Dashboard/NeedsAttention.php │ └── Tenant/TenantReviewPackCard.php ├── Models/ │ ├── OperationRun.php │ └── ReviewPack.php ├── Services/ │ └── ReviewPackService.php └── Support/OpsUx/ ├── ActiveRuns.php ├── OperationStatusNormalizer.php └── RunDetailPolling.php resources/views/ ├── filament/pages/operations/tenantless-operation-run-viewer.blade.php ├── filament/widgets/dashboard/needs-attention.blade.php └── filament/widgets/tenant/tenant-review-pack-card.blade.php tests/Feature/ ├── Operations/TenantlessOperationRunViewerTest.php ├── OpsUx/RunDetailPollingStopsOnTerminalTest.php └── ReviewPack/ReviewPackWidgetTest.php ``` **Structure Decision**: Keep the implementation inside the existing Laravel / Filament structure. Reuse current polling helpers and Blade widget patterns in place, with targeted updates limited to the two affected surfaces and their directly related tests. ## Testing Strategy - Extend helper-level coverage for run-detail active-versus-terminal polling behavior only if the shared helper changes. - Add page/widget assertions that active surfaces emit polling and terminal surfaces do not. - Keep verification targeted to: - `tests/Feature/OpsUx/RunDetailPollingStopsOnTerminalTest.php` - `tests/Feature/Operations/TenantlessOperationRunViewerTest.php` - `tests/Feature/ReviewPack/ReviewPackWidgetTest.php` - `tests/Feature/ReviewPack/ReviewPackGenerationTest.php` - `tests/Feature/ReviewPack/ReviewPackRbacTest.php` for unchanged tenant-scope access regression coverage - Manual QA will cover one active and one terminal example for each affected surface. ## Complexity Tracking No constitution violations or complexity exemptions are required for this plan.