按 plan ①②③④ 定稿(用户确认): - reviewer 三档统一 fable-5(不被 project.model 降档,保复审严格度) - planner hard 拆解 opus→fable-5(最烧脑用最强档);medium=opus/easy=sonnet 不变 - conflict 固定 fable-5(解冲突恒用最强档) - MODEL_FALLBACK_CHAIN: [fable-5, opus-4-8, sonnet-4-6](fable 置链首) - executor 档不变(per plan ②);CLAUDE.md 档位表同步更正 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
5.1 KiB
CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
Commands
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:
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.ndjsoninto 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_reviewapproval - Medium: agent writes a spec (what + why); requires
spec_reviewapproval - Easy: agent writes operations record; goes directly to
ready - All tasks with code changes pass through
exec_review(dual review: code-review + security audit) acceptatexec_reviewtriggers automatic--no-ffmerge;merge:falseskips 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
| Role | Easy | Medium | Hard |
|---|---|---|---|
| executor | claude-sonnet-4-6 | claude-opus-4-8 | claude-opus-4-8 |
| planner | claude-sonnet-4-6 | claude-opus-4-8 | claude-fable-5 |
| reviewer | claude-fable-5 | claude-fable-5 | claude-fable-5 |
| conflict | claude-fable-5 | claude-fable-5 | claude-fable-5 |
Reviewer/conflict use the strongest tier (fable-5) and are NOT downgraded by project-level model (preserves self-review/conflict-resolution rigor). Project-level model overrides executor/planner env vars; env vars override built-in defaults. Model fallback chain on unavailability: fable-5 → opus-4-8 → sonnet-4-6.
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 |