Files
initiative/specs/001-advance-turn/tasks.md

129 lines
6.7 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: Advance Turn
**Input**: Design documents from `/specs/001-advance-turn/`
**Prerequisites**: plan.md (required), spec.md (required)
**Organization**: Tasks follow the phased structure from plan.md. There is only one user story (US1 — Advance Turn, P1), so phases map directly to the plan's milestones.
## Format: `[ID] [P?] [Story?] Description`
- **[P]**: Can run in parallel (different files, no dependencies)
- **[US1]**: User Story 1 — Advance Turn
- Exact file paths included in every task
---
## Phase 1: Setup (Milestone 1 — Tooling)
**Purpose**: Initialize pnpm monorepo, Biome, TypeScript, Vitest, and layer boundary enforcement
- [X] T001 Initialize pnpm workspace and root config — create `pnpm-workspace.yaml`, `.nvmrc` (Node 22), root `package.json` (with `packageManager` pinning pnpm 10.6 and scripts: check, test, lint, format, typecheck), `biome.json`, and `tsconfig.base.json` (strict, composite, path aliases)
- [X] T002 [P] Create `packages/domain` package skeleton — `packages/domain/package.json` (`@initiative/domain`, no deps), `packages/domain/tsconfig.json` (extends base, composite), empty `packages/domain/src/index.ts`
- [X] T003 [P] Create `packages/application` package skeleton — `packages/application/package.json` (`@initiative/application`, depends on `@initiative/domain`), `packages/application/tsconfig.json` (extends base, references domain), empty `packages/application/src/index.ts`
- [X] T004 [P] Create `apps/web` package skeleton — `apps/web/package.json` (React 19, Vite 6.2, depends on both packages), `apps/web/tsconfig.json`, `apps/web/vite.config.ts`, `apps/web/index.html`, `apps/web/src/main.tsx`, `apps/web/src/App.tsx` (placeholder)
- [X] T005 Configure Vitest — add `vitest` as root dev dependency, create `vitest.config.ts` at root (workspace mode or per-package), verify `pnpm test` exits 0
- [X] T006 Create layer boundary check — `scripts/check-layer-boundaries.mjs` (scans domain/application for forbidden imports) and `packages/domain/src/__tests__/layer-boundaries.test.ts` (wraps script as Vitest test)
**Checkpoint**: `pnpm install` succeeds, `biome check .` runs, `tsc --build` compiles, `pnpm test` exits 0 with layer boundary test green.
---
## Phase 2: Domain Implementation — User Story 1: Advance Turn (Priority: P1) (Milestone 1)
**Goal**: Implement the complete AdvanceTurn domain logic as a pure function with all 8 acceptance scenarios and invariant tests.
**Independent Test**: Pure state transition — given an Encounter value and AdvanceTurn action, assert resulting Encounter and emitted domain events. No I/O, persistence, or UI needed.
- [ ] T007 [US1] Define domain types in `packages/domain/src/types.ts``CombatantId` (branded/opaque), `Combatant`, `Encounter` (combatants, activeIndex, roundNumber), factory `createEncounter` enforcing INV-1, INV-2, INV-3
- [ ] T008 [P] [US1] Define domain events in `packages/domain/src/events.ts``TurnAdvanced`, `RoundAdvanced`, `DomainEvent` union (plain data, no classes)
- [ ] T009 [US1] Implement `advanceTurn` in `packages/domain/src/advance-turn.ts` — pure function `(Encounter) => { encounter, events } | DomainError`, implements FR-001 through FR-005
- [ ] T010 [US1] Write tests for all 8 acceptance scenarios + invariants in `packages/domain/src/__tests__/advance-turn.test.ts` — scenarios 18, INV-1 through INV-5, event ordering on round wrap
- [ ] T011 [US1] Export public API from `packages/domain/src/index.ts` — re-export types, events, `advanceTurn`, `createEncounter`
**Checkpoint (Milestone 1)**: `pnpm check` passes (format + lint + typecheck + test + layer boundaries). All 8 scenarios + invariants green. No React/Vite imports in domain or application.
---
## Phase 3: Application + Web Shell (Milestone 2)
**Goal**: Wire up the application use case and minimal React UI with a "Next Turn" button.
- [ ] T012 Define port interface in `packages/application/src/ports.ts``EncounterStore` port: `get(): Encounter`, `save(e: Encounter)`
- [ ] T013 Implement `AdvanceTurnUseCase` in `packages/application/src/advance-turn-use-case.ts` — accepts `EncounterStore`, calls `advanceTurn`, saves result, returns events
- [ ] T014 Export public API from `packages/application/src/index.ts` — re-export use case and port types
- [ ] T015 Implement `useEncounter` hook in `apps/web/src/hooks/use-encounter.ts` — in-memory `EncounterStore` via React state, exposes encounter state + `advanceTurn` action, hardcoded 3-combatant demo
- [ ] T016 Wire up `apps/web/src/App.tsx` — display current combatant, round number, combatant list with active indicator, "Next Turn" button, emitted events
**Checkpoint (Milestone 2)**: `pnpm check` passes. `vite build` succeeds. Clicking "Next Turn" cycles combatants and increments rounds correctly.
---
## Dependencies & Execution Order
### Phase Dependencies
- **Phase 1 (Setup)**: No dependencies — start immediately
- **Phase 2 (Domain)**: Depends on Phase 1 completion
- **Phase 3 (App + Web)**: Depends on Phase 2 completion (needs domain types and `advanceTurn`)
### Within Phase 1
- T001 must complete first (workspace and root config)
- T002, T003, T004 can run in parallel [P] after T001
- T005 depends on T001 (needs root package.json)
- T006 depends on T002 and T005 (needs domain package + Vitest)
### Within Phase 2
- T007 must complete first (types needed by everything)
- T008 can run in parallel [P] with T007 (events are independent types)
- T009 depends on T007 and T008 (uses types and events)
- T010 depends on T009 (tests the implementation)
- T011 depends on T007, T008, T009 (exports all public API)
### Within Phase 3
- T012 first (port interface)
- T013 depends on T012 (uses port)
- T014 depends on T013 (exports use case)
- T015 depends on T014 (uses application layer)
- T016 depends on T015 (uses hook)
---
## Parallel Opportunities
```text
# After T001 completes:
T002, T003, T004 — all package skeletons in parallel
# After T007 starts:
T008 — domain events can be written in parallel with types
# Independent stories: only one user story (US1), so parallelism is within-phase only
```
---
## Implementation Strategy
### MVP First (Milestone 1)
1. Complete Phase 1: Setup (T001T006)
2. Complete Phase 2: Domain (T007T011)
3. **STOP and VALIDATE**: `pnpm check` passes, all 8 scenarios green
### Full Feature (Milestone 2)
4. Complete Phase 3: App + Web Shell (T012T016)
5. **VALIDATE**: `pnpm check` passes, app runs in browser
---
## Notes
- All task IDs (T001T016) match plan.md — no scope expansion
- Single user story (US1: Advance Turn) — no cross-story dependencies
- Tests (T010) are included as specified in plan.md and spec.md
- Domain package must have zero React/Vite imports (enforced by T006)