84 lines
3.7 KiB
Markdown
84 lines
3.7 KiB
Markdown
# 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.
|