Files
initiative/specs/017-combat-conditions/plan.md

4.0 KiB

Implementation Plan: Combat Conditions

Branch: 017-combat-conditions | Date: 2026-03-06 | Spec: spec.md Input: Feature specification from /specs/017-combat-conditions/spec.md

Summary

Add a conditions field to the domain Combatant type representing a set of active D&D 5e status conditions (blinded, charmed, etc.). A single toggleCondition domain operation manages the set with immutable state transitions (adds if absent, removes if present). The web layer renders conditions as compact Lucide icon tags with color coding below the combatant name, with a "+" button opening a popover picker for toggling conditions on/off.

Technical Context

Language/Version: TypeScript 5.8 (strict mode, verbatimModuleSyntax) Primary Dependencies: React 19, Vite 6, Tailwind CSS v4, Lucide React (icons) Storage: Browser localStorage (existing adapter, transparent JSON serialization) Testing: Vitest Target Platform: Browser (single-user, local-first) Project Type: Web application (monorepo with domain/application/web layers) Performance Goals: N/A (single-user local app, no performance-critical paths) Constraints: Conditions are visual tracking only; no mechanical effects in MVP Scale/Scope: 15 fixed conditions per the D&D 5e SRD

Constitution Check

GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.

Principle Status Notes
I. Deterministic Domain Core PASS toggleCondition is a pure function; condition registry is static data
II. Layered Architecture PASS Domain defines condition types and operations; Application orchestrates via use cases; Web renders UI
III. Agent Boundary N/A No agent layer involvement
IV. Clarification-First PASS Two clarifications resolved (display order, "+" button visibility)
V. Escalation Gates PASS Spec complete and clarified before planning
VI. MVP Baseline Language PASS FR-001 uses "MVP MUST support" language; homebrew conditions explicitly deferred
VII. No Gameplay Rules PASS Constitution contains no condition mechanics; spec handles that

Project Structure

Documentation (this feature)

specs/017-combat-conditions/
├── 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 (created by /speckit.tasks)

Source Code (repository root)

packages/domain/src/
├── types.ts                    # Add conditions field to Combatant
├── conditions.ts               # NEW: ConditionId type, CONDITION_DEFINITIONS registry, ordering
├── toggle-condition.ts         # NEW: toggleCondition domain operation (adds if absent, removes if present)
├── events.ts                   # Add ConditionAdded, ConditionRemoved events
├── index.ts                    # Re-export new symbols
└── __tests__/
    └── toggle-condition.test.ts  # NEW

packages/application/src/
├── toggle-condition-use-case.ts  # NEW
└── index.ts                      # Re-export new use case

apps/web/src/
├── components/
│   ├── combatant-row.tsx           # Add conditions area below name
│   ├── condition-tags.tsx          # NEW: renders active condition icon tags + "+" button
│   └── condition-picker.tsx        # NEW: popover picker for toggling conditions
├── hooks/
│   └── use-encounter.ts           # Add toggleCondition callback
└── persistence/
    └── encounter-storage.ts       # Add conditions rehydration validation

Structure Decision: Follows existing monorepo structure with domain/application/web layers. New domain files mirror the set-ac.ts pattern. UI components split into condition-tags (display) and condition-picker (interaction) for clarity.

Complexity Tracking

No violations. No entries needed.