e8fb2bc664
- docs/optimization-plan.html:纳入 worktree,顶部新增「★ 实现状态」章节 (优化点→实现→提交对照,2026-06-25 全部上线,含 3 个线上实测 bug 修复) - docs/index.html:登记 optimization-plan.html 到「设计方案」分类 - CLAUDE.md:模型档位表改为「按项目可配置 + 默认 opus-4.8」的解析优先级说明, 回退链改 opus→sonnet→fable,注明 fable-5 不再是内置默认 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
109 lines
5.6 KiB
Markdown
109 lines
5.6 KiB
Markdown
# CLAUDE.md
|
||
|
||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||
|
||
## Commands
|
||
|
||
```bash
|
||
npm install # install dependencies
|
||
npm run typecheck # tsc --noEmit (type check without build)
|
||
npm run build # compile TypeScript → dist/ (also copies schema.sql)
|
||
npm run dev # start daemon on http://127.0.0.1:4517
|
||
npm test # run all tests (node --test via tsx)
|
||
tsx --test test/<file>.test.ts # run a single test file
|
||
```
|
||
|
||
Worker processes can be run against TypeScript source directly (for dev/testing) via:
|
||
```bash
|
||
MAESTRO_WORKER_CMD="tsx src/executor/worker.ts" npm run dev
|
||
```
|
||
|
||
## Architecture
|
||
|
||
Maestro is a local-first daemon that manages tasks across multiple git projects. It drives tasks through a complexity-based approval pipeline and auto-executes approved tasks via headless Claude Code agents.
|
||
|
||
### Process Model (critical to understand)
|
||
|
||
The system is split into two strictly separated process roles:
|
||
|
||
**daemon** (`src/daemon/`) — the only DB writer. Responsible for:
|
||
- Serving REST + WebSocket API (`src/api/`)
|
||
- Running the orchestrator loop (tick = `ingest → reap → claim`)
|
||
- Spawning one worker OS process per task
|
||
- Ingesting worker output from `outbox.ndjson` into SQLite
|
||
- Reaping dead workers, managing retries/back-off, state transitions
|
||
|
||
**worker** (`src/executor/worker.ts` + `src/executor/pipeline.ts`) — a dumb executor that never touches the DB. Each task gets its own `node dist/executor/worker.js <runId>`. It reads only `runs/<runId>/job.json` and appends progress/results to `runs/<runId>/outbox.ndjson`. The daemon ingests this file idempotently via a `lastSeq` cursor.
|
||
|
||
Communication between daemon and worker is **file + signal only** (`job.json`, `outbox.ndjson`, `heartbeat`, `SIGTERM`). This makes execution survive daemon restarts.
|
||
|
||
### Key Source Modules
|
||
|
||
| Path | Purpose |
|
||
|---|---|
|
||
| `src/model/` | Types (`types.ts`), state machine (`status.ts`), complexity levels (`complexity.ts`), score scheduling algorithm (`scoring.ts`) |
|
||
| `src/store/` | SQLite access layer (`store.ts`), schema (`schema.sql`), state-machine guards, mappers |
|
||
| `src/daemon/orchestrator.ts` | Score-based task scheduling loop: `ingest → reap → claim` |
|
||
| `src/daemon/ingest.ts` | Reads worker outbox.ndjson, writes DB events, triggers WS push |
|
||
| `src/executor/protocol.ts` | File protocol definitions + heartbeat/liveness helpers |
|
||
| `src/executor/pipeline.ts` | Worker execution pipeline: worktree setup → agent run → verify → dual review → output |
|
||
| `src/executor/cc.ts` | Claude Agent SDK wrapper for headless CC runs |
|
||
| `src/executor/reviewer.ts` | Code review + security audit agent runs |
|
||
| `src/executor/merge.ts` | `--no-ff` auto-merge logic on exec_review accept |
|
||
| `src/api/server.ts` | Fastify REST + WebSocket server |
|
||
| `src/mcp/` | MCP server tools exposed to Claude Code sessions |
|
||
| `src/sync/` | One-way sync from legacy `todo.json` files |
|
||
| `web/` | Dashboard SPA (multi-project, real-time WS, inline approve/reject) |
|
||
|
||
### Task Lifecycle
|
||
|
||
```
|
||
init → [Hard: analyzing → plan_review] → [Medium: speccing → spec_review] → ready
|
||
→ queued → executing → exec_review → done
|
||
```
|
||
|
||
- **Hard**: planner agent produces analysis + task decomposition; requires `plan_review` approval
|
||
- **Medium**: agent writes a spec (what + why); requires `spec_review` approval
|
||
- **Easy**: agent writes operations record; goes directly to `ready`
|
||
- All tasks with code changes pass through `exec_review` (dual review: code-review + security audit)
|
||
- `accept` at `exec_review` triggers automatic `--no-ff` merge; `merge:false` skips merge
|
||
|
||
### Score Scheduling
|
||
|
||
```
|
||
score = P(self) + Σ P(completed deps) + Σ P(tasks blocked by self)
|
||
```
|
||
`P0=3, P1=2, P2=1`. Higher score → picked first. No preemption.
|
||
|
||
### Model Tier Assignment
|
||
|
||
Built-in default for **every role × every complexity** is `claude-opus-4-8` (`DEFAULT_MODEL` in `src/executor/models.ts`). Models are **configurable per project** via `projects.models` (JSON).
|
||
|
||
**Resolution order** (`resolveModel`, highest → lowest):
|
||
1. **`project.models[role]`** — per-project per-scenario config. Value is either a model id string (applies to all complexities) or `{easy,medium,hard}` (per-complexity). Applies to **all** roles incl. reviewer/conflict.
|
||
2. **legacy `project.model`** — single override, **executor/planner only** (NOT reviewer/conflict, preserving self-review/conflict-resolution independence).
|
||
3. **env vars** — `MAESTRO_MODEL_{EASY,MEDIUM,HARD}` (executor), `MAESTRO_MODEL_REVIEW_*` (reviewer), `MAESTRO_MODEL_PLAN_*` (planner).
|
||
4. **`DEFAULT_MODEL`** = `claude-opus-4-8`.
|
||
|
||
Example `projects.models`:
|
||
```json
|
||
{"executor":{"easy":"claude-sonnet-4-6","hard":"claude-opus-4-8"},"reviewer":"claude-fable-5"}
|
||
```
|
||
|
||
Model fallback chain on unavailability: `opus-4-8 → sonnet-4-6 → fable-5` (`MODEL_FALLBACK_CHAIN`). Note: `claude-fable-5` is no longer a built-in default (it is unavailable in some environments); configure it explicitly per project if desired.
|
||
|
||
### Data Directory
|
||
|
||
Default `~/.maestro/` — contains SQLite DB, `runs/<runId>/` directories (job.json, outbox.ndjson, heartbeat, sandbox.sb, transcripts), and git worktrees.
|
||
|
||
### Key Env Vars
|
||
|
||
| Var | Default | Note |
|
||
|---|---|---|
|
||
| `MAESTRO_PORT` | `4517` | daemon listen port |
|
||
| `MAESTRO_DATA_DIR` | `~/.maestro` | SQLite + worktree root |
|
||
| `MAESTRO_ORCH_INTERVAL` | `15` | orchestrator tick seconds; `0` disables |
|
||
| `MAESTRO_WORKER_CMD` | `node dist/executor/worker.js` | override for tsx dev |
|
||
| `MAESTRO_NOTIFY` | on | set `0` to disable macOS notifications |
|
||
| `MAESTRO_SANDBOX` | off | set `on` for OS-level write fence + ulimits on workers |
|