Files
initiative/specs/005-set-initiative/tasks.md

180 lines
8.4 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: Set Initiative
**Input**: Design documents from `/specs/005-set-initiative/`
**Prerequisites**: plan.md (required), spec.md (required), research.md, data-model.md, contracts/domain-api.md, quickstart.md
**Tests**: Tests are included as this project follows TDD conventions (test files exist for all domain functions).
**Organization**: Tasks are grouped by user story to enable independent implementation and testing of each story.
## 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, US3)
- Include exact file paths in descriptions
---
## Phase 1: Setup (Shared Infrastructure)
**Purpose**: No new project setup needed — existing monorepo. This phase covers foundational type and event changes shared across all user stories.
- [x] T001 Add optional `initiative` property to `Combatant` interface in `packages/domain/src/types.ts`
- [x] T002 Add `InitiativeSet` event type (with `combatantId`, `previousValue`, `newValue` fields) to `DomainEvent` union in `packages/domain/src/events.ts`
**Checkpoint**: Types compile, existing tests still pass (`pnpm check`)
---
## Phase 2: User Story 1 + User Story 2 — Set Initiative & Automatic Ordering (Priority: P1) MVP
**Goal**: Users can set/change/clear initiative values on combatants, and the encounter automatically reorders combatants from highest to lowest initiative.
**Independent Test**: Set initiative on multiple combatants and verify the combatant list is sorted descending by initiative value.
### Tests for User Stories 1 & 2
> **NOTE: Write these tests FIRST, ensure they FAIL before implementation**
- [x] T003 [US1] Write acceptance tests for setting initiative (set, change, reject non-integer) in `packages/domain/src/__tests__/set-initiative.test.ts`
- [x] T004 [US2] Write acceptance tests for automatic ordering (descending sort, stable sort for ties, reorder on change) in `packages/domain/src/__tests__/set-initiative.test.ts`
- [x] T005 Write invariant tests (determinism, immutability, event shape, roundNumber unchanged) in `packages/domain/src/__tests__/set-initiative.test.ts`
### Implementation for User Stories 1 & 2
- [x] T006 [US1] [US2] Implement `setInitiative(encounter, combatantId, value)` domain function in `packages/domain/src/set-initiative.ts` — validate combatant exists, validate integer, update initiative, stable-sort descending, emit `InitiativeSet` event
- [x] T007 Export `setInitiative` and related types from `packages/domain/src/index.ts`
- [x] T008 Implement `setInitiativeUseCase(store, combatantId, value)` in `packages/application/src/set-initiative-use-case.ts` following existing use case pattern (get → call → check error → save → return events)
- [x] T009 Export `setInitiativeUseCase` from `packages/application/src/index.ts`
**Checkpoint**: Domain tests pass, `pnpm check` passes. Core initiative logic is complete.
---
## Phase 3: User Story 3 — Combatants Without Initiative (Priority: P2)
**Goal**: Combatants without initiative appear after all combatants with initiative, preserving their relative order.
**Independent Test**: Create a mix of combatants with and without initiative and verify ordering (initiative-set first descending, then unset in insertion order).
### Tests for User Story 3
- [x] T010 [US3] Write acceptance tests for unset-initiative ordering (unset after set, multiple unset preserve order, setting initiative moves combatant up) in `packages/domain/src/__tests__/set-initiative.test.ts`
### Implementation for User Story 3
- [x] T011 [US3] Verify that sort logic in `packages/domain/src/set-initiative.ts` already handles `undefined` initiative correctly (combatants without initiative sort after those with initiative, stable sort within each group) — add handling if not already present in T006
**Checkpoint**: All ordering scenarios pass including mixed set/unset combatants.
---
## Phase 4: User Story 4 — Active Turn Preservation During Reorder (Priority: P2)
**Goal**: The active combatant's turn is preserved when initiative changes cause the combatant list to be reordered.
**Independent Test**: Set active combatant, change another combatant's initiative causing reorder, verify active turn still points to the same combatant.
### Tests for User Story 4
- [x] T012 [US4] Write acceptance tests for active turn preservation (reorder doesn't shift active turn, active combatant's own initiative change preserves turn) in `packages/domain/src/__tests__/set-initiative.test.ts`
### Implementation for User Story 4
- [x] T013 [US4] Verify that `activeIndex` identity-tracking in `packages/domain/src/set-initiative.ts` works correctly when reordering occurs — the logic (record active id before sort, find new index after sort) should already exist from T006; add or fix if needed
**Checkpoint**: Active turn is preserved through all reorder scenarios. `pnpm check` passes.
---
## Phase 5: Web Adapter Integration
**Purpose**: Wire initiative into the React UI so users can actually set initiative values.
- [x] T014 Add `setInitiative` callback to `useEncounter` hook in `apps/web/src/hooks/use-encounter.ts` — call `setInitiativeUseCase`, handle errors, append events
- [x] T015 Add initiative input field next to each combatant in `apps/web/src/App.tsx` — numeric input, display current value, clear button, call `setInitiative` on change
**Checkpoint**: Full feature works end-to-end in the browser. `pnpm check` passes.
---
## Phase 6: Polish & Cross-Cutting Concerns
**Purpose**: Edge case coverage and final validation.
- [x] T016 Write edge case tests (zero initiative, negative initiative, clearing initiative, all same value) in `packages/domain/src/__tests__/set-initiative.test.ts`
- [x] T017 Run `pnpm check` (format + lint + typecheck + test) and fix any issues
- [x] T018 Verify layer boundary compliance (domain imports no framework/adapter code)
---
## Dependencies & Execution Order
### Phase Dependencies
- **Phase 1 (Setup)**: No dependencies — types and events first
- **Phase 2 (US1+US2 MVP)**: Depends on Phase 1
- **Phase 3 (US3)**: Depends on Phase 2 (extends sort logic)
- **Phase 4 (US4)**: Depends on Phase 2 (extends activeIndex logic)
- **Phase 5 (Web Adapter)**: Depends on Phases 24 (needs complete domain + application layer)
- **Phase 6 (Polish)**: Depends on all previous phases
### User Story Dependencies
- **US1 + US2 (P1)**: Combined because sorting is inherent to setting initiative — they share the same domain function
- **US3 (P2)**: Extends the sort logic from US1+US2 to handle `undefined`. Can be developed immediately after Phase 2.
- **US4 (P2)**: Extends the `activeIndex` logic from US1+US2. Can be developed in parallel with US3.
### Parallel Opportunities
- **T001 and T002** can run in parallel (different files)
- **T003, T004, T005** can run in parallel (same file but different test groups — practically written together)
- **US3 (Phase 3) and US4 (Phase 4)** can run in parallel after Phase 2
- **T014 and T015** can run in parallel (different files)
---
## Parallel Example: Phase 2 (MVP)
```bash
# Tests first (all in same file, written together):
T003: Acceptance tests for setting initiative
T004: Acceptance tests for automatic ordering
T005: Invariant tests
# Then implementation:
T006: Domain function (core logic)
T007: Domain exports
T008: Application use case (after T006-T007)
T009: Application exports
```
---
## Implementation Strategy
### MVP First (User Stories 1 + 2)
1. Complete Phase 1: Type + event changes
2. Complete Phase 2: Domain function + use case with tests
3. **STOP and VALIDATE**: `pnpm check` passes, initiative setting and ordering works
4. Optionally wire up UI (Phase 5) for a minimal demo
### Incremental Delivery
1. Phase 1 → Types ready
2. Phase 2 → MVP: set initiative + auto-ordering works
3. Phase 3 → Unset combatants handled correctly
4. Phase 4 → Active turn preserved through reorders
5. Phase 5 → UI wired up, feature usable in browser
6. Phase 6 → Edge cases covered, quality verified
---
## Notes
- US1 and US2 are combined in Phase 2 because the domain function `setInitiative` inherently performs both setting and sorting — they cannot be meaningfully separated
- US3 and US4 are separable extensions of the sort and activeIndex logic respectively
- All domain tests follow existing patterns: helper functions for test data, acceptance scenarios mapped from spec, invariant tests for determinism/immutability
- Commit after each phase checkpoint