Implement the 003-remove-combatant feature that adds the possibility to remove a combatant from an encounter
This commit is contained in:
117
specs/003-remove-combatant/tasks.md
Normal file
117
specs/003-remove-combatant/tasks.md
Normal file
@@ -0,0 +1,117 @@
|
||||
# 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 (T001–T002)
|
||||
2. Complete Phase 2: Domain tests + function (T003–T005)
|
||||
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
|
||||
Reference in New Issue
Block a user