Clean up project documentation and constitution for post-MVP maturity

- CLAUDE.md: replace 32-line per-feature tech changelog with consolidated
  tech stack, add project structure and data/storage sections, remove stale
  Recent Changes
- README.md: rewrite for current feature set, fix bestiary description
  (import-based, not bundled), remove placeholder license section
- Constitution v2.2.0: remove unused Agent Boundary principle (MAJOR),
  add README and CLAUDE.md sync rules to Development Workflow (MINOR)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Lukas
2026-03-10 23:48:50 +01:00
parent 94d125d9c4
commit 47da942b73
3 changed files with 93 additions and 80 deletions

View File

@@ -1,14 +1,17 @@
<!-- <!--
Sync Impact Report Sync Impact Report
─────────────────── ───────────────────
Version change: 1.0.21.0.3 (PATCH — add merge-gate rule) Version change: 1.0.32.2.0 (MAJOR+MINOR — remove Agent Boundary, add README/CLAUDE.md sync rules)
Modified sections: Modified sections:
- Development Workflow: added automated-checks merge gate - Core Principles: removed III (Agent Boundary), renumbered IV→III, V→IV, VI→V, VII→VI
- Layered Architecture: removed Agent layer (4→3 layers)
- Clarification-First: reworded "the agent" → "Claude Code"
- Development Workflow: removed agent-assisted reference
Templates requiring updates: Templates requiring updates:
- .specify/templates/plan-template.md ✅ no update needed - .specify/templates/plan-template.md ⚠️ update Constitution Check if it references Agent Boundary
- .specify/templates/spec-template.md ✅ no update needed - .specify/templates/spec-template.md ⚠️ update Constitution Check if it references Agent Boundary
- .specify/templates/tasks-template.md ✅ no update needed - .specify/templates/tasks-template.md ✅ no update needed
Follow-up TODOs: none Follow-up TODOs: review templates for stale Agent Boundary references
--> -->
# Encounter Console Constitution # Encounter Console Constitution
@@ -29,7 +32,7 @@ be injected at the boundary, never sourced inside the domain layer.
### II. Layered Architecture ### II. Layered Architecture
The codebase MUST be organized into four layers with strict The codebase MUST be organized into three layers with strict
dependency direction: dependency direction:
1. **Domain** — pure types, state transitions, validation rules. 1. **Domain** — pure types, state transitions, validation rules.
@@ -39,34 +42,21 @@ dependency direction:
interfaces that Adapters implement. May import Domain only. interfaces that Adapters implement. May import Domain only.
3. **Adapters** — I/O, persistence, UI rendering, external APIs. 3. **Adapters** — I/O, persistence, UI rendering, external APIs.
May import Application and Domain. May import Application and Domain.
4. **Agent** — AI-assisted features (suggestions, analysis).
May import Application and Domain as read-only consumers.
A module in an inner layer MUST NOT import from an outer layer. A module in an inner layer MUST NOT import from an outer layer.
### III. Agent Boundary ### III. Clarification-First
The agent layer MAY read domain events and current state. The agent
MAY produce suggestions, annotations, or recommendations. The agent
MUST NOT mutate domain state directly. All agent-originated changes
MUST flow through the Application layer as explicit user-confirmed
commands.
- Agent output MUST be clearly labeled as suggestions.
- No silent or automatic application of agent recommendations.
### IV. Clarification-First
Before making any non-trivial assumption during specification, Before making any non-trivial assumption during specification,
planning, or implementation, the agent MUST surface a clarification planning, or implementation, Claude Code MUST surface a clarification
question to the user. "Non-trivial" means any decision that would question to the user. "Non-trivial" means any decision that would
alter observable behavior, data model shape, or public API surface. alter observable behavior, data model shape, or public API surface.
The agent MUST also ask when multiple valid interpretations exist, Claude Code MUST also ask when multiple valid interpretations exist,
when a choice would affect architectural layering, or when scope when a choice would affect architectural layering, or when scope
would expand beyond the current spec. The agent MUST NOT silently would expand beyond the current spec. Claude Code MUST NOT silently
choose among valid alternatives. choose among valid alternatives.
### V. Escalation Gates ### IV. Escalation Gates
Any feature, requirement, or scope change not present in the current Any feature, requirement, or scope change not present in the current
spec MUST be rejected at implementation time until the spec is spec MUST be rejected at implementation time until the spec is
@@ -77,7 +67,7 @@ explicitly updated. The workflow is:
3. Update the spec via `/speckit.specify` or `/speckit.clarify`. 3. Update the spec via `/speckit.specify` or `/speckit.clarify`.
4. Only then proceed with implementation. 4. Only then proceed with implementation.
### VI. MVP Baseline Language ### V. MVP Baseline Language
Constraints in this constitution and in specs MUST use MVP baseline Constraints in this constitution and in specs MUST use MVP baseline
language ("MVP baseline does not include X") rather than permanent language ("MVP baseline does not include X") rather than permanent
@@ -86,7 +76,7 @@ add capabilities in future iterations without constitutional
amendment. The current MVP baseline is local-first and single-user; amendment. The current MVP baseline is local-first and single-user;
this is a starting scope, not a permanent restriction. this is a starting scope, not a permanent restriction.
### VII. No Gameplay Rules in Constitution ### VI. No Gameplay Rules in Constitution
This constitution MUST NOT contain concrete gameplay mechanics, This constitution MUST NOT contain concrete gameplay mechanics,
rule-system specifics, or encounter resolution logic. Such details rule-system specifics, or encounter resolution logic. Such details
@@ -96,9 +86,9 @@ architecture, and quality — not product behavior.
## Scope Constraints ## Scope Constraints
- The Encounter Console's primary focus is initiative tracking and - The Encounter Console's primary focus is initiative tracking and
encounter state management. Adjacent capabilities (e.g., richer encounter state management. Adjacent capabilities (e.g., bestiary
game-engine features) are not in the MVP baseline but may be integration, richer game-engine features) may be added via spec
added via spec updates in future iterations. updates.
- Technology choices, UI framework, and storage mechanism are - Technology choices, UI framework, and storage mechanism are
spec-level decisions, not constitutional mandates. spec-level decisions, not constitutional mandates.
- Testing strategy (unit, integration, contract) is determined per - Testing strategy (unit, integration, contract) is determined per
@@ -117,8 +107,14 @@ architecture, and quality — not product behavior.
- Commits SHOULD be atomic and map to individual tasks where - Commits SHOULD be atomic and map to individual tasks where
practical. practical.
- Layer boundary compliance MUST be verified by automated import - Layer boundary compliance MUST be verified by automated import
rules or architectural tests. Agent-assisted or manual review MAY rules or architectural tests.
supplement but not replace automated checks. - When a feature adds, removes, or changes user-facing capabilities
described in README.md, the README MUST be updated in the same
change. Features that materially alter what the product does or
how it is set up SHOULD also be reflected in the README.
- When a feature changes the tech stack, project structure, or
architectural patterns documented in CLAUDE.md, the CLAUDE.md
MUST be updated in the same change.
## Governance ## Governance
@@ -142,4 +138,4 @@ MUST comply with its principles.
**Compliance review**: Every spec and plan MUST include a **Compliance review**: Every spec and plan MUST include a
Constitution Check section validating adherence to all principles. Constitution Check section validating adherence to all principles.
**Version**: 1.0.3 | **Ratified**: 2026-03-03 | **Last Amended**: 2026-03-03 **Version**: 2.2.0 | **Ratified**: 2026-03-03 | **Last Amended**: 2026-03-10

