@matt82198/aesop 0.4.0 → 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 CHANGED
@@ -7,6 +7,30 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  **Version scheme**: Stable releases are `0.x.y`; `0.x.0-beta.N` / `-rc.N` are pre-releases; `0.1.0-wave.N` were internal wave-milestone previews.
9
9
 
10
+ ## [0.4.1] - 2026-07-26
11
+
12
+ ### Onboarding overhaul
13
+ - **Config home-directory expansion** (PR #413): User-set `aesop_root: "~/myfleet"` now expands correctly via `.expanduser()` instead of treating tilde as a literal path.
14
+ - **Reproduce graceful degradation** (PR #413): Fresh scaffolds (`.git` present, no `package-lock.json`) detect scaffold mode and run installed-mode verification instead of failing on `npm ci`; clear one-line message on graceful degrade.
15
+ - **Scaffolder absolute paths** (PR #413): All NEXT STEPS `cd` commands in CLI output now print absolute resolved paths matching config's stored resolved paths (no relative dirs).
16
+ - **Scaffold and doctor fixes** (PR #407): Corrected path handling in scaffolder and doctor, improved validation logic, clearer guidance on remediation.
17
+ - **Setup docs field-name sync** (PR #405): Fixed CONFIGURE block field names and added missing Claude Code install steps; docs now match actual config structure.
18
+ - **Watchdog smoke-test verdict** (PR #406): New `watchdog --once` exits with explicit PASS/FAIL verdict for CI/doctor integration; clear signal for fleet health checks.
19
+
20
+ ### CI/test hardening
21
+ - **PowerShell syntax gate** (PR #401): Pre-commit CI gate validates all `*.ps1` files for correct syntax; prevents shell-script drift on Windows daemon scripts.
22
+ - **Workflow_dispatch on main-full** (PR #399): Main CI now accepts manual dispatch trigger for on-demand full-suite runs without waiting for a commit.
23
+ - **Self-updating test suite count gate** (PR #403): New `tools/verify_test_suite_count.py` auto-reconciles test counts in `tests/CLAUDE.md`; `--check` mode for CI (fail-closed on drift), `--fix` mode for lanes. Eliminates merge blocks from concurrent test additions.
24
+ - **Frontier-slice test depollution** (PR #400): Frontier-slice benchmark output now writes to gitignored temp location instead of polluting repo; clean CI artifacts.
25
+ - **Git-identity isolation + runtime tripwire** (PR #412): Fixed root cause of Test User ghost commits — 6 test files used shell fallthrough causing silent git config writes to shared `.git/config`. Now using direct `spawn('git', …, {cwd})` with no shell; runtime tripwire in `test_test_hygiene.py` fails suite if repo identity mutates during test run.
26
+
27
+ ### Honesty / stats
28
+ - **Stats truth-sync + verify tool** (PR #411): Fixed stale v0.1.0 stats in stats.json; new `scripts/verify-stats.sh` documents single-stats-source wrapper (`self_stats --check/--regenerate`); ancestor principles named (Temporal, Candea & Fox crash-only, Erlang/OTP, K8s reconciliation).
29
+ - **Self_stats squash-merge fix** (PR #398): Merged PR count now authoritative from GitHub API (387, up from undercounted 268). Git fallback for offline use handles both merge-commit and squash-merge styles; deduplicates on PR number.
30
+
31
+ ### Bench
32
+ - **gpt-4o-mini worker seat dogfood** (PR #404): Benchmark expands with gpt-4o-mini seated as worker model; includes real context-tip item-9 discrimination and co-model A/B measurement.
33
+
10
34
  ## [0.4.0] - 2026-07-25
11
35
 
12
36
  ### Added
package/README.md CHANGED
@@ -16,12 +16,14 @@
16
16
 
17
17
  **Aesop** is a **crash-recoverable orchestration harness** for multi-agent workflows on any repository. One-line theme: *stateless agent execution over git-backed durable memory*.
18
18
 
19
- Core idea: **agent behavior is source code.** Every decision lives in durable, human-diffable files—git history, plain-text STATE.md, append-only BUILDLOG.md, Python guardrails. When a machine fails, you re-read from disk. No vector DBs, no distributed consensus, no magic. This repo's own 251 merged PRs across 1088 commits were delivered by Aesop's own `/buildsystem` wave loop—a supervised loop under a human operator who sets goals and owns outward gates (npm publish, releases, history rewrites).
19
+ Core idea: **agent behavior is source code.** Every decision lives in durable, human-diffable files—git history, plain-text STATE.md, append-only BUILDLOG.md, Python guardrails. When a machine fails, you re-read from disk. No vector DBs, no distributed consensus, no magic. This repo's own 387 merged PRs across 1181 commits were delivered by Aesop's own `/buildsystem` wave loop—a supervised loop under a human operator who sets goals and owns outward gates (npm publish, releases, history rewrites).
20
20
 
21
- **Why it matters:** crash recovery is not a special path; it is how the system *always* starts. Stateless workers, persistent filesystem brain, Haiku-first dispatch (4.3× cheaper than hierarchical design, proven by real A/B), fail-closed guardrails (pre-push secret gate, kill-switch, cost ceiling), and observable heartbeats. The result: 251 PRs in 11 days; Haiku at 39/39 on a 39-task benchmark vs Opus 38/39, at ~1/3 the cost.
21
+ **Why it matters:** crash recovery is not a special path; it is how the system *always* starts. Stateless workers, persistent filesystem brain, Haiku-first dispatch (4.3× cheaper than hierarchical design, proven by real A/B), fail-closed guardrails (pre-push secret gate, kill-switch, cost ceiling), and observable heartbeats. The result: 387 PRs across 1181 commits; Haiku at 39/39 on a 39-task benchmark vs Opus 38/39, at ~1/3 the cost.
22
22
 
23
23
  **Why it's built this way:** [The Aesop Hypothesis](./docs/THE-AESOP-HYPOTHESIS.md) — the design philosophy, the trade-offs, the cancelled architectures with published data.
24
24
 
25
+ **New in 0.4.0:** Swap the **worker** and **orchestrator** model (Claude, Codex, or any OpenAI-compatible endpoint) from one `seats` config block without code changes. See [docs/MICROKERNEL.md](./docs/MICROKERNEL.md) for the two-seat architecture and a 60-second quickstart. Single-instance proven; multi-instance coordination is scheduled.
26
+
25
27
  ## Feature Demo
26
28
 
27
29
  **One-turn wave** — Run a complete build cycle (tests, build, docs, review, merge, audit) end-to-end:
@@ -92,17 +94,20 @@ Aesop is built entirely by its own `/buildsystem` wave cycle—running parallel
92
94
 
93
95
  | Metric | Value |
94
96
  | --- | --- |
95
- | Merged PRs | 251 <!-- metrics-verified: self_stats.py (git log) --> |
96
- | Total Commits | 1088 <!-- metrics-verified: self_stats.py (git log) --> |
97
- | Project Age | 11 days <!-- metrics-verified: self_stats.py (git log) --> |
97
+ | Merged PRs | 387 <!-- metrics-verified: self_stats.py (git log) --> |
98
+ | Total Commits | 1181 <!-- metrics-verified: self_stats.py (git log) --> |
99
+ | Project Age | 14 days <!-- metrics-verified: self_stats.py (git log) --> |
98
100
  | Waves | 30 <!-- metrics-verified: self_stats.py (git log) --> |
99
- | Insertions + Deletions | 186,587 <!-- metrics-verified: self_stats.py (git log) --> |
100
- | Files Tracked | 546 <!-- metrics-verified: self_stats.py (git log) --> |
101
+ | Insertions + Deletions | 222,290 <!-- metrics-verified: self_stats.py (git log) --> |
102
+ | Files Tracked | 642 <!-- metrics-verified: self_stats.py (git log) --> |
101
103
  | Distinct Co-authors | 11 <!-- metrics-verified: self_stats.py (git log) --> |
102
104
 
103
105
  <!-- STATS:END -->
104
106
 
105
107
 
108
+
109
+
110
+
106
111
  *Wave: one complete build cycle (intake → dispatch → verify → ship) run by the orchestration engine.*
107
112
 
108
113
 
@@ -115,7 +120,7 @@ Aesop is built entirely by its own `/buildsystem` wave cycle—running parallel
115
120
 
116
121
  ## Why Haiku-First Works
117
122
 
118
- The benchmark proves it: across 39 judgment tasks (code review, severity calibration, root-cause analysis, refactor equivalence, security spots), Haiku scored **39/39** vs Opus **38/39** at ~1/3 the per-token cost. See [`bench/results/2026-07-17-judgment-v3-haiku-sonnet-opus.md`](./bench/results/2026-07-17-judgment-v3-haiku-sonnet-opus.md). **Curated set, N=39** — Haiku 39/39 vs Opus 38/39; proves sufficiency for this workload, not frontier parity.
123
+ The benchmark proves sufficiency: across 39 judgment tasks (code review, severity calibration, root-cause analysis, refactor equivalence, security spots), Haiku scored **39/39** vs Opus **38/39** at ~1/3 the per-token cost. See [`bench/results/2026-07-17-judgment-v3-haiku-sonnet-opus.md`](./bench/results/2026-07-17-judgment-v3-haiku-sonnet-opus.md). The pre-declared ceiling rule (when ≥2 tiers score ≥92%, the instrument failed to discriminate) trips on this result — both Haiku and Sonnet achieved 39/39, meaning the benchmark maps a *sufficiency floor*, not tier equivalence. **Curated set, N=39; scoped to extraction and judgment tasks with context at the seam** — does NOT reach frontier reasoning, long-horizon planning, or open-ended synthesis. Full analysis: [`bench/results/2026-07-26-judgment-v3-ceiling-addendum.md`](./bench/results/2026-07-26-judgment-v3-ceiling-addendum.md) and [`bench/EQUIVALENCE-MARGIN.md`](./bench/EQUIVALENCE-MARGIN.md).
119
124
 
120
125
  ## Learn More
121
126
 
@@ -126,7 +131,7 @@ The benchmark proves it: across 39 judgment tasks (code review, severity calibra
126
131
  - **[docs/DISPATCH-MODEL.md](./docs/DISPATCH-MODEL.md)** — Cost analysis and scaling
127
132
  - **[docs/CARDINAL-RULES.md](./docs/CARDINAL-RULES.md)** — 10 foundational principles
128
133
  - **[docs/autonomous-swe.md](./docs/autonomous-swe.md)** — What "autonomous" means (and doesn't), evidence for all claims, honest limits
129
- - **[RELEASE-NOTES.md](./RELEASE-NOTES.md)** — Version 0.3.1 (the 0.3.0 milestone): non-Claude core proof (Codex wave), refinement-loop convergence, Windows-green CI
134
+ - **[RELEASE-NOTES.md](./RELEASE-NOTES.md)** — Version 0.4.0 (the two-seat micro-kernel): swappable worker + orchestrator models from one config, live orchestrator seat-swap gate, IPv6/DNS hardening, scaffolding completeness
130
135
 
131
136
  ## Contributing
132
137
 
@@ -141,6 +146,8 @@ The repo develops itself via its own `/buildsystem` loop; code changes are made
141
146
 
142
147
  **Source-available** under the [PolyForm Strict License 1.0.0](./LICENSE). You may read, run, and use the software for any permitted purpose, but **modification and redistribution are not permitted**. See [`LICENSE`](./LICENSE) for the full terms and the definition of permitted (noncommercial and personal) purposes.
143
148
 
149
+ **License history:** Aesop was released under the MIT License until 2026-07-17, when it was relicensed to PolyForm Strict 1.0.0. Snapshots cloned or forked before that date retain their original MIT license grant; new work lives under PolyForm Strict 1.0.0.
150
+
144
151
  Copyright 2026 Matt Culliton.
145
152
 
146
153
  ## References
package/bin/cli.js CHANGED
@@ -434,7 +434,7 @@ function generateConfigJson(targetDir, templateRoot, projectName, reposStr, repo
434
434
  }
435
435
 
436
436
  // Update with provided values
437
- exampleConfig.aesop_root = targetDir;
437
+ exampleConfig.aesop_root = path.resolve(targetDir);
438
438
  exampleConfig.brain_root = '~/.claude';
439
439
  exampleConfig.scripts_root = '~/scripts';
440
440
  exampleConfig.temp_root = '~/.aesop-temp';
@@ -467,14 +467,31 @@ function generateConfigJson(targetDir, templateRoot, projectName, reposStr, repo
467
467
 
468
468
  // Print next steps and optionally run watchdog (returns a Promise)
469
469
  async function printNextStepsAndWatchdog(rl, targetDir, configPath, port) {
470
- console.log('\n🎯 Next 2 commands to get started:\n');
471
- console.log(` 1. cd ${targetDir}`);
472
- console.log(' 2. bash daemons/run-watchdog.sh --once (one-time watchdog smoke test)');
473
- console.log(` 3. python3 ui/serve.py (or python as fallback; launch dashboard on localhost:${port})`);
474
- console.log('\n📖 Optional: Set up your brain (Claude Code orchestration memory):\n');
470
+ const resolvedTargetDir = path.resolve(targetDir);
471
+ console.log('\n🎯 NEXT STEPS — Customize, validate, and launch:\n');
472
+ console.log('1. Customize CLAUDE.md domains and team info:');
473
+ console.log(` cd ${resolvedTargetDir}`);
474
+ console.log(' Edit CLAUDE.md update domains, team, and project details');
475
+ console.log('');
476
+ console.log('2. Set real repository URLs in aesop.config.json:');
477
+ console.log(' Edit aesop.config.json — replace placeholder URLs (https://github.com/user/...) with actual repo URLs');
478
+ console.log('');
479
+ console.log('3. Copy the skills (required for orchestration):');
480
+ console.log(' cp ~/.claude/skills/power/SKILL.md . (verify it exists first)');
481
+ console.log(' cp ~/.claude/skills/buildsystem/SKILL.md . (verify it exists first)');
482
+ console.log('');
483
+ console.log('4. Run preflight checks:');
484
+ console.log(' aesop doctor (or: npx @matt82198/aesop doctor)');
485
+ console.log('');
486
+ console.log('5. Launch watchdog (one-time smoke test):');
487
+ console.log(' bash daemons/run-watchdog.sh --once');
488
+ console.log('');
489
+ console.log(`6. Launch dashboard (on localhost:${port}):`);
490
+ console.log(' python3 ui/serve.py (or python as fallback)\n');
491
+ console.log('📖 Optional: Set up your brain (Claude Code orchestration memory):\n');
475
492
  console.log(' mkdir -p ~/.claude/memory');
476
- console.log(` cp ${targetDir}/CLAUDE.md ~/.claude/CLAUDE.md (review and customize)`);
477
- console.log(` cp ${targetDir}/MEMORY-SEED.md ~/.claude/MEMORY.md (then add your facts)\n`);
493
+ console.log(` cp ${resolvedTargetDir}/CLAUDE.md ~/.claude/CLAUDE.md (review and customize)`);
494
+ console.log(` cp ${resolvedTargetDir}/MEMORY-SEED.md ~/.claude/MEMORY.md (then add your facts)\n`);
478
495
 
479
496
  return new Promise((resolve) => {
480
497
  rl.question('Run watchdog --once now? (y/N): ', (answer) => {
@@ -927,38 +944,91 @@ if (!isRuntimeCommand) {
927
944
  process.exit(0);
928
945
  } else if (wizardMode) {
929
946
  // Wizard mode with --yes flag (non-interactive)
930
- console.log('\n🎯 Next 3 commands to get started:\n');
931
- console.log(` 1. cd ${finalTargetDir}`);
932
- console.log(' 2. bash daemons/run-watchdog.sh --once (one-time watchdog smoke test)');
933
- console.log(` 3. python3 ui/serve.py (or python as fallback; launch dashboard on localhost:${dashboardPort})`);
934
- console.log('\n📖 Optional: Set up your brain (Claude Code orchestration memory):\n');
947
+ const resolvedFinalTargetDir = path.resolve(finalTargetDir);
948
+ console.log('\n🎯 NEXT STEPS — Customize, validate, and launch:\n');
949
+ console.log('1. Customize CLAUDE.md domains and team info:');
950
+ console.log(` cd ${resolvedFinalTargetDir}`);
951
+ console.log(' Edit CLAUDE.md update domains, team, and project details');
952
+ console.log('');
953
+ console.log('2. Set real repository URLs in aesop.config.json:');
954
+ console.log(' Edit aesop.config.json — replace placeholder URLs (https://github.com/user/...) with actual repo URLs');
955
+ console.log('');
956
+ console.log('3. Copy the skills (required for orchestration):');
957
+ console.log(' cp ~/.claude/skills/power/SKILL.md . (verify it exists first)');
958
+ console.log(' cp ~/.claude/skills/buildsystem/SKILL.md . (verify it exists first)');
959
+ console.log('');
960
+ console.log('4. Run preflight checks:');
961
+ console.log(' aesop doctor (or: npx @matt82198/aesop doctor)');
962
+ console.log('');
963
+ console.log('5. Launch watchdog (one-time smoke test):');
964
+ console.log(' bash daemons/run-watchdog.sh --once');
965
+ console.log('');
966
+ console.log(`6. Launch dashboard (on localhost:${dashboardPort}):`);
967
+ console.log(' python3 ui/serve.py (or python as fallback)');
968
+ console.log('');
969
+ console.log('📖 Optional: Set up your brain (Claude Code orchestration memory):\n');
935
970
  console.log(' mkdir -p ~/.claude/memory');
936
- console.log(` cp ${finalTargetDir}/CLAUDE.md ~/.claude/CLAUDE.md (review and customize)`);
937
- console.log(` cp ${finalTargetDir}/MEMORY-SEED.md ~/.claude/MEMORY.md (then add your facts)`);
971
+ console.log(` cp ${resolvedFinalTargetDir}/CLAUDE.md ~/.claude/CLAUDE.md (review and customize)`);
972
+ console.log(` cp ${resolvedFinalTargetDir}/MEMORY-SEED.md ~/.claude/MEMORY.md (then add your facts)`);
938
973
  process.exit(0);
939
974
  } else if (finalProjectName) {
975
+ const resolvedFinalTargetDir = path.resolve(finalTargetDir);
940
976
  console.log('\n✅ Headless scaffolding complete!\n');
941
- console.log('🎯 Next 3 commands to get started:\n');
942
- console.log(` 1. cd ${finalTargetDir}`);
943
- console.log(' 2. bash daemons/run-watchdog.sh --once (one-time watchdog smoke test)');
944
- console.log(` 3. python3 ui/serve.py (or python as fallback; launch dashboard on localhost:${dashboardPort})`);
945
- console.log('\n📖 Optional: Set up your brain (Claude Code orchestration memory):\n');
977
+ console.log('🎯 NEXT STEPS Customize, validate, and launch:\n');
978
+ console.log('1. Customize CLAUDE.md domains and team info:');
979
+ console.log(` cd ${resolvedFinalTargetDir}`);
980
+ console.log(' Edit CLAUDE.md update domains, team, and project details');
981
+ console.log('');
982
+ console.log('2. Set real repository URLs in aesop.config.json:');
983
+ console.log(' Edit aesop.config.json — replace placeholder URLs (https://github.com/user/...) with actual repo URLs');
984
+ console.log('');
985
+ console.log('3. Copy the skills (required for orchestration):');
986
+ console.log(' cp ~/.claude/skills/power/SKILL.md . (verify it exists first)');
987
+ console.log(' cp ~/.claude/skills/buildsystem/SKILL.md . (verify it exists first)');
988
+ console.log('');
989
+ console.log('4. Run preflight checks:');
990
+ console.log(' aesop doctor (or: npx @matt82198/aesop doctor)');
991
+ console.log('');
992
+ console.log('5. Launch watchdog (one-time smoke test):');
993
+ console.log(' bash daemons/run-watchdog.sh --once');
994
+ console.log('');
995
+ console.log(`6. Launch dashboard (on localhost:${dashboardPort}):`);
996
+ console.log(' python3 ui/serve.py (or python as fallback)');
997
+ console.log('');
998
+ console.log('📖 Optional: Set up your brain (Claude Code orchestration memory):\n');
946
999
  console.log(' mkdir -p ~/.claude/memory');
947
- console.log(` cp ${finalTargetDir}/CLAUDE.md ~/.claude/CLAUDE.md (review and customize)`);
948
- console.log(` cp ${finalTargetDir}/MEMORY-SEED.md ~/.claude/MEMORY.md (then add your facts)`);
1000
+ console.log(` cp ${resolvedFinalTargetDir}/CLAUDE.md ~/.claude/CLAUDE.md (review and customize)`);
1001
+ console.log(` cp ${resolvedFinalTargetDir}/MEMORY-SEED.md ~/.claude/MEMORY.md (then add your facts)`);
949
1002
  } else {
1003
+ const resolvedFinalTargetDir = path.resolve(finalTargetDir);
950
1004
  console.log('\n✅ Scaffold complete!\n');
951
- console.log('🎯 Next 3 commands to get started:\n');
952
- console.log(` 1. cd ${finalTargetDir}`);
953
- console.log(' 2. bash daemons/run-watchdog.sh --once (one-time watchdog smoke test)');
954
- console.log(` 3. python3 ui/serve.py (or python as fallback; launch dashboard on localhost:${dashboardPort})`);
955
- console.log('\n📖 Configuration steps (optional):\n');
956
- console.log(' cp aesop.config.example.json aesop.config.json (if not generated)');
957
- console.log(' Edit aesop.config.json with your configuration');
958
- console.log('\n📖 Optional: Set up your brain (Claude Code orchestration memory):\n');
1005
+ console.log('🎯 NEXT STEPS Customize, validate, and launch:\n');
1006
+ console.log('1. Create aesop.config.json from example:');
1007
+ console.log(' cp aesop.config.example.json aesop.config.json');
1008
+ console.log(` cd ${resolvedFinalTargetDir}`);
1009
+ console.log(' Edit aesop.config.json with your configuration and actual repository URLs');
1010
+ console.log('');
1011
+ console.log('2. Customize CLAUDE.md domains and team info:');
1012
+ console.log(' Edit CLAUDE-TEMPLATE.md and save as CLAUDE.md');
1013
+ console.log(' Update domains, team, and project details');
1014
+ console.log('');
1015
+ console.log('3. Copy the skills (required for orchestration):');
1016
+ console.log(' cp ~/.claude/skills/power/SKILL.md . (verify it exists first)');
1017
+ console.log(' cp ~/.claude/skills/buildsystem/SKILL.md . (verify it exists first)');
1018
+ console.log('');
1019
+ console.log('4. Run preflight checks:');
1020
+ console.log(' aesop doctor (or: npx @matt82198/aesop doctor)');
1021
+ console.log('');
1022
+ console.log('5. Launch watchdog (one-time smoke test):');
1023
+ console.log(' bash daemons/run-watchdog.sh --once');
1024
+ console.log('');
1025
+ console.log(`6. Launch dashboard (on localhost:${dashboardPort}):`);
1026
+ console.log(' python3 ui/serve.py (or python as fallback)');
1027
+ console.log('');
1028
+ console.log('📖 Optional: Set up your brain (Claude Code orchestration memory):\n');
959
1029
  console.log(' mkdir -p ~/.claude/memory');
960
- console.log(` cp ${finalTargetDir}/CLAUDE-TEMPLATE.md ~/.claude/CLAUDE.md (then edit domains/team info)`);
961
- console.log(` cp ${finalTargetDir}/MEMORY-SEED.md ~/.claude/MEMORY.md (then add your facts)`);
1030
+ console.log(` cp ${resolvedFinalTargetDir}/CLAUDE-TEMPLATE.md ~/.claude/CLAUDE.md (then edit domains/team info)`);
1031
+ console.log(` cp ${resolvedFinalTargetDir}/MEMORY-SEED.md ~/.claude/MEMORY.md (then add your facts)`);
962
1032
  }
963
1033
  console.log('\nFor full documentation, see the README.md in the scaffolded directory.');
964
1034
  process.exit(0);
@@ -228,6 +228,7 @@ main() {
228
228
  if [ "$MODE" = "--once" ]; then
229
229
  if check_halt "$AESOP_ROOT/state/FLEET-BACKUP.log"; then
230
230
  release_lock "$LOCK_DIR"
231
+ printf 'WATCHDOG SMOKE: PASSED\n'
231
232
  exit 0
232
233
  fi
233
234
  full_out=$("${CYCLE_CMD_ARRAY[@]}" 2>&1)
@@ -236,13 +237,16 @@ main() {
236
237
  if [ $cmd_exit -ne 0 ]; then
237
238
  err_msg="[$(date '+%F %T')] ERROR: cycle #1 failed with exit code $cmd_exit"
238
239
  echo "$err_msg" >> "$AESOP_ROOT/state/FLEET-BACKUP.log"
239
- echo "[ERROR: exit $cmd_exit]" >&2
240
+ printf 'WATCHDOG SMOKE: FAILED — [ERROR: exit %d]\n' "$cmd_exit" >&2
241
+ release_lock "$LOCK_DIR"
242
+ exit $cmd_exit
240
243
  fi
241
244
  if [ -n "$PYTHON_EXE" ]; then
242
245
  "$PYTHON_EXE" "$AESOP_ROOT/tools/alert_bridge.py" --scan || true
243
246
  fi
244
247
  release_lock "$LOCK_DIR"
245
- exit $cmd_exit
248
+ printf 'WATCHDOG SMOKE: PASSED\n'
249
+ exit 0
246
250
  fi
247
251
 
248
252
  n=0
package/docs/CONFIGURE.md CHANGED
@@ -10,8 +10,8 @@ After setup, you'll have an `aesop.config.json` in your harness root. This file
10
10
 
11
11
  ```json
12
12
  {
13
- "aesopRoot": "/home/user/aesop",
14
- "braindRoot": "/home/user/.claude",
13
+ "aesop_root": "/home/user/aesop",
14
+ "brain_root": "/home/user/.claude",
15
15
  "repos": [
16
16
  {
17
17
  "path": "/home/user/my-api",
@@ -22,14 +22,16 @@ After setup, you'll have an `aesop.config.json` in your harness root. This file
22
22
  "name": "web-frontend"
23
23
  }
24
24
  ],
25
- "dashboardPort": 8770,
25
+ "dashboard": {
26
+ "port": 8770
27
+ },
26
28
  "dashboardOrigin": "http://localhost:8770"
27
29
  }
28
30
  ```
29
31
 
30
32
  ### Field Reference
31
33
 
32
- #### `aesopRoot` (string, required)
34
+ #### `aesop_root` (string, required)
33
35
 
34
36
  Absolute path to this Aesop harness directory. Used by daemons to locate scripts and state files.
35
37
 
@@ -39,7 +41,7 @@ Absolute path to this Aesop harness directory. Used by daemons to locate scripts
39
41
 
40
42
  ---
41
43
 
42
- #### `braindRoot` (string, required)
44
+ #### `brain_root` (string, required)
43
45
 
44
46
  Absolute path to your Claude Code home directory. This is where skills (`.claude/skills/`) and memory (`.claude/MEMORY.md`) live.
45
47
 
@@ -78,7 +80,7 @@ Each repo object has:
78
80
 
79
81
  ---
80
82
 
81
- #### `dashboardPort` (number, default: 8770)
83
+ #### `dashboard.port` (number, default: 8770)
82
84
 
83
85
  HTTP port for the web dashboard. The dashboard runs a Python HTTP server on this port.
84
86
 
@@ -116,15 +118,17 @@ The origin (scheme + host + port) for the dashboard. Used for CORS validation an
116
118
 
117
119
  ```json
118
120
  {
119
- "aesopRoot": "/home/user/aesop",
120
- "braindRoot": "/home/user/.claude",
121
+ "aesop_root": "/home/user/aesop",
122
+ "brain_root": "/home/user/.claude",
121
123
  "repos": [
122
124
  {
123
125
  "path": "/home/user/my-app",
124
126
  "name": "my-app"
125
127
  }
126
128
  ],
127
- "dashboardPort": 8770,
129
+ "dashboard": {
130
+ "port": 8770
131
+ },
128
132
  "dashboardOrigin": "http://localhost:8770"
129
133
  }
130
134
  ```
@@ -133,8 +137,8 @@ The origin (scheme + host + port) for the dashboard. Used for CORS validation an
133
137
 
134
138
  ```json
135
139
  {
136
- "aesopRoot": "/home/user/aesop",
137
- "braindRoot": "/home/user/.claude",
140
+ "aesop_root": "/home/user/aesop",
141
+ "brain_root": "/home/user/.claude",
138
142
  "repos": [
139
143
  {
140
144
  "path": "/home/user/services/auth",
@@ -153,7 +157,9 @@ The origin (scheme + host + port) for the dashboard. Used for CORS validation an
153
157
  "name": "infrastructure"
154
158
  }
155
159
  ],
156
- "dashboardPort": 8770,
160
+ "dashboard": {
161
+ "port": 8770
162
+ },
157
163
  "dashboardOrigin": "http://localhost:8770"
158
164
  }
159
165
  ```
@@ -162,15 +168,17 @@ The origin (scheme + host + port) for the dashboard. Used for CORS validation an
162
168
 
163
169
  ```json
164
170
  {
165
- "aesopRoot": "C:\\Users\\user\\aesop",
166
- "braindRoot": "C:\\Users\\user\\.claude",
171
+ "aesop_root": "C:\\Users\\user\\aesop",
172
+ "brain_root": "C:\\Users\\user\\.claude",
167
173
  "repos": [
168
174
  {
169
175
  "path": "C:\\Users\\user\\projects\\my-api",
170
176
  "name": "api"
171
177
  }
172
178
  ],
173
- "dashboardPort": 8770,
179
+ "dashboard": {
180
+ "port": 8770
181
+ },
174
182
  "dashboardOrigin": "http://localhost:8770"
175
183
  }
176
184
  ```
@@ -205,14 +213,17 @@ Aesop credentials (GitHub tokens, API keys) should never go in `aesop.config.jso
205
213
  You can override config values via environment variables (optional):
206
214
 
207
215
  ```bash
208
- # Override the Aesop root
216
+ # Override the Aesop root (used by daemons)
209
217
  export AESOP_ROOT=/path/to/aesop
210
218
 
211
- # Override the Claude Code home
212
- export CLAUDE_CODE_HOME=/path/to/.claude
219
+ # Override the Aesop state directory (default: ./state)
220
+ export AESOP_STATE_ROOT=/path/to/state
221
+
222
+ # Override the Claude Code home (used by /power skill and orchestrator)
223
+ export BRAIN_ROOT=/path/to/.claude
213
224
 
214
- # Enable debug logging in daemons
215
- export DEBUG=1
225
+ # Override the scripts directory
226
+ export SCRIPTS_ROOT=/path/to/scripts
216
227
  ```
217
228
 
218
229
  If set, these override the values in `aesop.config.json`.
@@ -47,19 +47,39 @@ This tells you the orchestrator is ready.
47
47
 
48
48
  Before running a wave, you need ranked work. The orchestrator needs to know what to build.
49
49
 
50
- ### Create an initial backlog
50
+ ### Where your backlog lives
51
51
 
52
- In your orchestrator (Claude Code) or in a scratch file, write down 2–5 small tasks:
52
+ Create a `state/BACKLOG.md` file (or update the backlog section in `state/STATE.md`). Use this markdown format:
53
53
 
54
- **Example backlog**:
55
- ```
56
- P1: Add README docs for orchestration
57
- P2: Fix typo in dashboard title
58
- P2: Add unit test coverage for config loader
59
- P3: Document the watchdog daemon
54
+ ```markdown
55
+ # Wave 15 Backlog
56
+
57
+ ## P1: Critical
58
+
59
+ - [ ] Fix secret-scan gate hang (blocking CI) — backend-dev — 5min
60
+ - [ ] Update MEMORY.md with wave-15 learnings — docs-agent — 3min
61
+
62
+ ## P2: Features
63
+
64
+ - [ ] Add cost-ceiling dashboard widget — frontend-dev — 8min
65
+ - [ ] Implement fleet-ops monitoring — backend-dev — 10min
66
+
67
+ ## P3: Tech Debt
68
+
69
+ - [ ] Refactor monitor/collect-signals.mjs (duplicate checks) — backend-dev — 15min
70
+ - [ ] Add type hints to Python tools — test-bot — 10min
60
71
  ```
61
72
 
62
- **Backlog principles**:
73
+ **Backlog format**:
74
+ - **Sections**: Group by priority (P1/P2/P3)
75
+ - **Items**: Checkbox (`[ ]`) + title + agent type + time estimate
76
+ - **Sizing guide**:
77
+ - **3–5 min**: Typo fix, simple config change, one-line refactor
78
+ - **5–10 min**: New function, small feature, unit test
79
+ - **10–15 min**: Module refactor, feature with 2–3 functions
80
+ - **15+ min**: Split into smaller items (waves work best in 30–90 min total)
81
+
82
+ ### Backlog principles
63
83
 
64
84
  - **Sized for Haiku**: Each task should take 1 Haiku agent 3–10 minutes (not 30 minutes)
65
85
  - **Scoped**: "Fix auth timeout" is better than "Refactor auth system"
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,18 +219,48 @@ 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.
package/docs/PORTING.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  Guide for adopters porting the orchestration harness to a foreign repo. Step-by-step with prerequisites, scaffold, config, and the 10 likeliest failure modes from real deployments.
4
4
 
5
+ **Quick decision**:
6
+ - **New harness directory?** See [INSTALL.md](INSTALL.md) for the quick 5-minute scaffold.
7
+ - **Existing codebase?** You're in the right place. This guide covers integrating Aesop into your project with common pitfalls.
8
+
5
9
  ---
6
10
 
7
11
  ## Prerequisites