3.0 KiB
Implementation Plan: Edit Combatant
Branch: 004-edit-combatant | Date: 2026-03-03 | Spec: spec.md
Input: Feature specification from /specs/004-edit-combatant/spec.md
Summary
Add the ability to rename a combatant by id within an encounter. A pure domain function editCombatant validates the id and new name, returns the updated encounter with a CombatantUpdated event, or a DomainError. Wired through an application use case and exposed via the existing useEncounter hook to a minimal UI control.
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: Browser (localhost:5173) Project Type: Web application (monorepo: domain → application → web) Performance Goals: N/A — single-user local state, instant updates Constraints: Pure domain logic, no I/O in domain layer Scale/Scope: Single-user encounter tracker
Constitution Check
GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.
| Principle | Status | Notes |
|---|---|---|
| I. Deterministic Domain Core | PASS | editCombatant is a pure function: same encounter + id + name → same result |
| II. Layered Architecture | PASS | Domain function → use case → hook/UI. No layer violations. |
| III. Agent Boundary | N/A | No agent layer involvement |
| IV. Clarification-First | PASS | Spec is complete, no ambiguities remain |
| V. Escalation Gates | PASS | All work is within spec scope |
| VI. MVP Baseline Language | PASS | Spec uses "MVP baseline does not include" for out-of-scope items |
| VII. No Gameplay Rules | PASS | Constitution contains no gameplay logic |
Project Structure
Documentation (this feature)
specs/004-edit-combatant/
├── plan.md
├── research.md
├── data-model.md
├── quickstart.md
├── contracts/
└── tasks.md
Source Code (repository root)
packages/domain/src/
├── edit-combatant.ts # New: pure editCombatant function
├── events.ts # Modified: add CombatantUpdated event
├── types.ts # Unchanged (Combatant, Encounter, DomainError)
├── index.ts # Modified: re-export editCombatant
└── __tests__/
└── edit-combatant.test.ts # New: acceptance + invariant tests
packages/application/src/
├── edit-combatant-use-case.ts # New: use case wiring
└── index.ts # Modified: re-export use case
apps/web/src/
├── hooks/use-encounter.ts # Modified: add editCombatant action
└── App.tsx # Modified: add rename UI control
Structure Decision: Follows the existing monorepo layout (packages/domain → packages/application → apps/web). Each new file mirrors the pattern established by add-combatant and remove-combatant.