View File

@@ -5,7 +5,7 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
## Commands ## Commands
```bash ```bash
pnpm check # Merge gate — must pass before every commit (knip + format + lint + typecheck + test) pnpm check # Merge gate — must pass before every commit (knip + biome + typecheck + test + jscpd)
pnpm knip # Unused code detection (Knip) pnpm knip # Unused code detection (Knip)
pnpm test # Run all tests (Vitest) pnpm test # Run all tests (Vitest)
pnpm test:watch # Tests in watch mode pnpm test:watch # Tests in watch mode
@@ -27,11 +27,38 @@ apps/web (React 19 + Vite) → packages/application (use cases) → packages
``` ```
- **Domain** — Pure functions, no I/O, no framework imports. All state transitions are deterministic. Errors returned as values (`DomainError`), never thrown. Adapters may throw only for programmer errors. - **Domain** — Pure functions, no I/O, no framework imports. All state transitions are deterministic. Errors returned as values (`DomainError`), never thrown. Adapters may throw only for programmer errors.
- **Application** — Orchestrates domain calls via port interfaces (e.g., `EncounterStore`). No business logic here. - **Application** — Orchestrates domain calls via port interfaces (`EncounterStore`, `BestiarySourceCache`). No business logic here.
- **Web** — React adapter. Implements ports using hooks/state. - **Web** — React adapter. Implements ports using hooks/state. All UI components, routing, and user interaction live here.
Layer boundaries are enforced by `scripts/check-layer-boundaries.mjs`, which runs as a Vitest test. Domain and application must never import from React, Vite, or upper layers. Layer boundaries are enforced by `scripts/check-layer-boundaries.mjs`, which runs as a Vitest test. Domain and application must never import from React, Vite, or upper layers.
### Data & Storage
- **localStorage** — encounter persistence (adapter layer, JSON serialization)
- **IndexedDB** — bestiary source cache (`apps/web/src/adapters/bestiary-cache.ts`, via `idb` wrapper)
- **`data/bestiary/index.json`** — pre-built search index for creature lookup, generated by `scripts/generate-bestiary-index.mjs`
### Project Structure
```
apps/web/ React app — components, hooks, adapters
packages/domain/src/ Pure state transitions, types, validation
packages/application/src/ Use cases, port interfaces
data/bestiary/ Bestiary search index
scripts/ Build tooling (layer checks, index generation)
specs/<feature>/ Feature specs (spec.md, plan.md, tasks.md)
.specify/memory/ Project constitution
```
## Tech Stack
- TypeScript 5.8 (strict mode, `verbatimModuleSyntax`)
- React 19, Vite 6, Tailwind CSS v4
- Lucide React (icons)
- `idb` (IndexedDB wrapper for bestiary cache)
- Biome 2.0 (formatting + linting), Knip (unused code), jscpd (copy-paste detection)
- Vitest (testing), Lefthook (pre-commit hooks)
## Conventions ## Conventions
- **Biome 2.0** for formatting and linting (no Prettier, no ESLint). Tab indentation, 80-char lines. Imports are auto-organized alphabetically. - **Biome 2.0** for formatting and linting (no Prettier, no ESLint). Tab indentation, 80-char lines. Imports are auto-organized alphabetically.
@@ -50,40 +77,3 @@ The constitution (`.specify/memory/constitution.md`) governs all feature work:
3. **Clarification-First** — Ask before making non-trivial assumptions. 3. **Clarification-First** — Ask before making non-trivial assumptions.
4. **MVP Baseline** — Say "MVP baseline does not include X", never permanent bans. 4. **MVP Baseline** — Say "MVP baseline does not include X", never permanent bans.
5. **Every feature begins with a spec** — Spec → Plan → Tasks → Implementation. 5. **Every feature begins with a spec** — Spec → Plan → Tasks → Implementation.
## Active Technologies
- TypeScript 5.x (strict mode, verbatimModuleSyntax) + React 19, Vite (003-remove-combatant)
- In-memory React state (local-first, single-user MVP) (003-remove-combatant)
- TypeScript 5.x (project), Go binary via npm (Lefthook) + `lefthook` (npm devDependency) (006-pre-commit-gate)
- TypeScript 5.x (strict mode, verbatimModuleSyntax) + Knip v5 (new), Biome 2.0, Vitest, Vite 6, React 19 (007-add-knip)
- TypeScript 5.x (strict mode, verbatimModuleSyntax) + React 19, Vite 6, Biome 2.0, existing domain/application packages (008-persist-encounter)
- Browser localStorage (adapter layer only) (008-persist-encounter)
- TypeScript 5.x (strict mode, verbatimModuleSyntax) + React 19, Vite 6, Biome 2.0, Vites (009-combatant-hp)
- TypeScript 5.8 (strict mode, verbatimModuleSyntax) + React 19, Vite 6, Tailwind CSS v4, shadcn/ui, Lucide React (icons) (010-ui-baseline)
- N/A (no storage changes — localStorage persistence unchanged) (010-ui-baseline)
- TypeScript 5.8 (strict mode, verbatimModuleSyntax) + React 19, Vite 6, Tailwind CSS v4, shadcn/ui-style components, Lucide React (icons) (011-quick-hp-input)
- N/A (no storage changes -- existing localStorage persistence handles HP via `adjustHpUseCase`) (011-quick-hp-input)
- N/A (no storage changes -- existing localStorage persistence unchanged) (012-turn-navigation)
- N/A (no storage changes -- purely derived state, existing localStorage persistence unchanged) (013-hp-status-indicators)
- TypeScript 5.8 (strict mode, verbatimModuleSyntax) + jscpd (new dev dependency), Lefthook (existing), Biome 2.0 (existing), Knip (existing) (015-add-jscpd-gate)
- N/A (no storage changes) (015-add-jscpd-gate)
- Browser localStorage (existing adapter, transparent JSON serialization) (016-combatant-ac)
- TypeScript 5.8 (strict mode, verbatimModuleSyntax) + React 19, Vite 6, Tailwind CSS v4, Lucide React (icons) (017-combat-conditions)
- N/A (no storage changes — existing localStorage persistence unchanged) (019-combatant-row-declutter)
- TypeScript 5.8 (strict mode, verbatimModuleSyntax) + React 19, Tailwind CSS v4, Lucide React (icons) (020-fix-zero-hp-opacity)
- Browser localStorage (existing adapter, extended for creatureId) (021-bestiary-statblock)
- TypeScript 5.8 (strict mode, verbatimModuleSyntax) + React 19, Tailwind CSS v4 + React 19, Tailwind CSS v4, Vite 6 (022-fixed-layout-bars)
- N/A (no storage changes -- purely presentational) (022-fixed-layout-bars)
- Browser localStorage (existing adapter, updated to handle empty encounters) (023-clear-encounter)
- N/A (no storage changes — purely presentational fix) (024-fix-hp-popover-overflow)
- N/A (no storage changes — purely derived from existing bestiary data) (025-display-initiative)
- TypeScript 5.8 (strict mode, verbatimModuleSyntax) + React 19, Tailwind CSS v4, Lucide React (icons), Vite 6 (026-roll-initiative)
- N/A (no storage changes — existing localStorage persistence handles initiative via `setInitiativeUseCase`) (026-roll-initiative)
- N/A (no storage changes — purely presentational) (027-ui-polish)
- TypeScript 5.8 (strict mode, verbatimModuleSyntax) + React 19, Tailwind CSS v4, Vite 6 + Tailwind CSS v4 (CSS-native `@theme` theming), Lucide React (icons) (028-semantic-hover-tokens)
- TypeScript 5.8 (strict mode, verbatimModuleSyntax) + React 19, Vite 6, Tailwind CSS v4, Lucide React (icons), idb (IndexedDB wrapper) (029-on-demand-bestiary)
- IndexedDB for cached source data (new); localStorage for encounter persistence (existing, unchanged) (029-on-demand-bestiary)
- IndexedDB for cached source data (existing via `bestiary-cache.ts`); localStorage for encounter persistence (existing, unchanged) (030-bulk-import-sources)
## Recent Changes
- 003-remove-combatant: Added TypeScript 5.x (strict mode, verbatimModuleSyntax) + React 19, Vite

