@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.
Files changed (46) hide show
  1. package/CHANGELOG.md +47 -0
  2. package/README.md +24 -9
  3. package/aesop.config.example.json +16 -0
  4. package/bin/cli.js +107 -34
  5. package/daemons/run-watchdog.sh +6 -2
  6. package/docs/CONFIGURE.md +31 -20
  7. package/docs/FIRST-WAVE.md +29 -9
  8. package/docs/INSTALL.md +181 -26
  9. package/docs/MICROKERNEL.md +452 -0
  10. package/docs/PORTING.md +4 -0
  11. package/docs/README.md +7 -3
  12. package/docs/THE-AESOP-HYPOTHESIS.md +156 -0
  13. package/driver/CLAUDE.md +123 -123
  14. package/driver/README.md +40 -2
  15. package/driver/adjudication_gate.py +367 -0
  16. package/driver/aesop.config.example.json +20 -4
  17. package/driver/backend_config.py +603 -12
  18. package/driver/claude_code_driver.py +9 -17
  19. package/driver/codex_driver.py +80 -25
  20. package/driver/context_pack.py +454 -0
  21. package/driver/openai_compatible_driver.py +53 -11
  22. package/driver/openai_transport.py +31 -10
  23. package/driver/orchestrator_backend.py +332 -0
  24. package/driver/orchestrator_driver.py +589 -0
  25. package/driver/proc_util.py +134 -0
  26. package/driver/wave_loop.py +801 -59
  27. package/driver/wave_scheduler.py +361 -37
  28. package/monitor/collect-signals.mjs +83 -0
  29. package/package.json +1 -1
  30. package/state_store/coordination.py +65 -5
  31. package/tools/ci_merge_wait.py +88 -42
  32. package/tools/ci_shard_runner.py +128 -0
  33. package/tools/doctor.js +124 -12
  34. package/tools/reproduce.js +11 -2
  35. package/tools/seated_shadow_adjudication.py +920 -0
  36. package/tools/self_stats.py +61 -6
  37. package/tools/shadow_adjudication.py +1024 -0
  38. package/tools/verify_test_suite_count.py +250 -0
  39. package/tools/verify_ui_trio_redaction_proof.py +292 -0
  40. package/tools/wave_manifest_lint.py +485 -0
  41. package/tools/wave_scorecard.py +430 -0
  42. package/ui/config.py +1 -1
  43. package/ui/cost.py +176 -3
  44. package/ui/web/dist/assets/{index-CP68RIh3.js → index-4rp6B_ID.js} +1 -1
  45. package/ui/web/dist/assets/{index-CNQxaiOW.css → index-B2lTtpsH.css} +1 -1
  46. 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
- Check your versions:
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
- "aesopRoot": "/home/user/my-aesop",
105
- "braindRoot": "/home/user/.claude",
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
- "dashboardPort": 8770,
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
- - `aesopRoot` — path to this harness directory
173
- - `braindRoot` — path to Claude Code home (`~/.claude`)
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
- - `dashboardPort` — web dashboard port (default: 8770)
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 Claude Code home
191
- export CLAUDE_CODE_HOME=/home/user/.claude
225
+ # Optional: custom location for Aesop state directory (default: ./state)
226
+ export AESOP_STATE_ROOT=/home/user/my-aesop/state
192
227
 
193
- # Optional: enable debug output in daemons
194
- export DEBUG=1
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
- ### Configure a backend in aesop.config.json
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
- Add or modify the `backend` section:
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
- "backend": "openai-compatible",
236
- "model": "mistral",
237
- "base_url": "http://localhost:11434/v1",
238
- "api_key_env": "OLLAMA_API_KEY"
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 (it will use Mistral for subagent dispatch)
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 (GPT-4) | ~0.95 | 2 | Validate all JSON, run full test suite |
254
- | Ollama (Mistral) | ~0.70 | 4 (maximum) | Validate all JSON, adversarial review, expensive repair cap |
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
- Lower tiers cost less but require more orchestrator work. See [driver/README.md](../driver/README.md) for full verification-policy details.
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**: If your backend is over-verified (tier 4 when it should be tier 2), update `probe_capabilities()` in the driver to report higher accuracy scores honestly.
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
- 4. **Explore the dashboard** — `python3 ui/serve.py` then open http://localhost:8770
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.