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:
co-authored by
Claude Sonnet 5
parent
9ce34d8ca4
commit
aaa51ef475
@@ -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
|
||||
Reference in New Issue
Block a user