67 lines
3.9 KiB
Markdown
67 lines
3.9 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Commands
|
|
|
|
```bash
|
|
pnpm check # Merge gate — must pass before every commit (knip + format + lint + typecheck + test)
|
|
pnpm knip # Unused code detection (Knip)
|
|
pnpm test # Run all tests (Vitest)
|
|
pnpm test:watch # Tests in watch mode
|
|
pnpm typecheck # tsc --build (project references)
|
|
pnpm lint # Biome lint
|
|
pnpm format # Biome format (writes)
|
|
pnpm --filter web dev # Vite dev server (localhost:5173)
|
|
pnpm --filter web build # Production build
|
|
```
|
|
|
|
Run a single test file: `pnpm vitest run packages/domain/src/__tests__/advance-turn.test.ts`
|
|
|
|
## Architecture
|
|
|
|
Strict layered architecture with ports/adapters and enforced dependency direction:
|
|
|
|
```
|
|
apps/web (React 19 + Vite) → packages/application (use cases) → packages/domain (pure logic)
|
|
```
|
|
|
|
- **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.
|
|
- **Web** — React adapter. Implements ports using hooks/state.
|
|
|
|
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.
|
|
|
|
## Conventions
|
|
|
|
- **Biome 2.0** for formatting and linting (no Prettier, no ESLint). Tab indentation, 80-char lines. Imports are auto-organized alphabetically.
|
|
- **TypeScript strict mode** with `verbatimModuleSyntax`. Use `.js` extensions in relative imports when required by the repo's ESM settings (e.g., `./types.js`).
|
|
- **Branded types** for identity values (e.g., `CombatantId`). Prefer immutability/`readonly` where practical.
|
|
- **Domain events** are plain data objects with a `type` discriminant — no classes.
|
|
- **Tests** live in `packages/*/src/__tests__/*.test.ts`. Test pure functions directly; map acceptance scenarios and invariants from specs to individual `it()` blocks.
|
|
- **Feature specs** live in `specs/<feature>/` with spec.md, plan.md, tasks.md. The project constitution is at `.specify/memory/constitution.md`.
|
|
|
|
## Constitution (key principles)
|
|
|
|
The constitution (`.specify/memory/constitution.md`) governs all feature work:
|
|
|
|
1. **Deterministic Domain Core** — Pure state transitions only; no I/O, randomness, or clocks in domain.
|
|
2. **Layered Architecture** — Domain → Application → Adapters. Never skip layers or reverse dependencies.
|
|
3. **Clarification-First** — Ask before making non-trivial assumptions.
|
|
4. **MVP Baseline** — Say "MVP baseline does not include X", never permanent bans.
|
|
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)
|
|
|
|
## Recent Changes
|
|
- 003-remove-combatant: Added TypeScript 5.x (strict mode, verbatimModuleSyntax) + React 19, Vite
|