## Summary - add conditional polling support for the tenantless operation run viewer and tenant review pack card - add focused Pest coverage for active vs terminal polling behavior and related review pack access regressions - add the full Spec Kit artifacts for Spec 123, including spec, plan, research, data model, contracts, quickstart, tasks, and checklist ## Testing - `vendor/bin/sail artisan test --compact 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` - `vendor/bin/sail bin pint --dirty --format agent` ## Notes - Manual QA task `T014` in the Spec Kit checklist remains to be completed outside this automated flow. - Livewire v4.0+ compliance is unchanged. - No panel provider changes were made; provider registration remains in `bootstrap/providers.php`. - No global-search behavior was changed. - No destructive actions were added or modified. - No new Filament assets were introduced; existing deployment expectations for `php artisan filament:assets` remain unchanged. Co-authored-by: Ahmed Darrazi <ahmed.darrazi@live.de> Reviewed-on: #149
162 lines
9.2 KiB
Markdown
162 lines
9.2 KiB
Markdown
# 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.
|