View File

@@ -1,10 +1,17 @@
# Initiative Tracker # Encounter Console
A turn-based initiative tracker for tabletop RPG encounters. Click "Next Turn" to cycle through combatants and advance rounds. A local-first initiative tracker and encounter manager for tabletop RPGs (D&D 5e / 2024). Runs entirely in the browser — no server, no account, no data leaves your machine.
## What it does
- **Initiative tracking** — add combatants, roll initiative (manual or d20), cycle turns and rounds
- **Encounter state** — HP, AC, conditions, concentration tracking with visual status indicators
- **Bestiary integration** — import bestiary JSON sources, search creatures, and view full stat blocks
- **Persistent** — encounters survive page reloads via localStorage; bestiary data cached in IndexedDB
## Prerequisites ## Prerequisites
- Node.js 22 - Node.js 22+
- pnpm 10.6+ - pnpm 10.6+
## Getting Started ## Getting Started
@@ -14,9 +21,7 @@ pnpm install
pnpm --filter web dev pnpm --filter web dev
``` ```
Open the URL printed in your terminal (typically `http://localhost:5173`). Open `http://localhost:5173`.
The app starts with a 3-combatant demo encounter (Aria, Brak, Cael). Click **Next Turn** to advance through the initiative order. When the last combatant finishes their turn, the round number increments and the cycle restarts.
## Scripts ## Scripts
@@ -24,5 +29,27 @@ The app starts with a 3-combatant demo encounter (Aria, Brak, Cael). Click **Nex
|---------|-------------| |---------|-------------|
| `pnpm --filter web dev` | Start the dev server | | `pnpm --filter web dev` | Start the dev server |
| `pnpm --filter web build` | Production build | | `pnpm --filter web build` | Production build |
| `pnpm test` | Run all tests | | `pnpm test` | Run all tests (Vitest) |
| `pnpm check` | Full merge gate (format, lint, typecheck, test) | | `pnpm check` | Full merge gate (knip, biome, typecheck, test, jscpd) |
## Project Structure
```
apps/web/ React 19 + Vite — UI components, hooks, adapters
packages/domain/ Pure functions — state transitions, types, validation
packages/app/ Use cases — orchestrates domain via port interfaces
data/bestiary/ Bestiary index for creature search
scripts/ Build tooling (layer boundary checks, index generation)
specs/ Feature specifications (spec → plan → tasks)
```
## Architecture
Strict layered architecture with enforced dependency direction:
```
apps/web (adapters) → packages/application (use cases) → packages/domain (pure logic)
```
Domain is pure — no I/O, no randomness, no framework imports. Layer boundaries are enforced by automated import checks that run as part of the test suite. See [CLAUDE.md](./CLAUDE.md) for full conventions.