Implement the 016-combatant-ac feature that adds an optional Armor Class field to combatants with shield icon display and inline editing in the encounter tracker
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
81
specs/016-combatant-ac/plan.md
Normal file
81
specs/016-combatant-ac/plan.md
Normal file
@@ -0,0 +1,81 @@
|
||||
# Implementation Plan: Combatant Armor Class Display
|
||||
|
||||
**Branch**: `016-combatant-ac` | **Date**: 2026-03-06 | **Spec**: [spec.md](./spec.md)
|
||||
**Input**: Feature specification from `/specs/016-combatant-ac/spec.md`
|
||||
|
||||
## Summary
|
||||
|
||||
Add an optional Armor Class (AC) field to the Combatant domain type and display it in the encounter list as a shield icon with the numeric value next to each combatant's name. The feature follows the exact same patterns as existing optional fields (initiative, maxHp) through all layers: domain pure function, application use case, React UI component, and localStorage persistence.
|
||||
|
||||
## Technical Context
|
||||
|
||||
**Language/Version**: TypeScript 5.8 (strict mode, verbatimModuleSyntax)
|
||||
**Primary Dependencies**: React 19, Vite 6, Tailwind CSS v4, shadcn/ui-style components, Lucide React (icons)
|
||||
**Storage**: Browser localStorage (existing adapter, transparent JSON serialization)
|
||||
**Testing**: Vitest (pure domain function tests + storage round-trip tests)
|
||||
**Target Platform**: Browser (local-first, single-user)
|
||||
**Project Type**: Web application (monorepo: packages/domain, packages/application, apps/web)
|
||||
**Performance Goals**: N/A (trivial data addition, no performance concerns)
|
||||
**Constraints**: Offline-capable (localStorage only), no external dependencies added
|
||||
**Scale/Scope**: Single optional field addition across 3 layers
|
||||
|
||||
## Constitution Check
|
||||
|
||||
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*
|
||||
|
||||
| Principle | Status | Evidence |
|
||||
|-----------|--------|----------|
|
||||
| I. Deterministic Domain Core | PASS | `setAc` is a pure function: same input encounter + combatantId + ac value always produces the same output. No I/O, randomness, or clocks. |
|
||||
| II. Layered Architecture | PASS | Domain defines `setAc` (pure). Application defines `setAcUseCase` (orchestration via EncounterStore port). Web implements UI + persistence adapter. No reverse dependencies. |
|
||||
| III. Agent Boundary | N/A | No agent layer involvement. |
|
||||
| IV. Clarification-First | PASS | No non-trivial assumptions — feature follows established patterns for optional combatant fields. |
|
||||
| V. Escalation Gates | PASS | All functionality is within spec scope (FR-001 through FR-007). |
|
||||
| VI. MVP Baseline Language | PASS | Spec uses "MVP baseline does not include AC-based calculations." |
|
||||
| VII. No Gameplay Rules | PASS | AC is stored and displayed only — no combat resolution logic. |
|
||||
|
||||
**Gate result**: PASS — no violations.
|
||||
|
||||
## Project Structure
|
||||
|
||||
### Documentation (this feature)
|
||||
|
||||
```text
|
||||
specs/016-combatant-ac/
|
||||
├── plan.md
|
||||
├── research.md
|
||||
├── data-model.md
|
||||
├── quickstart.md
|
||||
└── tasks.md # Phase 2 output (/speckit.tasks)
|
||||
```
|
||||
|
||||
### Source Code (repository root)
|
||||
|
||||
```text
|
||||
packages/domain/src/
|
||||
├── types.ts # Add optional `ac` field to Combatant interface
|
||||
├── set-ac.ts # NEW: pure function to set/clear AC
|
||||
├── events.ts # Add AcSet event type
|
||||
├── index.ts # Re-export new function + event type
|
||||
└── __tests__/
|
||||
└── set-ac.test.ts # NEW: domain tests for setAc
|
||||
|
||||
packages/application/src/
|
||||
├── set-ac-use-case.ts # NEW: orchestration use case
|
||||
└── index.ts # Re-export new use case
|
||||
|
||||
apps/web/src/
|
||||
├── components/
|
||||
│ └── combatant-row.tsx # Add AC display (shield icon + value) + onSetAc callback
|
||||
├── hooks/
|
||||
│ └── use-encounter.ts # Add setAc action callback
|
||||
└── persistence/
|
||||
└── encounter-storage.ts # Add AC validation in loadEncounter rehydration
|
||||
└── __tests__/
|
||||
└── encounter-storage.test.ts # Add AC round-trip tests
|
||||
```
|
||||
|
||||
**Structure Decision**: Follows the existing monorepo layered architecture (domain → application → web). No new packages or structural changes needed.
|
||||
|
||||
## Complexity Tracking
|
||||
|
||||
> No violations — table not applicable.
|
||||
Reference in New Issue
Block a user