# Tasks: 096 — Ops Polish Bundle (Assignment job summaries + job dedupe + system job tracking + seeder DX) **Input**: Design documents from `specs/096-ops-polish-assignment-dedupe-system-tracking/` **Prerequisites**: `plan.md` (required), `spec.md` (required), `research.md`, `data-model.md`, `contracts/`, `quickstart.md` **Tests**: REQUIRED (Pest) for runtime behavior changes. **Operations**: This feature modifies queued/scheduled work, so tasks must ensure canonical `OperationRun` creation/reuse + DB-level active-run dedupe + safe failure summaries. **RBAC / Filament**: No authorization or Filament UI changes in scope. --- ## Phase 1: Setup (Docs + hygiene) **Purpose**: Ensure spec artifacts and plan alignment are clean before code work. - [X] T001 Fix duplicated FR numbering in specs/096-ops-polish-assignment-dedupe-system-tracking/spec.md - [X] T002 Sync plan references after edits in specs/096-ops-polish-assignment-dedupe-system-tracking/plan.md (ensure dedupe window semantics are described as a cooldown) --- ## Phase 2: Foundational (Blocking prerequisites) **Purpose**: Shared primitives used by all user stories. - [X] T003 Add operation label for `ops.reconcile_adapter_runs` in app/Support/OperationCatalog.php - [X] T004 Add expected duration for `ops.reconcile_adapter_runs` in app/Support/OperationCatalog.php - [X] T005 Do not add an enum case for `ops.reconcile_adapter_runs` in app/Support/OperationRunType.php (use the string type; enum is not a complete registry) - [X] T006 Implement a stable, non-secret fingerprint helper for assignment job identity in app/Support/OpsUx/AssignmentJobFingerprint.php - [X] T007 [P] Wire FetchAssignmentsJob identity inputs to use AssignmentJobFingerprint in app/Jobs/FetchAssignmentsJob.php - [X] T008 [P] Wire RestoreAssignmentsJob identity inputs to use AssignmentJobFingerprint in app/Jobs/RestoreAssignmentsJob.php **Checkpoint**: Foundation ready — story implementation can begin. --- ## Phase 3: User Story 1 — Assignment runs show durable summaries (Priority: P2) 🎯 MVP **Goal**: Persist consistent `OperationRun.summary_counts` for assignment fetch/restore runs (final attempt wins). **Independent Test**: Dispatch each job; assert `operation_runs.summary_counts` contains non-null `total`, `processed`, `failed`, and does not double-count across retries. ### Tests (write first) - [X] T009 [P] [US1] Add fetch summary persistence test in tests/Feature/Operations/AssignmentRunSummaryCountsTest.php - [X] T010 [P] [US1] Add restore summary persistence test in tests/Feature/Operations/AssignmentRunSummaryCountsTest.php ### Implementation - [X] T011 [US1] Persist terminal summary counts for fetch runs in app/Jobs/FetchAssignmentsJob.php via app/Services/OperationRunService.php::updateRun(...) - [X] T012 [US1] Persist terminal summary counts for restore runs in app/Jobs/RestoreAssignmentsJob.php via app/Services/OperationRunService.php::updateRun(...) - [X] T013 [US1] Ensure summary counts reflect final attempt (overwrite on completion) in app/Services/OperationRunService.php usage from app/Jobs/FetchAssignmentsJob.php - [X] T014 [US1] Ensure summary counts reflect final attempt (overwrite on completion) in app/Services/OperationRunService.php usage from app/Jobs/RestoreAssignmentsJob.php **Checkpoint**: Assignment runs always write durable counters. --- ## Phase 4: User Story 2 — Duplicate dispatches do not overlap (Priority: P2) **Goal**: Prevent concurrent overlap for the same logical assignment job identity. **Independent Test**: Dispatch the same job identity twice and verify only one execution performs work; the other is skipped/reuses the canonical active run. ### Tests (write first) - [X] T015 [P] [US2] Add dedupe test for fetch job in tests/Feature/Operations/AssignmentJobDedupeTest.php - [X] T016 [P] [US2] Add dedupe test for restore job in tests/Feature/Operations/AssignmentJobDedupeTest.php ### Implementation - [X] T017 [US2] Implement dispatch-time dedupe (reuse active `OperationRun`) for fetch in app/Jobs/FetchAssignmentsJob.php using app/Services/OperationRunService.php::ensureRunWithIdentity(...) - [X] T018 [US2] Implement dispatch-time dedupe (reuse active `OperationRun`) for restore in app/Jobs/RestoreAssignmentsJob.php using app/Services/OperationRunService.php::ensureRunWithIdentity(...) - [X] T019 [US2] Implement execute-time guard (skip when not canonical run) for fetch in app/Jobs/FetchAssignmentsJob.php - [X] T020 [US2] Implement execute-time guard (skip when not canonical run) for restore in app/Jobs/RestoreAssignmentsJob.php - [X] T021 [US2] Enforce dedupe window semantics (15 minutes) by reusing a recently completed identity (cooldown) in app/Services/OperationRunService.php (new helper) and call it from app/Jobs/FetchAssignmentsJob.php - [X] T022 [US2] Enforce dedupe window semantics (15 minutes) by reusing a recently completed identity (cooldown) in app/Services/OperationRunService.php (new helper) and call it from app/Jobs/RestoreAssignmentsJob.php **Checkpoint**: Duplicate dispatch/redelivery cannot cause overlapping work. --- ## Phase 5: User Story 3 — Housekeeping runs are tracked like everything else (Priority: P3) **Goal**: `ReconcileAdapterRunsJob` writes a workspace-scoped `OperationRun` with stable failure codes + sanitized messages. **Independent Test**: Execute the job successfully and with a forced failure; verify an `OperationRun` exists for `type = ops.reconcile_adapter_runs` with correct outcome and failure summary. ### Tests (write first) - [X] T023 [P] [US3] Add reconcile job success tracking test in tests/Feature/Operations/ReconcileAdapterRunsJobTrackingTest.php - [X] T024 [P] [US3] Add reconcile job failure tracking test in tests/Feature/Operations/ReconcileAdapterRunsJobTrackingTest.php ### Implementation - [X] T025 [US3] Create/reuse workspace-scoped run for housekeeping in app/Jobs/ReconcileAdapterRunsJob.php via app/Services/OperationRunService.php::ensureWorkspaceRunWithIdentity(...) - [X] T026 [US3] Persist terminal outcome + sanitized failure summary for housekeeping in app/Jobs/ReconcileAdapterRunsJob.php using app/Services/OperationRunService.php::updateRun(...) - [X] T027 [US3] Include stable failure code (e.g., `ops.reconcile_adapter_runs.failed`) for housekeeping failures in app/Jobs/ReconcileAdapterRunsJob.php **Checkpoint**: Housekeeping shows up in the operations ledger consistently. --- ## Phase 6: User Story 4 — Fresh seed flows work without manual intervention (Priority: P3) **Goal**: Seeding creates tenants with UUID v4 `external_id` and does not violate constraints. **Independent Test**: Run `migrate:fresh --seed` and assert the seeded tenant(s) have UUID v4 `external_id`. ### Tests (write first) - [X] T028 [P] [US4] Add seed external_id UUID test in tests/Feature/Seed/PoliciesSeederExternalIdTest.php ### Implementation - [X] T029 [US4] Generate UUID v4 `external_id` for seed tenant in database/seeders/PoliciesSeeder.php (do not reuse `INTUNE_TENANT_ID`) - [X] T034 [US4] Ensure seed workflow sets `workspace_id` for seeded tenant + policies to satisfy NOT NULL constraints in database/seeders/PoliciesSeeder.php - [X] T035 [US4] Ensure platform tenant seed sets `workspace_id` (default workspace) in database/seeders/PlatformUserSeeder.php **Checkpoint**: Seed workflow is reliable locally and in CI. --- ## Phase 7: Polish & Cross-Cutting Concerns **Purpose**: Consistency, formatting, and verification. - [X] T030 Run formatter on changed files (app/**, database/**, tests/**) via `vendor/bin/sail bin pint --dirty` - [X] T031 Run spec-focused tests in tests/Feature/Operations/AssignmentRunSummaryCountsTest.php and tests/Feature/Operations/AssignmentJobDedupeTest.php - [X] T032 Run spec-focused tests in tests/Feature/Operations/ReconcileAdapterRunsJobTrackingTest.php and tests/Feature/Seed/PoliciesSeederExternalIdTest.php --- ## Addendum: Constitution-required idempotency (queued/scheduled jobs) - [X] T033 [US3] Add overlap-prevention for ReconcileAdapterRunsJob so concurrent dispatch/schedule overlap cannot execute twice (lock/guard must be server-side) --- ## Dependencies & Execution Order ### User Story completion order - US1 (P2) → US2 (P2) → US3 (P3) → US4 (P3) ### Why - US1 establishes durable counters used by ops. - US2 dedupe builds on the same identity/counter plumbing. - US3 and US4 are independent after foundational primitives. --- ## Parallel execution examples ### US1 - T009 and T010 can run in parallel (same file, but split by responsibility). ### US2 - T015 and T016 can run in parallel. - T019 and T020 can run in parallel. ### US3 - T023 and T024 can run in parallel. ### US4 - T028 can run in parallel with US3 implementation tasks. --- ## Implementation strategy (MVP) - MVP scope: US1 only (Phase 3) after completing Phases 1–2. - After MVP validation: implement US2 next to reduce operational risk.