3.6 KiB
Implementation Plan: Combatant Concentration
Branch: 018-combatant-concentration | Date: 2026-03-06 | Spec: spec.md
Input: Feature specification from /specs/018-combatant-concentration/spec.md
Summary
Add concentration as a separate per-combatant boolean state (not a condition). A Brain icon toggle appears on hover (or stays visible when active), a colored left border accent marks concentrating combatants, and a pulse animation fires when a concentrating combatant takes damage. Implementation follows the existing toggle-condition pattern across all three layers (domain, application, web adapter).
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: Modern browsers (local-first, single-user) Project Type: Web application (monorepo: domain / application / web) Performance Goals: Instant UI response on toggle; pulse animation ~600-800ms Constraints: No migration needed for localStorage; new optional boolean field is backward-compatible Scale/Scope: Single-user encounter tracker; ~10-20 combatants per encounter
Constitution Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
| Principle | Status | Notes |
|---|---|---|
| I. Deterministic Domain Core | PASS | toggleConcentration is a pure function: same input encounter + combatant ID yields same output. No I/O, randomness, or clocks. |
| II. Layered Architecture | PASS | Domain defines the toggle function; Application orchestrates via EncounterStore port; Web adapter implements UI + persistence. No layer violations. |
| III. Agent Boundary | N/A | No agent/AI features in this feature. |
| IV. Clarification-First | PASS | Spec is fully specified; no NEEDS CLARIFICATION markers. |
| V. Escalation Gates | PASS | All work is within spec scope. |
| VI. MVP Baseline Language | PASS | No permanent bans introduced. |
| VII. No Gameplay Rules | PASS | Concentration is state tracking only; no automatic save mechanics or rule enforcement. |
All gates pass. No violations to track.
Project Structure
Documentation (this feature)
specs/018-combatant-concentration/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
└── tasks.md
Source Code (repository root)
packages/domain/src/
├── types.ts # Add isConcentrating to Combatant
├── events.ts # Add ConcentrationStarted/ConcentrationEnded
├── toggle-concentration.ts # New pure domain function
├── index.ts # Re-export new function + events
└── __tests__/
└── toggle-concentration.test.ts # New test file
packages/application/src/
├── toggle-concentration-use-case.ts # New use case
└── index.ts # Re-export
apps/web/src/
├── hooks/use-encounter.ts # Add toggleConcentration callback
├── components/combatant-row.tsx # Add Brain icon toggle + left border accent + pulse
├── persistence/encounter-storage.ts # Add isConcentrating to rehydration
└── App.tsx # Wire toggleConcentration prop
Structure Decision: Follows existing monorepo layout with domain/application/web layers. Each new file mirrors the established pattern (e.g., toggle-concentration.ts mirrors toggle-condition.ts).