3.7 KiB
Implementation Plan: Set Initiative
Branch: 005-set-initiative | Date: 2026-03-04 | Spec: 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)
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)
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.