@matt82198/aesop 0.1.0-beta.3 → 0.1.0-beta.4
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 +37 -94
- package/CLAUDE-TEMPLATE.md +115 -0
- package/README.md +89 -264
- package/aesop.config.example.json +27 -26
- package/bin/CLAUDE.md +39 -0
- package/bin/cli.js +368 -24
- package/daemons/CLAUDE.md +33 -0
- package/daemons/backup-fleet.sh +92 -21
- package/daemons/run-watchdog.sh +90 -10
- 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/RELIABILITY.md +61 -0
- package/docs/RESTORE.md +397 -0
- package/docs/SCRIPTS-POLICY.md +97 -0
- package/docs/spikes/tiered-cognition/ACTIVATION.md +125 -0
- package/docs/spikes/tiered-cognition/DESIGN.md +287 -0
- package/docs/spikes/tiered-cognition/FINDINGS.md +113 -0
- package/docs/spikes/tiered-cognition/README.md +29 -0
- package/docs/spikes/tiered-cognition/aesop-cognition.example.md +32 -0
- package/docs/spikes/tiered-cognition/force-model-policy.merged.mjs +673 -0
- package/docs/spikes/tiered-cognition/strip-tools-hook.mjs +434 -0
- package/hooks/CLAUDE.md +38 -0
- package/hooks/claude/force-model-policy.mjs +159 -0
- package/hooks/pre-push-policy.sh +753 -0
- package/monitor/.signal-state.json +3 -0
- package/monitor/ACTIONS.log +1 -0
- package/monitor/BRIEF.md +24 -0
- package/monitor/CHARTER.md +29 -8
- package/monitor/CLAUDE.md +40 -0
- package/monitor/SIGNALS.json +54 -0
- package/monitor/collect-signals.mjs +529 -62
- package/package.json +12 -3
- package/skills/CLAUDE.md +3 -0
- package/skills/power/SKILL.md +161 -0
- package/tools/CLAUDE.md +191 -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__/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__/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__/stall_check.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/buildlog.py +182 -0
- package/tools/ci_merge_wait.py +204 -0
- package/tools/ensure_state.py +94 -0
- package/tools/eod_sweep.py +239 -0
- package/tools/fleet_ledger.py +272 -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 +131 -31
- package/tools/stall_check.py +172 -0
- package/tools/verify_dash.py +694 -0
- package/tools/verify_submit_encoding.py +194 -0
- package/ui/CLAUDE.md +109 -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__/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 +179 -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 +58 -0
- package/ui/api/tracker.py +116 -0
- package/ui/collectors.py +586 -0
- package/ui/config.py +114 -0
- package/ui/csrf.py +140 -0
- package/ui/handler.py +426 -0
- package/ui/render.py +29 -0
- package/ui/serve.py +68 -796
- package/ui/sse.py +168 -0
- package/ui/templates/dashboard.html +1202 -0
|
@@ -0,0 +1,307 @@
|
|
|
1
|
+
# Git Pre-Push Hook Installation Guide
|
|
2
|
+
|
|
3
|
+
**Ship a hook, not a memo.** The pre-push policy hook is **auto-installed during scaffold** (see below). This guide explains customization, verification, and org-wide distribution.
|
|
4
|
+
|
|
5
|
+
## Security Model: Local Convenience Defense Only
|
|
6
|
+
|
|
7
|
+
**IMPORTANT**: The pre-push hook is a **local-machine convenience defense** — it is **NOT cryptographic protection**. Any developer can bypass it with `git push --no-verify` or by editing/deleting `.git/hooks/pre-push`. The audit log (`SECURITY-AUDIT.log`) is stored locally and can also be edited by a user with file system access.
|
|
8
|
+
|
|
9
|
+
**Real enforcement requires server-side branch protection.** See GitHub Configuration below.
|
|
10
|
+
|
|
11
|
+
## What the Hook Does
|
|
12
|
+
|
|
13
|
+
`hooks/pre-push-policy.sh` enforces two checks at git push time:
|
|
14
|
+
|
|
15
|
+
1. **Branch Policy**: Blocks direct pushes to `main` or `master` branches (feature branches only).
|
|
16
|
+
2. **Secret Scan**: Runs `tools/secret_scan.py --staged` to detect credentials before they reach the remote.
|
|
17
|
+
|
|
18
|
+
Both blocks append a JSON audit record to `state/SECURITY-AUDIT.log` with timestamp, repo, reason, and user — creating a reviewable trail of policy enforcement.
|
|
19
|
+
|
|
20
|
+
## Auto-Installation During Scaffold
|
|
21
|
+
|
|
22
|
+
**Default Behavior:** When you scaffold a new aesop fleet with `npx @matt82198/aesop [target-dir]`, the CLI automatically installs the pre-push hook into `.git/hooks/pre-push`.
|
|
23
|
+
|
|
24
|
+
- **On Unix/macOS/Git Bash**: Creates a symlink so hook updates are automatic
|
|
25
|
+
- **On Windows**: Copies the hook directly (symlinks don't work reliably on all NTFS setups)
|
|
26
|
+
- **Idempotent**: Re-running scaffold doesn't clobber a user-customized hook
|
|
27
|
+
- **Preserve Existing**: If you have a different pre-push hook, scaffold warns and preserves it
|
|
28
|
+
- **Force Replace**: Use `npx @matt82198/aesop [target-dir] --force` to replace any existing hook
|
|
29
|
+
|
|
30
|
+
**Example:**
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
# Initial scaffold (creates and installs hook automatically)
|
|
34
|
+
npx @matt82198/aesop my-fleet
|
|
35
|
+
|
|
36
|
+
# Later: re-scaffold the same directory (preserves customizations)
|
|
37
|
+
npx @matt82198/aesop my-fleet
|
|
38
|
+
|
|
39
|
+
# Force replace (even if hook was customized)
|
|
40
|
+
npx @matt82198/aesop my-fleet --force
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Manual Installation
|
|
44
|
+
|
|
45
|
+
If you're installing into an existing repo (not scaffolded), or you need to manually add the hook:
|
|
46
|
+
|
|
47
|
+
### Option 1: Symlink (Linux / macOS / Git Bash on Windows)
|
|
48
|
+
|
|
49
|
+
The cleanest method — hook stays in sync with repo updates:
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
ln -s ../../hooks/pre-push-policy.sh .git/hooks/pre-push
|
|
53
|
+
chmod +x .git/hooks/pre-push
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### Option 2: Copy (Windows, or to break sync)
|
|
57
|
+
|
|
58
|
+
Copy the hook directly into `.git/hooks/`:
|
|
59
|
+
|
|
60
|
+
```powershell
|
|
61
|
+
Copy-Item hooks\pre-push-policy.sh .git\hooks\pre-push
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
On Windows PowerShell, mark it executable if your git respects file mode:
|
|
65
|
+
|
|
66
|
+
```bash
|
|
67
|
+
git config core.filemode false
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Testing
|
|
71
|
+
|
|
72
|
+
Before committing to org-wide deployment, verify the hook works:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
bash hooks/pre-push-policy.sh --test
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Expected output: **PASS** for all three checks (branch policy, feature branch allowance, audit log format).
|
|
79
|
+
|
|
80
|
+
## GitHub Configuration (Server-Side Enforcement)
|
|
81
|
+
|
|
82
|
+
To pair this local hook with real enforcement, enable branch protection on GitHub:
|
|
83
|
+
|
|
84
|
+
### Step 1: Create a Protected Branch
|
|
85
|
+
|
|
86
|
+
1. Go to your GitHub repo **Settings** > **Branches**.
|
|
87
|
+
2. Click **Add rule** under "Branch protection rules".
|
|
88
|
+
3. Enter branch name pattern: `main` (or `master`, depending on your default branch).
|
|
89
|
+
|
|
90
|
+
### Step 2: Enable Required Protections
|
|
91
|
+
|
|
92
|
+
- **Require pull request reviews before merging**: ✓ (enforces PR review workflow)
|
|
93
|
+
- **Require status checks to pass before merging**: ✓ (use this for CI)
|
|
94
|
+
- **Require branches to be up to date before merging**: ✓
|
|
95
|
+
- **Restrict who can push to matching branches**: ✓ (optional; allows only admins to push to main)
|
|
96
|
+
|
|
97
|
+
### Step 3: Dismiss Stale Reviews (Recommended)
|
|
98
|
+
|
|
99
|
+
- **Dismiss stale pull request approvals when new commits are pushed**: ✓
|
|
100
|
+
|
|
101
|
+
### Example: Minimal Protected Branch Rule for `main`
|
|
102
|
+
|
|
103
|
+
| Setting | Value |
|
|
104
|
+
|---------|-------|
|
|
105
|
+
| Branch name pattern | `main` |
|
|
106
|
+
| Require pull request reviews | Yes (1 approval) |
|
|
107
|
+
| Require status checks to pass | Yes (if you have CI) |
|
|
108
|
+
| Require branches up to date | Yes |
|
|
109
|
+
| Restrict pushes to | Admins only |
|
|
110
|
+
|
|
111
|
+
Once this is configured, even if a developer bypasses the local hook with `--no-verify`, the remote will **refuse the push**.
|
|
112
|
+
|
|
113
|
+
## Audit Log Format & Integrity
|
|
114
|
+
|
|
115
|
+
Each block writes one JSON line to `${AESOP_ROOT:-$HOME/aesop}/state/SECURITY-AUDIT.log`:
|
|
116
|
+
|
|
117
|
+
```json
|
|
118
|
+
{"seq":1,"prev_hash":"GENESIS","ts":"2025-07-12T14:32:01Z","repo":"aesop","event":"push_blocked","reason":"secret_scan_failure","user":"alice"}
|
|
119
|
+
{"seq":2,"prev_hash":"f4b92becb47baa447e839330cf3c0c6e8dea947acc9ec372bb99063ee416d036","ts":"2025-07-12T14:32:02Z","repo":"aesop","event":"push_blocked","reason":"secret_scan_failure","user":"bob"}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
**Fields:**
|
|
123
|
+
- `seq`: Monotonically increasing sequence number (starts at 1). Enables detection of truncation or missing entries.
|
|
124
|
+
- `prev_hash`: SHA-256 hash of the previous line (without trailing newline). First entry uses `"GENESIS"`. Enables tampering detection.
|
|
125
|
+
- `ts`: ISO-8601 UTC timestamp
|
|
126
|
+
- `repo`: Repository basename
|
|
127
|
+
- `event`: Always `push_blocked` (or `secret_scan_unavailable`)
|
|
128
|
+
- `reason`: `push_to_protected_branch`, `secret_scan_failure`, or other block reason
|
|
129
|
+
- `user`: Git user.name (fallback: "unknown"); all special characters and control chars are JSON-escaped
|
|
130
|
+
|
|
131
|
+
**Write Safety & Concurrent Access:**
|
|
132
|
+
All audit log writes are protected by a file-system atomic lock (`.audit-log-lock/` directory). This ensures that concurrent pushes from different repositories (or simultaneous local pushes) do not corrupt the hash chain. The lock has a 300-second stale-lock recovery mechanism to handle crashed holders.
|
|
133
|
+
|
|
134
|
+
**Tail Hash Anchor:**
|
|
135
|
+
Each write also updates `${AESOP_ROOT:-$HOME/aesop}/state/.audit-tail-hash` with the SHA-256 hash of the newly appended line. This sidecar file acts as an anchor against tail truncation.
|
|
136
|
+
|
|
137
|
+
### Verifying Audit Log Integrity
|
|
138
|
+
|
|
139
|
+
The hash chain and truncation anchor allow you to detect if someone edited, deleted, or truncated audit log entries:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
bash hooks/pre-push-policy.sh --verify-audit-log
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Output on intact log:
|
|
146
|
+
```
|
|
147
|
+
Audit log verification OK (42 entries)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Output if line tampering is detected:
|
|
151
|
+
```
|
|
152
|
+
Error: Hash chain broken at line 15
|
|
153
|
+
Expected prev_hash: f4b92becb47baa447e839330cf3c0c6e8dea947acc9ec372bb99063ee416d036
|
|
154
|
+
Actual prev_hash: abc123...
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
Output if tail truncation is detected:
|
|
158
|
+
```
|
|
159
|
+
TRUNCATION SUSPECTED: Tail hash mismatch (stored: f4b..., actual: 8e6...)
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
The truncation detection compares the stored tail hash (`state/.audit-tail-hash`) against the actual SHA-256 hash of the current log's last line. If someone deletes the last N lines, the hashes will not match.
|
|
163
|
+
|
|
164
|
+
**Note**: Verification is a convenience check; it does not prevent tampering on a machine where the attacker has file system access. For real auditability, centralize audit logs to a secure remote (e.g., CloudWatch, Datadog, or a separate immutable log server).
|
|
165
|
+
|
|
166
|
+
Parse the log with standard JSON tools:
|
|
167
|
+
|
|
168
|
+
```bash
|
|
169
|
+
cat state/SECURITY-AUDIT.log | jq '.reason' | sort | uniq -c
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Org Distribution & Customization
|
|
173
|
+
|
|
174
|
+
### Standard Distribution
|
|
175
|
+
|
|
176
|
+
1. Commit the hook to a shared repo or policy repository.
|
|
177
|
+
2. Instruct teams to symlink or copy per option above.
|
|
178
|
+
3. Communicate audit log location and parsing examples.
|
|
179
|
+
|
|
180
|
+
### Customizing Checks
|
|
181
|
+
|
|
182
|
+
To add org-specific rules (e.g., branch naming conventions, required CI status):
|
|
183
|
+
|
|
184
|
+
1. Edit `hooks/pre-push-policy.sh` and add a new check function:
|
|
185
|
+
```bash
|
|
186
|
+
check_my_org_policy() {
|
|
187
|
+
# your logic here
|
|
188
|
+
return 0 or 1
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
2. Call it from `main()` before exit, and log blocks:
|
|
193
|
+
```bash
|
|
194
|
+
if ! check_my_org_policy; then
|
|
195
|
+
log_block "my_org_policy_violation"
|
|
196
|
+
exit 1
|
|
197
|
+
fi
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
3. Update `run_test_mode()` to include test cases for the new check.
|
|
201
|
+
|
|
202
|
+
4. Commit and redistribute.
|
|
203
|
+
|
|
204
|
+
### Disabling in CI/CD
|
|
205
|
+
|
|
206
|
+
If CI systems need to bypass the hook (e.g., for automated releases), set:
|
|
207
|
+
|
|
208
|
+
```bash
|
|
209
|
+
export GIT_SKIP_HOOKS=pre-push
|
|
210
|
+
git push
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
Or use `git push --no-verify` (explicitly allowing humans to opt out).
|
|
214
|
+
|
|
215
|
+
## Audit Log Rotation
|
|
216
|
+
|
|
217
|
+
The audit log is append-only. For long-running deployments, consider log rotation:
|
|
218
|
+
|
|
219
|
+
```bash
|
|
220
|
+
if [ -f state/SECURITY-AUDIT.log ] && [ $(stat -f%z state/SECURITY-AUDIT.log 2>/dev/null || stat -c%s state/SECURITY-AUDIT.log) -gt 1000000 ]; then
|
|
221
|
+
mv state/SECURITY-AUDIT.log "state/SECURITY-AUDIT.$(date +%Y%m%d-%H%M%S).log"
|
|
222
|
+
fi
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
## Troubleshooting
|
|
226
|
+
|
|
227
|
+
**Hook not running?**
|
|
228
|
+
- Verify `.git/hooks/pre-push` exists and is executable: `ls -la .git/hooks/pre-push`
|
|
229
|
+
- Check symlink target if using option 1: `readlink .git/hooks/pre-push`
|
|
230
|
+
- Git version must be 1.8.2+; run `git --version`
|
|
231
|
+
|
|
232
|
+
**"Push blocked" but no reason in audit log?**
|
|
233
|
+
- Check `${AESOP_ROOT:-$HOME/aesop}/state/` directory exists and is writable.
|
|
234
|
+
- Verify git config: `git config user.name` is not empty.
|
|
235
|
+
|
|
236
|
+
**Secret scan warns but doesn't block?**
|
|
237
|
+
- `secret_scan.py` must exist at `AESOP_ROOT/tools/secret_scan.py`.
|
|
238
|
+
- If missing, the hook warns but allows push (fail-open default).
|
|
239
|
+
- For fail-closed behavior, edit the hook and remove the early `return 0`.
|
|
240
|
+
|
|
241
|
+
## References
|
|
242
|
+
|
|
243
|
+
- Hook source: `hooks/pre-push-policy.sh`
|
|
244
|
+
- Secret scanner: `tools/secret_scan.py`
|
|
245
|
+
- Audit log location: `state/SECURITY-AUDIT.log` (git-ignored)
|
|
246
|
+
- Cardinal rule: [CARDINAL-RULES.md](CARDINAL-RULES.md)
|
|
247
|
+
|
|
248
|
+
## Claude Code hooks
|
|
249
|
+
|
|
250
|
+
Beyond git hooks, aesop ships policy for the agent harness itself.
|
|
251
|
+
`hooks/claude/force-model-policy.mjs` is a Claude Code **PreToolUse** hook that
|
|
252
|
+
enforces the "subagents are always Haiku" cardinal rule in code: every `Agent`
|
|
253
|
+
or `Task` dispatch whose `model` is absent or non-compliant is rewritten to the
|
|
254
|
+
policy model before the subagent launches. Versioned in git, it is org policy
|
|
255
|
+
you can review, diff, and test — not a memo agents can forget.
|
|
256
|
+
|
|
257
|
+
### What it enforces
|
|
258
|
+
|
|
259
|
+
- **Model policy**: subagent dispatches run on `haiku` by default. If
|
|
260
|
+
`aesop.config.json` defines `cardinal_rules.subagent_model` (looked up in
|
|
261
|
+
`$AESOP_ROOT`, then the working directory), that model is enforced instead.
|
|
262
|
+
- **Rewrite, not block**: non-compliant dispatches are allowed through with
|
|
263
|
+
`model` rewritten via the hook output contract
|
|
264
|
+
(`hookSpecificOutput.updatedInput`), so work proceeds at the right cost tier.
|
|
265
|
+
- **Fail-open reliability**: malformed input produces no output and exit 0.
|
|
266
|
+
The hook never crashes the harness and never logs payload contents.
|
|
267
|
+
|
|
268
|
+
### Registration (settings.json)
|
|
269
|
+
|
|
270
|
+
Add to `.claude/settings.json` in the project (or `~/.claude/settings.json`
|
|
271
|
+
for user-wide enforcement):
|
|
272
|
+
|
|
273
|
+
```json
|
|
274
|
+
{
|
|
275
|
+
"hooks": {
|
|
276
|
+
"PreToolUse": [
|
|
277
|
+
{
|
|
278
|
+
"matcher": "Agent|Task",
|
|
279
|
+
"hooks": [
|
|
280
|
+
{
|
|
281
|
+
"type": "command",
|
|
282
|
+
"command": "node \"$CLAUDE_PROJECT_DIR/hooks/claude/force-model-policy.mjs\""
|
|
283
|
+
}
|
|
284
|
+
]
|
|
285
|
+
}
|
|
286
|
+
]
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
If the hook lives outside the project (e.g., a shared policy checkout), use an
|
|
292
|
+
absolute path to the `.mjs` file instead of `$CLAUDE_PROJECT_DIR`.
|
|
293
|
+
|
|
294
|
+
### Escape hatch
|
|
295
|
+
|
|
296
|
+
For dispatches that genuinely need a bigger model, include the literal marker
|
|
297
|
+
`[[ALLOW-NON-HAIKU]]` anywhere in the subagent prompt. The hook passes the
|
|
298
|
+
dispatch through untouched — and because the marker sits in the prompt, every
|
|
299
|
+
opt-out is visible in the transcript and auditable after the fact.
|
|
300
|
+
|
|
301
|
+
### Testing
|
|
302
|
+
|
|
303
|
+
```bash
|
|
304
|
+
node --test tests/force-model-policy.test.mjs
|
|
305
|
+
```
|
|
306
|
+
|
|
307
|
+
Covers the rewrite, escape-hatch, malformed-stdin, and config-override cases.
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
# How the Wave Loop Works (The Fast, Cheap Way)
|
|
2
|
+
|
|
3
|
+
**TL;DR**: Aesop's `/buildsystem` runs one cycle per wave: rank backlog → fan out parallel Haiku agents → watchdog catches hangs → verify + merge → close with audits. The result: **lower cost (Haiku is ~1/3 the cost of Sonnet) and faster wall-clock from running agents in parallel** through parallelism and cheap subagents, while the orchestrator stays busy planning next work.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## The Wave Cycle at a Glance
|
|
8
|
+
|
|
9
|
+
A **wave** is one complete delivery loop:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
1. Rank Backlog (~10 min)
|
|
13
|
+
↓
|
|
14
|
+
2. Fan Out (spawn 5–8 parallel Haiku agents, ~80 min)
|
|
15
|
+
↓
|
|
16
|
+
3. Watchdog (catch stalls, respawn as needed)
|
|
17
|
+
↓
|
|
18
|
+
4. Verify + Merge (orchestrator reviews outputs, merges PRs, ~30 min)
|
|
19
|
+
↓
|
|
20
|
+
5. Close: Audit + Ideation + Fleet Ops (~20 min)
|
|
21
|
+
↓
|
|
22
|
+
6. NEXT WAVE: feed the backlog with findings
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
**Wallclock time per wave**: 2–3 hours. **Token spend**: ~$0.03. **What ships**: 5–8 small, tested features/fixes.
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## 1. Rank Backlog (10 min)
|
|
30
|
+
|
|
31
|
+
Before spawning agents, you decide what to build. Use these lenses:
|
|
32
|
+
|
|
33
|
+
- **Priority**: P1 blockers first, P2 quality/UX, P3 tech debt
|
|
34
|
+
- **Sizing**: fit each item to a Haiku agent (scoped <5 min reasoning)
|
|
35
|
+
- **Ownership**: assign one agent type per item (backend-dev for APIs, frontend-dev for UI, test-bot for test fixes)
|
|
36
|
+
|
|
37
|
+
**Example backlog after ranking**:
|
|
38
|
+
```
|
|
39
|
+
P1: Fix auth timeout (backend-dev)
|
|
40
|
+
P1: Add verify-dash UTF-8 check (frontend-dev)
|
|
41
|
+
P2: Refactor config loader (backend-dev)
|
|
42
|
+
P3: Simplify hook test suite (test-bot)
|
|
43
|
+
P3: Document wave cycle (docs-agent)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
**Productivity win**: Ranked backlog prevents "what should I build next?" tax. Agents don't guess — they execute known work.
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
|
|
50
|
+
## 2. Fan Out (80 min, all in parallel)
|
|
51
|
+
|
|
52
|
+
The orchestrator spawns 5–8 Haiku agents **in one command**, one per backlog item. Each agent:
|
|
53
|
+
|
|
54
|
+
- Gets a **scoped brief** (what to build, acceptance criteria)
|
|
55
|
+
- **Works in its own worktree** (no conflicts, safe parallelism)
|
|
56
|
+
- **Commits + pushes** when done
|
|
57
|
+
- **Opens a PR** with a summary
|
|
58
|
+
|
|
59
|
+
Example spawn:
|
|
60
|
+
```
|
|
61
|
+
→ Haiku-1 (auth): "fix timeout, add tests, commit & PR"
|
|
62
|
+
→ Haiku-2 (UI): "add UTF-8 check to /submit, update test"
|
|
63
|
+
→ Haiku-3 (refactor): "simplify config, preserve API"
|
|
64
|
+
→ Haiku-4 (tests): "prune old hooks, keep coverage >90%"
|
|
65
|
+
→ Haiku-5 (docs): "write HOW-THE-LOOP-WORKS.md"
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**Productivity win**: the agents run concurrently instead of one at a time, and each Haiku costs 1/3 of Sonnet (1/5 of Opus) — so the fleet is both faster in wall-clock and far cheaper than one expensive agent working serially.
|
|
69
|
+
|
|
70
|
+
---
|
|
71
|
+
|
|
72
|
+
## 3. Watchdog (Continuous, 80 min)
|
|
73
|
+
|
|
74
|
+
While agents work, a background watchdog:
|
|
75
|
+
|
|
76
|
+
- **Polls every 10s**: checks agent heartbeats and PR status
|
|
77
|
+
- **Respawns hung agents**: if >200s idle, TaskStop + relaunch (max 3 auto-retries)
|
|
78
|
+
- **Escalates hangs**: after 3 retries, mark BLOCKED and surface to you
|
|
79
|
+
|
|
80
|
+
**No human waiting**. The watchdog runs autonomously.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 4. Verify + Merge (30 min)
|
|
85
|
+
|
|
86
|
+
Once all 5 agents finish (or hit 3-retry cap), the orchestrator:
|
|
87
|
+
|
|
88
|
+
1. **Reviews each PR** (code review, test coverage, no known-broken state)
|
|
89
|
+
2. **Approves + merges** (or routes back to agent for fixes)
|
|
90
|
+
3. **Runs integration tests** (do the merged features work together?)
|
|
91
|
+
4. **Updates main** (all work lands together, not one-at-a-time)
|
|
92
|
+
|
|
93
|
+
**Example merge sequence**:
|
|
94
|
+
```
|
|
95
|
+
✓ Haiku-1 PR #95: auth timeout fix (APPROVED)
|
|
96
|
+
✓ Haiku-2 PR #96: UTF-8 check (APPROVED)
|
|
97
|
+
✓ Haiku-3 PR #97: config refactor (APPROVED)
|
|
98
|
+
✓ Haiku-4 PR #98: test prune (APPROVED)
|
|
99
|
+
✓ Haiku-5 PR #99: docs (APPROVED)
|
|
100
|
+
→ Merge all 5 → run integration tests → green ✓
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
**Productivity win**: Batch PR reviews (all at once) + single merge transaction = faster feedback loops, fewer context-switches.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 5. Close (20 min): Audit + Ideation + Fleet Ops
|
|
108
|
+
|
|
109
|
+
Before the next wave, close this one:
|
|
110
|
+
|
|
111
|
+
- **Audit**: Did all 5 agents follow rules? (branch discipline, secret-scan gate, test coverage)
|
|
112
|
+
- **Ideation**: What went well? What bottlenecked? Any tech-debt findings to backlog?
|
|
113
|
+
- **Fleet ops**: Rotate logs (BUILDLOG.md archives), update MEMORY.md with learnings, clean up worktrees
|
|
114
|
+
|
|
115
|
+
**Example findings**:
|
|
116
|
+
```
|
|
117
|
+
✓ 5/5 agents followed rules
|
|
118
|
+
✓ All PRs had tests
|
|
119
|
+
→ Config refactor revealed opportunity: auto-gen schemas (P3, backlog for wave 12)
|
|
120
|
+
→ UTF-8 check is cheap; suggest expanding to other endpoints (P2)
|
|
121
|
+
→ One agent took 95 min (slightly over 80); consider smaller tasks next wave
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
**Productivity win**: Intentional retrospective prevents repeating mistakes. Backlog feeds into the next wave's ranking, so you build on learnings, not starting fresh each time.
|
|
125
|
+
|
|
126
|
+
---
|
|
127
|
+
|
|
128
|
+
## Why It's Fast & Cheap
|
|
129
|
+
|
|
130
|
+
| Metric | Aesop Wave | All-Opus Equivalent |
|
|
131
|
+
|--------|-----------|-------------------|
|
|
132
|
+
| **Agents** | 5 Haiku + 1 Opus orchestrator | 6 Opus |
|
|
133
|
+
| **Time** | ~2–3 hours (parallel) | ~12+ hours (serial) |
|
|
134
|
+
| **Cost** | ~$0.03 | ~$0.18 |
|
|
135
|
+
| **Test coverage** | Required per agent | Often skipped in time-crunch |
|
|
136
|
+
| **Outputs** | All PRs merged, all tests green | Might be 1–2 half-finished features |
|
|
137
|
+
|
|
138
|
+
**Key levers**:
|
|
139
|
+
1. **Parallelism**: agents work concurrently instead of one-at-a-time (measured example: wave-10's 5-agent fleet finished in ~293s of wall-clock vs ~897s if run serially — about 3x)
|
|
140
|
+
2. **Cheap subagents**: Haiku is 1/3 the cost of Sonnet and 1/5 the cost of Opus (exact on both input and output); running many in parallel keeps spend low
|
|
141
|
+
3. **Orchestrator stays lean**: reads only STATE.md + BUILDLOG.md + git one-liners (no re-reading entire codebase)
|
|
142
|
+
4. **No idle time**: while agents work, orchestrator plans next phase (never blocking on agents)
|
|
143
|
+
|
|
144
|
+
---
|
|
145
|
+
|
|
146
|
+
## When the Loop Stalls (Retry Cap & Escalation)
|
|
147
|
+
|
|
148
|
+
If an agent hangs 3 times on the same task:
|
|
149
|
+
|
|
150
|
+
1. **Auto-retry 1–3**: Watchdog relaunches agent (same prompt, no changes)
|
|
151
|
+
2. **On 4th hang**: Mark BLOCKED in BUILDLOG.md, surface to you
|
|
152
|
+
3. **You decide**: Break the task smaller, escalate to Sonnet, or park it and move on
|
|
153
|
+
|
|
154
|
+
**Why a cap?** Infinite retries waste tokens and hide real problems (task too big, external dependency broken, etc.). 3 retries = 6 min of agent time; if still stuck, it's a human decision.
|
|
155
|
+
|
|
156
|
+
---
|
|
157
|
+
|
|
158
|
+
## About /buildsystem and /power Skills
|
|
159
|
+
|
|
160
|
+
**Important**: The `/buildsystem` and `/power` skills are **orchestrator-brain skills** installed to `~/.claude/skills/`, not files inside the aesop template. They are invoked via Claude Code as slash commands.
|
|
161
|
+
|
|
162
|
+
- **Location**: `~/.claude/skills/buildsystem/` and `~/.claude/skills/power/` on your workstation.
|
|
163
|
+
- **Template copy**: The aesop repo contains skill definitions in `skills/` for reference and setup (copy these to `~/.claude/skills/` on first use).
|
|
164
|
+
- **Invocation**: In Claude Code, type `/power` to prime your orchestrator brain, or `/buildsystem` to start a wave cycle.
|
|
165
|
+
|
|
166
|
+
See [skills/power/SKILL.md](../skills/power/SKILL.md) for detailed setup instructions.
|
|
167
|
+
|
|
168
|
+
## Next Steps
|
|
169
|
+
|
|
170
|
+
1. Run `/buildsystem` to start a wave (orchestrator handles the flow)
|
|
171
|
+
2. Monitor via the TUI dashboard (`bash dash/watchdog-gui.sh`)
|
|
172
|
+
3. After merge, review findings to feed the next backlog
|
|
173
|
+
4. Rinse, repeat
|
|
174
|
+
|
|
175
|
+
For deep dives on cost/dispatch patterns, see [DISPATCH-MODEL.md](DISPATCH-MODEL.md). For reliability guarantees, see [RELIABILITY.md](RELIABILITY.md).
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Memory Index Template
|
|
2
|
+
|
|
3
|
+
This is the canonical index of team facts. Each fact is **one file, one truth**.
|
|
4
|
+
|
|
5
|
+
## Format
|
|
6
|
+
|
|
7
|
+
### Index line
|
|
8
|
+
```
|
|
9
|
+
- [Title](file.md) — [1-line hook]
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
### Fact frontmatter
|
|
13
|
+
Every memory file opens with:
|
|
14
|
+
```
|
|
15
|
+
---
|
|
16
|
+
name: [Fact name]
|
|
17
|
+
description: [One sentence]
|
|
18
|
+
type: [user|feedback|project|reference]
|
|
19
|
+
---
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
**Types**: `user` (who you are), `feedback` (decisions/learnings), `project` (repo-specific), `reference` (how-tos/patterns).
|
|
23
|
+
|
|
24
|
+
## Examples
|
|
25
|
+
|
|
26
|
+
### Memory file: `~/.claude/memory/dispatch-principles.md`
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
---
|
|
30
|
+
name: Dispatch cost lever
|
|
31
|
+
description: Why Haiku subagents are the single most important cost optimization.
|
|
32
|
+
type: reference
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
Subagents are ALWAYS Haiku (1/3 Sonnet cost). This is the cost lever.
|
|
36
|
+
Six to eight Haiku agents in parallel cost ~25% of all-Opus fleet...
|
|
37
|
+
[Full context here]
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Memory file: `~/.claude/memory/team-goals.md`
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
---
|
|
44
|
+
name: 2026 Q2 goals
|
|
45
|
+
description: Ship [feature] by end of June, maintain <200ms latency on [metric].
|
|
46
|
+
type: feedback
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
Primary goal: [...]
|
|
50
|
+
Secondary goal: [...]
|
|
51
|
+
Constraints: [...]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Index entry (in MEMORY.md)
|
|
55
|
+
|
|
56
|
+
```
|
|
57
|
+
- [Dispatch principles](memory/dispatch-principles.md) — Haiku is 1/3 cost, default subagent tier
|
|
58
|
+
- [Team goals](memory/team-goals.md) — Q2 2026 roadmap and constraints
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Create new facts by adding a file and an index line. The orchestrator reads the index at session start.
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# Aesop Documentation Index
|
|
2
|
+
|
|
3
|
+
Aesop is a fable-fleet orchestration harness for Claude Code. It runs fast, cheap delivery waves: parallel Haiku agents, lower cost via Haiku-first dispatch and faster wall-clock via parallel agents.
|
|
4
|
+
|
|
5
|
+
**New to Aesop?** Start here: [HOW-THE-LOOP-WORKS.md](HOW-THE-LOOP-WORKS.md) — a walkthrough of one wave cycle and why it's productive.
|
|
6
|
+
|
|
7
|
+
For deeper governance + operational rules, see the reference docs below.
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
- [HOW-THE-LOOP-WORKS.md](HOW-THE-LOOP-WORKS.md) — Concrete walkthrough of one `/buildsystem` wave (rank → fan out → verify → merge → close)
|
|
14
|
+
|
|
15
|
+
## Core Governance & Rules (Reference)
|
|
16
|
+
|
|
17
|
+
- [CARDINAL-RULES.md](CARDINAL-RULES.md) — Foundational operational principles (dispatch model, cost, subagent discipline, retry caps)
|
|
18
|
+
- [RELIABILITY.md](RELIABILITY.md) — Reliability core: never wait, inputs always produce outputs, pride bar for completion
|
|
19
|
+
- [CHECKPOINTING.md](CHECKPOINTING.md) — Durable STATE.md/BUILDLOG.md lifecycle, recovery on resume, log rotation patterns
|
|
20
|
+
- [SCRIPTS-POLICY.md](SCRIPTS-POLICY.md) — Local-only execution, shared script library, task-local vs. reusable heuristics
|
|
21
|
+
- [DISPATCH-MODEL.md](DISPATCH-MODEL.md) — Fable/Haiku orchestration patterns and cost calculations
|
|
22
|
+
- [GOVERNANCE.md](GOVERNANCE.md) — Single-instance loops, single-writer files, heartbeat protocol, security gates
|
|
23
|
+
|
|
24
|
+
## The Five Pillars
|
|
25
|
+
|
|
26
|
+
### 1. Onboarding Templates
|
|
27
|
+
- [MEMORY-TEMPLATE.md](MEMORY-TEMPLATE.md) — Canonical index format and structure for team memory & facts
|
|
28
|
+
|
|
29
|
+
### 2. Policy Hooks
|
|
30
|
+
- [HOOK-INSTALL.md](HOOK-INSTALL.md) — Install and customize `hooks/pre-push-policy.sh` (branch/secret enforcement at push time)
|
|
31
|
+
|
|
32
|
+
### 3. Behavioral PRs
|
|
33
|
+
- [BEHAVIORAL-PR-REVIEW.md](BEHAVIORAL-PR-REVIEW.md) — Checklist for reviewing PRs that modify rules, policies, or orchestration behavior
|
|
34
|
+
|
|
35
|
+
### 4. Forensics (Git-Bisectable Agent Debugging)
|
|
36
|
+
- [FORENSICS.md](FORENSICS.md) — Reconstruct agent failures using `tools/agent-forensics.sh`; make agent behavior git-debuggable
|
|
37
|
+
|
|
38
|
+
### 5. Restore (Cross-Machine Reconstitution)
|
|
39
|
+
- [RESTORE.md](RESTORE.md) — Reconstitute Aesop & fleet on a new machine from git + watchdog backups after a wipe
|
|
40
|
+
|
|
41
|
+
## Operational Guides
|
|
42
|
+
|
|
43
|
+
- [PUBLISHING.md](PUBLISHING.md) — Release Aesop to npm using GitHub Actions with OIDC trusted publishing
|
|
44
|
+
- [av-resilience.md](av-resilience.md) — Antivirus & behavioral-engine resilience patterns for reliable agent execution
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Reliability & Core Obligations
|
|
2
|
+
|
|
3
|
+
**TL;DR**: Three rules for shipping production work: (1) orchestrator never idles (spawn next task while agents run), (2) every action produces observable output (silence = failure), (3) pride bar — verify end-to-end before marking done. Together: reliable, visible, trustworthy automation.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## NEVER WAIT: Keep the orchestrator busy
|
|
8
|
+
|
|
9
|
+
The orchestrator must never go idle while background work is in flight. Every moment waiting on agents or builds is spent producing forward progress:
|
|
10
|
+
|
|
11
|
+
- Dispatch the next unblocked work unit
|
|
12
|
+
- Extend planning documentation (roadmaps, next phases)
|
|
13
|
+
- Stage ideas and observations to memory
|
|
14
|
+
- Queue important facts via the inbox pattern
|
|
15
|
+
- Always offer the user an actionable idea for what to do next
|
|
16
|
+
|
|
17
|
+
**Key principle**: "Waiting on X" is never a complete status — it must come with "meanwhile, doing/proposing Y." Never burn cycles re-reading state that scoped agents will report anyway.
|
|
18
|
+
|
|
19
|
+
## Inputs ALWAYS produce outputs
|
|
20
|
+
|
|
21
|
+
Every dispatched agent, loop cycle, tool run, and workflow MUST emit an observable output:
|
|
22
|
+
- A brief summary
|
|
23
|
+
- A log line
|
|
24
|
+
- A heartbeat signal
|
|
25
|
+
- Or an explicit `FAILED` or `EMPTY` marker
|
|
26
|
+
|
|
27
|
+
**Silence is never acceptable.** No output = failure, and the watchdog treats it as a hang. Never swallow a result; never let a task end without reporting something.
|
|
28
|
+
|
|
29
|
+
## The pride bar: never ship until you would be proud to deliver it
|
|
30
|
+
|
|
31
|
+
"An agent returned a brief" and "tests pass" are checkpoints, not completion.
|
|
32
|
+
|
|
33
|
+
**Done means:**
|
|
34
|
+
- Verified end-to-end (not just isolated tests)
|
|
35
|
+
- Briefs cross-checked against reality
|
|
36
|
+
- Test artifacts cleaned up
|
|
37
|
+
- Loose ends closed or explicitly logged as pending decisions
|
|
38
|
+
- Nothing known-broken shipped silently
|
|
39
|
+
|
|
40
|
+
If you would hesitate to hand it over under your own name, it is not done — keep going. Shipping something you're not proud of erodes team trust and creates technical debt that costs more to fix later.
|
|
41
|
+
|
|
42
|
+
## Why these matter
|
|
43
|
+
|
|
44
|
+
**Cache persistence.** Consistent outputs and reliable checkpoints mean the prompt cache stays warm and effective. Broken shortcuts kill cache hit rates and waste tokens.
|
|
45
|
+
|
|
46
|
+
**Team trust.** Silence erodes confidence in agent-driven work. Observable outputs, explicit failures, and the pride bar rebuild and maintain trust.
|
|
47
|
+
|
|
48
|
+
**Cost containment.** Retries, debug loops, and rollbacks all cost tokens. Getting it right the first time (through upfront verification and deliberate finishing) is cheaper than fixing broken work later.
|
|
49
|
+
|
|
50
|
+
## Implementation checklist
|
|
51
|
+
|
|
52
|
+
- Daemons emit heartbeats every cycle (even on error)
|
|
53
|
+
- Logs are append-only; every action logged with timestamp
|
|
54
|
+
- If a subagent stalls >200s, watchdog respawns it
|
|
55
|
+
- Orchestrator briefs the user with findings while delegating to subagents (never idle)
|
|
56
|
+
- Before marking work done, verify end-to-end and cross-check briefs against reality
|
|
57
|
+
- On task completion, ask: "Would I be proud to deliver this under my name?"
|
|
58
|
+
|
|
59
|
+
---
|
|
60
|
+
|
|
61
|
+
These three principles together form the **reliability core**: keep working (never wait), always report (inputs → outputs), and never compromise on quality (pride bar). They enable scaling from 1 orchestrator to dozens of parallel subagents without losing control, visibility, or production readiness.
|