docs: compress AGENTS.md + split combat-skills.ts (432 → 187+248 lines)
Build and Publish Mana Loop Docker Image / build-and-publish (push) Failing after 32s

This commit is contained in:
2026-05-14 15:34:50 +02:00
parent 3e5b634815
commit 5cbe672b8f
8 changed files with 818 additions and 556 deletions
+43 -251
View File
@@ -1,288 +1,80 @@
# Mana Loop — Agent Guide
**Mana Loop** is a browser-based incremental/idle game. Pure client-side Next.js + Zustand no backend, no database, no server state.
Browser incremental/idle game. Next.js 16 + Zustand, no backend.
---
## 🔑 Git
## 🔑 Git Credentials
**HTTPS URL with credentials:**
```
https://n8n-gitea:tkF9HFgxL2k4cmT@gitea.tailf367e3.ts.net/Anexim/Mana-Loop.git
```
**Configure once per session:**
```bash
git config --global user.name "n8n-gitea"
git config --global user.email "n8n-gitea@anexim.local"
```
---
## Workflow
## ⚠️ Mandatory Git Workflow
Every session:
```bash
# Start
cd /home/user/repos/Mana-Loop && git pull origin master
# Finish
git add -A
git commit -m "type: short description"
git push origin master
# ... work ...
git add -A && git commit -m "type: desc" && git push origin master
```
No exceptions. Always pull first, always push when done.
## Session Start
---
1. `docs/project-structure.txt`
2. `docs/dependency-graph.json`
3. `get_repo_summary` → resume in-progress or pick top todo
4. `update_issue_status``ai:in-progress`
5. Work, log with `add_comment`, then `update_issue_status``ai:done`
## 🗂️ Gitea Is The Source Of Truth
## Labels
All task state lives in Gitea issues. No markdown files track status — the issue label and comments are the record.
`ai:todo` | `ai:in-progress` | `ai:review` | `ai:blocked` | `ai:done`
**Gitea URL:** `https://gitea.tailf367e3.ts.net/Anexim/Mana-Loop`
## Terminal Tool
**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 |
Always pair `run_command``get_process_status` in same turn. Use `wait: 120` for long tasks.
### Session Start Protocol
## Sub-Agents
```
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)
```
Use for 3+ sequential independent calls. Zero context from parent — paste everything needed.
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.
## Architecture
**How to use `dependency-graph.json`:**
```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';
Object.entries(d)
.filter(([,deps]) => deps.some(dep => dep.includes(target)))
.forEach(([f]) => console.log(f));
"
- **Stack:** Next.js 16, TS 5, Tailwind 4 + shadcn/ui, Zustand+persist, Vitest/Playwright, Bun
- **Active stores:** `src/lib/game/stores/{game,mana,combat,prestige,skill,ui}Store.ts`
- **Legacy (migrating):** `src/lib/game/store/` and `store-modules/`
- **Crafting:** 3-step flow — Design → Prepare → Apply via `crafting-actions/`
- **Skills v2:** `constants/skills-v2.ts` + `computeStats()` in effects
- **Effects:** All stat mods through `getUnifiedEffects()` — never read skill levels directly
# 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'));
console.log(JSON.stringify(d[key], null, 2));
"
```
### Adding Effects
1. `data/enchantment-effects.ts`
2. `effects.ts``computeEquipmentEffects()`
3. Access via `getUnifiedEffects(state)`
### Progress Logging
### Adding Skills
1. `constants/skills-v2.ts`
2. `computeStats()` mapping
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
### Adding Spells
1. `constants/spells.ts`
2. `data/enchantment-effects.ts`
3. `constants/skills-v2.ts` research skill
4. `EFFECT_RESEARCH_MAPPING`
If you stop mid-task for any reason, leave a comment with `STATUS: STOPPED` so the next session knows exactly where to resume.
## Banned
---
Lifesteal/healing, scroll crafting, ascension skills, LabTab, pause, mana types: `life`, `blood`, `wood`, `mental`, `force`
## ⚙️ Terminal Tool Protocol — READ THIS
## File Limit
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.
400 lines max (pre-commit hook enforces).
**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`.
---
## 🤖 Sub-Agent Usage
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).
**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.
**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`)
**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
---
## 🛠️ Tools Available
| Tool | When to use |
|------|-------------|
| `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** |
> ⚠️ `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.
---
## 🏗️ Project Architecture
### Stack
- **Framework:** Next.js 16, App Router
- **Language:** TypeScript 5
- **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/ ← ✅ 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 |
Cross-store reads:
```typescript
// In combatStore.ts reading mana state:
const manaState = useManaStore.getState();
```
### 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.
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 game logic via `getUnifiedEffects(state)`
### Crafting System (3-Step Enchantment)
Flow: **Design → Prepare → Apply**
Action modules:
- `crafting-actions/design-actions.ts`
- `crafting-actions/preparation-actions.ts`
- `crafting-actions/application-actions.ts`
The crafting store is the **single source of truth** for enchantment selection state. Never use local component state for selected effects.
### 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/`.
---
## 🔍 Impact Analysis (Before Editing Shared Files)
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.
---
## ✅ Definition of Done
A task is complete only when ALL of these are true:
- [ ] 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)
---
## 🚫 Banned — Never Add These
- **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
**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):** Fire 🔥, Water 💧, Air 🌬️, Earth ⛰️, Light ☀️, Dark 🌑, Death 💀
## Mana Types
**Base (7):** Fire 🔥 Water 💧 Air 🌬️ Earth ⛰️ Light ☀️ Dark 🌑 Death 💀
**Utility (1):** Transference 🔗
**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
---
## ⚡ Quick Reference — Adding Things
**New effect:**
1. Define in `data/enchantment-effects.ts`
2. Add stat mapping in `effects.ts``computeEquipmentEffects()`
3. Apply via `getUnifiedEffects(state)`
**New skill:**
1. Define in `constants/skills-v2.ts`
2. Add to `computeStats()` effect mapping
**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`
**Exotic (3):** Sand+Sand+Light=Crystal, Fire+Fire+Light=Stellar, Dark+Dark+Death=Void