docs: add CLAUDE.md with architecture and dev commands

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-14 00:34:36 +08:00
+100
View File
@@ -0,0 +1,100 @@
# 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
| Role | Easy | Medium | Hard |
|---|---|---|---|
| executor | claude-sonnet-4-6 | claude-opus-4-8 | claude-fable-5 |
| reviewer | claude-sonnet-4-6 | claude-opus-4-8 | claude-opus-4-8 |
Project-level `model` setting overrides env vars; env vars override built-in defaults.
### 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 |