@matt82198/aesop 0.3.2 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +47 -0
- package/README.md +24 -9
- package/aesop.config.example.json +16 -0
- package/bin/cli.js +107 -34
- package/daemons/run-watchdog.sh +6 -2
- package/docs/CONFIGURE.md +31 -20
- package/docs/FIRST-WAVE.md +29 -9
- package/docs/INSTALL.md +181 -26
- package/docs/MICROKERNEL.md +452 -0
- package/docs/PORTING.md +4 -0
- package/docs/README.md +7 -3
- package/docs/THE-AESOP-HYPOTHESIS.md +156 -0
- package/driver/CLAUDE.md +123 -123
- package/driver/README.md +40 -2
- package/driver/adjudication_gate.py +367 -0
- package/driver/aesop.config.example.json +20 -4
- package/driver/backend_config.py +603 -12
- package/driver/claude_code_driver.py +9 -17
- package/driver/codex_driver.py +80 -25
- package/driver/context_pack.py +454 -0
- package/driver/openai_compatible_driver.py +53 -11
- package/driver/openai_transport.py +31 -10
- package/driver/orchestrator_backend.py +332 -0
- package/driver/orchestrator_driver.py +589 -0
- package/driver/proc_util.py +134 -0
- package/driver/wave_loop.py +801 -59
- package/driver/wave_scheduler.py +361 -37
- package/monitor/collect-signals.mjs +83 -0
- package/package.json +1 -1
- package/state_store/coordination.py +65 -5
- package/tools/ci_merge_wait.py +88 -42
- package/tools/ci_shard_runner.py +128 -0
- package/tools/doctor.js +124 -12
- package/tools/reproduce.js +11 -2
- package/tools/seated_shadow_adjudication.py +920 -0
- package/tools/self_stats.py +61 -6
- package/tools/shadow_adjudication.py +1024 -0
- package/tools/verify_test_suite_count.py +250 -0
- package/tools/verify_ui_trio_redaction_proof.py +292 -0
- package/tools/wave_manifest_lint.py +485 -0
- package/tools/wave_scorecard.py +430 -0
- package/ui/config.py +1 -1
- package/ui/cost.py +176 -3
- package/ui/web/dist/assets/{index-CP68RIh3.js → index-4rp6B_ID.js} +1 -1
- package/ui/web/dist/assets/{index-CNQxaiOW.css → index-B2lTtpsH.css} +1 -1
- package/ui/web/dist/index.html +2 -2
package/docs/INSTALL.md
CHANGED
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
**TL;DR**: Install Aesop in ~5 minutes using `npx`, set your repos, then verify with a single watchdog test run.
|
|
4
4
|
|
|
5
|
+
**New repo?** Follow the scaffolding guide below.
|
|
6
|
+
**Existing repo?** See [PORTING.md](PORTING.md) for adopting Aesop on a foreign codebase (with 10 common pitfalls covered).
|
|
7
|
+
|
|
5
8
|
---
|
|
6
9
|
|
|
7
10
|
## Prerequisites
|
|
@@ -15,7 +18,26 @@ Before you start, make sure you have:
|
|
|
15
18
|
- **Python** (v3.10+) — for secret-scan and log rotation
|
|
16
19
|
- **jq** (optional) — for TUI dashboard parsing
|
|
17
20
|
|
|
18
|
-
|
|
21
|
+
### Install Claude Code CLI
|
|
22
|
+
|
|
23
|
+
Claude Code is required to run `/power` and `/buildsystem` skills.
|
|
24
|
+
|
|
25
|
+
**Download and install**:
|
|
26
|
+
- Visit https://claude.com/claude-code to download and install Claude Code for your operating system
|
|
27
|
+
|
|
28
|
+
**Verify installation**:
|
|
29
|
+
```bash
|
|
30
|
+
claude --version
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Expected output: `Claude Code vX.Y.Z` (v0.1 or higher)
|
|
34
|
+
|
|
35
|
+
**If not on PATH**: On macOS/Linux, add the install directory to your `$PATH`. On Windows, the installer registers Claude Code in your PATH automatically. If `claude` is not found:
|
|
36
|
+
- Reinstall Claude Code and ensure the installer adds it to PATH
|
|
37
|
+
- Or add the installation directory to PATH manually (usually `~/.claude/bin` or `C:\Program Files\Claude Code\bin`)
|
|
38
|
+
|
|
39
|
+
### Check your versions
|
|
40
|
+
|
|
19
41
|
```bash
|
|
20
42
|
claude --version
|
|
21
43
|
git --version
|
|
@@ -61,6 +83,15 @@ cp -r skills/power/ ~/.claude/skills/power/
|
|
|
61
83
|
cp -r skills/buildsystem/ ~/.claude/skills/buildsystem/
|
|
62
84
|
```
|
|
63
85
|
|
|
86
|
+
**Verify the skills were copied**:
|
|
87
|
+
```bash
|
|
88
|
+
# Check both skills exist
|
|
89
|
+
ls -la ~/.claude/skills/power/SKILL.md
|
|
90
|
+
ls -la ~/.claude/skills/buildsystem/SKILL.md
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Expected output: Two SKILL.md files should exist.
|
|
94
|
+
|
|
64
95
|
### Step 3: Verify the installation
|
|
65
96
|
|
|
66
97
|
Run the watchdog once to test everything:
|
|
@@ -79,6 +110,8 @@ Expected output:
|
|
|
79
110
|
|
|
80
111
|
If you see errors, check the logs in `state/FLEET-BACKUP.log`.
|
|
81
112
|
|
|
113
|
+
**Note**: The `reproduce` command runs full test suites if you're working in the aesop repo itself. For scaffolded fleets, verification uses `aesop doctor` + `watchdog --once` to check preflight requirements and basic health.
|
|
114
|
+
|
|
82
115
|
---
|
|
83
116
|
|
|
84
117
|
## Manual Setup: Git Clone (For Development)
|
|
@@ -101,8 +134,8 @@ Open `aesop.config.json` and customize for your repos (see [CONFIGURE.md](CONFIG
|
|
|
101
134
|
|
|
102
135
|
```json
|
|
103
136
|
{
|
|
104
|
-
"
|
|
105
|
-
"
|
|
137
|
+
"aesop_root": "/home/user/my-aesop",
|
|
138
|
+
"brain_root": "/home/user/.claude",
|
|
106
139
|
"repos": [
|
|
107
140
|
{
|
|
108
141
|
"path": "/home/user/my-repo1",
|
|
@@ -113,7 +146,9 @@ Open `aesop.config.json` and customize for your repos (see [CONFIGURE.md](CONFIG
|
|
|
113
146
|
"name": "my-frontend"
|
|
114
147
|
}
|
|
115
148
|
],
|
|
116
|
-
"
|
|
149
|
+
"dashboard": {
|
|
150
|
+
"port": 8770
|
|
151
|
+
},
|
|
117
152
|
"dashboardOrigin": "http://localhost:8770"
|
|
118
153
|
}
|
|
119
154
|
```
|
|
@@ -169,10 +204,10 @@ After setup, you'll have:
|
|
|
169
204
|
### Configuration files
|
|
170
205
|
|
|
171
206
|
- **aesop.config.json** — Main configuration (git-ignored, never commit credentials)
|
|
172
|
-
- `
|
|
173
|
-
- `
|
|
207
|
+
- `aesop_root` — path to this harness directory
|
|
208
|
+
- `brain_root` — path to Claude Code home (`~/.claude`)
|
|
174
209
|
- `repos` — list of monitored repositories
|
|
175
|
-
- `
|
|
210
|
+
- `dashboard.port` — web dashboard port (default: 8770)
|
|
176
211
|
- `dashboardOrigin` — CORS origin validation
|
|
177
212
|
|
|
178
213
|
- **aesop.config.example.json** — Template with defaults (commit this, use as reference)
|
|
@@ -184,35 +219,149 @@ After setup, you'll have:
|
|
|
184
219
|
Optional environment variables you can set in your shell:
|
|
185
220
|
|
|
186
221
|
```bash
|
|
187
|
-
# Point to the Aesop harness root (used by daemons)
|
|
222
|
+
# Point to the Aesop harness root (used by daemons and tools)
|
|
188
223
|
export AESOP_ROOT=/home/user/my-aesop
|
|
189
224
|
|
|
190
|
-
# Optional: custom location for
|
|
191
|
-
export
|
|
225
|
+
# Optional: custom location for Aesop state directory (default: ./state)
|
|
226
|
+
export AESOP_STATE_ROOT=/home/user/my-aesop/state
|
|
192
227
|
|
|
193
|
-
# Optional:
|
|
194
|
-
export
|
|
228
|
+
# Optional: custom location for Claude Code home (used by /power skill)
|
|
229
|
+
export BRAIN_ROOT=/home/user/.claude
|
|
230
|
+
|
|
231
|
+
# Optional: custom location for reusable scripts directory
|
|
232
|
+
export SCRIPTS_ROOT=/home/user/scripts
|
|
195
233
|
```
|
|
196
234
|
|
|
197
235
|
---
|
|
198
236
|
|
|
237
|
+
## Already Have Aesop? Quick Setup
|
|
238
|
+
|
|
239
|
+
If you've already scaffolded Aesop and just need to get running:
|
|
240
|
+
|
|
241
|
+
1. **Verify your config**:
|
|
242
|
+
```bash
|
|
243
|
+
node -e "console.log(JSON.parse(require('fs').readFileSync('aesop.config.json')))"
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
2. **Verify the setup**:
|
|
247
|
+
```bash
|
|
248
|
+
bash daemons/run-watchdog.sh --once
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
3. **Copy skills** (if not done yet):
|
|
252
|
+
```bash
|
|
253
|
+
cp -r skills/power/ ~/.claude/skills/power/
|
|
254
|
+
cp -r skills/buildsystem/ ~/.claude/skills/buildsystem/
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
4. **Run your first wave**:
|
|
258
|
+
- Open Claude Code
|
|
259
|
+
- Type `/power` to prime your brain
|
|
260
|
+
- Type `/buildsystem` to start a wave (see [FIRST-WAVE.md](FIRST-WAVE.md))
|
|
261
|
+
|
|
262
|
+
---
|
|
263
|
+
|
|
199
264
|
## Using Non-Claude Backends
|
|
200
265
|
|
|
201
266
|
By default, Aesop uses Claude Code (the orchestration harness) as its backend. You can configure it to use other models via the **AgentDriver abstraction**—enabling Ollama, OpenAI-compatible endpoints, OpenRouter, and more.
|
|
202
267
|
|
|
203
|
-
|
|
268
|
+
For the conceptual picture (the two swappable seats, what's proven vs. bounded about swapping them, and a 60-second copy-paste quickstart), see **[MICROKERNEL.md](MICROKERNEL.md)**. The rest of this section is the config-mechanics reference.
|
|
269
|
+
|
|
270
|
+
### The unified two-seat config (0.4.0)
|
|
271
|
+
|
|
272
|
+
One namespaced `seats` block in `aesop.config.json` selects BOTH seats:
|
|
273
|
+
|
|
274
|
+
- **`seats.worker`** — the coding agents (AgentDriver). Same fields as the
|
|
275
|
+
legacy flat block below; takes precedence over it when both are present.
|
|
276
|
+
- **`seats.orchestrator`** — the decision seat (`OrchestratorDriver.decide()`).
|
|
277
|
+
`"harness"` (default) means the live Claude Code session itself makes
|
|
278
|
+
decisions; `"openai-compatible"` routes decisions to an API model.
|
|
279
|
+
|
|
280
|
+
**Swap a seat's model** — change just its block:
|
|
281
|
+
|
|
282
|
+
```json
|
|
283
|
+
{
|
|
284
|
+
"seats": {
|
|
285
|
+
"worker": {
|
|
286
|
+
"backend": "openai-compatible",
|
|
287
|
+
"base_url": "http://localhost:11434/v1",
|
|
288
|
+
"model": "mistral",
|
|
289
|
+
"is_local": true
|
|
290
|
+
},
|
|
291
|
+
"orchestrator": {
|
|
292
|
+
"backend": "openai-compatible",
|
|
293
|
+
"model": "gpt-4o-mini",
|
|
294
|
+
"api_key_env": "OPENAI_API_KEY"
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
```
|
|
204
299
|
|
|
205
|
-
|
|
300
|
+
That is a local-Ollama worker fleet with a hosted `gpt-4o-mini` decision seat.
|
|
301
|
+
To swap the worker to OpenRouter, replace `seats.worker` with
|
|
302
|
+
`{"backend": "openai-compatible", "base_url": "https://openrouter.ai/api/v1",
|
|
303
|
+
"model": "openai/gpt-4-turbo", "api_key_env": "OPENROUTER_API_KEY"}` — nothing
|
|
304
|
+
else changes. API keys are read from the env var named by `api_key_env` at
|
|
305
|
+
call time and are never stored in the config; `"is_local": true` endpoints
|
|
306
|
+
need no key at all — and for exactly that reason `is_local` is only accepted
|
|
307
|
+
with a loopback `base_url` (`localhost`, `127.0.0.1`, `::1`).
|
|
308
|
+
|
|
309
|
+
`api_key_env` is checked with a **best-effort heuristic**, allowlist-primary:
|
|
310
|
+
known LLM-provider key names (`OPENAI_API_KEY`, `ANTHROPIC_API_KEY`,
|
|
311
|
+
`OPENROUTER_API_KEY`, `TOGETHER_API_KEY`, `GROQ_API_KEY`, `MISTRAL_API_KEY`,
|
|
312
|
+
`DEEPSEEK_API_KEY`, `FIREWORKS_API_KEY`, `OLLAMA_API_KEY`,
|
|
313
|
+
`AZURE_OPENAI_API_KEY`, `GOOGLE_API_KEY`) are accepted silently; names that
|
|
314
|
+
don't look like key env vars or contain obvious non-LLM secret fragments
|
|
315
|
+
(`SECRET`/`TOKEN`/`PASSWORD`/`ACCESS`/...) are rejected; any other
|
|
316
|
+
key-shaped name (custom LLM gateways) is **allowed but prints a loud
|
|
317
|
+
NOTICE** — the env var's value will be sent as a Bearer token to your
|
|
318
|
+
`base_url`, so that NOTICE is the real signal: review it whenever a
|
|
319
|
+
non-provider name shows up at load time.
|
|
320
|
+
|
|
321
|
+
Asymmetry worth knowing: a **worker** `openai-compatible` seat REQUIRES
|
|
322
|
+
`base_url`; the **orchestrator** seat may omit it (defaults to the hosted
|
|
323
|
+
OpenAI endpoint).
|
|
324
|
+
|
|
325
|
+
**No `seats` block? Nothing changes.** Existing installs keep today's exact
|
|
326
|
+
behavior: Claude Code workers + harness orchestrator, no OpenAI backend
|
|
327
|
+
constructed, no key required. A pre-0.4.0 **legacy flat** backend block
|
|
328
|
+
(`{"backend": "codex", ...}` at the top level) also changes nothing by
|
|
329
|
+
itself: it still parses and validates, but it stays **inert** in the wave
|
|
330
|
+
scheduler's default path until you migrate it to `seats.worker` — on older
|
|
331
|
+
installs that block was documented but consumed by nothing, so activating it
|
|
332
|
+
silently would change behavior under you. (`cardinal_rules.orchestrator_model`
|
|
333
|
+
from older scaffolds was write-only and is retired; the orchestrator seat's
|
|
334
|
+
model now lives in `seats.orchestrator.model`.)
|
|
335
|
+
|
|
336
|
+
Consumers: `driver/wave_scheduler.py` builds its worker driver from this
|
|
337
|
+
config (CLI `--driver claude|codex` remains an override), and
|
|
338
|
+
`tools/shadow_adjudication.py` / `tools/seated_shadow_adjudication.py` build
|
|
339
|
+
their live orchestrator backend from `seats.orchestrator` (CLI `--model`
|
|
340
|
+
remains an override).
|
|
341
|
+
|
|
342
|
+
### The legacy flat block (parse-compatible, but migrate it)
|
|
343
|
+
|
|
344
|
+
Pre-0.4.0 docs described a flat top-level block:
|
|
206
345
|
|
|
207
346
|
```json
|
|
208
347
|
{
|
|
209
348
|
"backend": "openai-compatible",
|
|
210
349
|
"model": "ollama-mistral",
|
|
211
350
|
"base_url": "http://localhost:11434/v1",
|
|
212
|
-
"api_key_env": "OLLAMA_API_KEY"
|
|
351
|
+
"api_key_env": "OLLAMA_API_KEY",
|
|
352
|
+
"is_local": true
|
|
213
353
|
}
|
|
214
354
|
```
|
|
215
355
|
|
|
356
|
+
It still parses and validates (and direct `build_driver()` callers honor
|
|
357
|
+
it), but the wave scheduler's default path treats it as **inert** and keeps
|
|
358
|
+
the Claude Code worker: to actually activate a configured worker there, put
|
|
359
|
+
the same fields under `seats.worker` (`{"seats": {"worker": { ...this
|
|
360
|
+
block... }}}`).
|
|
361
|
+
|
|
362
|
+
Set `"is_local": true` for local/small models (Ollama etc.) — it raises the
|
|
363
|
+
verification tier honestly (tier 3 instead of hosted tier 2).
|
|
364
|
+
|
|
216
365
|
Supported backends:
|
|
217
366
|
- `"claude"` (default) — Claude Code CLI harness
|
|
218
367
|
- `"openai-compatible"` — OpenAI Chat Completions API (Ollama, OpenRouter, etc.)
|
|
@@ -229,17 +378,22 @@ ollama serve
|
|
|
229
378
|
# 2. In another terminal, pull a model
|
|
230
379
|
ollama pull mistral
|
|
231
380
|
|
|
232
|
-
# 3. Configure Aesop to use it
|
|
381
|
+
# 3. Configure Aesop to use it (seats.worker is the opt-in surface)
|
|
233
382
|
cat > aesop.config.json <<EOF
|
|
234
383
|
{
|
|
235
|
-
"
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
384
|
+
"seats": {
|
|
385
|
+
"worker": {
|
|
386
|
+
"backend": "openai-compatible",
|
|
387
|
+
"model": "mistral",
|
|
388
|
+
"base_url": "http://localhost:11434/v1",
|
|
389
|
+
"api_key_env": "OLLAMA_API_KEY",
|
|
390
|
+
"is_local": true
|
|
391
|
+
}
|
|
392
|
+
}
|
|
239
393
|
}
|
|
240
394
|
EOF
|
|
241
395
|
|
|
242
|
-
# 4. Start Aesop (
|
|
396
|
+
# 4. Start Aesop (components that dispatch through the AgentDriver seam will use Mistral)
|
|
243
397
|
npx @matt82198/aesop my-fleet --name "my-api"
|
|
244
398
|
```
|
|
245
399
|
|
|
@@ -250,16 +404,16 @@ The AgentDriver framework applies **honest verification tiers** — weaker backe
|
|
|
250
404
|
| Backend | Accuracy | Verification Tier | What it means |
|
|
251
405
|
|---------|----------|-------------------|---------------|
|
|
252
406
|
| Claude Code | ~0.99 | 1 (minimal) | Orchestrator trusts output; spot-check tests |
|
|
253
|
-
| OpenAI (
|
|
254
|
-
|
|
|
407
|
+
| Hosted OpenAI-compatible (codex / OpenRouter) | ~0.92 | 2 | Validate all JSON, ~50% spot-check, adversarial review |
|
|
408
|
+
| Local small model (`"is_local": true`, e.g. Ollama) | ~0.80 | 3 | Validate all JSON, heavy spot-check, adversarial review |
|
|
255
409
|
|
|
256
|
-
|
|
410
|
+
Higher tiers mean MORE orchestrator verification work: weaker backends raise, never lower, the orchestrator's burden. See [driver/README.md](../driver/README.md) for full verification-policy details.
|
|
257
411
|
|
|
258
412
|
### Troubleshooting
|
|
259
413
|
|
|
260
414
|
**Backend won't connect**: Check `OLLAMA_API_KEY` (or your backend's API key env var) is set and the `base_url` is reachable.
|
|
261
415
|
|
|
262
|
-
**Verification tier too strict**:
|
|
416
|
+
**Verification tier too strict**: The tier comes from the driver's `probe_capabilities()` honesty contract — never inflate accuracy to lower it. For hosted-quality models, leave `"is_local"` unset (tier 2); reserve `"is_local": true` (tier 3) for genuinely small local models.
|
|
263
417
|
|
|
264
418
|
For more details, see [driver/README.md](../driver/README.md).
|
|
265
419
|
|
|
@@ -333,6 +487,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -File daemons/install-tasks.ps1 -D
|
|
|
333
487
|
2. **Read [CONFIGURE.md](CONFIGURE.md)** — Customize repos, ports, and brain root
|
|
334
488
|
3. **Run [FIRST-WAVE.md](FIRST-WAVE.md)** — Test a full `/power` → `/buildsystem` cycle
|
|
335
489
|
4. **Understand [CONCEPTS.md](CONCEPTS.md)** — Learn the dispatch model and state model
|
|
336
|
-
|
|
490
|
+
5. **Read [MICROKERNEL.md](MICROKERNEL.md)** — Swap the worker or orchestrator seat to a non-Claude model
|
|
491
|
+
6. **Explore the dashboard** — `python3 ui/serve.py` then open http://localhost:8770
|
|
337
492
|
|
|
338
493
|
For troubleshooting, see the [Aesop README](../README.md#troubleshooting) or [GOVERNANCE.md](GOVERNANCE.md) for operational policies.
|