From f2f30c800226abd7f3c10d6029c578766b13ce44 Mon Sep 17 00:00:00 2001 From: funman300 Date: Wed, 6 May 2026 04:42:24 +0000 Subject: [PATCH] docs: adopt unified-3.0 Claude rule set + trim duplications MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adopts the four-file rule set the player added to the working tree: - CLAUDE.md grows from a 114-line pointer doc to the 571-line `unified-3.0` rulebook: hard global constraints (§2), engine rules (§3), asset rules (§4), code standards (§5), build + verification (§6), git workflow (§7), the change-control ASK BEFORE list (§8), and the Context Injection System (§14). - CLAUDE_SPEC.md — formal architecture spec: crate dependency graph with forbidden_deps, data ownership map, state-machine invariants ("52 cards always exist", "no duplicate IDs", "all cards belong to exactly one pile"), sync merge contract, server contract, validation checklist. - CLAUDE_WORKFLOW.md — two-agent Builder/Guardian pipeline with hard-fail patterns that auto-reject (core uses IO/Bevy/network, GameState mutated outside GameLogicSystem, blocking async on main thread, duplicate logic, merge altered incorrectly). - CLAUDE_PROMPT_PACK.md — task-type templates. Three duplicate rule passages removed: - CLAUDE_SPEC.md §0 dropped no_panics_in_core / core_is_pure / event_driven_engine — already canonical in CLAUDE.md §2.1, §2.3, §3.1. Kept single_source_of_truth and sync_is_additive (those describe data flow, not in CLAUDE.md). - CLAUDE_SPEC.md §11 Prohibited Patterns now references CLAUDE.md §11 instead of restating the same five forbidden items. - ARCHITECTURE.md Design Principles dropped the pure-core / no-panics / UI-first bullets — those are enforcement constraints living in CLAUDE.md §2.1, §2.3, §3.3; this file describes the design that motivates them. Kept the offline-first, one-language, and plugin-based-Bevy bullets (those are descriptive, not enforcement). Co-Authored-By: Claude Opus 4.7 (1M context) --- ARCHITECTURE.md | 5 +- CLAUDE.md | 605 ++++++++++++++++++++++++++++++++++++------ CLAUDE_PROMPT_PACK.md | 497 ++++++++++++++++++++++++++++++++++ CLAUDE_SPEC.md | 292 ++++++++++++++++++++ CLAUDE_WORKFLOW.md | 335 +++++++++++++++++++++++ 5 files changed, 1657 insertions(+), 77 deletions(-) create mode 100644 CLAUDE_PROMPT_PACK.md create mode 100644 CLAUDE_SPEC.md create mode 100644 CLAUDE_WORKFLOW.md diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 1e04e0a..53e0b0d 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -47,11 +47,10 @@ Solitaire Quest is a cross-platform Klondike Solitaire game written in Rust, tar ### Design Principles - **Offline first.** The local file is always the source of truth. Sync is additive, never destructive. -- **Pure core.** All game logic lives in a dependency-free Rust crate with no Bevy, no network, and no I/O. This keeps it fully unit-testable and portable. -- **No panics in game logic.** Every state transition returns `Result<_, MoveError>`. Panics are only acceptable in startup/configuration code. - **One language, one repo.** The game client, sync client, shared types, and sync server are all Rust crates in a single Cargo workspace. - **Plugin-based Bevy architecture.** Each major feature is a Bevy `Plugin`. Systems are small and single-purpose. Cross-system communication uses Bevy `Event`s. -- **UI-first interaction.** Every player-triggered action — new game, undo, draw, pause, open stats / settings / help / profile / leaderboard, etc. — must be reachable from a visible UI control. Keyboard shortcuts exist only as optional accelerators for power users; they are never the sole entry point. A player using only mouse or touch must be able to perform every action. New gameplay features ship with the UI control alongside the system that backs it. + +Pure-core, no-panics-in-game-logic, and UI-first-interaction constraints are enforced by CLAUDE.md §2.1, §2.3, and §3.3 respectively — those are the canonical statements; this file describes the design that motivates them. --- diff --git a/CLAUDE.md b/CLAUDE.md index a5ffc6d..1a4b2fe 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -1,114 +1,571 @@ -# Solitaire Quest — Claude Code Instructions +# CLAUDE.md -See @ARCHITECTURE.md for full project design, crate responsibilities, data models, and API reference. +version: unified-3.0 --- -## Project Layout +# 0. Role of This File -```text -solitaire_core/ # Pure Rust game logic — NO Bevy, NO network, NO I/O -solitaire_sync/ # Shared API types — NO Bevy, serde/uuid/chrono only -solitaire_data/ # Persistence + SyncProvider trait + server client -solitaire_engine/ # Bevy ECS systems, components, plugins -solitaire_server/ # Axum sync server binary -solitaire_app/ # Thin binary entry point -assets/ # Source assets — embedded at compile time via include_bytes!() +This document defines: + +* **Execution rules (what Claude must do)** +* **System constraints (what Claude must never violate)** +* **Operational architecture (how code is structured)** + +For full system design details: +→ `ARCHITECTURE.md` (authoritative source of truth) + +This file overrides all conversational assumptions. + +--- + +# 1. System Architecture (Authoritative Mapping) + +## 1.1 Crates + +```text id="crate_map" +solitaire_core/ # PURE logic (no IO, no Bevy, deterministic) +solitaire_sync/ # Shared API + merge logic +solitaire_data/ # Persistence + sync client +solitaire_engine/ # Bevy ECS + UI + gameplay orchestration +solitaire_server/ # Axum backend (optional sync layer) +solitaire_app/ # Entry binary +assets/ # Runtime assets (except audio) ``` --- -## Build & Test Commands +## 1.2 Architecture Source of Truth -```bash -# Dev run (fast compile via dynamic linking) -cargo run -p solitaire_app --features bevy/dynamic_linking +* Full system design: `ARCHITECTURE.md` +* This file NEVER redefines system design +* This file ONLY enforces behavior -# Release build -cargo build --workspace --release +--- -# All tests — MUST pass before any commit +# 2. Hard Global Constraints (NON-NEGOTIABLE) + +These override all other instructions. + +## 2.1 Core Determinism + +* `solitaire_core` MUST: + + * be deterministic + * be side-effect free + * never depend on Bevy / IO / async + +--- + +## 2.2 Sync Isolation + +* `solitaire_sync`: + + * no Bevy + * no IO + * no engine dependencies +* merge logic must be pure functions only + +--- + +## 2.3 Error Policy + +* NO `unwrap()` +* NO `panic!()` in runtime/game logic +* All state transitions: + +```rust id="err_model" +Result +``` + +--- + +## 2.4 Threading Rules + +* Sync must run on `AsyncComputeTaskPool` +* NEVER block Bevy main thread + +--- + +## 2.5 Persistence Rules + +* atomic writes only: + + * write `.tmp` + * rename atomically +* no partial state writes allowed + +--- + +## 2.6 Security Rules + +* credentials ONLY via `keyring` +* NEVER store secrets in: + + * files + * logs + * source code + +--- + +## 2.7 Sync System Rules + +* All sync backends implement: + +```rust id="sync_trait" +trait SyncProvider +``` + +* `SyncPlugin` MUST be backend-agnostic +* NEVER match on backend inside ECS systems + +--- + +# 3. Engine Rules (Bevy Layer) + +## 3.1 ECS Design + +* systems = single responsibility +* communication = Events only +* shared state = Resources only +* per-entity state = Components only + +--- + +## 3.2 Game State Authority + +* ONLY `GameStateResource` can mutate game state +* UI systems MUST NOT directly modify core logic + +--- + +## 3.3 UI-First Constraint (CRITICAL) + +Every player action MUST: + +* have a visible UI control +* NOT rely solely on keyboard shortcuts + +Keyboard shortcuts are: +→ optional accelerators only + +--- + +## 3.4 Layout System + +* recompute on `WindowResized` +* no fixed resolution assumptions + +--- + +# 4. Asset System Rules + +## 4.1 Runtime Assets (AssetServer) + +Loaded via: + +* `CardImageSet` +* `BackgroundImageSet` +* `FontResource` + +Includes: + +* cards +* backgrounds +* fonts + +--- + +## 4.2 Embedded Assets + +Only audio: + +```text id="audio_rule" +include_bytes!() +``` + +--- + +## 4.3 Test Compatibility Rule + +All asset loaders MUST accept: + +```rust id="asset_fallback" +Option> +``` + +Must degrade gracefully under `MinimalPlugins`. + +--- + +# 5. Code Standards + +## 5.1 Error Handling + +* use `thiserror` +* no `Box` in libraries + +--- + +## 5.2 Public API Rules + +* prefer `Into` over concrete types +* all public items require doc comments + +--- + +## 5.3 Derive Order + +```rust id="derive_order" +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +``` + +--- + +## 5.4 Performance Rules + +* NO `clone()` in hot paths +* profile before optimizing + +--- + +## 5.5 SQL Rules + +* ONLY `sqlx::query!` +* NO raw SQL strings + +--- + +# 6. Build & Verification Rules + +These are mandatory before ANY commit. + +```bash id="build_rules" cargo test --workspace - -# Lint — MUST pass clean (zero warnings) cargo clippy --workspace -- -D warnings - -# Run sync server locally -cargo run -p solitaire_server - -# Check a single crate -cargo test -p solitaire_core -cargo clippy -p solitaire_core -- -D warnings ``` --- -## Hard Rules +# 7. Git Workflow Rules -- `solitaire_core` and `solitaire_sync` must never gain Bevy or network dependencies. -- No `unwrap()` or `panic!()` in game logic. All state transitions return `Result<_, MoveError>`. -- Audio assets are embedded at compile time using `include_bytes!()` in `audio_plugin.rs`. -- Card faces (52 PNGs in `assets/cards/faces/`), card backs (`assets/cards/backs/back_N.png`), board backgrounds (`assets/backgrounds/bg_N.png`), and the UI font (`assets/fonts/main.ttf`) are loaded at runtime via `AssetServer::load()` and stored as `Handle`/`Handle` in the `CardImageSet`, `BackgroundImageSet`, and `FontResource` resources. The `assets/` directory must ship alongside the binary. -- Asset-loading systems take `Option>` so they degrade cleanly under `MinimalPlugins` (tests). When `CardImageSet` is absent, `card_plugin` falls back to a `Text2d` rank+suit overlay; when `BackgroundImageSet` is absent, the board falls back to a solid colour. -- Atomic file writes only: write to `filename.json.tmp`, then `rename()`. -- Passwords and tokens are stored in the OS keychain via the `keyring` crate — never in plaintext files or logs. -- Sync runs on `AsyncComputeTaskPool` — never block the Bevy main thread. -- All sync backends implement the `SyncProvider` trait. The `SyncPlugin` is backend-agnostic — never `match` on `SyncBackend` inside a Bevy system. -- `cargo clippy --workspace -- -D warnings` must pass clean after every change. -- `cargo test --workspace` must pass after every change. +## Commit format + +```text id="commit_fmt" +type(scope): description +``` + +Examples: + +* feat(core): add draw-three rules +* fix(engine): correct drag z-order +* test(core): undo boundary cases --- -## Code Style +## Commit conditions -- Use `thiserror` for error types. Never `Box` in library crates. -- Prefer `Into` over concrete types in public API function parameters. -- All public items must have doc comments (`///`). Private items: comment only when non-obvious. -- Derive order convention: `#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]` -- Bevy systems: one responsibility per system. Use `Events` for cross-system communication, never shared mutable state. -- SQL queries: use `sqlx::query!` macros (compile-time checked), not raw string queries. -- No `clone()` calls in hot paths (game loop systems). Profile before optimising elsewhere. +* tests must pass +* clippy must be clean + +NEVER commit otherwise --- -## Bevy Conventions +# 8. Change Control (ASK BEFORE DOING) -- One `Plugin` per major feature: `CardPlugin`, `AudioPlugin`, `AchievementPlugin`, `UIPlugin`, `SyncPlugin`. -- Resources own shared state. Events communicate between systems. Components own per-entity data. -- All UI screens are built with Bevy UI (`bevy::ui`). Never mix UI layout and game logic in the same system. -- Layout is recomputed on `WindowResized` — never assume a fixed window size. -- **UI-first.** Every player-triggered action (new game, undo, draw, pause, open stats / settings / help / profile / leaderboard, switch mode, etc.) must be reachable from a visible UI control. Keyboard shortcuts are optional accelerators — never the sole entry point. New gameplay features ship with the UI control alongside the system that backs it; do not merge a feature that is keyboard-only. +Claude must request confirmation before: + +* adding dependencies +* modifying `solitaire_sync` +* changing DB schema +* introducing `unsafe` +* changing merge strategy --- -## Git Workflow +# 9. System Mental Model (IMPORTANT) -- Commit after each passing phase, not after every file change. -- Commit message format: `type(scope): description` - - `feat(core): add draw-three mode validation` - - `fix(engine): card z-order during drag` - - `test(core): undo stack boundary conditions` - - `chore(server): add sqlx migration 002` -- Never commit with failing tests or clippy warnings. -- Never commit secrets, `.env` files, or `*.db` files. +```text id="mental_model" +Core (rules + deterministic logic) + ↓ +Engine (Bevy orchestration) + ↓ +Data layer (persistence + sync) + ↓ +Server (optional external system) +``` + +Core is always the source of truth. --- -## Ask Before Doing +# 10. Known Platform Pitfalls -- Adding a new crate dependency (discuss alternatives first). -- Changing a type in `solitaire_sync` (breaking change on both client and server). -- Altering the database schema (requires a new sqlx migration). -- Introducing `unsafe` code anywhere. -- Changing the merge strategy in `solitaire_sync::merge()`. +Must always be handled explicitly: + +* Bevy `Time` uses `f32` +* `sqlx::migrate!()` path is crate-relative +* `dirs::data_dir()` may return `None` +* Linux may lack keyring backend --- -## Lessons Learned +# 11. Forbidden Patterns -> Add entries here when Claude makes a mistake so it isn't repeated. +* game logic inside Bevy systems +* duplication across crates +* blocking async calls in ECS +* insecure credential storage +* bypassing core logic layer -- Bevy's `Time` resource uses `f32` seconds; convert to `u64` only when writing to `StatsSnapshot`. -- `sqlx::migrate!()` macro path is relative to the crate root, not the workspace root. -- `keyring` on Linux requires a running secret service (e.g. GNOME Keyring or KWallet) — handle `Error::NoStorageAccess` gracefully and fall back to prompting the user. -- `dirs::data_dir()` returns `None` on some minimal Linux environments — always handle the `None` case explicitly, do not unwrap. +--- + +# 12. Execution Rules for Claude + +When generating code: + +1. respect crate boundaries +2. minimize diff size +3. do not expand scope +4. follow existing patterns +5. preserve invariants + +If unclear: +→ ask before acting + +--- + +# 13. Relationship to ARCHITECTURE.md + +| File | Role | +| --------------- | ------------------------- | +| CLAUDE.md | execution + constraints | +| ARCHITECTURE.md | system design truth | +| Both combined | full system understanding | + +--- +# 14. Context Injection System (AUTOMATIC SCOPE FILTER) + +## 14.1 Purpose + +Before generating any response, Claude MUST construct a **minimal relevant context set**. + +This prevents: + +* architectural drift +* irrelevant spec loading +* over-engineering +* cross-crate confusion + +--- + +## 14.2 Input Classification Step (MANDATORY) + +Every request MUST be classified into exactly one task type: + +```text id="task_types" +feature +bugfix +refactor +system_design +bevy_system +core_logic +sync +optimization +test +debug +``` + +If uncertain → ask clarification. + +--- + +## 14.3 Context Selection Engine + +After classification, Claude MUST include ONLY the relevant sections below. + +--- + +## 14.4 Context Map (CORE RULESET) + +### feature + +Include: + +* §2 Hard Global Constraints +* §3 Engine Rules +* ARCHITECTURE.md (crate of target feature only) +* relevant data models (GameState, SyncPayload if needed) + +--- + +### bugfix + +Include: + +* §2 Hard Global Constraints +* §5 Code Standards +* affected crate boundaries +* relevant system (engine/core/sync only) + +--- + +### refactor + +Include: + +* §3 Engine Rules +* §5 Code Standards +* §11 Forbidden Patterns +* target crate boundaries + +--- + +### system_design + +Include: + +* ARCHITECTURE.md (FULL) +* §9 Mental Model +* §1 System Architecture Mapping + +--- + +### core_logic + +Include: + +* solitaire_core rules only +* GameState model +* MoveError model +* §2.1–2.3 constraints + +--- + +### bevy_system + +Include: + +* §3 Engine Rules +* ECS rules (Events/Resources/Components) +* UI-first constraint +* relevant plugin system only + +--- + +### sync + +Include: + +* SyncProvider trait +* merge strategy rules +* solitaire_sync models +* §2.6 Sync Rules + +--- + +### optimization + +Include: + +* target crate only +* §5.4 Performance Rules +* hot path constraints + +--- + +### test + +Include: + +* §6 Build Rules +* relevant module +* expected invariants + +--- + +### debug + +Include: + +* target file/module only +* §2.3 Error Policy +* runtime assumptions relevant to failure + +--- + +## 14.5 Context Compression Rules + +Claude MUST obey: + +* never include full ARCHITECTURE.md unless system_design +* max 2 crates per response unless explicitly required +* prefer function-level context over file-level context +* exclude unrelated plugins/systems + +--- + +## 14.6 Context Priority Order + +When space is limited: + +1. Hard Constraints (§2) +2. Target crate rules +3. Data models +4. Only then: architecture snippets + +--- + +## 14.7 “No Context Pollution” Rule + +Claude must NOT include: + +* unrelated crates +* unrelated plugins +* unused data models +* full architecture dumps +* speculative systems + +--- + +## 14.8 Self-Check Before Execution + +Before writing code, Claude MUST verify: + +* [ ] Is only relevant context included? +* [ ] Is at least one hard constraint present? +* [ ] Am I touching more than one crate unnecessarily? +* [ ] Am I duplicating ARCHITECTURE.md content? + +If any fail → revise context selection. + +--- + +## 14.9 Injection Output Format (Internal Model) + +Claude should behave as if it constructed: + +```text id="ctx_format" +[SELECTED TASK TYPE] + +[MINIMAL REQUIRED RULES] + +[MINIMAL ARCHITECTURE SLICES] + +[RELEVANT MODELS] + +[REQUEST] +``` + +--- + +## 14.10 Relationship to ARCHITECTURE.md + +* ARCHITECTURE.md = source of truth +* CLAUDE.md = execution constraints +* THIS SECTION = filtering layer between them + +--- + +# END CONTEXT INJECTION SYSTEM diff --git a/CLAUDE_PROMPT_PACK.md b/CLAUDE_PROMPT_PACK.md new file mode 100644 index 0000000..865cae8 --- /dev/null +++ b/CLAUDE_PROMPT_PACK.md @@ -0,0 +1,497 @@ +# CLAUDE_PROMPT_PACK.md + +version: 1.0 + +--- + +# 0. GLOBAL INSTRUCTION (prepend to every prompt) + +``` +You must follow CLAUDE_SPEC.md strictly. + +Rules: +- Do not expand scope beyond what is defined +- Do not refactor unrelated code +- Do not introduce new dependencies +- Prefer minimal, surgical changes +- Use existing patterns in the codebase +- Return minimal diffs or changed functions only + +Before writing code: +1. List relevant constraints from CLAUDE_SPEC.md +2. Identify risks +3. Then implement +``` + +--- + +# 1. FEATURE IMPLEMENTATION + +``` +# TASK: Feature Implementation + +feature: "" + +goal: +"" + +scope: +crates: [] +systems: [] +files: [] + +non_goals: +- "" + +constraints: +- must follow CLAUDE_SPEC.md +- event-driven architecture required +- no blocking operations +- no cross-crate leakage + +acceptance_criteria: +- "" +- "" + +edge_cases: +- "" + +--- + +## Required Patterns + +Use this pattern for systems: + + +--- + +## Output Format + +intent: +plan: +constraints_used: +risks: + +code_changes: +(minimal diffs only) + +notes: +``` + +--- + +# 2. BUGFIX + +``` +# TASK: Bug Fix + +bug_description: +"" + +expected_behavior: +"" + +root_cause_hint (optional): +"" + +scope: +crates: [] +files: [] + +constraints: +- minimal fix only +- no refactors unless required +- must add regression protection if applicable + +--- + +## Requirements + +1. Identify root cause +2. Fix it minimally +3. Preserve all invariants +4. Do not change unrelated logic + +--- + +## Output Format + +analysis: +root_cause: +fix_strategy: + +code_changes: +(minimal diff) + +regression_test (only if high-value): + +notes: +``` + +--- + +# 3. REFACTOR + +``` +# TASK: Refactor + +target: +"" + +goal: +"" + +scope: +crates: [] +files: [] + +non_goals: +- no behavior changes +- no new features + +constraints: +- must preserve behavior exactly +- must respect crate boundaries +- must not duplicate logic + +--- + +## Refactor Type + +- [ ] simplify logic +- [ ] reduce duplication +- [ ] improve readability +- [ ] performance (non-invasive) + +--- + +## Output Format + +analysis: +issues_found: + +refactor_plan: + +code_changes: +(diff only) + +verification: +- behavior unchanged: yes/no +- invariants preserved: yes/no + +notes: +``` + +--- + +# 4. SYSTEM DESIGN (NEW FEATURE) + +``` +# TASK: System Design + +feature: +"" + +goal: +"" + +constraints: +- must fit existing architecture +- must follow plugin + event model +- must not violate crate boundaries + +--- + +## Required Output + +design: + +components: +- plugins: +- systems: +- events: +- resources: + +data_flow: +(step-by-step) + +integration_points: +- where it connects to existing systems + +risks: +- "" + +tradeoffs: +- "" + +--- + +## DO NOT + +- write full implementation +- modify unrelated systems +``` + +--- + +# 5. NEW BEVY SYSTEM + +``` +# TASK: Add Bevy System + +system_name: +"" + +trigger: +(event or condition) + +reads: +[Resources] + +writes: +[Resources] + +emits: +[Events] + +constraints: +- must be event-driven +- must not directly mutate unrelated state +- must be single responsibility + +--- + +## Output Format + +system_signature: + +implementation: +(code only) + +notes: +``` + +--- + +# 6. CORE LOGIC FUNCTION (solitaire_core) + +``` +# TASK: Core Logic Implementation + +function: +"" + +goal: +"" + +rules: +- no IO +- no async +- no Bevy +- deterministic + +invariants: +- "" +- "" + +errors: +- "" + +--- + +## Output Format + +constraints_checked: + +implementation: +(code only) + +edge_case_handling: + +notes: +``` + +--- + +# 7. SYNC / MERGE LOGIC + +``` +# TASK: Sync Logic + +goal: +"" + +constraints: +- must be deterministic +- must be idempotent +- must be lossless +- must not delete data + +rules: +- counters → max +- times → min +- collections → union + +--- + +## Output Format + +analysis: + +merge_logic: + +code_changes: + +invariants_verified: +- deterministic +- idempotent +- lossless + +notes: +``` + +--- + +# 8. PERFORMANCE OPTIMIZATION + +``` +# TASK: Optimization + +target: +"" + +constraints:CLAUDE_WORKFLOW.md +- no behavior change +- no architecture change +- minimal code changes + +--- + +## Output Format + +analysis: +bottleneck: + +optimization_strategy: + +code_changes: + +impact_estimate: + +notes: +``` + +--- + +# 9. TEST GENERATION (STRICT MODE) + +``` +# TASK: Test Generation + +target: +"" + +reason: +- bugfix | complex logic | invariant protection + +constraints: +- no redundant tests +- must test real behavior +- must fail if logic breaks + +--- + +## Output Format + +test_cases: +- "" + +test_code: + +notes: +``` + +--- + +# 10. DEBUGGING / INVESTIGATION + +``` +# TASK: Debug + +problem: +"" + +context: +"" + +--- + +## Required Steps + +1. List possible causes +2. Narrow down most likely +3. Suggest verification steps +4. Provide minimal fix + +--- + +## Output Format + +hypotheses: + +most_likely: + +verification_steps: + +fix: + +notes: +``` + +--- + +# 11. HARD CONSTRAINT OVERRIDE (RARE) + +``` +# TASK: Exception Handling + +reason: +"" + +requested_exception: +"" + +justification: +"" + +--- + +## Output Format + +analysis: + +alternatives_considered: + +final_decision: + +risk: +``` + +--- + +# 12. STOP CONDITIONS (always append) + +``` +Stop when: +- acceptance criteria are met +- code is minimal and correct + +Do NOT: +- expand scope +- refactor unrelated code +- optimize prematurely +``` + +--- + +# END diff --git a/CLAUDE_SPEC.md b/CLAUDE_SPEC.md new file mode 100644 index 0000000..ec0e559 --- /dev/null +++ b/CLAUDE_SPEC.md @@ -0,0 +1,292 @@ +# CLAUDE_SPEC.md + +version: 1.0 + +--- + +## 0. Global Rules + +(Core determinism, panic policy, and event-driven engine constraints live in CLAUDE.md §2.1, §2.3, §3.1. Listed here only when they add information CLAUDE.md doesn't carry.) + +rules: + +* id: single_source_of_truth + description: "GameStateResource is the only mutable game state in runtime" + +* id: sync_is_additive + description: "Remote data must never destructively overwrite local data" + +--- + +## 1. Crate Graph + +crates: +solitaire_core: +depends_on: [rand, serde, chrono] +forbidden_deps: [bevy, reqwest, tokio, std::fs] + +solitaire_sync: +depends_on: [serde, serde_json, uuid, chrono] +role: "shared_types" + +solitaire_data: +depends_on: [solitaire_core, solitaire_sync, reqwest, tokio, keyring] +role: "persistence_and_sync" + +solitaire_engine: +depends_on: [bevy, kira, solitaire_core, solitaire_data] +role: "runtime_engine" + +solitaire_server: +depends_on: [solitaire_sync, axum, sqlx, jsonwebtoken] +role: "backend" + +solitaire_app: +depends_on: [solitaire_engine] +role: "entrypoint" + +--- + +## 2. Data Ownership + +ownership: +GameState: +owner: solitaire_core +mutable_in: solitaire_engine +access_pattern: "via GameStateResource only" + +StatsSnapshot: +owner: solitaire_data + +PlayerProgress: +owner: solitaire_data + +AchievementRecord: +owner: solitaire_data + +SyncPayload: +owner: solitaire_sync + +--- + +## 3. State Transitions + +state_machine: +GameState: +transitions: +- action: move_cards +returns: Result + +``` + - action: draw + returns: Result + + - action: undo + returns: Result + +invariants: + - "52 cards always exist" + - "no duplicate card IDs" + - "all cards belong to exactly one pile" +``` + +--- + +## 4. Event System + +events: + +input: +- MoveRequestEvent +- DrawRequestEvent +- UndoRequestEvent +- NewGameRequestEvent + +state: +- StateChangedEvent +- GameWonEvent + +meta: +- AchievementUnlockedEvent +- SyncCompleteEvent + +rules: + +* "Input events trigger core logic" +* "Core logic emits state events" +* "UI reacts to state events only" + +--- + +## 5. Sync Contract + +sync: + +provider_trait: +methods: +- pull() -> SyncPayload +- push(payload) -> SyncResponse + +guarantees: +- "non-blocking during gameplay" +- "blocking allowed on exit only" + +merge: +rules: +counters: "max" +best_times: "min" +collections: "union" +achievements: "never removed" + +``` +properties: + - deterministic + - idempotent + - lossless +``` + +--- + +## 6. Persistence + +storage: + +format: json + +files: +- stats.json +- progress.json +- achievements.json +- settings.json +- game_state.json + +guarantees: +- atomic_write: true +- crash_safe: true + +--- + +## 7. Engine Rules + +engine: + +mutation_rules: +- "Only GameLogicSystem mutates GameState" +- "UI systems are read-only" + +threading: +- "sync runs on AsyncComputeTaskPool" +- "main thread must never block" + +plugins: +pattern: "feature_isolation" +communication: "events" + +--- + +## 8. Server Contract + +server: + +auth: +method: jwt +access_expiry: 24h +refresh_expiry: 30d + +endpoints: +- POST /api/auth/register +- POST /api/auth/login +- GET /api/sync/pull +- POST /api/sync/push + +limits: +payload_max: 1MB +rate_limit: "10 req/min auth routes" + +--- + +## 9. Achievement System + +achievements: + +definition_location: solitaire_core +state_location: solitaire_data + +types: +- condition_based +- event_driven + +rule: +- "achievements cannot be revoked" + +--- + +## 10. Testing Rules + +testing: + +philosophy: +- "test real failures" +- "avoid redundant tests" + +required_coverage: +solitaire_core: +- move_validation +- undo_integrity +- win_detection + +``` +solitaire_sync: + - merge_correctness + - idempotency +``` + +--- + +## 11. Prohibited Patterns + +(See CLAUDE.md §11 for the canonical forbidden-patterns list.) + +--- + +## 12. Extension Points + +extensibility: + +sync_backends: +pattern: "implement SyncProvider" + +game_modes: +location: solitaire_core::GameMode + +plugins: +rule: "new feature = new plugin" + +--- + +## 13. Validation Checklist (for Claude) + +validation: + +* check: "crate dependency rules respected" +* check: "no panics in core" +* check: "events used for cross-system communication" +* check: "GameState mutations centralized" +* check: "merge function properties preserved" +* check: "no blocking operations in main loop" + +--- + +## 14. Mental Model + +model: + +layers: +- core +- engine +- data +- server + +flow: +- input -> engine -> core -> engine -> ui +- data <-> sync <-> server diff --git a/CLAUDE_WORKFLOW.md b/CLAUDE_WORKFLOW.md new file mode 100644 index 0000000..58e8a9a --- /dev/null +++ b/CLAUDE_WORKFLOW.md @@ -0,0 +1,335 @@ +# CLAUDE_WORKFLOW.md + +version: 1.0 + +--- + +## 0. Overview + +This workflow defines a **two-agent system**: + +* **Builder Agent** → writes and modifies code +* **Guardian Agent** → enforces architecture + rejects invalid changes + +No code is considered valid unless it passes Guardian validation. + +--- + +## 1. Agent Roles + +### 1.1 Builder Agent + +role: "code_generation" + +responsibilities: + +* implement features +* refactor code +* generate tests (only when justified) +* follow CLAUDE_SPEC.md + +constraints: + +* cannot bypass validation +* must declare intent before writing code + +output_contract: +must_produce: +- change_summary +- files_modified +- reasoning (short) +- code_diff + +--- + +### 1.2 Guardian Agent + +role: "architecture_enforcement" + +responsibilities: + +* validate against CLAUDE_SPEC.md +* detect violations +* reject or approve changes +* suggest minimal fixes (not full rewrites) + +constraints: + +* no feature implementation +* no large rewrites +* must be deterministic + +output_contract: +must_produce: +- status: APPROVED | REJECTED +- violations[] +- required_fixes[] +- optional_improvements[] + +--- + +## 2. Workflow Pipeline + +```text +User Request + ↓ +Builder Agent (proposal + code) + ↓ +Guardian Agent (validation) + ↓ +IF approved → commit +IF rejected → feedback → Builder retry +``` + +--- + +## 3. Builder Protocol + +### Step 1 — Intent Declaration + +Builder MUST start with: + +```yaml +intent: + feature: "" + crates_touched: [] + systems_affected: [] + risk_level: low|medium|high +``` + +--- + +### Step 2 — Plan + +```yaml +plan: + - step: "..." + - step: "..." +``` + +--- + +### Step 3 — Implementation + +* Only modify declared crates +* Follow ownership rules +* Use events for cross-system communication + +--- + +### Step 4 — Output + +```yaml +change_summary: "..." + +files_modified: + - path: ... + change: "..." + +violations_self_check: + - none | list + +notes: "short reasoning" +``` + +--- + +## 4. Guardian Protocol + +### Step 1 — Spec Validation + +Check against: + +* crate boundaries +* mutation rules +* event system usage +* sync guarantees +* forbidden patterns + +--- + +### Step 2 — Invariant Validation + +Must verify: + +* GameState invariants preserved +* no new panic paths +* no blocking calls in engine +* merge properties unchanged + +--- + +### Step 3 — Output Decision + +#### APPROVED + +```yaml +status: APPROVED + +notes: + - "no violations" +``` + +--- + +#### REJECTED + +```yaml +status: REJECTED + +violations: + - id: core_purity_violation + file: "solitaire_core/src/..." + reason: "uses std::fs" + +required_fixes: + - "move IO to solitaire_data" + +optional_improvements: + - "simplify event naming" +``` + +--- + +## 5. Enforcement Rules + +### Hard Fail (automatic rejection) + +* core crate uses IO / Bevy / network +* GameState mutated outside GameLogicSystem +* blocking async on main thread +* duplicate logic across crates +* merge function altered incorrectly + +--- + +### Soft Fail (allowed but flagged) + +* unnecessary complexity +* redundant tests +* minor architectural drift + +--- + +## 6. Iteration Loop + +Max attempts per task: **3** + +```text +Attempt 1 → Reject → Fix +Attempt 2 → Reject → Fix +Attempt 3 → Final decision +``` + +If still failing: +→ escalate to user + +--- + +## 7. Diff Strategy + +Builder MUST produce: + +* minimal diffs +* no unrelated refactors +* no formatting-only changes + +--- + +## 8. Test Strategy Integration + +Builder rules: + +* only add tests if: + + * fixing a bug + * protecting complex logic + * validating invariants + +Guardian rejects: + +* redundant tests +* no-op tests + +--- + +## 9. Optional Extensions + +### 9.1 Third Agent (Optimizer) + +role: performance + cleanup + +runs AFTER approval: + +* reduce allocations +* simplify logic +* improve ECS scheduling + +--- + +### 9.2 CI Integration + +Pipeline: + +```text +Builder → Guardian → cargo check → clippy → tests +``` + +Guardian runs BEFORE compilation to catch structural issues early. + +--- + +## 10. Example Interaction + +### Builder + +```yaml +intent: + feature: "undo stack limit fix" + crates_touched: [solitaire_core] + risk_level: low +``` + +```yaml +change_summary: "limit undo stack to 64 entries" + +files_modified: + - solitaire_core/src/game_state.rs + +notes: "prevents unbounded memory growth" +``` + +--- + +### Guardian + +```yaml +status: APPROVED + +notes: + - "respects core constraints" + - "no invariant violations" +``` + +--- + +## 11. Mental Model + +* Builder = **creative** +* Guardian = **strict** + +Builder explores +Guardian enforces + +Neither replaces the other. + +--- + +## 12. Success Criteria + +System is working if: + +* architectural violations go to ~0 +* code stays consistent across features +* refactors become safe +* complexity grows sub-linearly