Files
initiative/specs/025-display-initiative/plan.md

69 lines
3.6 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.
# Implementation Plan: Display Initiative
**Branch**: `025-display-initiative` | **Date**: 2026-03-10 | **Spec**: [spec.md](./spec.md)
**Input**: Feature specification from `/specs/025-display-initiative/spec.md`
## Summary
Add initiative modifier and passive initiative display to the creature stat block panel. A pure domain function calculates initiative as DEX modifier + (proficiency multiplier × proficiency bonus) from bestiary data. The bestiary adapter parses the `initiative.proficiency` field from 5etools JSON. The stat block component displays the result as "Initiative +X (Y)" in the header area next to AC, matching the Monster Manual 2024 format.
## Technical Context
**Language/Version**: TypeScript 5.8 (strict mode, verbatimModuleSyntax)
**Primary Dependencies**: React 19, Vite 6, Tailwind CSS v4, Lucide React (icons)
**Storage**: N/A (no storage changes — purely derived from existing bestiary data)
**Testing**: Vitest
**Target Platform**: Browser (single-page web app)
**Project Type**: Web application (monorepo: domain → application → web adapter)
**Performance Goals**: N/A (simple arithmetic calculation, no performance concerns)
**Constraints**: Domain layer must remain pure — no I/O or framework imports
**Scale/Scope**: ~500 creatures in bestiary dataset
## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
| Principle | Status | Notes |
|-----------|--------|-------|
| I. Deterministic Domain Core | PASS | Initiative calculation is a pure function: `(dex, cr, profMultiplier) → modifier`. No I/O, randomness, or clocks. |
| II. Layered Architecture | PASS | Domain: pure `calculateInitiative` function. Adapter: parse `initiative.proficiency` from raw JSON into `Creature` type. Web: display in `StatBlock` component. No layer violations. |
| III. Agent Boundary | N/A | No agent layer involvement. |
| IV. Clarification-First | PASS | Feature is fully specified — formula, display format, and positioning are all explicit. |
| V. Escalation Gates | PASS | Display-only scope is clearly bounded. FR-007 explicitly excludes initiative rolling. |
| VI. MVP Baseline Language | PASS | Spec uses "MVP baseline does not include automatic initiative rolling or encounter order integration." |
| VII. No Gameplay Rules | PASS | Initiative calculation formula is in the feature spec, not the constitution. |
**Gate result: PASS** — no violations.
## Project Structure
### Documentation (this feature)
```text
specs/025-display-initiative/
├── plan.md # This file
├── research.md # Phase 0 output
├── data-model.md # Phase 1 output
├── quickstart.md # Phase 1 output
└── tasks.md # Phase 2 output (/speckit.tasks command)
```
### Source Code (repository root)
```text
packages/domain/src/
├── creature-types.ts # MODIFY: add initiativeProficiency field to Creature
├── initiative.ts # NEW: pure calculateInitiative function
├── index.ts # MODIFY: export new function and types
└── __tests__/
└── initiative.test.ts # NEW: tests for initiative calculation
apps/web/src/
├── adapters/
│ └── bestiary-adapter.ts # MODIFY: parse initiative.proficiency from raw JSON
└── components/
└── stat-block.tsx # MODIFY: display initiative in header area
```
**Structure Decision**: Follows existing monorepo layout. New domain function in its own file (`initiative.ts`) matching the pattern of other domain functions (e.g., `hp-status.ts`). No new packages or layers needed.