180 lines
8.4 KiB
Markdown
180 lines
8.4 KiB
Markdown
# 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 2–4 (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
|