# 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.
