# Implementation Plan: Set Initiative **Branch**: `005-set-initiative` | **Date**: 2026-03-04 | **Spec**: [spec.md](./spec.md) **Input**: Feature specification from `/specs/005-set-initiative/spec.md` ## Summary Add an optional integer initiative property to combatants and a `setInitiative` domain function that sets/changes/clears the value and automatically reorders combatants descending by initiative (unset last, stable sort for ties). The active combatant's turn is preserved through reorders by tracking identity rather than position. ## Technical Context **Language/Version**: TypeScript 5.x (strict mode, verbatimModuleSyntax) **Primary Dependencies**: React 19, Vite **Storage**: In-memory React state (local-first, single-user MVP) **Testing**: Vitest **Target Platform**: Web browser (localhost:5173 dev) **Project Type**: Web application (monorepo: domain → application → web adapter) **Performance Goals**: N/A (local in-memory, trivial data sizes) **Constraints**: Pure domain functions, no I/O in domain layer **Scale/Scope**: Single-user, single encounter ## Constitution Check *GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.* | Principle | Status | Notes | |-----------|--------|-------| | I. Deterministic Domain Core | PASS | `setInitiative` is a pure function: same encounter + id + value → same result. No I/O, randomness, or clocks. | | II. Layered Architecture | PASS | Domain function in `packages/domain`, use case in `packages/application`, UI in `apps/web`. Dependency direction preserved. | | III. Agent Boundary | N/A | No agent layer involvement in this feature. | | IV. Clarification-First | PASS | Spec has no NEEDS CLARIFICATION markers. All design decisions are spec-driven. | | V. Escalation Gates | PASS | Feature scope matches spec exactly. No out-of-scope additions. | | VI. MVP Baseline Language | PASS | Spec uses "MVP baseline does not include" for secondary tiebreakers. | | VII. No Gameplay Rules | PASS | Constitution contains no gameplay mechanics; initiative logic is in the spec. | All gates pass. No violations to justify. **Post-Design Re-check**: All gates still pass. The `setInitiative` domain function is pure, layering is preserved, and no out-of-scope additions were introduced during design. ## Project Structure ### Documentation (this feature) ```text specs/005-set-initiative/ ├── spec.md ├── plan.md # This file ├── research.md # Phase 0 output ├── data-model.md # Phase 1 output ├── quickstart.md # Phase 1 output ├── contracts/ # Phase 1 output │ └── domain-api.md ├── checklists/ │ └── requirements.md └── tasks.md # Phase 2 output (via /speckit.tasks) ``` ### Source Code (repository root) ```text packages/domain/src/ ├── types.ts # Modified: add initiative to Combatant ├── events.ts # Modified: add InitiativeSet event ├── set-initiative.ts # New: setInitiative domain function ├── index.ts # Modified: export setInitiative └── __tests__/ └── set-initiative.test.ts # New: tests for setInitiative packages/application/src/ ├── set-initiative-use-case.ts # New: setInitiativeUseCase └── index.ts # Modified: export use case apps/web/src/ ├── hooks/ │ └── use-encounter.ts # Modified: add setInitiative callback └── App.tsx # Modified: add initiative input field ``` **Structure Decision**: Follows existing monorepo layered structure. Each new domain operation gets its own file per established convention. ## Complexity Tracking No constitution violations. Table not needed.