# 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