@matt82198/aesop 0.1.0-beta.3 → 0.1.0-beta.5
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 +79 -95
- package/CLAUDE-TEMPLATE.md +115 -0
- package/README.md +126 -245
- package/aesop.config.example.json +34 -26
- package/bin/CLAUDE.md +67 -0
- package/bin/cli.js +593 -36
- package/daemons/CLAUDE.md +36 -0
- package/daemons/backup-fleet.sh +92 -21
- package/daemons/run-watchdog.sh +95 -12
- package/dash/CLAUDE.md +32 -0
- package/dash/dash-extra.mjs +194 -21
- package/dash/watchdog-gui.sh +23 -6
- package/docs/BEHAVIORAL-PR-REVIEW.md +86 -0
- package/docs/CHECKPOINTING.md +100 -0
- package/docs/DISPATCH-MODEL.md +11 -7
- package/docs/FORENSICS.md +204 -0
- package/docs/GOVERNANCE.md +4 -2
- package/docs/HOOK-INSTALL.md +307 -0
- package/docs/HOW-THE-LOOP-WORKS.md +175 -0
- package/docs/MEMORY-TEMPLATE.md +61 -0
- package/docs/README.md +44 -0
- package/docs/RELEASING.md +159 -0
- package/docs/RELIABILITY.md +61 -0
- package/docs/RESTORE.md +397 -0
- package/docs/SCRIPTS-POLICY.md +97 -0
- package/docs/archive/README.md +3 -0
- package/docs/archive/spikes/tiered-cognition/ACTIVATION.md +125 -0
- package/docs/archive/spikes/tiered-cognition/DESIGN.md +287 -0
- package/docs/archive/spikes/tiered-cognition/FINDINGS.md +113 -0
- package/docs/archive/spikes/tiered-cognition/README.md +27 -0
- package/docs/archive/spikes/tiered-cognition/aesop-cognition.example.md +32 -0
- package/docs/archive/spikes/tiered-cognition/force-model-policy.merged.mjs +673 -0
- package/docs/archive/spikes/tiered-cognition/strip-tools-hook.mjs +434 -0
- package/docs/case-study-portfolio.md +61 -0
- package/docs/self-stats-data.json +11 -0
- package/docs/templates/FLEET-OPS-ANALYSIS.example.md +27 -0
- package/docs/templates/FLEET-OPS-RECOMMENDATIONS.example.md +24 -0
- package/docs/templates/PROPOSALS-LOG.example.md +64 -0
- package/hooks/CLAUDE.md +61 -0
- package/hooks/claude/force-model-policy.mjs +159 -0
- package/hooks/pre-push-policy.sh +753 -0
- package/mcp/CLAUDE.md +213 -0
- package/mcp/package.json +26 -0
- package/mcp/server.mjs +543 -0
- package/monitor/.signal-state.json +3 -0
- package/monitor/ACTIONS.log +1 -0
- package/monitor/BRIEF.md +24 -0
- package/monitor/CHARTER.md +75 -88
- package/monitor/CLAUDE.md +40 -0
- package/monitor/SIGNALS.json +54 -0
- package/monitor/collect-signals.mjs +613 -61
- package/package.json +15 -3
- package/scan/fleet-scan.example.mjs +292 -0
- package/skills/CLAUDE.md +3 -0
- package/skills/healthcheck/SKILL.md +44 -0
- package/skills/power/SKILL.md +161 -0
- package/state_store/CLAUDE.md +39 -0
- package/state_store/__init__.py +24 -0
- package/state_store/__pycache__/__init__.cpython-314.pyc +0 -0
- package/state_store/__pycache__/api.cpython-314.pyc +0 -0
- package/state_store/__pycache__/export.cpython-314.pyc +0 -0
- package/state_store/__pycache__/ingest.cpython-314.pyc +0 -0
- package/state_store/__pycache__/projections.cpython-314.pyc +0 -0
- package/state_store/__pycache__/store.cpython-314.pyc +0 -0
- package/state_store/api.py +35 -0
- package/state_store/export.py +19 -0
- package/state_store/ingest.py +24 -0
- package/state_store/projections.py +52 -0
- package/state_store/store.py +102 -0
- package/tools/CLAUDE.md +72 -0
- package/tools/__pycache__/alert_bridge.cpython-314.pyc +0 -0
- package/tools/__pycache__/buildlog.cpython-314.pyc +0 -0
- package/tools/__pycache__/ci_merge_wait.cpython-314.pyc +0 -0
- package/tools/__pycache__/ensure_state.cpython-314.pyc +0 -0
- package/tools/__pycache__/eod_sweep.cpython-314.pyc +0 -0
- package/tools/__pycache__/fleet_ledger.cpython-314.pyc +0 -0
- package/tools/__pycache__/fleet_prompt_extractor.cpython-314.pyc +0 -0
- package/tools/__pycache__/healthcheck.cpython-314.pyc +0 -0
- package/tools/__pycache__/heartbeat.cpython-314.pyc +0 -0
- package/tools/__pycache__/inbox_drain.cpython-314.pyc +0 -0
- package/tools/__pycache__/launch_tui.cpython-314.pyc +0 -0
- package/tools/__pycache__/metrics_gate.cpython-314.pyc +0 -0
- package/tools/__pycache__/orchestrator_status.cpython-314.pyc +0 -0
- package/tools/__pycache__/power_selftest.cpython-314.pyc +0 -0
- package/tools/__pycache__/prepublish_scan.cpython-314.pyc +0 -0
- package/tools/__pycache__/rotate_logs.cpython-314.pyc +0 -0
- package/tools/__pycache__/scanner_selftest.cpython-314.pyc +0 -0
- package/tools/__pycache__/secret_scan.cpython-314.pyc +0 -0
- package/tools/__pycache__/self_stats.cpython-314.pyc +0 -0
- package/tools/__pycache__/session_usage_summary.cpython-314.pyc +0 -0
- package/tools/__pycache__/stall_check.cpython-314.pyc +0 -0
- package/tools/__pycache__/transcript_replay.cpython-314.pyc +0 -0
- package/tools/__pycache__/transcript_timeline.cpython-314.pyc +0 -0
- package/tools/__pycache__/verify_dash.cpython-314.pyc +0 -0
- package/tools/__pycache__/verify_submit_encoding.cpython-314.pyc +0 -0
- package/tools/agent-forensics.sh +186 -0
- package/tools/alert_bridge.py +449 -0
- package/tools/buildlog.py +182 -0
- package/tools/ci_merge_wait.py +317 -0
- package/tools/ensure_state.py +94 -0
- package/tools/eod_sweep.py +239 -0
- package/tools/fleet_ledger.py +272 -0
- package/tools/fleet_prompt_extractor.py +134 -0
- package/tools/healthcheck.py +296 -0
- package/tools/heartbeat.py +131 -0
- package/tools/inbox_drain.py +249 -0
- package/tools/launch_tui.py +51 -3
- package/tools/lock.mjs +211 -0
- package/tools/metrics_gate.py +205 -0
- package/tools/orchestrator_status.py +99 -0
- package/tools/power_selftest.py +386 -0
- package/tools/prepublish_scan.py +84 -0
- package/tools/proposals.mjs +248 -0
- package/tools/reconstitute.sh +467 -0
- package/tools/rotate_logs.py +228 -0
- package/tools/scanner_selftest.py +303 -0
- package/tools/secret_scan.py +138 -31
- package/tools/self_stats.py +509 -0
- package/tools/session_usage_summary.py +198 -0
- package/tools/stall_check.py +172 -0
- package/tools/svg_to_png.mjs +50 -0
- package/tools/transcript_replay.py +236 -0
- package/tools/transcript_timeline.py +184 -0
- package/tools/verify_dash.py +513 -0
- package/tools/verify_submit_encoding.py +202 -0
- package/ui/CLAUDE.md +125 -0
- package/ui/__pycache__/agents.cpython-314.pyc +0 -0
- package/ui/__pycache__/collectors.cpython-314.pyc +0 -0
- package/ui/__pycache__/config.cpython-314.pyc +0 -0
- package/ui/__pycache__/cost.cpython-314.pyc +0 -0
- package/ui/__pycache__/csrf.cpython-314.pyc +0 -0
- package/ui/__pycache__/handler.cpython-314.pyc +0 -0
- package/ui/__pycache__/render.cpython-314.pyc +0 -0
- package/ui/__pycache__/serve.cpython-314.pyc +0 -0
- package/ui/__pycache__/sse.cpython-314.pyc +0 -0
- package/ui/agents.py +183 -0
- package/ui/api/__init__.py +84 -0
- package/ui/api/__pycache__/__init__.cpython-314.pyc +0 -0
- package/ui/api/__pycache__/submit.cpython-314.pyc +0 -0
- package/ui/api/__pycache__/tracker.cpython-314.pyc +0 -0
- package/ui/api/submit.py +97 -0
- package/ui/api/tracker.py +116 -0
- package/ui/collectors.py +735 -0
- package/ui/config.py +123 -0
- package/ui/cost.py +260 -0
- package/ui/csrf.py +144 -0
- package/ui/handler.py +676 -0
- package/ui/render.py +49 -0
- package/ui/serve.py +68 -796
- package/ui/sse.py +183 -0
- package/ui/web/.gitattributes +13 -0
- package/ui/web/dist/assets/index-2LZDQirC.js +9 -0
- package/ui/web/dist/assets/index-D4M1qyOv.css +1 -0
- package/ui/web/dist/index.html +14 -0
- package/ui/web/index.html +13 -0
- package/ui/web/package-lock.json +2225 -0
- package/ui/web/package.json +26 -0
- package/ui/web/src/App.test.tsx +74 -0
- package/ui/web/src/App.tsx +142 -0
- package/ui/web/src/CONTRIBUTING-UI.md +49 -0
- package/ui/web/src/components/AgentRow.css +187 -0
- package/ui/web/src/components/AgentRow.test.tsx +209 -0
- package/ui/web/src/components/AgentRow.tsx +207 -0
- package/ui/web/src/components/AgentsPanel.css +108 -0
- package/ui/web/src/components/AgentsPanel.test.tsx +41 -0
- package/ui/web/src/components/AgentsPanel.tsx +58 -0
- package/ui/web/src/components/AlertsPanel.css +88 -0
- package/ui/web/src/components/AlertsPanel.test.tsx +51 -0
- package/ui/web/src/components/AlertsPanel.tsx +67 -0
- package/ui/web/src/components/BacklogPanel.test.tsx +126 -0
- package/ui/web/src/components/BacklogPanel.tsx +122 -0
- package/ui/web/src/components/CostChart.css +110 -0
- package/ui/web/src/components/CostChart.test.tsx +144 -0
- package/ui/web/src/components/CostChart.tsx +152 -0
- package/ui/web/src/components/CostTable.css +93 -0
- package/ui/web/src/components/CostTable.test.tsx +165 -0
- package/ui/web/src/components/CostTable.tsx +94 -0
- package/ui/web/src/components/EventsFeed.css +68 -0
- package/ui/web/src/components/EventsFeed.test.tsx +36 -0
- package/ui/web/src/components/EventsFeed.tsx +31 -0
- package/ui/web/src/components/HealthHeader.css +137 -0
- package/ui/web/src/components/HealthHeader.test.tsx +278 -0
- package/ui/web/src/components/HealthHeader.tsx +281 -0
- package/ui/web/src/components/InboxForm.css +135 -0
- package/ui/web/src/components/InboxForm.test.tsx +208 -0
- package/ui/web/src/components/InboxForm.tsx +116 -0
- package/ui/web/src/components/MessagesTail.module.css +144 -0
- package/ui/web/src/components/MessagesTail.test.tsx +176 -0
- package/ui/web/src/components/MessagesTail.tsx +94 -0
- package/ui/web/src/components/ReposPanel.css +90 -0
- package/ui/web/src/components/ReposPanel.test.tsx +45 -0
- package/ui/web/src/components/ReposPanel.tsx +67 -0
- package/ui/web/src/components/Scorecard.css +106 -0
- package/ui/web/src/components/Scorecard.test.tsx +117 -0
- package/ui/web/src/components/Scorecard.tsx +85 -0
- package/ui/web/src/components/Timeline.module.css +151 -0
- package/ui/web/src/components/Timeline.test.tsx +215 -0
- package/ui/web/src/components/Timeline.tsx +99 -0
- package/ui/web/src/components/TrackerBoard.test.tsx +121 -0
- package/ui/web/src/components/TrackerBoard.tsx +107 -0
- package/ui/web/src/components/TrackerCard.test.tsx +180 -0
- package/ui/web/src/components/TrackerCard.tsx +160 -0
- package/ui/web/src/components/TrackerForm.test.tsx +189 -0
- package/ui/web/src/components/TrackerForm.tsx +144 -0
- package/ui/web/src/lib/api.ts +218 -0
- package/ui/web/src/lib/format.test.ts +89 -0
- package/ui/web/src/lib/format.ts +103 -0
- package/ui/web/src/lib/sanitizeUrl.test.ts +84 -0
- package/ui/web/src/lib/sanitizeUrl.ts +38 -0
- package/ui/web/src/lib/types.ts +230 -0
- package/ui/web/src/lib/useHashRoute.test.ts +60 -0
- package/ui/web/src/lib/useHashRoute.ts +23 -0
- package/ui/web/src/lib/useSSE.ts +175 -0
- package/ui/web/src/main.tsx +10 -0
- package/ui/web/src/styles/global.css +179 -0
- package/ui/web/src/styles/theme.css +184 -0
- package/ui/web/src/styles/work.css +572 -0
- package/ui/web/src/test/fixtures.ts +385 -0
- package/ui/web/src/test/setup.ts +49 -0
- package/ui/web/src/views/Activity.module.css +43 -0
- package/ui/web/src/views/Activity.test.tsx +89 -0
- package/ui/web/src/views/Activity.tsx +31 -0
- package/ui/web/src/views/Cost.css +87 -0
- package/ui/web/src/views/Cost.test.tsx +142 -0
- package/ui/web/src/views/Cost.tsx +54 -0
- package/ui/web/src/views/Overview.css +51 -0
- package/ui/web/src/views/Overview.test.tsx +76 -0
- package/ui/web/src/views/Overview.tsx +46 -0
- package/ui/web/src/views/Work.test.tsx +82 -0
- package/ui/web/src/views/Work.tsx +79 -0
- package/ui/web/src/vite-env.d.ts +10 -0
- package/ui/web/tsconfig.json +22 -0
- package/ui/web/vite.config.ts +25 -0
- package/ui/web/vitest.config.ts +12 -0
package/README.md
CHANGED
|
@@ -9,345 +9,226 @@
|
|
|
9
9
|
<p align="center">
|
|
10
10
|
<a href="https://www.npmjs.com/package/@matt82198/aesop"><img src="https://img.shields.io/npm/v/@matt82198/aesop/beta" alt="npm"></a>
|
|
11
11
|
<a href="LICENSE"><img src="https://img.shields.io/npm/l/@matt82198/aesop" alt="license"></a>
|
|
12
|
+
<a href="https://github.com/matt82198/aesop/actions/workflows/ci.yml"><img src="https://github.com/matt82198/aesop/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
|
|
12
13
|
</p>
|
|
13
14
|
|
|
14
|
-
**Aesop** is an open-source orchestration harness for Claude Code
|
|
15
|
+
**Aesop** is an open-source orchestration harness for Claude Code that builds itself. It runs a `/buildsystem` wave cycle—ranking a backlog, fanning out parallel Haiku agents (1/3 the cost of Opus), watchdogging them, verifying merges, then feeding the next wave via audit + ideation + fleet-ops monitoring. **This repo's own PRs are built by Aesop's own loop.** Dogfooding, not doctrine.
|
|
15
16
|
|
|
16
|
-
|
|
17
|
+
What you get: **cost-optimized multi-agent dispatch** (Haiku-first subagents, lean orchestrator), **durable state** (git-committed checkpoints survive wipes), **observable machinery** (every agent run logged, every cost tracked), **live dashboard** (real-time fleet health at http://localhost:8770), and **security gates** (secret-scan blocks pushes, CI validates each merge).
|
|
17
18
|
|
|
18
|
-
##
|
|
19
|
+
## What You Get
|
|
19
20
|
|
|
20
|
-
|
|
21
|
+
- **Parallel Haiku fleets** — Cheap, scoped subagents dispatch in parallel; orchestrator stays lean on main thread.
|
|
22
|
+
- **Durable state** — STATE.md + BUILDLOG.md checkpoints survive machine wipes; re-sync on resume, zero data loss.
|
|
23
|
+
- **Observable & auditable** — Every agent run logged, every cost tracked, every security event triaged.
|
|
24
|
+
- **Self-healing watchdog** — Runs every 150s: backs up work, scans for secrets, detects drift, restores on reboot.
|
|
25
|
+
- **Live web dashboard** — Real-time fleet health, security alerts, work-item kanban at `http://localhost:8770`.
|
|
26
|
+
- **Secret-scan gates** — Pre-push hook blocks leaks; audit trail logged. Pair with GitHub branch protection for enforcement.
|
|
21
27
|
|
|
22
|
-
##
|
|
28
|
+
## Get Started (3 steps, 5 min)
|
|
23
29
|
|
|
24
|
-
|
|
30
|
+
**Note:** Aesop is in beta. Install the `@beta` tag for the latest prerelease (0.1.0-beta.1+).
|
|
25
31
|
|
|
26
|
-
|
|
27
|
-
- **Durable state**: git-committed checkpoints (STATE.md, BUILDLOG.md) survive machine wipes and interruptions.
|
|
28
|
-
- **Observable machinery**: every agent run logged, every cost tracked, every security breach detected.
|
|
29
|
-
- **Self-healing watchdog**: runs every 150s, backs up work, scans for secrets and drift, restores on reboot.
|
|
30
|
-
- **Refinement monitor**: standing Haiku loop that watches orchestration health and auto-acts on rule friction.
|
|
31
|
-
- **TUI dashboard**: real-time fleet status, security alerts, heartbeat liveness.
|
|
32
|
-
|
|
33
|
-
## Install & Quick Start
|
|
34
|
-
|
|
35
|
-
### Option 1: npm (Recommended for quick scaffolding)
|
|
36
|
-
|
|
37
|
-
**Note:** Aesop is currently in beta. Install the prerelease version:
|
|
32
|
+
### Quickest path: npx scaffold
|
|
38
33
|
|
|
39
34
|
```bash
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
35
|
+
npx @matt82198/aesop@beta my-fleet \
|
|
36
|
+
--name "my-api" \
|
|
37
|
+
--repos "/path/to/repo1,/path/to/repo2"
|
|
43
38
|
cd my-fleet
|
|
44
39
|
|
|
45
|
-
# Configure
|
|
46
|
-
cp aesop.config.example.json aesop.config.json
|
|
47
|
-
# Edit aesop.config.json with your paths and repos
|
|
48
|
-
|
|
49
40
|
# Start the daemon
|
|
50
41
|
bash daemons/run-watchdog.sh --once
|
|
51
42
|
|
|
52
|
-
# Launch
|
|
43
|
+
# Launch dashboard on localhost:8770
|
|
53
44
|
python ui/serve.py
|
|
54
45
|
```
|
|
55
46
|
|
|
56
|
-
|
|
47
|
+
Pre-push hook auto-installed. See [docs/HOOK-INSTALL.md](./docs/HOOK-INSTALL.md) for branch protection pairing.
|
|
57
48
|
|
|
58
|
-
|
|
59
|
-
```bash
|
|
60
|
-
npm install -g @matt82198/aesop@beta
|
|
61
|
-
aesop my-fleet
|
|
62
|
-
```
|
|
49
|
+
**State Store**: Aesop uses an event-sourced SQLite WAL backing store (`state_store/`) for durable state persistence. The `tracker.json` file is automatically re-rendered as an export for git-friendly checkpointing. Mutations follow a dual-path model: append new events via the StateAPI, then rendered exports for external consumption.
|
|
63
50
|
|
|
64
|
-
###
|
|
51
|
+
### Or: git clone for hacking
|
|
65
52
|
|
|
66
53
|
```bash
|
|
67
54
|
git clone https://github.com/matt82198/aesop ~/aesop
|
|
68
55
|
cd ~/aesop
|
|
69
56
|
cp aesop.config.example.json aesop.config.json
|
|
70
|
-
# Edit
|
|
57
|
+
# Edit paths and repos
|
|
71
58
|
|
|
72
|
-
# Start the daemon
|
|
73
59
|
export AESOP_ROOT=$HOME/aesop
|
|
74
60
|
bash $AESOP_ROOT/daemons/run-watchdog.sh --once
|
|
75
|
-
|
|
76
|
-
# Launch the dashboard
|
|
77
61
|
python ui/serve.py
|
|
78
62
|
```
|
|
79
63
|
|
|
80
|
-
##
|
|
81
|
-
|
|
82
|
-
### Directory layout
|
|
64
|
+
## How It Works
|
|
83
65
|
|
|
84
66
|
```
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
67
|
+
daemons/run-watchdog.sh Every 150s: backs up work, scans secrets, detects drift
|
|
68
|
+
↓
|
|
69
|
+
orchestrator (via Claude Code) Reads backlog, dispatches Haiku subagents in parallel
|
|
70
|
+
↓
|
|
71
|
+
parallel Haiku fleet Tiny, scoped domains (tests, build, review, docs, etc.)
|
|
72
|
+
↓
|
|
73
|
+
watchdog verifies & merges GREEN → push to main
|
|
74
|
+
↓
|
|
75
|
+
monitor/collect-signals.mjs Audits orchestration health, feeds next wave's backlog
|
|
76
|
+
↓
|
|
77
|
+
STATE.md + BUILDLOG.md Git-committed, survives machine wipes
|
|
93
78
|
```
|
|
94
79
|
|
|
95
|
-
|
|
80
|
+
See [docs/DISPATCH-MODEL.md](./docs/DISPATCH-MODEL.md) for cost analysis and parallel patterns.
|
|
96
81
|
|
|
97
|
-
|
|
82
|
+
<!-- SELF-STATS:START -->
|
|
98
83
|
|
|
99
|
-
|
|
100
|
-
git clone <aesop-repo> ~/aesop
|
|
101
|
-
cd ~/aesop
|
|
102
|
-
cp aesop.config.example.json aesop.config.json
|
|
103
|
-
# Edit aesop.config.json with your paths and repos
|
|
104
|
-
```
|
|
84
|
+
## Aesop builds itself
|
|
105
85
|
|
|
106
|
-
|
|
86
|
+
Aesop is built entirely by its own `/buildsystem` wave cycle—running parallel Haiku fleets across ranked backlog items, verifying merges, auditing orchestration health. These stats are the receipts: all numbers computed LIVE from git, verified by anyone who clones.
|
|
107
87
|
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
88
|
+
| Metric | Value |
|
|
89
|
+
| --- | --- |
|
|
90
|
+
| Merged PRs | 141 <!-- metrics-verified: self_stats.py (git log) --> |
|
|
91
|
+
| Total Commits | 377 <!-- metrics-verified: self_stats.py (git log) --> |
|
|
92
|
+
| Project Age | 3 days <!-- metrics-verified: self_stats.py (git log) --> |
|
|
93
|
+
| Waves | 15 <!-- metrics-verified: self_stats.py (git log) --> |
|
|
94
|
+
| Insertions + Deletions | 70,439 <!-- metrics-verified: self_stats.py (git log) --> |
|
|
95
|
+
| Files Tracked | 257 <!-- metrics-verified: self_stats.py (git log) --> |
|
|
96
|
+
| Distinct Co-authors | 7 <!-- metrics-verified: self_stats.py (git log) --> |
|
|
112
97
|
|
|
113
|
-
|
|
98
|
+
<!-- SELF-STATS:END -->
|
|
114
99
|
|
|
115
|
-
|
|
100
|
+
## Recommended Agents
|
|
116
101
|
|
|
117
|
-
|
|
102
|
+
Aesop pairs well with the open-source [Claude specialized-agent catalog](https://github.com/anthropics/claude-code/tree/main/agents) — a library of ~130 domain-specific agents (TDD orchestrators, security reviewers, performance engineers, etc.). For optimal results, install agents from the upstream source and pair them with Aesop's cost-optimized Haiku dispatch. This is optional; Aesop works standalone with general-purpose Claude Code agents.
|
|
118
103
|
|
|
119
|
-
|
|
120
|
-
python $AESOP_ROOT/ui/serve.py
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
Opens `http://localhost:8770` with:
|
|
124
|
-
- Real-time daemon heartbeats and liveness
|
|
125
|
-
- Active subagent tracking
|
|
126
|
-
- Security alerts panel
|
|
127
|
-
- Recent events log
|
|
128
|
-
- Inbox for orchestrator communication
|
|
129
|
-
- Repository sync status
|
|
130
|
-
|
|
131
|
-
See `ui/README.md` for configuration, environment variables, and troubleshooting.
|
|
104
|
+
## Use with Claude Code
|
|
132
105
|
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
If you prefer a terminal-based interface:
|
|
106
|
+
If you're using **Claude Code**, invoke `/power` at the start of each session. It loads your orchestrator brain (cardinal rules, domain map, team memory, system state) and outputs a health brief. Setup once:
|
|
136
107
|
|
|
137
108
|
```bash
|
|
138
|
-
#
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
# On Unix:
|
|
142
|
-
bash ~/aesop/dash/watchdog-gui.sh &
|
|
109
|
+
# Copy the /power skill
|
|
110
|
+
cp -r skills/power/ ~/.claude/skills/power/
|
|
143
111
|
```
|
|
144
112
|
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
#### 4. Arm the monitor loop
|
|
148
|
-
|
|
149
|
-
```bash
|
|
150
|
-
# If using Claude Code, add to your CLAUDE.md or invoke via /power:
|
|
151
|
-
# Runs collect-signals.mjs every cycle, emits BRIEF.md + SIGNALS.json,
|
|
152
|
-
# then acts on AUTO-tier findings or stages PROPOSE-tier changes.
|
|
153
|
-
```
|
|
113
|
+
Then in Claude Code, type `/power` or `/buildsystem` to start a wave cycle. See [skills/power/SKILL.md](./skills/power/SKILL.md) for details.
|
|
154
114
|
|
|
155
|
-
##
|
|
115
|
+
## Core Principles
|
|
156
116
|
|
|
157
|
-
|
|
117
|
+
1. **Haiku-first dispatch** — Subagents always cheap; orchestrator stays lean on main thread.
|
|
118
|
+
2. **Durable state** — STATE.md + BUILDLOG.md survive wipes; re-sync on resume.
|
|
119
|
+
3. **Observable** — Every agent run logged, every cost tracked, every security event triaged.
|
|
120
|
+
4. **TDD-first** — Fail tests before implementation; one Haiku per scoped domain.
|
|
121
|
+
5. **Never wait** — Dispatch work in parallel; connect with heartbeats, not polling.
|
|
122
|
+
6. **Push discipline** — feature/* branches only; secret-scan gates every push.
|
|
158
123
|
|
|
159
|
-
|
|
160
|
-
2. **TDD-first**: Fail tests before implementation. Tiny scoped domains; one Haiku per domain.
|
|
161
|
-
3. **Reliability**: Every input produces output (brief/log/heartbeat/FAILED). Never wait.
|
|
162
|
-
4. **Durable state**: STATE.md + BUILDLOG.md checkpoints survive wipes. Re-sync on resume.
|
|
163
|
-
5. **Push discipline**: feature/branch → PR (never main). Continuously push green work.
|
|
164
|
-
6. **Control files**: Single-writer discipline (STATE.md orchestrator, MEMORY.md keeper, BUILDLOG.md append-only).
|
|
165
|
-
7. **Local execution**: Python runs locally only (no cloud runners). Reusable scripts in ~/scripts.
|
|
166
|
-
8. **Secret gates**: `secret_scan.py` blocks every push. No credentials in repos.
|
|
167
|
-
9. **Observability**: Every agent run logged, every cost tracked, every security event triaged.
|
|
124
|
+
Read [docs/CARDINAL-RULES.md](./docs/CARDINAL-RULES.md) for the full text.
|
|
168
125
|
|
|
169
126
|
## Requirements
|
|
170
127
|
|
|
171
|
-
-
|
|
172
|
-
-
|
|
173
|
-
-
|
|
174
|
-
-
|
|
175
|
-
-
|
|
176
|
-
-
|
|
128
|
+
- Claude Code CLI (v0.1+)
|
|
129
|
+
- Git (v2.40+)
|
|
130
|
+
- Bash (v4+) or Git Bash on Windows
|
|
131
|
+
- Node.js (v18+) for dashboard and monitor
|
|
132
|
+
- Python (v3.10+) for log rotation and secret-scan
|
|
133
|
+
- jq (optional) for TUI dashboard
|
|
177
134
|
|
|
178
|
-
##
|
|
135
|
+
## Scaling Cheaply
|
|
179
136
|
|
|
180
|
-
|
|
137
|
+
The **dispatch model** fans work across parallel Haiku subagents (each 1/3 the cost of Opus). The orchestrator stays lean on the main thread, coordinating via durable STATE.md. Result: ~25% the cost of an all-Opus fleet.
|
|
181
138
|
|
|
182
|
-
|
|
183
|
-
cp aesop.config.example.json aesop.config.json
|
|
184
|
-
```
|
|
139
|
+
**Action tiers**: AUTO (immediate, logged) for read-only checks and appends; PROPOSE (staged in `monitor/PROPOSALS.md`) for changes requiring approval. See [docs/GOVERNANCE.md](./docs/GOVERNANCE.md).
|
|
185
140
|
|
|
186
|
-
|
|
187
|
-
- Set `aesop_root`, `brain_root`, `scripts_root`, `temp_root` to your paths.
|
|
188
|
-
- List your project repos under `repos[]`.
|
|
189
|
-
- Tune watchdog and monitor cycle times.
|
|
190
|
-
- Disable secret-scan if you don't have `tools/secret_scan.py` yet.
|
|
141
|
+
## Security
|
|
191
142
|
|
|
192
|
-
|
|
143
|
+
The pre-push hook (`hooks/pre-push-policy.sh`) enforces branch discipline and secret scanning locally. It is bypassable (use `--no-verify` to skip), so **pair it with GitHub branch protection** for real enforcement:
|
|
193
144
|
|
|
194
|
-
```bash
|
|
195
|
-
mkdir -p ~/aesop/state
|
|
196
|
-
mkdir -p ~/.heartbeats
|
|
197
145
|
```
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
Example stub:
|
|
204
|
-
```python
|
|
205
|
-
#!/usr/bin/env python3
|
|
206
|
-
import sys
|
|
207
|
-
sys.exit(0) # TODO: implement secret scanning
|
|
146
|
+
Settings > Branches > main
|
|
147
|
+
✓ Require pull request reviews
|
|
148
|
+
✓ Require status checks to pass
|
|
149
|
+
✓ Dismiss stale PR approvals
|
|
150
|
+
✓ Restrict pushes to (Admins only)
|
|
208
151
|
```
|
|
209
152
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
```bash
|
|
213
|
-
export AESOP_ROOT=$HOME/aesop
|
|
214
|
-
bash $AESOP_ROOT/daemons/run-watchdog.sh &
|
|
215
|
-
```
|
|
153
|
+
Private brain (`~/.claude`) is never committed to this repo. Keep `aesop.config.json` git-ignored. Implement `tools/secret_scan.py` with your security rules. See [docs/HOOK-INSTALL.md](./docs/HOOK-INSTALL.md) for setup.
|
|
216
154
|
|
|
217
|
-
|
|
155
|
+
## Dashboard (Wave-14 Rewrite)
|
|
218
156
|
|
|
219
|
-
|
|
157
|
+
The dashboard is a **React 18 + Vite + TypeScript** single-page app with four hash-routed views:
|
|
220
158
|
|
|
159
|
+
### Viewing the Dashboard
|
|
221
160
|
```bash
|
|
222
|
-
|
|
161
|
+
python ui/serve.py
|
|
223
162
|
```
|
|
163
|
+
Opens `http://localhost:8770` — live fleet health, security alerts, work-item kanban, cost analytics.
|
|
224
164
|
|
|
225
|
-
###
|
|
165
|
+
### Architecture
|
|
166
|
+
- **Backend**: Python stdlib HTTP server (`ui/handler.py`) serves the built React app + JSON/SSE APIs (`/api/state`, `/api/cost`, `/events`).
|
|
167
|
+
- **Frontend**: `ui/web/` (React app) is built to `dist/` (committed to git) and served as static files by the Python server.
|
|
168
|
+
- **CSRF protection**: Token injected into `dist/index.html` via sentinel substitution; mutations gated by `/submit` and `/api/tracker` endpoints.
|
|
226
169
|
|
|
227
|
-
|
|
170
|
+
### Development
|
|
228
171
|
```bash
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
The monitor will read `BRIEF.md` and `SIGNALS.json` each cycle and act on findings.
|
|
234
|
-
|
|
235
|
-
## Usage Patterns
|
|
236
|
-
|
|
237
|
-
### Dispatch model (how to scale cheaply)
|
|
238
|
-
|
|
239
|
-
```plaintext
|
|
240
|
-
Orchestrator (main thread)
|
|
241
|
-
├─ Haiku subagent 1 (domain A: tests)
|
|
242
|
-
├─ Haiku subagent 2 (domain B: build)
|
|
243
|
-
├─ Haiku subagent 3 (domain C: review)
|
|
244
|
-
└─ Haiku subagent 4 (domain D: docs)
|
|
172
|
+
cd ui/web
|
|
173
|
+
npm install
|
|
174
|
+
npm run dev # Vite dev server with API proxy to http://localhost:8770
|
|
175
|
+
npm run build # Build to dist/ (commit the dist/)
|
|
245
176
|
```
|
|
246
177
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
### Action tiers (AUTO vs PROPOSE)
|
|
250
|
-
|
|
251
|
-
- **AUTO**: immediate + logged (read-only checks, appends to logs, heartbeat updates).
|
|
252
|
-
- **PROPOSE**: staged in `monitor/PROPOSALS.md`, requires user approval before execution.
|
|
253
|
-
|
|
254
|
-
### Heartbeat pattern
|
|
255
|
-
|
|
256
|
-
Daemons write epoch-seconds to `.heartbeat` files. The dashboard reads these to detect stalls:
|
|
257
|
-
- Watchdog: alert if >300s old.
|
|
258
|
-
- Monitor: alert if >3600s old.
|
|
259
|
-
- Custom loops: check before spawning (skip if <200s).
|
|
178
|
+
The dev server proxies `/data`, `/api`, `/events`, `/agent`, `/submit` to the Python backend on :8770, so the frontend can develop against live APIs.
|
|
260
179
|
|
|
261
|
-
|
|
180
|
+
### Views
|
|
181
|
+
- **Overview**: Fleet agents, security alerts, recent events.
|
|
182
|
+
- **Work** (`#/work`): Tracker kanban (4 lanes: proposed/ranked/in-progress/done), audit backlog progress.
|
|
183
|
+
- **Activity** (`#/activity`): Agent timeline, main-thread message tail (live reasoning).
|
|
184
|
+
- **Cost** (`#/cost`): Per-model spend/tokens, per-day bar chart, verdict scorecard (success/failure rates).
|
|
262
185
|
|
|
263
|
-
|
|
186
|
+
## Extending Aesop
|
|
264
187
|
|
|
265
|
-
|
|
266
|
-
- `state/` and `.log` files are git-ignored (keep runtime data local).
|
|
267
|
-
- Implement `tools/secret_scan.py` with your own security rules.
|
|
268
|
-
- Use `secret_scan.py` as a gate on every push (don't bypass).
|
|
188
|
+
**Custom signal collectors**: Edit `monitor/collect-signals.mjs` to add domain-specific health checks.
|
|
269
189
|
|
|
270
|
-
|
|
190
|
+
**Custom watchdog hooks**: Edit `daemons/backup-fleet.sh` to run linters, integrate with your CI, or customize secret-scan logic.
|
|
271
191
|
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
Edit `monitor/collect-signals.mjs`:
|
|
275
|
-
```javascript
|
|
276
|
-
// Example: detect junk scripts
|
|
277
|
-
function findJunkScripts() {
|
|
278
|
-
const junk = fs.readdirSync('/tmp').filter(f => f.endsWith('.py'));
|
|
279
|
-
return junk;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// Then add to signals:
|
|
283
|
-
signals.junkScripts = findJunkScripts();
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
### Customize the watchdog
|
|
287
|
-
|
|
288
|
-
Edit `daemons/backup-fleet.sh`:
|
|
289
|
-
- Parse `aesop.config.json` to discover repos dynamically.
|
|
290
|
-
- Add per-repo hooks (e.g., run linters before backup).
|
|
291
|
-
- Implement your own secret-scan gate.
|
|
292
|
-
|
|
293
|
-
### Extend the dashboard
|
|
294
|
-
|
|
295
|
-
Edit `dash/watchdog-gui.sh`:
|
|
296
|
-
- Add panels for CPU/memory/disk usage.
|
|
297
|
-
- Integrate with your monitoring system.
|
|
298
|
-
- Color-code alerts by severity.
|
|
192
|
+
**Dashboard components**: Add React components in `ui/web/src/components/` or new views in `ui/web/src/views/`. Rebuild and commit `dist/`.
|
|
299
193
|
|
|
300
194
|
## Troubleshooting
|
|
301
195
|
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
196
|
+
| Issue | Check |
|
|
197
|
+
|-------|-------|
|
|
198
|
+
| Watchdog doesn't start | `state/FLEET-BACKUP.log` for errors; verify `AESOP_ROOT` is set |
|
|
199
|
+
| Dashboard shows "unavailable" | Install Node.js v18+; check `dash-extra.mjs` is in sync |
|
|
200
|
+
| Secret-scan blocks push | Add suppression to `tools/secret_scan.py`; no auto-bypass (by design) |
|
|
201
|
+
| Monitor doesn't start | Verify Node.js on PATH; check `monitor/BRIEF.md` for logs |
|
|
305
202
|
|
|
306
|
-
|
|
203
|
+
For deeper docs, see `docs/`:
|
|
204
|
+
- `CARDINAL-RULES.md` — full 10 principles
|
|
205
|
+
- `DISPATCH-MODEL.md` — cost analysis and patterns
|
|
206
|
+
- `CHECKPOINTING.md` — how STATE.md + BUILDLOG.md survive wipes
|
|
207
|
+
- `GOVERNANCE.md` — AUTO/PROPOSE tiers
|
|
208
|
+
- `case-study-portfolio.md` — How Aesop built its own portfolio site; full audit trail and cost breakdown
|
|
307
209
|
|
|
308
|
-
|
|
309
|
-
- Install Node.js v18+ and re-run.
|
|
210
|
+
See [CHANGELOG.md](./CHANGELOG.md) for release notes.
|
|
310
211
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
Add a suppression to your `tools/secret_scan.py`. Aesop never auto-bypasses gates (by design).
|
|
314
|
-
|
|
315
|
-
### Monitor doesn't start
|
|
212
|
+
## Contributing
|
|
316
213
|
|
|
317
|
-
|
|
214
|
+
Aesop welcomes improvements. The repo uses its own `/buildsystem` loop for development—PRs from `feature/*` branches are built, tested, and merged by Aesop itself. To contribute:
|
|
318
215
|
|
|
319
|
-
|
|
216
|
+
1. Fork and create a `feature/*` branch.
|
|
217
|
+
2. Write failing tests first (TDD).
|
|
218
|
+
3. Open a PR; Aesop's wave cycle will verify and merge.
|
|
320
219
|
|
|
321
|
-
|
|
322
|
-
- `CARDINAL-RULES.md` — full text of the 10 cardinal rules.
|
|
323
|
-
- `DISPATCH-MODEL.md` — cost analysis and parallel orchestration patterns.
|
|
324
|
-
- `STATE-MACHINE.md` — how STATE.md and BUILDLOG.md survive wipes.
|
|
325
|
-
- `MONITOR-GOVERNANCE.md` — monitor AUTO/PROPOSE tiers and approval flow.
|
|
220
|
+
Maintain the core principles: **Haiku-first** subagents, **lean** orchestrator, **durable** state, **observable** machinery.
|
|
326
221
|
|
|
327
222
|
## License
|
|
328
223
|
|
|
329
|
-
MIT
|
|
330
|
-
|
|
331
|
-
## Contributing
|
|
332
|
-
|
|
333
|
-
Aesop is open-source and welcomes improvements. To contribute:
|
|
334
|
-
|
|
335
|
-
1. Fork this repo.
|
|
336
|
-
2. Create a feature branch: `git checkout -b feature/your-idea`.
|
|
337
|
-
3. Add tests (TDD first).
|
|
338
|
-
4. Commit with clear messages.
|
|
339
|
-
5. Push to origin and open a PR.
|
|
340
|
-
|
|
341
|
-
Maintain the cardinal rules: keep subagents cheap (Haiku), orchestrator lean, state durable, and machinery observable.
|
|
224
|
+
MIT. See `LICENSE`.
|
|
342
225
|
|
|
343
226
|
## References
|
|
344
227
|
|
|
345
|
-
- [Anthropic Claude API](https://docs.anthropic.com)
|
|
228
|
+
- [Anthropic Claude API docs](https://docs.anthropic.com)
|
|
346
229
|
- [Claude Code CLI](https://github.com/anthropics/claude-code)
|
|
347
|
-
- [Git
|
|
348
|
-
- Inspiration: "The Missing Memory Layer", "Agent Cost Trauma", "120 Words to Shipped" (publications on AI orchestration patterns).
|
|
230
|
+
- [Git docs](https://git-scm.com/doc)
|
|
349
231
|
|
|
350
232
|
---
|
|
351
233
|
|
|
352
|
-
**Aesop
|
|
353
|
-
Built with the fable-fleet dispatch model in mind. May your orchestrator be wise and your subagents swift.
|
|
234
|
+
**Aesop**: Fable-fleet orchestration, built by Aesop itself. May your orchestrator be wise and your subagents swift.
|
|
@@ -1,47 +1,55 @@
|
|
|
1
1
|
{
|
|
2
|
-
"description": "Aesop configuration
|
|
3
|
-
"
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
"description": "Aesop configuration. Precedence: environment variables > config file > built-in defaults.",
|
|
3
|
+
"_paths": {
|
|
4
|
+
"aesop_root": "Set via AESOP_ROOT env var (no config key)",
|
|
5
|
+
"brain_root": "Override via BRAIN_ROOT env var or config; default: {aesop_root}/../.claude",
|
|
6
|
+
"scripts_root": "Override via SCRIPTS_ROOT env var or config; default: {aesop_root}/../scripts",
|
|
7
|
+
"temp_root": "Override via TEMP_ROOT env var or config; default: system temp + /claude",
|
|
8
|
+
"state_root": "Override via AESOP_STATE_ROOT env var or config; default: {aesop_root}/state",
|
|
9
|
+
"fleet_root": "Override via AESOP_FLEET_ROOT env var or config; default: $HOME. SECURITY: all repository clone targets must remain under fleet_root to prevent credential harvesting across account boundaries. The monitor validates clone targets on each cycle and surfaces violations as HIGH alerts.",
|
|
10
|
+
"transcripts_root": "Override via AESOP_TRANSCRIPTS_ROOT env var or config; default: ~/.claude/projects"
|
|
11
|
+
},
|
|
12
|
+
"brain_root": "~/.claude",
|
|
13
|
+
"scripts_root": "~/scripts",
|
|
14
|
+
"temp_root": "~/.aesop-temp",
|
|
15
|
+
"_temp_root_notes": "Portable path for temporary aesop files. ~ expands to home directory on both Windows and POSIX. Alternatively, on Windows set to %TEMP%/aesop, on POSIX set to /tmp/aesop. Config loaders expand ~ at runtime.",
|
|
16
|
+
"state_root": "./state",
|
|
17
|
+
"fleet_root": "/path/to/fleet",
|
|
18
|
+
"transcripts_root": "~/.claude/projects",
|
|
7
19
|
"repos": [
|
|
8
20
|
{
|
|
9
21
|
"path": "/path/to/project1",
|
|
10
22
|
"name": "project1",
|
|
23
|
+
"url": "https://github.com/user/project1.git",
|
|
11
24
|
"primary_branch": "main",
|
|
12
25
|
"backup_branch": "backup/wip"
|
|
13
26
|
},
|
|
14
27
|
{
|
|
15
28
|
"path": "/path/to/project2",
|
|
16
29
|
"name": "project2",
|
|
30
|
+
"url": "git@github.com:user/project2.git",
|
|
17
31
|
"primary_branch": "main",
|
|
18
32
|
"backup_branch": "backup/wip"
|
|
19
33
|
}
|
|
20
34
|
],
|
|
21
|
-
"watchdog": {
|
|
22
|
-
"cycle_seconds": 150,
|
|
23
|
-
"heartbeat_threshold_seconds": 200,
|
|
24
|
-
"enable_secret_scan": true,
|
|
25
|
-
"secret_scan_script": "tools/secret_scan.py"
|
|
26
|
-
},
|
|
27
35
|
"monitor": {
|
|
28
|
-
"enable": true,
|
|
29
|
-
"cycle_seconds": 3600,
|
|
30
|
-
"heartbeat_threshold_seconds": 3600,
|
|
31
|
-
"memory_staleness_days": 30,
|
|
32
36
|
"log_max_lines": 500,
|
|
33
|
-
"log_max_kb": 40
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
"log_max_kb": 40,
|
|
38
|
+
"extended_signals": false,
|
|
39
|
+
"heartbeat_thresholds": {
|
|
40
|
+
"monitor": 3600,
|
|
41
|
+
"watchdog": 300,
|
|
42
|
+
"default": 1800
|
|
43
|
+
}
|
|
39
44
|
},
|
|
40
45
|
"cardinal_rules": {
|
|
41
|
-
"subagent_model": "haiku"
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
"
|
|
45
|
-
"
|
|
46
|
+
"subagent_model": "haiku"
|
|
47
|
+
},
|
|
48
|
+
"alerts": {
|
|
49
|
+
"_comment": "Slack/Discord webhook integration for fleet alerts. webhook_url: null (default) disables alerts (feature opt-in). SETUP: (1) Slack: Create an app at https://api.slack.com/apps, enable 'Incoming Webhooks', add a new webhook to your channel, copy the Webhook URL. (2) Discord: In your Discord server, go to Server Settings > Integrations > Webhooks, create a webhook, copy its URL. SECURITY: NEVER commit a real webhook URL to version control — retrieve at runtime via environment variable AESOP_ALERTS_WEBHOOK_URL or load from a .env.local file. Provider: 'slack' (block-kit format) or 'discord' (embed format). min_severity: filter by HIGH/CRITICAL/etc. heartbeat_stall_s: alert if watchdog heartbeat older than N seconds (null = skip).",
|
|
50
|
+
"webhook_url": null,
|
|
51
|
+
"provider": "slack",
|
|
52
|
+
"min_severity": "HIGH",
|
|
53
|
+
"heartbeat_stall_s": 600
|
|
46
54
|
}
|
|
47
55
|
}
|
package/bin/CLAUDE.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# bin/ — CLI scaffolder
|
|
2
|
+
|
|
3
|
+
**Purpose**: Node.js CLI entry point that clones the aesop orchestration template into a target directory with idempotent validation, plus an interactive onboarding wizard for new adopters.
|
|
4
|
+
|
|
5
|
+
## Invocation
|
|
6
|
+
|
|
7
|
+
- **npm registry**: `npx @matt82198/aesop [target-dir]` (default: `aesop-fleet`)
|
|
8
|
+
- **Local dev**: `node bin/cli.js [target-dir]`
|
|
9
|
+
- **Help**: `npx @matt82198/aesop --help` or `-h`
|
|
10
|
+
- **Interactive wizard**: `npx @matt82198/aesop wizard` (on a TTY, prompts; with `--yes`, uses defaults)
|
|
11
|
+
|
|
12
|
+
## What gets copied
|
|
13
|
+
|
|
14
|
+
Files in `filesToCopy` array (cli.js line 57–69):
|
|
15
|
+
- **Directories**: `daemons/`, `dash/`, `monitor/`, `tools/`, `ui/`, `docs/`
|
|
16
|
+
- **Files**: `aesop.config.example.json`, `README.md`, `LICENSE`, `CHANGELOG.md`, `CLAUDE-TEMPLATE.md`
|
|
17
|
+
- **Brain templates** (in docs/): `MEMORY-TEMPLATE.md` (via docs/ directory copy)
|
|
18
|
+
|
|
19
|
+
## What does NOT get copied
|
|
20
|
+
|
|
21
|
+
- `aesop.config.json` (users must `cp aesop.config.example.json` and edit)
|
|
22
|
+
- `state/` (runtime durable state, git-ignored, created by daemons)
|
|
23
|
+
- `.git/`, `node_modules/`, build artifacts
|
|
24
|
+
|
|
25
|
+
## Post-scaffold guidance
|
|
26
|
+
|
|
27
|
+
Scaffolder prints steps for users:
|
|
28
|
+
1. `cd target-dir && cp aesop.config.example.json aesop.config.json`
|
|
29
|
+
2. Edit config with paths and repos
|
|
30
|
+
3. Initialize brain: `cp CLAUDE-TEMPLATE.md ~/.claude/CLAUDE.md` (edit)
|
|
31
|
+
4. Initialize memory: `cp docs/MEMORY-TEMPLATE.md ~/.claude/MEMORY.md` (edit)
|
|
32
|
+
5. Test daemon: `bash daemons/run-watchdog.sh --once`
|
|
33
|
+
6. Launch dashboard: `python ui/serve.py`
|
|
34
|
+
|
|
35
|
+
## Interactive wizard (`aesop wizard`)
|
|
36
|
+
|
|
37
|
+
The wizard mode provides an interactive onboarding flow for new adopters, guiding them through fleet setup in ~60 seconds:
|
|
38
|
+
|
|
39
|
+
1. **Trigger**: `npx @matt82198/aesop wizard` on a TTY (interactive terminal)
|
|
40
|
+
2. **Questions** (all have sensible defaults, press Enter-Enter-Enter to skip):
|
|
41
|
+
- Project name (default: "my-fleet")
|
|
42
|
+
- Repos to watch (auto-discovers git repos under `~`, offers choices)
|
|
43
|
+
- Dashboard port (default: 8770, validates 1–65535)
|
|
44
|
+
- Brain root directory (default: `~/.claude`)
|
|
45
|
+
3. **Output**:
|
|
46
|
+
- Scaffolds template files
|
|
47
|
+
- Generates CLAUDE.md (substituted with project name)
|
|
48
|
+
- Generates aesop.config.json (with discovered repos)
|
|
49
|
+
- Prints "next 3 commands" epilogue
|
|
50
|
+
- Offers to run `watchdog --once` smoke test immediately
|
|
51
|
+
4. **Non-interactive mode** (`--yes` flag or non-TTY stdin): Uses defaults, zero prompts (CI-safe)
|
|
52
|
+
|
|
53
|
+
### Wizard implementation details
|
|
54
|
+
|
|
55
|
+
- **Repo discovery** (`discoverRepos`): Scans `~` for `.git` directories at first level (non-recursive)
|
|
56
|
+
- **Port validation** (`validatePort`): Rejects invalid ports, accepts 1–65535
|
|
57
|
+
- **Portable paths**: All config paths use `~` form (`~/.claude`, `~/scripts`, etc.) for cross-platform compatibility
|
|
58
|
+
- **Defaults**: Every prompt has a default so users can skip it (press Enter)
|
|
59
|
+
- **Non-destructive**: Never overwrites existing `aesop.config.json` without user confirmation
|
|
60
|
+
|
|
61
|
+
## Invariants & gotchas
|
|
62
|
+
|
|
63
|
+
- **Idempotent on empty targets**: Fails if `targetDir` exists and is non-empty (non-destructive). Safe to retry.
|
|
64
|
+
- **Adding shipped files**: Any new file/dir added to `filesToCopy` array must also be added to `package.json` `files` array (lines 9–21 in package.json) so npm publish includes it.
|
|
65
|
+
- **No machine-specific paths**: Use relative paths only; `__dirname` and `path.join()` handle cross-platform resolution.
|
|
66
|
+
- **Wizard prompts are async**: Main execution is wrapped in async IIFE to support readline prompts
|
|
67
|
+
- **Help text accuracy**: If invocation steps or output paths change, update help text
|