Files
initiative/specs/003-remove-combatant/tasks.md

118 lines
4.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Tasks: Remove Combatant
**Input**: Design documents from `/specs/003-remove-combatant/`
**Prerequisites**: plan.md, spec.md, research.md, data-model.md
**Tests**: Included — spec requires all six acceptance scenarios as automated tests (SC-002).
**Organization**: Tasks grouped by user story for independent implementation and testing.
## Format: `[ID] [P?] [Story] Description`
- **[P]**: Can run in parallel (different files, no dependencies)
- **[Story]**: Which user story this task belongs to (e.g., US1, US2)
- Exact file paths included in descriptions
## Phase 1: Foundational (Event Type)
**Purpose**: Add the CombatantRemoved event type that all subsequent tasks depend on.
- [x] T001 Add `CombatantRemoved` interface and extend `DomainEvent` union in `packages/domain/src/events.ts`
- [x] T002 Export `CombatantRemoved` type from `packages/domain/src/index.ts`
**Checkpoint**: CombatantRemoved event type available for domain function and UI event display.
---
## Phase 2: User Story 1 - Remove Combatant Domain Logic (Priority: P1) MVP
**Goal**: Pure `removeCombatant` domain function that removes a combatant by ID, adjusts activeIndex correctly, preserves roundNumber, and emits CombatantRemoved.
**Independent Test**: Call `removeCombatant` with various encounter states and verify combatant list, activeIndex, roundNumber, events, and error cases.
### Tests for User Story 1
> **NOTE: Write these tests FIRST, ensure they FAIL before implementation**
- [x] T003 [US1] Write acceptance tests for `removeCombatant` in `packages/domain/src/__tests__/remove-combatant.test.ts` covering all 6 spec scenarios: remove after active (AS-1), remove before active (AS-2), remove active combatant mid-list (AS-3), remove active combatant at end/wrap (AS-4), remove only combatant (AS-5), ID not found error (AS-6). Also test: event shape (CombatantRemoved with id+name), roundNumber invariance, and determinism.
### Implementation for User Story 1
- [x] T004 [US1] Implement `removeCombatant` pure function and `RemoveCombatantSuccess` type in `packages/domain/src/remove-combatant.ts` — find combatant by ID, compute new activeIndex per data-model rules, filter combatant list, emit CombatantRemoved event, return DomainError for not-found
- [x] T005 [US1] Export `removeCombatant` and `RemoveCombatantSuccess` from `packages/domain/src/index.ts`
**Checkpoint**: All 6 acceptance tests pass. Domain function is complete and independently testable.
---
## Phase 3: User Story 2 - Application + UI Wiring (Priority: P2)
**Goal**: Wire removeCombatant through application use case and expose via minimal UI with a remove button per combatant.
**Independent Test**: Render encounter UI, click remove on a combatant, verify it disappears from the list and event log updates.
### Implementation for User Story 2
- [x] T006 [P] [US2] Create `removeCombatantUseCase` in `packages/application/src/remove-combatant-use-case.ts` — follows existing pattern: `store.get()``removeCombatant()``store.save()` → return events or DomainError
- [x] T007 [US2] Export `removeCombatantUseCase` from `packages/application/src/index.ts`
- [x] T008 [US2] Add `removeCombatant(id: CombatantId)` callback to `useEncounter` hook in `apps/web/src/hooks/use-encounter.ts` — call use case, append events to log on success
- [x] T009 [US2] Add remove button per combatant and `CombatantRemoved` event display case in `apps/web/src/App.tsx`
**Checkpoint**: Full vertical slice works — GM can remove combatants from UI, initiative order updates correctly, event log shows removal.
---
## Phase 4: Polish & Cross-Cutting Concerns
- [x] T010 Run `pnpm check` (format + lint + typecheck + test) and fix any issues
---
## Dependencies & Execution Order
### Phase Dependencies
- **Phase 1 (Foundational)**: No dependencies — start immediately
- **Phase 2 (US1 Domain)**: Depends on Phase 1 (needs CombatantRemoved type)
- **Phase 3 (US2 App+UI)**: Depends on Phase 2 (needs domain function)
- **Phase 4 (Polish)**: Depends on Phase 3
### Within Each Phase
- T001 → T002 (export after defining)
- T003 (tests first) → T004 (implement) → T005 (export)
- T006 → T007 (export after creating use case file)
- T008 depends on T006+T007 (needs use case)
- T009 depends on T008 (needs hook callback)
### Parallel Opportunities
- Within T003, individual test cases are independent
---
## Implementation Strategy
### MVP First (User Story 1 Only)
1. Complete Phase 1: Event type (T001T002)
2. Complete Phase 2: Domain tests + function (T003T005)
3. **STOP and VALIDATE**: All 6 acceptance tests pass
4. Domain is complete and usable without UI
### Full Feature
1. Phase 1 → Phase 2 → Phase 3 → Phase 4
2. Each phase adds a testable increment
3. Commit after each phase checkpoint
---
## Notes
- [P] tasks = different files, no dependencies
- [Story] label maps task to specific user story
- Tests written first (TDD) per spec requirement SC-002
- Commit after each phase checkpoint
- Total: 10 tasks across 4 phases