# Implementation Plan: Combatant Concentration **Branch**: `018-combatant-concentration` | **Date**: 2026-03-06 | **Spec**: [spec.md](./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) ```text specs/018-combatant-concentration/ ├── plan.md ├── research.md ├── data-model.md ├── quickstart.md └── tasks.md ``` ### Source Code (repository root) ```text 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`).