tasks: task breakdown for problem resolution feature (009)

49 tasks across 9 phases (6 user stories + setup/foundational/polish).
Unlike 007/008, this feature's user stories are genuinely sequential
(doc04's own investigation -> root cause -> solution -> verification ->
resolution -> reopen chain), so each story's dependency on the last is
real, not just priority-driven ordering -- called out explicitly since
User Story 4 (P2, verification) is a structural prerequisite of User
Story 5 (P1, resolution) despite the lower priority label.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
saqib mir
2026-09-03 14:39:11 +05:30
co-authored by Claude Sonnet 5
parent 9ce34d8ca4
commit aaa51ef475
+355
View File
@@ -0,0 +1,355 @@
---
description: "Task list for 009-problem-resolution"
---
# Tasks: Problem Resolution
**Input**: Design documents from `specs/009-problem-resolution/`
**Prerequisites**: [plan.md](./plan.md), [spec.md](./spec.md), [research.md](./research.md),
[data-model.md](./data-model.md),
[contracts/problem-resolution-contract.md](./contracts/problem-resolution-contract.md),
[quickstart.md](./quickstart.md)
**Tests**: Included as first-class tasks. This feature's pure logic is the existence-chain
validation (each step's precondition) and the auto-close due-window predicate; the rest is
sequential-workflow wiring best proven end-to-end against real Postgres.
**Organization**: Tasks are grouped by user story (US1 = P1 investigation, US2 = P1 root cause,
US3 = P1 solution states, US4 = P2 verification, US5 = P1 resolution/confirmation/auto-close,
US6 = P2 reopen).
## Format: `[ID] [P?] [Story] Description`
All file paths are relative to `supporthub-api/` (repo root).
---
## Phase 1: Setup
- [ ] T001 [P] Populate `src/modules/problem-management/investigation/` with the full standard
shape (`controller/`, `routes/`, `schema/`, `repository/`, `service/`, `types/`, `mapper/`,
`constants/`, `index.ts`), replacing the `InvestigationService.getInvestigationStatus` stub
- [ ] T002 [P] Populate `src/modules/problem-management/root-causes/` the same way, replacing the
`RootCausesService.getRootCause` stub
- [ ] T003 [P] Populate `src/modules/problem-management/solutions/` the same way, replacing the
`SolutionsService.getSolutions` stub
- [ ] T004 [P] Populate `src/modules/problem-management/verification/` the same way, replacing
the `VerificationService.verifySolution` stub
- [ ] T005 [P] Populate `src/modules/problem-management/resolutions/` the same way, replacing the
`ResolutionsService.getResolutions` stub — this module additionally gets the auto-close
sweep and the two new customer-facing routes (later tasks)
- [ ] T006 [P] Add `src/config/problem-resolution.ts` (`problemResolutionConfig
.autoCloseWaitingHours`, reading a new `RESOLUTION_AUTO_CLOSE_WAITING_HOURS` env var,
default `72`) and register it in `src/config/index.ts`'s re-export list
---
## Phase 2: Foundational (Blocking Prerequisites)
**Purpose**: Schema for every entity, shared by every user story.
**⚠️ CRITICAL**: No user-story stage work can begin until this phase is complete.
- [ ] T007 Add `Investigation`, `RootCause`, `Solution`, `SolutionImplementation`,
`SolutionVerification`, `Resolution` models to `prisma/schema.prisma` per data-model.md,
plus `Problem.investigations`/`Problem.rootCauses`/`Problem.solutions` and
`Ticket.resolution` back-relations (depends on T001-T005)
- [ ] T008 Run `npm run prisma:generate` and create the migration (`npm run prisma:migrate`) for
T007 (depends on T007)
**Checkpoint**: Schema migrated. User stories can now be built.
---
## Phase 3: User Story 1 - Structured investigation, preserved across attempts (Priority: P1) 🎯 MVP (part 1)
**Goal**: Investigation CRUD with the version-row-per-attempt guarantee and internal-notes
exclusion from customer-facing reads.
**Independent Test**: Quickstart Scenario 1.
### Tests for User Story 1
- [ ] T009 [US1] Integration test covering Quickstart Scenario 1 (create, retrieve with every
field intact, customer-safe variant omits `internalNotes`, a second investigation preserves
the first) against a real Postgres in `tests/integration/problem-resolution-flow.test.ts`
(depends on T008)
### Implementation for User Story 1
- [ ] T010 [US1] Add `InvestigationRepository` (`create`, `findAllForProblem` ordered newest
first, `findMostRecentForProblem`) in `investigation/repository/` (depends on T008)
- [ ] T011 [US1] Add Zod create schema (`investigator`, `findings`, `evidence?`,
`internalNotes?`, `status?`) in `investigation/schema/`
- [ ] T012 [US1] Add `InvestigationService.record`/`listForProblem` (agent-facing, includes
`internalNotes`) and `listForProblemCustomerSafe` (strips `internalNotes`, FR-003) in
`investigation/service/` (depends on T010, T011)
- [ ] T013 [US1] Add `POST/GET /admin/problems/:problemId/investigations` (gated by
`fastify.authenticate`) and `GET /problems/:problemId/investigations` (ungated, customer-
safe) routes in `investigation/controller/` + `routes/`, registered from `src/api/routes.ts`
(depends on T012)
- [ ] T014 [US1] Run Quickstart Scenario 1 locally and confirm all 3 steps pass
**Checkpoint**: Investigations can be recorded and read correctly, with the customer-safe
redaction guarantee in place.
---
## Phase 4: User Story 2 - Root cause requires an investigation on file (Priority: P1) 🎯 MVP (part 2)
**Goal**: RootCause CRUD gated on an existing investigation, with a validated type enum.
**Independent Test**: Quickstart Scenario 2.
### Tests for User Story 2
- [ ] T015 [US2] Integration test covering Quickstart Scenario 2 (rejected with no investigation,
accepted after one exists, rejected with an invalid type) — implemented as the "Scenario 2"
case in `tests/integration/problem-resolution-flow.test.ts` (depends on T009, T014)
- [ ] T016 [P] [US2] Unit test for the type-validation Zod schema (five valid values, everything
else rejected) in `tests/unit/problem-management/root-cause-schema.test.ts`
### Implementation for User Story 2
- [ ] T017 [US2] Add `RootCauseRepository` (`create`, `findAllForProblem`) in
`root-causes/repository/` (depends on T008)
- [ ] T018 [US2] Add Zod create schema (`type` as a 5-value enum, `description`) in
`root-causes/schema/`
- [ ] T019 [US2] Add `RootCausesService.record`: resolve-or-`409` on the problem having at least
one investigation (T010's `findMostRecentForProblem`, via `investigation`'s public
`index.ts`) — in `root-causes/service/` (depends on T012, T017, T018)
- [ ] T020 [US2] Add `POST /admin/problems/:problemId/root-causes` route (gated by
`fastify.authenticate`) in `root-causes/controller/` + `routes/`, registered from
`src/api/routes.ts` (depends on T019)
- [ ] T021 [US2] Run Quickstart Scenario 2 locally and confirm all 3 steps pass
**Checkpoint**: Root causes are correctly gated on investigation existing first.
---
## Phase 5: User Story 3 - Solution proposed, approved, implemented as distinct states (Priority: P1) 🎯 MVP (part 3)
**Goal**: Solution CRUD gated on root cause existing; approval as an explicit action;
implementation gated on approval, one-to-one.
**Independent Test**: Quickstart Scenario 3.
### Tests for User Story 3
- [ ] T022 [US3] Integration test covering Quickstart Scenario 3 (rejected with no root cause,
created with `approved: false`, implementation rejected before approval, accepted after,
a second implementation rejected) — "Scenario 3" case in
`tests/integration/problem-resolution-flow.test.ts` (depends on T015, T021)
### Implementation for User Story 3
- [ ] T023 [US3] Add `SolutionRepository` (`create`, `findById`, `approve`,
`findMostRecentForProblem`) and `SolutionImplementationRepository` (`create`, `findBySolutionId`)
in `solutions/repository/` (depends on T008)
- [ ] T024 [US3] Add Zod schemas (`proposed`; implementation's `notes?`, `implementedBy`) in
`solutions/schema/`
- [ ] T025 [US3] Add `SolutionsService.propose`: resolve-or-`409` on the problem having at least
one root cause (T017's repository, via `root-causes`'s public `index.ts`) — `approve` —
`recordImplementation`: resolve-or-`409` on `approved: true` and no existing implementation
— in `solutions/service/` (depends on T019, T023, T024)
- [ ] T026 [US3] Add `POST /admin/problems/:problemId/solutions`,
`PATCH /admin/solutions/:solutionId/approve`,
`POST /admin/solutions/:solutionId/implementation` routes (gated by `fastify.authenticate`)
in `solutions/controller/` + `routes/`, registered from `src/api/routes.ts` (depends on
T025)
- [ ] T027 [US3] Run Quickstart Scenario 3 locally and confirm all 5 steps pass
**Checkpoint**: All three P1 record-keeping user stories are complete — the full investigation
through implementation chain is enforced and correct. This is the feature's structural MVP.
---
## Phase 6: User Story 4 - Verification, and failure re-investigates or escalates (Priority: P2)
**Goal**: SolutionVerification CRUD gated on implementation existing, one-to-one; a failed
verification supports either a fresh investigation or the existing `HUMAN_ESCALATION` transition.
**Independent Test**: Quickstart Scenario 4.
### Tests for User Story 4
- [ ] T028 [US4] Integration test covering Quickstart Scenario 4 (successful verification;
failed verification recorded but unusable for resolution; failure + reinvestigate creates a
fresh Investigation row; failure + escalate transitions the ticket to `HUMAN_ESCALATION`
and 007 auto-assigns) — "Scenario 4" case in
`tests/integration/problem-resolution-flow.test.ts` (depends on T022)
### Implementation for User Story 4
- [ ] T029 [US4] Add `SolutionVerificationRepository` (`create`, `findBySolutionId`) in
`verification/repository/` (depends on T008)
- [ ] T030 [US4] Add Zod schema (`method` as a 4-value enum, `result`, `evidence?`) in
`verification/schema/`
- [ ] T031 [US4] Add `VerificationService.record`: resolve-or-`409` on the solution having an
implementation (T023's repository) and no existing verification — in `verification/
service/` (depends on T023, T029, T030)
- [ ] T032 [US4] Add `POST /admin/solutions/:solutionId/verification` route (gated by
`fastify.authenticate`) in `verification/controller/` + `routes/`, registered from
`src/api/routes.ts` (depends on T031)
- [ ] T033 [US4] Run Quickstart Scenario 4 locally and confirm all 4 steps pass (steps 3-4 call
T012's `InvestigationService.record` and `ticketsService.updateStatus` directly — no new
production code beyond what US1/003/007 already provide, per research.md's decision to
reuse the existing transition rather than add new escalation machinery)
**Checkpoint**: Verification is correctly gated and its failure path reuses existing mechanisms
rather than inventing new ones.
---
## Phase 7: User Story 5 - Resolution, customer confirmation, and durable auto-close (Priority: P1)
**Goal**: Resolution gated on a successful verification; explicit customer confirmation via
002's trust boundary; a durable, directly-callable auto-close sweep as the fallback.
**Independent Test**: Quickstart Scenario 5.
### Tests for User Story 5
- [ ] T034 [P] [US5] Unit test for the auto-close due-window predicate (a pending ticket older
than the configured waiting period is due; a pending ticket younger than it is not; a
non-pending ticket is never selected) in
`tests/unit/problem-management/auto-close-sweep.test.ts`
- [ ] T035 [US5] Integration test covering Quickstart Scenario 5 (resolution rejected without a
successful verification; accepted after, ticket reaches `RESOLUTION_PENDING_CUSTOMER`;
customer confirmation via the trust-boundary route reaches `RESOLVED`; a second ticket aged
past the configured window reaches `RESOLVED` via a direct call to the sweep) — "Scenario 5"
case in `tests/integration/problem-resolution-flow.test.ts` (depends on T028)
### Implementation for User Story 5
- [ ] T036 [US5] Add `ResolutionRepository` (`create`, `findByTicketId`) in
`resolutions/repository/` (depends on T008)
- [ ] T037 [US5] Add Zod schema (`outcome`, `resolvedBy`) in `resolutions/schema/`
- [ ] T038 [US5] Add `ResolutionsService.record(ticketId, outcome, resolvedBy)`: resolves the
ticket's `problemId`, resolve-or-`409` on a `Solution` with `verification.result: 'success'`
existing for it (T023/T029's repositories), creates the `Resolution`, and transitions the
ticket to `RESOLUTION_PENDING_CUSTOMER` via `ticketsService.updateStatus` — in
`resolutions/service/resolutions.service.ts` (depends on T023, T029, T036, T037)
- [ ] T039 [US5] Add `ResolutionsService.confirmByCustomer(ticketId)` /
`runAutoCloseSweep()`: the former transitions `RESOLUTION_PENDING_CUSTOMER → RESOLVED`
directly; the latter queries every `RESOLUTION_PENDING_CUSTOMER` ticket whose `updatedAt` is
older than `problemResolutionConfig.autoCloseWaitingHours` and transitions each the same way
— a single, directly-callable, side-effect-only method (research.md — no worker process
needed to invoke it in tests) — in `resolutions/service/resolutions.service.ts` (depends on
T006, T038)
- [ ] T040 [US5] Add `POST /admin/tickets/:ticketId/resolution` (gated by `fastify.authenticate`)
and `POST /v1/support/tickets/:ticketId/confirm-resolution` (gated by
`fastify.authenticateProductIntegration` + `fastify.checkIntegrationRateLimit`, verifying
the token's tenant/user matches the ticket's own — research.md) routes in
`resolutions/controller/` + `routes/`, registered from `src/api/routes.ts` (depends on
T038, T039)
- [ ] T041 [US5] Replace `registerCleanupWorker()`'s stub body in `src/jobs/cleanup/index.ts`:
schedule a repeatable job (every 5 minutes) on `QueueName.CLEANUP` whose processor calls
T039's `runAutoCloseSweep` — and register it from `src/bootstrap/queue.bootstrap.ts`
(depends on T039)
- [ ] T042 [US5] Run Quickstart Scenario 5 locally and confirm all 4 steps pass
**Checkpoint**: Every P1 user story is complete. The full investigation-to-resolution chain
works, gated correctly at every step, with both an explicit and a durable-fallback path to
`RESOLVED`. This is the feature's MVP.
---
## Phase 8: User Story 6 - Reopen (Priority: P2)
**Goal**: A resolved or closed ticket can be reopened by the customer or an agent, re-entering
`IN_PROGRESS` through two real, audited transitions, touching nothing else.
**Independent Test**: Quickstart Scenario 6.
### Tests for User Story 6
- [ ] T043 [US6] Integration test covering Quickstart Scenario 6 (customer reopen reaches
`IN_PROGRESS` via `REOPENED`; the prior `Resolution` and any `SLARun` are unchanged; agent
reopen of a `CLOSED` ticket produces the same result attributed to the agent) — "Scenario 6"
case in `tests/integration/problem-resolution-flow.test.ts` (depends on T035)
### Implementation for User Story 6
- [ ] T044 [US6] Add `TicketsService.reopen(ticketId, actor)` (007/003's existing
`ticketing/tickets` module): resolve-or-`409` if status isn't `RESOLVED`/`CLOSED`, then two
sequential `updateStatus` calls (`REOPENED`, then `IN_PROGRESS`) — in `ticketing/tickets/
service/tickets.service.ts` (depends on T008 — no new schema, reuses 003's own state
machine and repository)
- [ ] T045 [US6] Add `POST /v1/support/tickets/:ticketId/reopen` (customer, trust boundary) and
`POST /admin/tickets/:ticketId/reopen` (agent, `fastify.authenticate`) routes in
`ticketing/tickets/controller/` + `routes/` (depends on T044)
- [ ] T046 [US6] Run Quickstart Scenario 6 locally and confirm all 4 steps pass
**Checkpoint**: All six user stories work independently and together — the full doc 04 workflow,
from first investigation through resolution, confirmation, auto-close, and reopen.
---
## Phase 9: Polish & Cross-Cutting Concerns
- [ ] T047 [P] Update `specs/009-problem-resolution/checklists/requirements.md` Notes with any
implementation-time findings
- [ ] T048 Run `npx tsx scripts/check-architecture.ts` and `npm run lint`/`npm run typecheck`
- [ ] T049 Full regression: `npm run test:unit` (scoped to `tests/unit`) to confirm nothing broke
elsewhere, then the full integration suite (including 003's and 007's own suites, since
T044 modifies `ticketing/tickets`) against real Docker-provisioned Postgres/Redis
---
## Dependencies & Execution Order
### Phase Dependencies
- **Setup (Phase 1)**: No dependencies
- **Foundational (Phase 2)**: Depends on Setup — BLOCKS all user stories
- **User Story 1 (Phase 3)**: Depends on Foundational — no dependency on US2-US6
- **User Story 2 (Phase 4)**: Depends on US1 (the investigation it's gated on)
- **User Story 3 (Phase 5)**: Depends on US2 (the root cause it's gated on)
- **User Story 4 (Phase 6)**: Depends on US3 (the implementation it's gated on)
- **User Story 5 (Phase 7)**: Depends on US4 (the successful verification it's gated on)
- **User Story 6 (Phase 8)**: Depends on US5 (a ticket has to reach `RESOLVED`/`CLOSED` before
reopening it means anything)
- **Polish (Phase 9)**: Depends on all six user stories
This feature's user stories are more strictly sequential than 007's or 008's — doc 04's own
workflow is a straight chain (investigation → root cause → solution → verification →
resolution → reopen), not a set of independently orderable capabilities, so each phase's
dependency here is real, not just priority-driven sequencing.
### Parallel Opportunities
- T001-T006 (independent scaffolding)
- T016 (unit test) alongside T017-T018 (the schema it tests)
- T034 (unit test) alongside T039 (the sweep it tests)
- T047 in Polish
---
## Implementation Strategy
### MVP First (User Stories 1-3, then 5)
1. Setup + Foundational (T001-T008)
2. User Story 1 (T009-T014) → investigations recorded and readable
3. User Story 2 (T015-T021) → root causes correctly gated
4. User Story 3 (T022-T027) → solutions proposed/approved/implemented correctly
5. **User Story 4 is P2** — skippable for a first MVP cut if verification's own gating isn't
needed yet, but User Story 5 (Resolution) depends on it structurally (a successful
verification is Resolution's own precondition), so in practice build order is 1→2→3→4→5
regardless of priority label — same "dependency order isn't always priority order" note 006
and 007's own tasks.md already made.
6. User Story 5 (T034-T042) → resolution, confirmation, and auto-close all work
7. **STOP and VALIDATE**: Quickstart Scenarios 1-5 pass.
### Incremental Delivery
1. Setup + Foundational → schema migrated
2. Add User Story 1 → investigations exist
3. Add User Story 2 → root causes correctly gated
4. Add User Story 3 → solutions move through real states
5. Add User Story 4 → verification gated, failure path reuses existing mechanisms
6. Add User Story 5 → resolution + confirmation + auto-close (P1-complete, MVP)
7. Add User Story 6 → reopen, closing the loop 008 left open
8. Polish → full regression