# Tasks: Operations Auto-Refresh Pass **Input**: Design documents from `/specs/123-operations-auto-refresh/` **Prerequisites**: plan.md, spec.md, research.md, data-model.md, contracts/polling-contracts.yaml, quickstart.md **Tests**: Tests are REQUIRED for this runtime behavior change. Use Pest feature tests via Sail. **Operations**: No new `OperationRun` type or lifecycle work is required for this feature; tasks must reuse existing `OperationRun` observability semantics and preserve the existing tenantless Monitoring route. **RBAC**: No authorization model changes are planned; tasks must preserve existing workspace membership checks for the tenantless run viewer and existing tenant capability checks for every tenant-scoped host surface that renders the review pack card. **Filament UI Action Surfaces**: The affected Filament surfaces change passive refresh behavior only; no new actions, destructive flows, or action-matrix rows are introduced beyond the approved spec exemption. **Filament UI UX-001**: No Create/Edit/View layout changes are required; tasks must preserve existing viewer and card layouts while adding non-noisy auto-refresh behavior. **Organization**: Tasks are grouped by user story so each story remains independently testable. ## Phase 1: Setup (Shared Context) **Purpose**: Align implementation with the approved polling contract and current codebase patterns before editing runtime code. - [X] T001 [P] Review the approved polling behavior in specs/123-operations-auto-refresh/spec.md, specs/123-operations-auto-refresh/research.md, specs/123-operations-auto-refresh/contracts/polling-contracts.yaml, and specs/123-operations-auto-refresh/quickstart.md - [X] T002 [P] Inspect the current shared polling implementations in app/Support/OpsUx/RunDetailPolling.php, app/Filament/Resources/OperationRunResource.php, app/Filament/Widgets/Dashboard/NeedsAttention.php, and resources/views/filament/widgets/dashboard/needs-attention.blade.php --- ## Phase 2: Foundational (Blocking Prerequisites) **Purpose**: Confirm the active-vs-terminal state sources that both polling surfaces depend on. **⚠️ CRITICAL**: No user story work should begin until this phase is complete. - [X] T003 Confirm polling state ownership in app/Support/OpsUx/OperationStatusNormalizer.php, app/Support/ReviewPackStatus.php, app/Models/ReviewPack.php, app/Services/ReviewPackService.php, and app/Jobs/GenerateReviewPackJob.php so active and terminal semantics stay consistent across both surfaces **Checkpoint**: Shared polling semantics are confirmed and user-story implementation can begin. --- ## Phase 3: User Story 1 - Watch an active operation complete (Priority: P1) 🎯 MVP **Goal**: Make the tenantless operation run viewer update automatically while a run remains active. **Independent Test**: Open `/admin/operations/{run}` for queued and running runs and verify the page emits auto-refresh behavior; open the same page for a completed run and verify it does not rely on manual refresh for active monitoring. ### Tests for User Story 1 ⚠️ > **NOTE**: Add or update these tests first and ensure they fail before implementation. - [X] T004 [P] [US1] Extend tests/Feature/OpsUx/RunDetailPollingStopsOnTerminalTest.php to cover the shared queued/running polling contract and age-based interval expectations in app/Support/OpsUx/RunDetailPolling.php - [X] T005 [P] [US1] Extend tests/Feature/Operations/TenantlessOperationRunViewerTest.php to assert queued and running runs render polling markup on the `/admin/operations/{run}` viewer while preserving the existing workspace-membership and tenant-entitlement access semantics on that canonical route ### Implementation for User Story 1 - [X] T006 [US1] Ensure app/Filament/Pages/Operations/TenantlessOperationRunViewer.php and resources/views/filament/pages/operations/tenantless-operation-run-viewer.blade.php surface the shared polling contract from app/Filament/Resources/OperationRunResource.php without breaking the existing hidden-tab and mounted-action guards in app/Support/OpsUx/RunDetailPolling.php **Checkpoint**: User Story 1 should now allow operators to watch active tenantless runs update automatically. --- ## Phase 4: User Story 2 - Monitor review pack generation from the card (Priority: P2) **Goal**: Make the tenant review pack card refresh itself while generation is queued or in progress. **Independent Test**: Open any tenant-scoped host surface that renders `TenantReviewPackCard`, trigger review-pack generation, and verify the card refreshes itself until the pack finishes. ### Tests for User Story 2 ⚠️ - [X] T007 [P] [US2] Extend tests/Feature/ReviewPack/ReviewPackWidgetTest.php to assert queued and generating review pack states render `wire:poll.10s` on the card while preserving the widget’s existing tenant membership and review-pack capability behavior - [X] T008 [P] [US2] Extend tests/Feature/ReviewPack/ReviewPackGenerationTest.php to keep `queued` and `generating` aligned as the only active lifecycle states that should drive card polling ### Implementation for User Story 2 - [X] T009 [US2] Add a review-pack polling interval resolver in app/Filament/Widgets/Tenant/TenantReviewPackCard.php that returns `10s` only when the latest pack status is `queued` or `generating` - [X] T010 [US2] Apply conditional root-level polling markup in resources/views/filament/widgets/tenant/tenant-review-pack-card.blade.php using the interval exposed by app/Filament/Widgets/Tenant/TenantReviewPackCard.php **Checkpoint**: User Story 2 should now let users observe review pack generation without manual refresh. --- ## Phase 5: User Story 3 - Avoid noisy refresh behavior on completed work (Priority: P3) **Goal**: Stop polling cleanly for terminal or unknown states so completed surfaces remain stable. **Independent Test**: Open completed/failed tenantless runs plus ready/failed/expired/no-pack review card states and confirm none of them emit polling markup or restart refresh loops. ### Tests for User Story 3 ⚠️ - [X] T011 [P] [US3] Extend tests/Feature/Operations/TenantlessOperationRunViewerTest.php to assert completed and failed tenantless runs render without polling markup when loaded directly in a terminal state, without regressing the route’s existing 404 and 403 behavior - [X] T012 [P] [US3] Extend tests/Feature/ReviewPack/ReviewPackWidgetTest.php to assert ready, failed, expired, and no-pack card states render without polling markup ### Implementation for User Story 3 - [X] T013 [US3] Harden non-active fallback logic in app/Support/OpsUx/RunDetailPolling.php and app/Filament/Widgets/Tenant/TenantReviewPackCard.php so terminal or unrecognized states always resolve to `null` polling without visible UI churn **Checkpoint**: User Story 3 should now guarantee stable terminal states across both surfaces. --- ## Phase 6: Polish & Cross-Cutting Concerns **Purpose**: Final verification, manual QA, and formatting across all stories. - [ ] T014 Perform the manual QA flow from specs/123-operations-auto-refresh/quickstart.md for one active and one terminal tenantless run plus one active and one terminal review pack generation lifecycle - [X] T015 Run focused Pest coverage with `vendor/bin/sail artisan test --compact` for tests/Feature/OpsUx/RunDetailPollingStopsOnTerminalTest.php, tests/Feature/Operations/TenantlessOperationRunViewerTest.php, tests/Feature/ReviewPack/ReviewPackWidgetTest.php, and tests/Feature/ReviewPack/ReviewPackGenerationTest.php - [X] T016 Run `vendor/bin/sail bin pint --dirty --format agent` - [X] T017 Run existing non-regression authorization coverage with `vendor/bin/sail artisan test --compact` for tests/Feature/Operations/TenantlessOperationRunViewerTest.php and tests/Feature/ReviewPack/ReviewPackRbacTest.php to confirm routes, ownership semantics, and access rules remain unchanged --- ## Dependencies & Execution Order ### Phase Dependencies - **Setup (Phase 1)**: No dependencies; can start immediately. - **Foundational (Phase 2)**: Depends on Setup completion; blocks all user stories. - **User Story 1 (Phase 3)**: Depends on Foundational completion; this is the MVP. - **User Story 2 (Phase 4)**: Depends on Foundational completion; can proceed after US1 or in parallel once shared polling semantics are confirmed. - **User Story 3 (Phase 5)**: Depends on Foundational completion and benefits from US1/US2 polling hooks being in place. - **Polish (Phase 6)**: Depends on completion of the desired user stories. ### User Story Dependencies - **US1**: No dependency on other stories; delivers the primary operator-facing value. - **US2**: No dependency on US1; it depends only on the shared polling semantics confirmed in Phase 2. - **US3**: Depends on the active-polling implementation paths from US1 and US2 so terminal-state behavior can be finalized and verified. ### Within Each User Story - Tests should be added or updated first and observed failing before implementation. - Shared helper or resolver changes should land before Blade markup changes that consume them. - Story-specific verification should complete before moving to the next priority. ### Parallel Opportunities - T001 and T002 can run in parallel. - T004 and T005 can run in parallel. - T007 and T008 can run in parallel. - T011 and T012 can run in parallel. - After Phase 2, US1 and US2 can be implemented in parallel if different contributors own the run viewer and review pack card. --- ## Parallel Example: User Story 1 ```bash Task: "Extend tests/Feature/OpsUx/RunDetailPollingStopsOnTerminalTest.php to cover the shared queued/running polling contract and age-based interval expectations" Task: "Extend tests/Feature/Operations/TenantlessOperationRunViewerTest.php to assert queued and running runs render polling markup on the /admin/operations/{run} viewer" ``` --- ## Parallel Example: User Story 2 ```bash Task: "Extend tests/Feature/ReviewPack/ReviewPackWidgetTest.php to assert queued and generating review pack states render wire:poll.10s on the card" Task: "Extend tests/Feature/ReviewPack/ReviewPackGenerationTest.php to keep queued and generating aligned as the only active lifecycle states that should drive card polling" ``` --- ## Parallel Example: User Story 3 ```bash Task: "Extend tests/Feature/Operations/TenantlessOperationRunViewerTest.php to assert completed and failed tenantless runs render without polling markup" Task: "Extend tests/Feature/ReviewPack/ReviewPackWidgetTest.php to assert ready, failed, expired, and no-pack card states render without polling markup" ``` --- ## Implementation Strategy ### MVP First (User Story 1 Only) 1. Complete Phase 1: Setup 2. Complete Phase 2: Foundational 3. Complete Phase 3: User Story 1 4. Validate queued and running tenantless operation runs auto-refresh correctly 5. Stop and review before broadening the change to the tenant review pack card if needed ### Incremental Delivery 1. Ship the tenantless run viewer polling improvement in US1 2. Add review pack card polling in US2 3. Harden terminal-state stability and non-active fallback behavior in US3 4. Finish with focused Sail tests, manual QA, and Pint ### Parallel Team Strategy With multiple contributors: 1. One contributor owns tenantless run viewer tests and implementation (US1) 2. One contributor owns review pack card tests and implementation (US2) 3. One contributor validates terminal/noisy-state regression coverage (US3) 4. Recombine for focused Sail test execution and formatting --- ## Notes - [P] tasks touch different files and can be executed in parallel. - User story labels map each task to the corresponding story in spec.md. - No migrations, no new routes, and no dependency changes are expected. - Manual QA evidence belongs in review artifacts, not committed files.