chore: cleanup — remove dead weight, update .gitignore for binary test artifacts
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 31s
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 31s
This commit is contained in:
Binary file not shown.
@@ -1,14 +0,0 @@
|
||||
{
|
||||
"repoPath": "/home/user/repos/Mana-Loop",
|
||||
"lastCommit": "54d5e576abe2890bafb82ec682a6a73c2d7b8617",
|
||||
"indexedAt": "2026-05-07T10:03:30.497Z",
|
||||
"remoteUrl": "https://n8n-gitea:tkf9hfgxl2k4cmt@gitea.tailf367e3.ts.net/Anexim/Mana-Loop",
|
||||
"stats": {
|
||||
"files": 353,
|
||||
"nodes": 3795,
|
||||
"edges": 6409,
|
||||
"communities": 93,
|
||||
"processes": 146,
|
||||
"embeddings": 0
|
||||
}
|
||||
}
|
||||
@@ -1,33 +1,17 @@
|
||||
# Mana Loop — Project Architecture Guide for AI Agents
|
||||
# Mana Loop — Agent Guide
|
||||
|
||||
This document provides everything an AI agent needs to work on this codebase safely and effectively. **Read it in full before writing a single line of code.**
|
||||
|
||||
|
||||
## ⚠️ TERMINAL TOOL PROTOCOL
|
||||
After calling `run_command`, you MUST immediately call `get_process_status`
|
||||
with `wait: 30` in the SAME response. Never stop generating after a
|
||||
`status: "running"` result — always follow up immediately.
|
||||
|
||||
After ANY Edit tool call, immediately call read_file to verify
|
||||
the change is present. If it's not, use write_file instead.
|
||||
**Mana Loop** is a browser-based incremental/idle game. Pure client-side Next.js + Zustand — no backend, no database, no server state.
|
||||
|
||||
---
|
||||
|
||||
## 🔑 Git Credentials (SAVE THESE)
|
||||
|
||||
**Repository:** `git@gitea.tailf367e3.ts.net:Anexim/Mana-Loop.git`
|
||||
## 🔑 Git Credentials
|
||||
|
||||
**HTTPS URL with credentials:**
|
||||
```
|
||||
https://n8n-gitea:tkF9HFgxL2k4cmT@gitea.tailf367e3.ts.net/Anexim/Mana-Loop.git
|
||||
```
|
||||
|
||||
**Credentials:**
|
||||
- **User:** n8n-gitea
|
||||
- **Email:** n8n-gitea@anexim.local
|
||||
- **Password:** tkF9HFgxL2k4cmT
|
||||
|
||||
**To configure git:**
|
||||
**Configure once per session:**
|
||||
```bash
|
||||
git config --global user.name "n8n-gitea"
|
||||
git config --global user.email "n8n-gitea@anexim.local"
|
||||
@@ -35,125 +19,66 @@ git config --global user.email "n8n-gitea@anexim.local"
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ MANDATORY GIT WORKFLOW — MUST BE FOLLOWED
|
||||
## ⚠️ Mandatory Git Workflow
|
||||
|
||||
**Before starting ANY work, you MUST:**
|
||||
|
||||
1. **Pull the latest changes:**
|
||||
Every session:
|
||||
```bash
|
||||
# Start
|
||||
cd /home/user/repos/Mana-Loop && git pull origin master
|
||||
```
|
||||
|
||||
2. **Do your task** — Make all necessary code changes
|
||||
|
||||
3. **Before finishing, commit and push:**
|
||||
```bash
|
||||
cd /home/user/repos/Mana-Loop
|
||||
# Finish
|
||||
git add -A
|
||||
git commit -m "descriptive message about changes"
|
||||
git commit -m "type: short description"
|
||||
git push origin master
|
||||
```
|
||||
|
||||
This workflow is **enforced and non-negotiable**. Every session must start with `git pull` and end with `git push`.
|
||||
No exceptions. Always pull first, always push when done.
|
||||
|
||||
---
|
||||
|
||||
## 🎯 CURRENT PRIORITY — READ THIS FIRST
|
||||
## 🗂️ Gitea Is The Source Of Truth
|
||||
|
||||
Every session must start by reading the active strategy document to know what to work on:
|
||||
All task state lives in Gitea issues. No markdown files track status — the issue label and comments are the record.
|
||||
|
||||
**Gitea URL:** `https://gitea.tailf367e3.ts.net/Anexim/Mana-Loop`
|
||||
|
||||
**Labels:**
|
||||
| Label | Meaning |
|
||||
|---|---|
|
||||
| `ai:todo` | Not started |
|
||||
| `ai:in-progress` | Being worked on now |
|
||||
| `ai:review` | Done, needs human review |
|
||||
| `ai:blocked` | Stuck — comment explains why |
|
||||
| `ai:done` | Complete, issue closed |
|
||||
|
||||
### Session Start Protocol
|
||||
|
||||
```
|
||||
1. Read docs/project-structure.txt ← mandatory, every session
|
||||
2. Read docs/dependency-graph.json ← mandatory, every session
|
||||
3. Call get_repo_summary → see what's in-progress, blocked, todo
|
||||
4. If an issue is in-progress → call get_issue_context on it and resume
|
||||
5. If nothing in-progress → pick the highest-priority todo
|
||||
6. Call update_issue_status → move it to "in-progress"
|
||||
7. Work on it
|
||||
8. Log significant steps with add_comment
|
||||
9. When done → update_issue_status to "done" (closes the issue)
|
||||
```
|
||||
|
||||
Steps 1 and 2 are non-negotiable even if you think you know the codebase. `project-structure.txt` tells you exactly where files live so you don't waste tool calls searching. `dependency-graph.json` tells you the blast radius of any change before you make it — who imports what, so you never edit a shared file blind.
|
||||
|
||||
**How to use `dependency-graph.json`:**
|
||||
```bash
|
||||
cat docs/strategy/overall-remediation-plan.md
|
||||
```
|
||||
|
||||
The strategy defines the current phase and task queue. **Do not pick tasks on your own.** Always work on the highest-priority incomplete task from the strategy.
|
||||
|
||||
Current active task queue (update this when the strategy changes):
|
||||
|
||||
| # | Task | Status |
|
||||
|---|------|--------|
|
||||
| TASK-001 | Playwright setup + baseline E2E tests | ⬜ |
|
||||
| TASK-002 | Enchanting E2E tests (3-step flow) | ⬜ |
|
||||
| TASK-003 | Equipment E2E tests (equip, 2H block, unequip) | ⬜ |
|
||||
| TASK-004 | Combat E2E tests (cast, HP, floor advance) | ⬜ |
|
||||
| TASK-005 | `globals.css` design tokens | ⬜ |
|
||||
| TASK-006 | Left panel redesign | ⬜ |
|
||||
| TASK-007 | Skill system v2 (`computeStats` + migration) | ⬜ |
|
||||
| TASK-008 | Enchanting UI fix (store as source of truth) | ⬜ |
|
||||
| TASK-009 | Attunement expansion (new attunements + path choice) | ⬜ |
|
||||
| TASK-010 | Prestige rework (path bonuses) | ⬜ |
|
||||
| TASK-011 | Full UI redesign (remaining tabs) | ⬜ |
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Crash Recovery Protocol
|
||||
|
||||
If the agent's session ends mid-task, a fresh session **must** resume from where it left off, not restart.
|
||||
|
||||
### Saving progress (MANDATORY after every significant step):
|
||||
```
|
||||
Call save_progress with:
|
||||
task_id: "TASK-XXX-task-name"
|
||||
status: "in_progress"
|
||||
completed_steps: ["step 1 description", "step 2 description"]
|
||||
next_step: "what to do next"
|
||||
notes: "any context for the next session"
|
||||
project_path: "/home/user/repos/Mana-Loop"
|
||||
```
|
||||
|
||||
### On session start — check for existing progress:
|
||||
```bash
|
||||
cat docs/.workflow/TASK-XXX-task-name.json 2>/dev/null
|
||||
```
|
||||
|
||||
If a Work-in-Progress entry exists in the active-task-log:
|
||||
- **Resume from the last recorded step.** Do not restart the task.
|
||||
- Read the saved notes to understand context.
|
||||
|
||||
If no Work-in-Progress entry exists:
|
||||
- Initialize the task using the Task Initialization Protocol below.
|
||||
|
||||
---
|
||||
|
||||
## 📖 MANDATORY CONTEXT FILES — READ BEFORE EVERY TASK
|
||||
|
||||
**You must read these files at the start of every session before writing any code:**
|
||||
|
||||
```bash
|
||||
# 1. Auto-generated project file tree
|
||||
cat docs/project-structure.txt
|
||||
|
||||
# 2. Module dependency graph — who imports whom
|
||||
cat docs/dependency-graph.json
|
||||
|
||||
# 3. Circular dependency report — red alert if non-empty
|
||||
cat docs/circular-deps.txt
|
||||
|
||||
# 4. The strategy document (active priorities)
|
||||
cat docs/strategy/overall-remediation-plan.md
|
||||
|
||||
# 5. Any existing progress checkpoint for current task
|
||||
cat docs/.workflow/TASK-*.json 2>/dev/null
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### How to use `docs/dependency-graph.json`
|
||||
|
||||
The graph is a JSON object where **keys are files** and **values are arrays of files they import**.
|
||||
|
||||
**To find the blast radius of changing a file** (what will break):
|
||||
```bash
|
||||
# What files will break if I touch stores/skillStore.ts?
|
||||
node -e "
|
||||
const d = require('./docs/dependency-graph.json').graph;
|
||||
const target = 'stores/skillStore.ts';
|
||||
const affected = Object.entries(d).filter(([,deps]) => deps.some(dep => dep.includes(target)));
|
||||
affected.forEach(([f]) => console.log(f));
|
||||
Object.entries(d)
|
||||
.filter(([,deps]) => deps.some(dep => dep.includes(target)))
|
||||
.forEach(([f]) => console.log(f));
|
||||
"
|
||||
```
|
||||
|
||||
**To find what a file depends on** (its imports):
|
||||
```bash
|
||||
# What does a file depend on?
|
||||
node -e "
|
||||
const d = require('./docs/dependency-graph.json').graph;
|
||||
const key = Object.keys(d).find(k => k.includes('skillStore'));
|
||||
@@ -161,451 +86,203 @@ console.log(JSON.stringify(d[key], null, 2));
|
||||
"
|
||||
```
|
||||
|
||||
### How to use `docs/circular-deps.txt`
|
||||
### Progress Logging
|
||||
|
||||
If this file contains anything other than "No circular dependencies found", **stop and fix the circulars before touching any of the involved files**. Circular imports are the #1 cause of silent runtime failures in this codebase.
|
||||
Use `add_comment` on the issue to log what you did. A good comment includes:
|
||||
- What was changed and why
|
||||
- Any errors encountered and how they were resolved
|
||||
- Exact files modified
|
||||
- Output of `bun run typecheck` or `bun run test` if relevant
|
||||
|
||||
### When to re-generate the dependency graph manually
|
||||
|
||||
The graph is auto-generated on commit via husky, but if you need fresh data mid-session:
|
||||
```bash
|
||||
node .husky/scripts/generate-dependency-graph.js
|
||||
```
|
||||
If you stop mid-task for any reason, leave a comment with `STATUS: STOPPED` so the next session knows exactly where to resume.
|
||||
|
||||
---
|
||||
|
||||
## 🧰 AVAILABLE TOOLS IN THIS ENVIRONMENT
|
||||
## ⚙️ Terminal Tool Protocol — READ THIS
|
||||
|
||||
The following OpenWebUI tools are available in this agent session. Use them — they exist to make your work safer and faster.
|
||||
The terminal tool is **async**. `run_command` starts a process and returns immediately with `status: "running"`. You **must** follow up with `get_process_status` in the same response turn.
|
||||
|
||||
**Correct pattern — always do this:**
|
||||
```
|
||||
run_command({ command: "cd /home/user/repos/Mana-Loop && bun run typecheck" })
|
||||
→ { status: "running", id: "abc123" }
|
||||
|
||||
[IMMEDIATELY call — do NOT stop here]
|
||||
|
||||
get_process_status({ process_id: "abc123", wait: 60 })
|
||||
→ { status: "done", output: [...] }
|
||||
```
|
||||
|
||||
**Never** end your response after seeing `status: "running"`. Always call `get_process_status` in the same turn. If you hit output length limits, the user will say "continue" and you pick up from `get_process_status`.
|
||||
|
||||
For long-running commands (full tsc, test suite), use `wait: 120`.
|
||||
|
||||
---
|
||||
|
||||
### 1. Sub Agent (`run_sub_agent`, `run_parallel_sub_agents`)
|
||||
## 🤖 Sub-Agent Usage
|
||||
|
||||
**What it does:** Delegates a tool-heavy task to a fresh isolated context. The sub-agent runs its own tool loop and returns only the final result, keeping the main conversation context clean.
|
||||
Use `run_sub_agent` when a task needs 3+ sequential tool calls that don't depend on the main conversation (file reading, grep investigations, isolated fixes).
|
||||
|
||||
**When to use it:**
|
||||
- Any investigation that requires 3+ sequential tool calls (file reads, git operations, analysis)
|
||||
- Parallel research tasks that don't depend on each other
|
||||
- Heavy grep/search operations that would pollute the main context
|
||||
**Key rule:** Sub-agents have zero context from the parent conversation. Paste everything they need directly into the `prompt` field — file contents, task description, constraints, expected output format.
|
||||
|
||||
**How to invoke:**
|
||||
```
|
||||
Call run_sub_agent with:
|
||||
description: "Brief task summary shown as status"
|
||||
prompt: "Full detailed instructions — include ALL context the sub-agent needs,
|
||||
it has NO access to this conversation history"
|
||||
```
|
||||
**When to use sub-agents:**
|
||||
- Investigating what files access a given function/type
|
||||
- Running a fix + typecheck + commit as an isolated unit
|
||||
- Parallel context gathering (use `run_parallel_sub_agents`)
|
||||
|
||||
**Critical:** The sub-agent starts with zero context. Paste the relevant file contents, task spec, and constraints directly into the `prompt` field. Do not assume it knows anything.
|
||||
|
||||
**Parallel tasks:**
|
||||
```
|
||||
Call run_parallel_sub_agents with:
|
||||
tasks: [
|
||||
{ description: "...", prompt: "..." },
|
||||
{ description: "...", prompt: "..." }
|
||||
]
|
||||
```
|
||||
Use this when tasks are independent (e.g. investigating combat while also reading skill files).
|
||||
**When NOT to use sub-agents:**
|
||||
- Simple single-file reads — just read the file directly
|
||||
- Tasks that need the result of a prior tool call from this session
|
||||
|
||||
---
|
||||
|
||||
### 2. Dev Workflow Pro (`save_progress`, `run_checks`)
|
||||
## 🛠️ Tools Available
|
||||
|
||||
**What it does:** Runs quality checks (`typecheck`, `lint`, `test`) from within the agent session, and saves task progress as JSON checkpoints in `docs/.workflow/`.
|
||||
|
||||
**⚠️ Configuration required:** The `project_path` valve must be set to `/home/user/repos/Mana-Loop` for this tool to work. If it returns "Project path is missing", the valve isn't configured — fall back to `run_sub_agent` with a shell command.
|
||||
|
||||
**Verify it works:**
|
||||
```
|
||||
Call run_checks with:
|
||||
checks: ["lint"]
|
||||
project_path: "/home/user/repos/Mana-Loop"
|
||||
```
|
||||
If this returns ✅ lint output, it's working. If it errors, use the sub-agent fallback below.
|
||||
|
||||
**Sub-agent fallback (always works):**
|
||||
```
|
||||
Call run_sub_agent with:
|
||||
description: "Run lint and typecheck"
|
||||
prompt: "cd /home/user/repos/Mana-Loop && bun run lint && bun run typecheck.
|
||||
Return the full output including any errors."
|
||||
```
|
||||
|
||||
**Saving progress between sessions:**
|
||||
```
|
||||
Call save_progress with:
|
||||
task_id: "TASK-001-playwright-setup"
|
||||
status: "in_progress"
|
||||
completed_steps: ["installed playwright", "configured playwright.config.ts"]
|
||||
next_step: "write first E2E test for enchanting flow"
|
||||
notes: "need to verify test:ui script works before writing tests"
|
||||
project_path: "/home/user/repos/Mana-Loop"
|
||||
```
|
||||
Progress is saved to `docs/.workflow/TASK-001-playwright-setup.json`. Read it at the start of a resumed task.
|
||||
|
||||
---
|
||||
|
||||
### 3. Advisor (`ask_advisor`, `debate`)
|
||||
|
||||
**What it does:** Calls a specialist LLM in complete isolation to get a second opinion before making a decision. Zero context pollution — only your question and the context you paste reaches it.
|
||||
|
||||
**When to use it — this is mandatory for:**
|
||||
- Splitting or refactoring any file → use `advisor_type: "refactor"`
|
||||
- Any new game mechanic that touches more than 2 systems → use `advisor_type: "code"`
|
||||
- Design decisions that could affect balance or lore → use `advisor_type: "lore"`
|
||||
- Before committing a significant implementation → use `advisor_type: "review"`
|
||||
|
||||
**Advisor types:**
|
||||
| Type | When to use |
|
||||
| Tool | When to use |
|
||||
|------|-------------|
|
||||
| `refactor` | Before splitting any file. Paste the FULL file content in `context`. |
|
||||
| `code` | TypeScript / React / Zustand / game architecture decisions |
|
||||
| `lore` | Game mechanic consistency, attunement balance, prestige design |
|
||||
| `review` | Bug-finding pass on a plan or code snippet before committing |
|
||||
| `challenge` | Argues AGAINST your approach — run before major architectural decisions |
|
||||
| `general` | Anything else |
|
||||
| `get_repo_summary` | Session start — see all open issues by state |
|
||||
| `get_issue_context` | Resuming — read issue body + all comments |
|
||||
| `update_issue_status` | Move issue through workflow, optionally add comment |
|
||||
| `add_comment` | Log progress, errors, decisions on an issue |
|
||||
| `create_issue` | Found a new bug or task that warrants its own issue |
|
||||
| `run_sub_agent` | Delegate isolated investigation or fix |
|
||||
| `run_parallel_sub_agents` | Parallel independent investigations |
|
||||
| `ask_advisor` | Second opinion before a refactor or architectural decision |
|
||||
| `run_command` + `get_process_status` | Terminal commands (always pair these) |
|
||||
| `read_file` | Read a file |
|
||||
| `write_file` | Write a file (prefer over Edit for whole-file rewrites) |
|
||||
| `Edit` | Targeted in-file edits — **always verify with `read_file` after** |
|
||||
|
||||
**Example — checking a refactor plan:**
|
||||
```
|
||||
Call ask_advisor with:
|
||||
question: "I want to split skillStore.ts into skillStore.ts and skillEvolution.ts.
|
||||
Is this safe? What are the circular import risks?"
|
||||
advisor_type: "refactor"
|
||||
context: "[paste the full skillStore.ts content here]"
|
||||
```
|
||||
> ⚠️ `Edit` silently returns `""` on both success and failure. Always read the file back after editing to confirm the change applied. If it didn't, use `write_file` instead.
|
||||
|
||||
---
|
||||
|
||||
### 4. Game Dev Agent Skills (Inlet Filter)
|
||||
## 🏗️ Project Architecture
|
||||
|
||||
**What it does:** Automatically injects engineering skill workflows (spec, TDD, debug, refactor, perf, review, security) into the system prompt based on keywords in your message.
|
||||
|
||||
**⚠️ This is a Filter, not a Tool — it requires specific setup to work:**
|
||||
|
||||
1. It must be added as a **Filter** in OpenWebUI under Workspace → Functions → Filters (NOT under Tools)
|
||||
2. It must be toggled **ON** for the current model or workspace
|
||||
3. Keyword detection is automatic — the workflow injects based on what words appear in the user's message
|
||||
|
||||
**Trigger keywords:**
|
||||
| Skill | Keywords that activate it |
|
||||
|-------|--------------------------|
|
||||
| `spec` | spec, specifications, prd, scope, requirements |
|
||||
| `debug` | bug, error, crash, broken, fix, not working |
|
||||
| `plan` | plan, breakdown, tasks, todo, roadmap, milestone |
|
||||
| `implement` | implement, build, write, create, add feature |
|
||||
| `tdd` | test, tdd, unit test, failing test, coverage, vitest |
|
||||
| `perf` | slow, lag, fps, frame time, memory leak, optimise |
|
||||
| `review` | review, code quality, refactor, clean up, PR |
|
||||
| `security` | auth, login, token, exploit, injection, hack |
|
||||
|
||||
**If it's not injecting:** Check that it's installed as a Filter (not a Tool) and is enabled for the active model. In forced mode, set the `forced_skill` valve to the skill you want instead of `"auto"`.
|
||||
|
||||
---
|
||||
|
||||
## 🔴 BEFORE EDITING ANY FILE — Impact Analysis Protocol
|
||||
|
||||
Before modifying a function, store, or component, always answer these questions:
|
||||
|
||||
```bash
|
||||
# 1. Who imports this file?
|
||||
node -e "
|
||||
const d = require('./docs/dependency-graph.json').graph;
|
||||
const me = 'stores/skillStore.ts'; // change this
|
||||
Object.entries(d).filter(([,v]) => v.some(dep => dep.includes(me)))
|
||||
.forEach(([f]) => console.log('imports me:', f));
|
||||
"
|
||||
|
||||
# 2. Are there circular deps involving this file?
|
||||
grep -i "skillStore" docs/circular-deps.txt
|
||||
|
||||
# 3. What tests cover this file?
|
||||
find src -name "*.test.ts" | xargs grep -l "skillStore" 2>/dev/null
|
||||
```
|
||||
|
||||
If the impact is HIGH (5+ files import it, or it's in a circular chain) — call the Advisor with `advisor_type: "review"` or `advisor_type: "challenge"` before making changes.
|
||||
|
||||
---
|
||||
|
||||
## 🗂️ Project Overview
|
||||
|
||||
**Mana Loop** is a browser-based incremental/idle game built with:
|
||||
- **Framework:** Next.js 16 with App Router
|
||||
### Stack
|
||||
- **Framework:** Next.js 16, App Router
|
||||
- **Language:** TypeScript 5
|
||||
- **Styling:** Tailwind CSS 4 with shadcn/ui components
|
||||
- **State Management:** Zustand with persist middleware (modular store architecture)
|
||||
- **Database:** Prisma ORM with SQLite
|
||||
- **Test Runner:** Vitest
|
||||
- **Package Manager:** Bun
|
||||
|
||||
## Core Game Loop
|
||||
|
||||
1. **Mana Gathering** — Click or auto-generate mana over time
|
||||
2. **Studying** — Spend mana to learn skills and spells
|
||||
3. **Combat** — Climb the Spire, defeat guardians, sign pacts
|
||||
4. **Crafting** — Enchant equipment with spell effects via 3-step process
|
||||
5. **Prestige** — Reset progress for permanent bonuses (Insight)
|
||||
|
||||
---
|
||||
|
||||
## Directory Structure
|
||||
|
||||
**See `docs/project-structure.txt` for the full auto-generated tree.** The key directories:
|
||||
- **Styling:** Tailwind CSS 4 + shadcn/ui
|
||||
- **State:** Zustand with persist middleware — **all game state lives here, no backend**
|
||||
- **Tests:** Vitest (unit), Playwright (E2E)
|
||||
- **Package manager:** Bun
|
||||
|
||||
### Key Directories
|
||||
```
|
||||
src/lib/game/stores/ # ✅ USE THESE — Zustand store modules
|
||||
src/lib/game/crafting-actions/ # Modular crafting system
|
||||
src/lib/game/data/ # Game data definitions
|
||||
src/lib/game/constants/ # Game constants by domain
|
||||
src/lib/game/utils/ # Utility functions
|
||||
src/lib/game/store/ # ⚠️ LEGACY — migration in progress
|
||||
src/lib/game/store-modules/ # ⚠️ LEGACY — being migrated to utils/
|
||||
src/lib/game/skill-evolution-modules/ # ⚠️ LEGACY — being replaced by computeStats()
|
||||
src/components/game/ # All game UI components (modular structure)
|
||||
src/lib/game/stores/__tests__/ # Store-level unit tests
|
||||
e2e/ # Playwright E2E tests (added in Phase 0)
|
||||
src/lib/game/stores/ ← ✅ Active Zustand store modules (USE THESE)
|
||||
src/lib/game/crafting-actions/ ← Modular crafting actions
|
||||
src/lib/game/constants/ ← Game data (guardians, spells, skills, elements)
|
||||
src/lib/game/types/ ← TypeScript interfaces
|
||||
src/lib/game/utils/ ← Pure utility functions
|
||||
src/lib/game/store/ ← ⚠️ Legacy store slices (migration in progress)
|
||||
src/lib/game/store-modules/ ← ⚠️ Legacy modules (being replaced)
|
||||
src/components/game/ ← All UI components
|
||||
e2e/ ← Playwright E2E tests
|
||||
```
|
||||
|
||||
---
|
||||
### Store Map
|
||||
| Store | File | Owns |
|
||||
|-------|------|------|
|
||||
| Game | `stores/gameStore.ts` | Core state, tick loop, equip/unequip |
|
||||
| Mana | `stores/manaStore.ts` | Raw mana, elements, conversion |
|
||||
| Combat | `stores/combatStore.ts` | Spire, spells, floor progression |
|
||||
| Prestige | `stores/prestigeStore.ts` | Insight, upgrades, loop end |
|
||||
| Skill | `stores/skillStore.ts` | Skill levels, studying |
|
||||
| UI | `stores/uiStore.ts` | Modal state, debug flags |
|
||||
|
||||
## Key Systems
|
||||
|
||||
### State Management
|
||||
|
||||
| Store | File | Responsibility |
|
||||
|-------|------|---------------|
|
||||
| Game Store | `stores/gameStore.ts` | Core state, tick loop, equip/unequip |
|
||||
| Mana Store | `stores/manaStore.ts` | Raw mana, elements, conversion |
|
||||
| Combat Store | `stores/combatStore.ts` | Spire, spells, floor progression |
|
||||
| Prestige Store | `stores/prestigeStore.ts` | Insight, upgrades, loop end |
|
||||
| Skill Store | `stores/skillStore.ts` | Skill levels, studying |
|
||||
| UI Store | `stores/uiStore.ts` | Modal state, debug flags |
|
||||
|
||||
Cross-store access pattern:
|
||||
Cross-store reads:
|
||||
```typescript
|
||||
// In combatStore.ts, reading mana state:
|
||||
// In combatStore.ts reading mana state:
|
||||
const manaState = useManaStore.getState();
|
||||
```
|
||||
|
||||
### Effect System (`effects.ts`) — CRITICAL
|
||||
### Effect System — Critical
|
||||
All stat modifications flow through `getUnifiedEffects(state)` in `effects.ts`. **Never read skill levels directly to compute a stat.** Always use the unified effects object.
|
||||
|
||||
All stat modifications flow through `getUnifiedEffects(state)`. **Never read skill levels directly to compute a stat** — always use the unified effects object.
|
||||
|
||||
When adding a new stat:
|
||||
1. Add to `ComputedEffects` interface in `upgrade-effects.ts`
|
||||
Adding a new stat:
|
||||
1. Add to `ComputedEffects` interface in `upgrade-effects.types.ts`
|
||||
2. Add mapping in `computeEquipmentEffects()` in `effects.ts`
|
||||
3. Apply in the relevant game logic using `getUnifiedEffects(state)`
|
||||
3. Apply in game logic via `getUnifiedEffects(state)`
|
||||
|
||||
### Crafting System (3-Step Enchantment)
|
||||
Flow: **Design → Prepare → Apply**
|
||||
|
||||
The enchantment flow is **Design → Prepare → Apply**. Each step is in its own action module:
|
||||
Action modules:
|
||||
- `crafting-actions/design-actions.ts`
|
||||
- `crafting-actions/preparation-actions.ts`
|
||||
- `crafting-actions/application-actions.ts`
|
||||
|
||||
The store is the **single source of truth** for enchantment selection state — never use local component state for selected effects.
|
||||
The crafting store is the **single source of truth** for enchantment selection state. Never use local component state for selected effects.
|
||||
|
||||
### Skill System (v2 — `computeStats()`)
|
||||
|
||||
The old `skill-evolution-modules/` system is being replaced by a flat `computeStats()` function (see strategy doc Phase 1). Until migration is complete:
|
||||
- Old skills still exist in `skill-evolution-modules/`
|
||||
- New skills will be defined in `constants/skills-v2.ts`
|
||||
- `computeStats()` in `constants/skills-v2.ts` is the authoritative stat calculator
|
||||
### Skill System (v2)
|
||||
New skills: define in `constants/skills-v2.ts`, add to `computeStats()`.
|
||||
Old skills: still in `skill-evolution-modules/` — migration ongoing.
|
||||
Never add new skills to `skill-evolution-modules/`.
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ Common Pitfalls
|
||||
## 🔍 Impact Analysis (Before Editing Shared Files)
|
||||
|
||||
1. **Forgetting `getUnifiedEffects()`** — never modify stats directly; use the effect system
|
||||
2. **Using legacy store** — always use `stores/` (new), not `store/` (legacy)
|
||||
3. **Not checking circular deps** — read `docs/circular-deps.txt` before modifying shared files
|
||||
4. **Bypassing crafting-actions** — use modular actions for any crafting feature
|
||||
5. **Using local state for enchantment selection** — always use the crafting store
|
||||
6. **Adding skills to `skill-evolution-modules/`** — use `constants/skills-v2.ts` for new skills
|
||||
Before modifying any file imported by 3+ other files, check the dependency graph you read at session start. If 5+ files import it, or it's in a circular chain (check `docs/circular-deps.txt`), use `ask_advisor` with `advisor_type: "review"` before touching it.
|
||||
|
||||
---
|
||||
|
||||
## 🧪 Testing Priorities
|
||||
## ✅ Definition of Done
|
||||
|
||||
Tests are non-negotiable. Run `npm run test` before every commit. All tests must pass.
|
||||
A task is complete only when ALL of these are true:
|
||||
|
||||
**Priority order (if time is short, protect these first):**
|
||||
|
||||
| Priority | Test Type | What |
|
||||
|----------|-----------|------|
|
||||
| 🔴 Critical | E2E | Enchantment flow (Design → Prepare → Apply) |
|
||||
| 🔴 Critical | E2E | Gear equipping + 2H weapon blocking |
|
||||
| 🔴 Critical | E2E | Combat tick and floor advancement |
|
||||
| 🟡 High | E2E | Locked effects cannot be selected |
|
||||
| 🟡 High | Unit | Store actions that modify `rawMana` |
|
||||
| 🟡 High | Unit | Store actions that modify `equippedInstances` |
|
||||
| 🟡 High | Unit | `computeStats()` returns correct values per skill level |
|
||||
| 🟢 Medium | Unit | `computeRegen`, `computeMaxMana`, `calcDamage` |
|
||||
| 🟢 Medium | Unit | `canAffordSpellCost`, `spendRawMana`, `deductSpellCost` |
|
||||
|
||||
**When fixing a bug:** write the failing test FIRST, then fix until it passes.
|
||||
|
||||
Test locations:
|
||||
- E2E: `e2e/*.spec.ts`
|
||||
- Store tests: `src/lib/game/stores/__tests__/`
|
||||
- Store-level tests: `src/lib/game/store-tests/`
|
||||
- Split tests: `src/lib/game/stores-split-tests/`
|
||||
- [ ] Implementation done
|
||||
- [ ] `bun run typecheck` — 0 errors
|
||||
- [ ] `bun run lint` — 0 errors
|
||||
- [ ] Relevant tests pass (`bun run test`)
|
||||
- [ ] New tests added for any bug fix or new system
|
||||
- [ ] Changes committed and pushed
|
||||
- [ ] Gitea issue updated to `ai:done` (closes the issue)
|
||||
|
||||
---
|
||||
|
||||
## Git Hooks (Husky)
|
||||
## 🚫 Banned — Never Add These
|
||||
|
||||
### Pre-Commit Hook (`.husky/pre-commit`)
|
||||
|
||||
Runs automatically before each commit:
|
||||
1. **File Size Check** — no staged file may exceed 400 lines
|
||||
2. **Project Structure** — regenerates `docs/project-structure.txt`
|
||||
3. **Dependency Graph** — regenerates `docs/dependency-graph.json` and `docs/circular-deps.txt` via madge
|
||||
4. Auto-stages all generated docs files
|
||||
|
||||
### Post-Merge Hook (`.husky/post-merge`)
|
||||
|
||||
Runs after merge — auto-installs if `package.json` changed.
|
||||
|
||||
### Madge Setup
|
||||
|
||||
If `docs/dependency-graph.json` is missing or stale, install madge and regenerate:
|
||||
```bash
|
||||
bun add -d madge
|
||||
node .husky/scripts/generate-dependency-graph.js
|
||||
```
|
||||
- **Lifesteal / healing mechanics** — player cannot take damage
|
||||
- **Scroll crafting** — violates NO INSTANT FINISHING design pillar
|
||||
- **Ascension skills** — deleted
|
||||
- **LabTab** — permanently removed, do not re-add under any name
|
||||
- **Pause button** — does not exist
|
||||
- **Mana types:** `life`, `blood`, `wood`, `mental`, `force` — banned
|
||||
|
||||
---
|
||||
|
||||
## File Size Guidelines
|
||||
## 📐 File Size
|
||||
|
||||
**400 lines maximum** per file (enforced by pre-commit hook).
|
||||
|
||||
| Directory | Purpose | Target |
|
||||
|-----------|---------|--------|
|
||||
| `stores/` | Zustand store modules | < 400 lines |
|
||||
| `crafting-actions/` | Crafting system actions | < 400 lines |
|
||||
| `constants/` | Game constants by domain | < 400 lines |
|
||||
| `data/` | Game data definitions | < 400 lines |
|
||||
| `components/game/tabs/` | UI tab components | < 400 lines |
|
||||
|
||||
---
|
||||
|
||||
## 🚫 Banned Content
|
||||
|
||||
### Never Add These
|
||||
|
||||
- **Lifesteal / Healing mechanics** — the player cannot take damage. Healing is unnecessary.
|
||||
- **Scroll Crafting** — violates NO INSTANT FINISHING design pillar.
|
||||
- **Ascension Skills** — deleted.
|
||||
|
||||
### Banned Mana Types
|
||||
|
||||
Never re-add: `life`, `blood`, `wood`, `mental`, `force`
|
||||
|
||||
### Removed Features
|
||||
|
||||
- **LabTab** — permanently removed. Do not re-add under any name.
|
||||
- **Pause button** — does not exist. Do not add one.
|
||||
**400 lines maximum** per file — enforced by pre-commit hook. If a file approaches this, split it before the hook rejects the commit.
|
||||
|
||||
---
|
||||
|
||||
## 🔮 Mana Types Reference
|
||||
|
||||
### Base (7)
|
||||
| Element | Symbol | Color |
|
||||
|---------|--------|-------|
|
||||
| Fire | 🔥 | #FF6B35 |
|
||||
| Water | 💧 | #4ECDC4 |
|
||||
| Air | 🌬️ | #00D4FF |
|
||||
| Earth | ⛰️ | #F4A261 |
|
||||
| Light | ☀️ | #FFD700 |
|
||||
| Dark | 🌑 | #9B59B6 |
|
||||
| Death | 💀 | #778CA3 |
|
||||
**Base (7):** Fire 🔥, Water 💧, Air 🌬️, Earth ⛰️, Light ☀️, Dark 🌑, Death 💀
|
||||
|
||||
### Utility (1)
|
||||
| Element | Symbol | Color |
|
||||
|---------|--------|-------|
|
||||
| Transference | 🔗 | #1ABC9C |
|
||||
**Utility (1):** Transference 🔗
|
||||
|
||||
### Compound (3) — Fire+Earth=Metal, Earth+Water=Sand, Fire+Air=Lightning
|
||||
**Compound (3):** Fire+Earth=Metal, Earth+Water=Sand, Fire+Air=Lightning
|
||||
|
||||
### Exotic (3) — Sand+Sand+Light=Crystal, Fire+Fire+Light=Stellar, Dark+Dark+Death=Void
|
||||
**Exotic (3):** Sand+Sand+Light=Crystal, Fire+Fire+Light=Stellar, Dark+Dark+Death=Void
|
||||
|
||||
---
|
||||
|
||||
## Adding New Things — Quick Reference
|
||||
## ⚡ Quick Reference — Adding Things
|
||||
|
||||
### New Effect
|
||||
**New effect:**
|
||||
1. Define in `data/enchantment-effects.ts`
|
||||
2. Add stat mapping in `effects.ts` → `computeEquipmentEffects()`
|
||||
3. Apply in game logic using `getUnifiedEffects(state)`
|
||||
3. Apply via `getUnifiedEffects(state)`
|
||||
|
||||
### New Skill
|
||||
1. Define in `constants/skills-v2.ts` (NOT `skill-evolution-modules/`)
|
||||
**New skill:**
|
||||
1. Define in `constants/skills-v2.ts`
|
||||
2. Add to `computeStats()` effect mapping
|
||||
3. UI auto-reads from structure
|
||||
|
||||
### New Spell
|
||||
**New spell:**
|
||||
1. Define in `constants/spells.ts`
|
||||
2. Add enchantment in `data/enchantment-effects.ts`
|
||||
3. Add research skill in `constants/skills-v2.ts`
|
||||
4. Map research to effect in `EFFECT_RESEARCH_MAPPING`
|
||||
|
||||
---
|
||||
|
||||
## 🔄 Agent Operational Protocol
|
||||
|
||||
### 1. State & Resumption Protocol
|
||||
|
||||
Before starting any implementation work, determine the current project state:
|
||||
|
||||
1. Read:
|
||||
- `docs/strategy/overall-remediation-plan.md`
|
||||
- `docs/active-task-log.md` (if it exists)
|
||||
- `docs/.workflow/TASK-*.json` (any saved progress)
|
||||
|
||||
2. Identify the first roadmap item marked `[ ]` in the **Current Priority** table at the top of this file.
|
||||
|
||||
3. If a Work-in-Progress entry exists for that task, **resume from the last recorded step**. Do not restart.
|
||||
|
||||
4. If no Work-in-Progress entry exists, initialize using the Task Initialization Protocol.
|
||||
|
||||
### 2. Task Initialization Protocol
|
||||
|
||||
Before modifying code for a new task:
|
||||
|
||||
1. Update `docs/active-task-log.md`
|
||||
2. Record: task ID, objective, files expected to change, current status, planned tests
|
||||
3. Run baseline validation **before** editing:
|
||||
```bash
|
||||
bun run lint && bun run test
|
||||
```
|
||||
4. Record any failing baseline tests before implementation begins
|
||||
5. Call `save_progress` after completing each significant step
|
||||
|
||||
### 3. Definition of Done
|
||||
|
||||
A task is only complete when ALL of the following are true:
|
||||
|
||||
- [ ] Implementation is complete
|
||||
- [ ] Lint passes
|
||||
- [ ] All relevant tests pass (see Testing Priorities above)
|
||||
- [ ] New tests added for bug fixes or new systems
|
||||
- [ ] `docs/strategy/overall-remediation-plan.md` updated: `[ ]` → `[x]`
|
||||
- [ ] `docs/active-task-log.md` updated (marked `ARCHIVED` or cleared)
|
||||
- [ ] Changes committed and pushed:
|
||||
```bash
|
||||
git add -A
|
||||
git commit -m "feat: [task] — [summary]"
|
||||
git push origin master
|
||||
```
|
||||
|
||||
### 4. Roadmap Execution Rules
|
||||
|
||||
- Work on **ONE** roadmap task at a time unless explicitly told otherwise
|
||||
- Do not perform unrelated refactors
|
||||
- Do not expand scope beyond current task acceptance criteria
|
||||
- Large redesigns → split into `docs/tasks/`
|
||||
- Every task maps back to a strategy item
|
||||
|
||||
Reference in New Issue
Block a user