@matt82198/aesop 0.1.0-beta.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.
@@ -0,0 +1,180 @@
1
+ # Aesop Dispatch Model — Cost & Orchestration Patterns
2
+
3
+ ## The fable conceit
4
+
5
+ In Aesop's Fables, Aesop (the narrator) directs the characters (tortoise, hare, fox, etc.) through moral tales. Here, **Aesop (the orchestrator)** directs a fleet of **Fables (the subagents)** toward reliable task completion.
6
+
7
+ The tortoise represents deliberate, resourceful thinking; the hare, quick speed. Together (slow orchestrator + fast subagents), they're unbeatable.
8
+
9
+ ## Cost model
10
+
11
+ ### Baseline: all-Opus fleet
12
+
13
+ ```
14
+ 5 tasks × 10 min each × Opus cost (~60 tokens/min for reasoning)
15
+ = 5 × 10 × 60 = 3,000 tokens/session
16
+ ```
17
+
18
+ ### Aesop dispatch: Opus + 5 Haiku
19
+
20
+ ```
21
+ 1 orchestrator (Opus, 5 min thinking) = 5 × 60 = 300 tokens
22
+ 5 subagents (Haiku, 2 min each) = 5 × 2 × 20 = 200 tokens
23
+ Total = 500 tokens/session
24
+ = **83% savings** vs all-Opus
25
+ ```
26
+
27
+ ### Scaling to 10 parallel domains
28
+
29
+ ```
30
+ 1 orchestrator (Opus, 8 min) = 480 tokens
31
+ 10 subagents (Haiku, 3 min each) = 600 tokens
32
+ Total = 1,080 tokens
33
+ = **90% savings** vs 10 Opus tasks
34
+ ```
35
+
36
+ ## Dispatch patterns
37
+
38
+ ### Pattern 1: Fan-out (wide parallelism)
39
+
40
+ **Use case**: 10 independent tasks with no dependencies.
41
+
42
+ ```
43
+ Orchestrator
44
+ ├─ Haiku-1: Test domain (write test, red → green)
45
+ ├─ Haiku-2: Build domain (compile, package)
46
+ ├─ Haiku-3: Docs domain (README, examples)
47
+ ├─ Haiku-4: Security domain (audit, review)
48
+ └─ Haiku-5: Deployment domain (stage, verify)
49
+
50
+ Total cost: 1 Opus + 5 Haiku ≈ $0.003 per session
51
+ ```
52
+
53
+ ### Pattern 2: Sequential with handoff
54
+
55
+ **Use case**: Feature across 3 layers (API → DB → UI) with dependencies.
56
+
57
+ ```
58
+ Orchestrator → Phase 1
59
+ ├─ Haiku-1: API spec + tests
60
+ └─ (wait for Haiku-1 to complete)
61
+ → Phase 2
62
+ ├─ Haiku-2: DB schema (reads Haiku-1 output)
63
+ └─ (wait)
64
+ → Phase 3
65
+ ├─ Haiku-3: UI (reads both outputs)
66
+ └─ Haiku-4: Integration test
67
+
68
+ Orchestrator reassembles + QA
69
+ Total cost: still 1 Opus + 4 Haiku = **90% savings**
70
+ ```
71
+
72
+ ### Pattern 3: Hierarchical (supervisor + workers)
73
+
74
+ **Use case**: Complex codebase review (split into modules, each reviewed in parallel).
75
+
76
+ ```
77
+ Orchestrator
78
+ ├─ Review-Supervisor (Sonnet, splits codebase into 5 modules)
79
+ │ ├─ Haiku-1: auth module
80
+ │ ├─ Haiku-2: api module
81
+ │ ├─ Haiku-3: db module
82
+ │ ├─ Haiku-4: ui module
83
+ │ └─ Haiku-5: config module
84
+ └─ (Sonnet synthesizes reviews into final report)
85
+
86
+ Cost: 1 Opus + 1 Sonnet + 5 Haiku = ~$0.015 (still 75% savings)
87
+ ```
88
+
89
+ ## Decision flowchart
90
+
91
+ When you have a new task, ask:
92
+
93
+ ```
94
+ Is this task scoped to <5 min reasoning?
95
+ ├─ YES → Use Haiku subagent (cost: ~$0.0002)
96
+ ├─ NO → Can I decompose it into smaller tasks?
97
+ │ ├─ YES → Fan-out to multiple Haiku (cost: $0.001–0.003)
98
+ │ └─ NO → Use Opus (cost: ~$0.004)
99
+ └─ Does this need final review/synthesis?
100
+ ├─ YES → Opus orchestrator does it (cost: ~$0.002)
101
+ └─ NO → Done (subagent output is final)
102
+ ```
103
+
104
+ ## Anti-patterns
105
+
106
+ ### ❌ All-Opus fleet
107
+
108
+ **Cost**: 10× baseline. **Why**: throws CPU power at problems that are scoped.
109
+
110
+ **Fix**: Decompose into Haiku-sized tasks.
111
+
112
+ ### ❌ Giant orchestrator context
113
+
114
+ **Cost**: token waste, slower decisions. **Why**: reads full logs, commits, code diffs.
115
+
116
+ **Fix**: Orchestrator reads STATE.md + BUILDLOG.md + git one-liners only. Delegate research to Haiku.
117
+
118
+ ### ❌ Silent hangs
119
+
120
+ **Cost**: invisible waste (subagent stalls, orchestrator waits). **Why**: no heartbeat, no timeout.
121
+
122
+ **Fix**: Heartbeat every 60s min. Watchdog respawns >200s stale. Orchestrator never waits>60s (spawn next task).
123
+
124
+ ### ❌ Cloud Python execution
125
+
126
+ **Cost**: latency + complexity. **Why**: cloud runners add overhead, partial failure risk.
127
+
128
+ **Fix**: All Python runs locally. Cloud agents spawn only for distributed compute (rare).
129
+
130
+ ## Token spend tracking
131
+
132
+ ### Log format (FLEET-LEDGER.md)
133
+
134
+ ```
135
+ | timestamp | domain | subagent | tokens | result |
136
+ |--|--|--|--|--|
137
+ | 2024-01-15T10:30:00 | auth | haiku | 1200 | SUCCESS |
138
+ | 2024-01-15T10:35:00 | ui | haiku | 950 | SUCCESS |
139
+ | 2024-01-15T10:40:00 | test | haiku | 1100 | FAILED (1r) |
140
+ | 2024-01-15T10:45:00 | test | haiku | 1050 | SUCCESS |
141
+ ```
142
+
143
+ ### Cost signals to watch
144
+
145
+ 1. **Spend spike** (+20% baseline): investigate domain; may need larger model.
146
+ 2. **Respawn loop** (same domain 3+ times): subagent repeatedly failing; escalate to Sonnet or orchestrator review.
147
+ 3. **Serial bottleneck** (orchestrator >500 tokens): parallelism breaking down; split smaller or delegate.
148
+
149
+ ### Optimization levers
150
+
151
+ - **Fan-out more tasks**: go from 2 Haiku to 5.
152
+ - **Shift to Sonnet**: if 3 Haiku respawns in a row, use Sonnet once for harder task.
153
+ - **Reduce orchestrator context**: read fewer files, shorter CLAUDE.md.
154
+ - **Cache cardinal rules**: use prompt caching on base CLAUDE.md (reused every session).
155
+
156
+ ## Orchestrator role (the slow tortoise)
157
+
158
+ - **Reading**: STATE.md (phase + next steps), BUILDLOG.md (latest 10 entries), git one-liners.
159
+ - **Deciding**: which 3–5 Haiku to spawn, what task each gets, how to reassemble results.
160
+ - **Waiting**: while subagents run in parallel, orchestrator uses time to:
161
+ - Brief user on progress.
162
+ - Spot-check one Haiku output.
163
+ - Plan next phase.
164
+ - **Synthesizing**: reads Haiku results, updates STATE.md, decides next phase or declares done.
165
+
166
+ **Golden rule**: Orchestrator thinks 5–10 min per hour of wallclock time (while agents run). Never blocks; never waits idle.
167
+
168
+ ## Subagent role (the swift fables)
169
+
170
+ - **Scoped task**: <5 min pure reasoning per task.
171
+ - **Clear acceptance criteria**: from orchestrator brief.
172
+ - **Output**: append to BUILDLOG.md, return result to orchestrator.
173
+ - **Failure**: log reason, don't retry (orchestrator decides retry).
174
+ - **Speed**: finish in <2 min if possible; alert orchestrator if >5 min (break task smaller).
175
+
176
+ **Golden rule**: Subagents stay cheap and fast. If a Haiku takes >10 min, you've scoped too large.
177
+
178
+ ---
179
+
180
+ **Summary**: Aesop's dispatch model trades a small amount of orchestration complexity for **10× cost savings** and **4× speed** (via parallelism). It works by keeping subagents small, orchestrator lean, and feedback constant.
@@ -0,0 +1,150 @@
1
+ # Publishing Aesop to npm
2
+
3
+ This guide explains how to publish new releases of Aesop to npm using GitHub Actions with OIDC trusted publishing (zero tokens, zero OTP prompts).
4
+
5
+ ## Overview
6
+
7
+ The publish workflow (`.github/workflows/publish.yml`) is triggered automatically when you **publish a GitHub Release**. It uses npm's OIDC trusted publishing feature to authenticate with npm — no tokens, no 2FA/passkey prompts, no OTP required.
8
+
9
+ ## One-Time Setup on npmjs.com
10
+
11
+ ### Step 1: Add a Trusted Publisher
12
+
13
+ You must configure GitHub as a trusted publisher for `@matt82198/aesop` on npmjs.com. This tells npm to allow publishes from the GitHub Actions workflow without a token.
14
+
15
+ **Steps:**
16
+
17
+ 1. Go to **[npmjs.com/package/@matt82198/aesop/settings](https://www.npmjs.com/package/@matt82198/aesop/settings)** (substitute your actual username/package name).
18
+ - If the package doesn't exist yet, you'll need to create it first (see bootstrap caveat below).
19
+
20
+ 2. Click **Settings** → **Access** (or **Publishing** on newer UI).
21
+
22
+ 3. Scroll to **Trusted Publishers** (or **Publishing from CI/CD**).
23
+
24
+ 4. Click **Add a Trusted Publisher** → Select **GitHub Actions**.
25
+
26
+ 5. Enter these values:
27
+ - **Organization:** `matt82198` (your GitHub username or org)
28
+ - **Repository:** `aesop`
29
+ - **Workflow:** `publish.yml`
30
+
31
+ 6. Click **Save** or **Add**.
32
+
33
+ npm will now allow publishes from the `publish.yml` workflow in the `aesop` repo without a token.
34
+
35
+ ### Step 2: Verify npm Version
36
+
37
+ The workflow automatically ensures npm >= 11.5.1 (OIDC requirement). If you're publishing locally (not recommended), confirm:
38
+
39
+ ```bash
40
+ npm --version # Should be 11.5.1 or higher
41
+ ```
42
+
43
+ ## Publishing a Release
44
+
45
+ ### Via GitHub Web UI (Recommended)
46
+
47
+ 1. Go to your repo's **Releases** page.
48
+ 2. Click **Draft a new release**.
49
+ 3. **Tag version:** Enter a version (e.g., `0.1.0`, `0.1.0-beta.1`).
50
+ 4. **Release title:** E.g., "Aesop 0.1.0".
51
+ 5. **Description:** Add release notes (optional).
52
+ 6. Click **Publish release**.
53
+
54
+ The workflow will automatically trigger and:
55
+ - Check out your code.
56
+ - Run secret scanning to ensure no credentials are accidentally published.
57
+ - Determine the dist-tag:
58
+ - If version contains a hyphen (prerelease, e.g., `0.1.0-beta.1`): `npm publish --tag beta`
59
+ - Otherwise (stable): `npm publish --tag latest`
60
+ - Publish to npm with no token or passkey prompt.
61
+
62
+ ### Via Git CLI
63
+
64
+ ```bash
65
+ git tag 0.1.0 -a -m "Release Aesop 0.1.0"
66
+ git push origin 0.1.0
67
+ # Then go to GitHub Releases and click "Create release from tag"
68
+ # (Or use gh CLI: gh release create 0.1.0 --generate-notes)
69
+ ```
70
+
71
+ ## Dist-Tag Logic
72
+
73
+ The workflow automatically selects a dist-tag based on the version in `package.json`:
74
+
75
+ - **Prerelease versions** (contain hyphen):
76
+ - `0.1.0-beta.1` → `npm publish --tag beta`
77
+ - `0.1.0-rc.1` → `npm publish --tag beta`
78
+ - `1.0.0-alpha` → `npm publish --tag beta`
79
+
80
+ - **Stable versions** (no hyphen):
81
+ - `0.1.0` → `npm publish --tag latest`
82
+ - `1.0.0` → `npm publish --tag latest`
83
+
84
+ Users installing with `npm install @matt82198/aesop` will get the latest stable version by default. Beta versions can be installed with `npm install @matt82198/aesop@beta`.
85
+
86
+ ## Secret Scanning
87
+
88
+ Before every publish, the workflow runs:
89
+
90
+ ```bash
91
+ python3 tools/secret_scan.py .
92
+ ```
93
+
94
+ This scans the entire package tree for credentials (API keys, tokens, PEM files, etc.). **If any are found, the publish will fail.** This is a safety gate — credentials should never appear in published npm packages.
95
+
96
+ If a false positive occurs (e.g., pattern documentation), add the pragma to the file's first 10 lines:
97
+
98
+ ```python
99
+ # secretscan: allow-pattern-docs
100
+ ```
101
+
102
+ See `tools/secret_scan.py` for full pragma documentation.
103
+
104
+ ## Bootstrap Caveat: First Publish
105
+
106
+ **Important:** npm trusted publishing requires the package to already exist on npmjs.com before you can attach a trusted publisher.
107
+
108
+ - **If the package does NOT yet exist:** You'll need a **one-time bootstrap publish** using either:
109
+ 1. An npm **Automation token** (kept in a personal CI/CD secret, used once, then deleted).
110
+ 2. The npm web flow (manual login with passkey, generate temporary token).
111
+
112
+ After the first publish, the package exists and the trusted publisher is active for all future releases.
113
+
114
+ - **If the package already exists:** Skip this step. The workflow will publish directly with no token or passkey.
115
+
116
+ **To bootstrap (one-time only):**
117
+
118
+ 1. Generate an npm Automation token at [npmjs.com/settings/tokens](https://npmjs.com/settings/tokens) (API type, pub access).
119
+ 2. Add it as a GitHub secret (e.g., `NPM_TOKEN`).
120
+ 3. Update the workflow `env` section to use it:
121
+ ```yaml
122
+ env:
123
+ NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
124
+ ```
125
+ 4. After the first publish succeeds, **remove the secret from the workflow** (revert to `NODE_AUTH_TOKEN: ${{ secrets.npm_token || '' }}`).
126
+ 5. The trusted publisher is now active for future releases.
127
+
128
+ ## Troubleshooting
129
+
130
+ ### Publish fails: "No permission to publish"
131
+
132
+ → **Trusted publisher not configured.** Go to npmjs.com settings and add it (step 1 above).
133
+
134
+ ### Publish fails: "npm: command not found"
135
+
136
+ → Shouldn't happen (actions/setup-node handles this). Check Node 22 is installed.
137
+
138
+ ### Publish fails: "Secret scan found credentials"
139
+
140
+ → Run `python3 tools/secret_scan.py .` locally to identify the leak. Remove or redact it, re-commit, then re-release.
141
+
142
+ ### I'm using a passkey-only account and get OTP prompts
143
+
144
+ → That's exactly why we use OIDC. Trusted publishing bypasses passkey+OTP entirely. Ensure the workflow and trusted publisher are correctly configured.
145
+
146
+ ## References
147
+
148
+ - [npm OIDC Trusted Publishing](https://docs.npmjs.com/generating-and-authenticating-with-deploy-tokens#authenticating-with-oidc)
149
+ - [GitHub Actions: Setting up Node.js](https://github.com/actions/setup-node)
150
+ - [Secret Scanning Tool](../tools/secret_scan.py)
@@ -0,0 +1,246 @@
1
+ # Antivirus (AV) Resilience & Behavioral Engine Design Patterns
2
+
3
+ ## Problem Statement
4
+
5
+ Antivirus and behavioral-analysis engines (SentinelOne, Windows Defender, etc.) may:
6
+ - **Delete tool binaries mid-session** when they trigger heuristic alerts (Claude Code, git-bash, node, python)
7
+ - **Suspend processes** during scanning, causing temporary hangs or failed tool invocations
8
+ - **Block file writes** to protected directories, silently failing git operations or log appends
9
+ - **Trigger false positives** on legitimate automation workflows (agent dispatch, secret scanning, process spawning)
10
+
11
+ This is not a security breach—it's a *compatibility* problem with legitimate automation tools. Aesop must survive these disruptions gracefully.
12
+
13
+ ---
14
+
15
+ ## Design Principles
16
+
17
+ ### 1. **Continuous Push Discipline**
18
+ - **Every cycle completes a push**, not just a stash or backup. If one file blocks due to AV, push the rest.
19
+ - **Philosophy**: A partially-pushed state (some repos synced, some stalled) is **better** than no push at all.
20
+ - **Implementation**:
21
+ - `daemons/backup-fleet.sh` processes repos independently; one BLOCKED repo doesn't stall others.
22
+ - `state/FLEET-BACKUP.log` logs each outcome (CLEAN, PUSHED, SNAPSHOTTED, BLOCKED) per repo.
23
+ - Watchdog cycle completes successfully even if 1 of 10 repos fails.
24
+
25
+ ### 2. **Surgical Single-File Recovery**
26
+ - **Minimize scope of recovery**. If a binary is deleted, re-fetch only that one binary, not the whole toolchain.
27
+ - **Pattern**:
28
+ - Monitor tool invocation failures: `python: command not found`, `git: not found`.
29
+ - Trigger minimal reinstall: `apt-get install python`, `git clone <tool>`.
30
+ - Resume immediately without waiting for manual intervention.
31
+ - **Why**: Batch slowdowns (full OS update, system restart) are much worse than targeted tool recovery.
32
+
33
+ ### 3. **Avoid Mass Process Kills**
34
+ - **Anti-pattern**: Restarting the orchestrator, killing all agents, wiping state when one process hangs.
35
+ - **Pattern**:
36
+ - Use tight heartbeat timeouts (300s for watchdog, 3600s for monitor).
37
+ - Kill **only** the stalled agent by its PID; main orchestrator stays alive.
38
+ - Log the kill and its reason (e.g., "heartbeat age 450s > threshold 300s").
39
+ - Resume the agent or defer to next cycle.
40
+
41
+ ### 4. **Idempotent Push Refs**
42
+ - **Backup refs are date-stamped, not timestamped**: `backup/wip-20260711`, not `backup/wip-20260711-134521`.
43
+ - **Why**: Multiple backup attempts on the same day write to the same ref, so git naturally deduplicates them.
44
+ - **Recovery**: If a push partially fails and the process dies, the next cycle tries again to the same ref and succeeds without creating orphaned branches.
45
+
46
+ ### 5. **Tracked-Files-Only Secret Scanning**
47
+ - **Scan only modified files**, not the entire repo (which includes .gitignored binaries, node_modules, build artifacts).
48
+ - **Pattern**:
49
+ ```bash
50
+ git diff --name-only HEAD | xargs secret_scan.py
51
+ git ls-files -m | xargs secret_scan.py
52
+ ```
53
+ - **Why**:
54
+ - AV engines sometimes block access to large binary files during scanning. Scanning a 500MB node_modules triggers false-positive rate.
55
+ - Scanning only tracked changes is **faster** and **more reliable** than full-directory scans.
56
+ - Mirrors what a push gate would actually check (`git diff` before commit).
57
+
58
+ ---
59
+
60
+ ## Failure Modes & Recovery
61
+
62
+ ### Scenario 1: Binary Deletion Mid-Cycle
63
+
64
+ **What happens:**
65
+ ```bash
66
+ $ bash /path/to/aesop/daemons/backup-fleet.sh
67
+ [2026-07-11 10:30:15] === cycle start ===
68
+ [2026-07-11 10:30:16] SentinelOne deletes git.exe (false positive on automation)
69
+ $ git fetch -q
70
+ bash: git: command not found
71
+ [2026-07-11 10:30:17] BLOCKED: my-project-repo
72
+ ```
73
+
74
+ **Recovery:**
75
+ 1. Watchdog detects BLOCKED outcome → logs to FLEET-BACKUP.log.
76
+ 2. Next cycle (150s later) detects repo is touched (uncommitted files remain).
77
+ 3. Retry `is_touched()` → re-fetch → get `command not found` again.
78
+ 4. **Manual intervention path**: User or admin runs:
79
+ ```bash
80
+ # Re-install git (OS-specific)
81
+ winget install Git.Git # Windows
82
+ apt-get install git # Linux
83
+ ```
84
+ 5. Next watchdog cycle succeeds (binary is back).
85
+
86
+ **Design choice**: Watchdog logs but doesn't auto-repair missing binaries (policy: fail safely, log clearly, resume on next cycle).
87
+
88
+ ---
89
+
90
+ ### Scenario 2: Process Suspension During Secret Scan
91
+
92
+ **What happens:**
93
+ ```bash
94
+ $ python secret_scan.py file1.py file2.py file3.py
95
+ # AV engine suspends python.exe during scan of large file
96
+ [waiting indefinitely or timing out after 30s]
97
+ ```
98
+
99
+ **Recovery:**
100
+ 1. `scan_tracked_files()` runs with implicit timeout (scan completes or fails).
101
+ 2. If timeout, `scan_tracked_files` returns non-zero exit code → BLOCKED outcome.
102
+ 3. Files remain uncommitted (no push attempt).
103
+ 4. **Recommendation**: Tune secret-scan to scan **only staged files** (via `git diff --cached`), reducing scope.
104
+
105
+ ---
106
+
107
+ ### Scenario 3: Orchestrator Heartbeat Stale
108
+
109
+ **What happens:**
110
+ ```bash
111
+ # Watchdog daemon hung (AV locked python.exe; backup-fleet.sh stalled)
112
+ # Heartbeat timestamp = 1720680915 (5 minutes ago)
113
+ $ cat state/.watchdog-heartbeat
114
+ 1720680915
115
+ $ date +%s
116
+ 1720681215 # Current time, 300s later
117
+ # Dashboard threshold = 300s for watchdog
118
+ # Status: STALE
119
+ ```
120
+
121
+ **Recovery:**
122
+ 1. Dashboard shows `STALE (age: 300s+)` in red.
123
+ 2. User checks logs (`state/FLEET-BACKUP.log`) to diagnose why daemon stalled.
124
+ 3. Options:
125
+ - **If binary is missing**: Reinstall and restart watchdog.
126
+ - **If process is hung**: Kill it (`pkill -f run-watchdog.sh`) and restart.
127
+ - **If it's a false stall**: Wait for next cycle (watchdog usually recovers).
128
+ 4. Restart watchdog:
129
+ ```bash
130
+ bash $AESOP_ROOT/daemons/run-watchdog.sh
131
+ ```
132
+
133
+ ---
134
+
135
+ ## Best Practices
136
+
137
+ ### For Aesop Operators
138
+
139
+ 1. **Monitor the dashboard**. STALE heartbeats are your canary in the coal mine.
140
+ 2. **Review FLEET-BACKUP.log** weekly for BLOCKED outcomes. Investigate patterns.
141
+ 3. **Keep security scanner narrow**: Scan only staged files (`--staged`), not entire repos.
142
+ 4. **Whitelist Aesop tools in your AV**:
143
+ - `C:\Program Files\Git\bin\bash.exe`
144
+ - `python.exe` (if Python is on PATH)
145
+ - Node.js (if using orchestration monitor)
146
+ - The Aesop root directory itself (read-only, no execution harm)
147
+
148
+ ### For Aesop Developers
149
+
150
+ 1. **Test against real AV**. Spin up a test VM with SentinelOne or similar and deliberately trigger false positives.
151
+ 2. **Log all process invocations**. Include PID, command, exit code, stderr (first 100 chars).
152
+ 3. **Use tight timeouts** (30s for secret scans, 5s for git commands). Fail fast, don't hang.
153
+ 4. **Implement single-instance guards** via heartbeat files. Don't spawn multiple instances of the same daemon.
154
+ 5. **Design for recovery**: Every log entry should make it obvious to a human or script *why* something failed and *what to do next*.
155
+
156
+ ---
157
+
158
+ ## Configuration & Tuning
159
+
160
+ ### Heartbeat Thresholds (seconds)
161
+
162
+ Tune these based on your infrastructure speed:
163
+
164
+ ```bash
165
+ get_hb_threshold() {
166
+ local name="$1"
167
+ case "$name" in
168
+ *monitor*) echo 3600 ;; # Orchestration monitor: 1 hour (low-frequency signal collection)
169
+ *watchdog*) echo 300 ;; # Watchdog daemon: 5 minutes (tight, frequent backup cycles)
170
+ *backup*) echo 300 ;; # Backup script: 5 minutes (same cadence as watchdog)
171
+ *) echo 300 ;; # Default: 5 minutes
172
+ esac
173
+ }
174
+ ```
175
+
176
+ - **Increase thresholds** if your infrastructure is slow (slow disks, high load, slow network).
177
+ - **Decrease thresholds** if you want faster failure detection (but risk false STALE alerts during heavy AV scans).
178
+
179
+ ### Secret Scanning Scope
180
+
181
+ Change `scan_tracked_files()` to scan only staged files instead of modified files:
182
+
183
+ ```bash
184
+ scan_tracked_files() {
185
+ local repo="$1"
186
+ # Alternative: scan only files staged for commit
187
+ git diff --cached --name-only 2>/dev/null | xargs -r secret_scan.py
188
+ }
189
+ ```
190
+
191
+ ### Logging Detail
192
+
193
+ Increase logging verbosity to diagnose AV conflicts:
194
+
195
+ ```bash
196
+ log "git fetch returned $?: $(cd $repo && git fetch -q origin 2>&1 | head -c 100)"
197
+ ```
198
+
199
+ ---
200
+
201
+ ## Testing & Validation
202
+
203
+ ### Test Case: Simulate Binary Deletion
204
+
205
+ ```bash
206
+ # 1. Start watchdog in background
207
+ bash $AESOP_ROOT/daemons/run-watchdog.sh &
208
+ WATCHDOG_PID=$!
209
+
210
+ # 2. Simulate git deletion
211
+ mv /c/Program\ Files/Git/bin/git.exe /tmp/git.exe.bak
212
+
213
+ # 3. Wait for next cycle
214
+ sleep 160
215
+
216
+ # 4. Check logs
217
+ tail -20 $AESOP_ROOT/state/FLEET-BACKUP.log
218
+
219
+ # 5. Restore git
220
+ mv /tmp/git.exe.bak /c/Program\ Files/Git/bin/git.exe
221
+
222
+ # 6. Next cycle should recover
223
+ sleep 160
224
+ tail -10 $AESOP_ROOT/state/FLEET-BACKUP.log
225
+ ```
226
+
227
+ ### Expected Output
228
+
229
+ ```
230
+ [2026-07-11 10:30:15] === cycle start ===
231
+ [2026-07-11 10:30:16] BLOCKED: my-repo
232
+ [2026-07-11 10:30:16] === cycle end ===
233
+ [2026-07-11 10:32:16] === cycle start ===
234
+ [2026-07-11 10:32:17] CLEAN: my-repo # (or PUSHED if changes made during downtime)
235
+ [2026-07-11 10:32:17] === cycle end ===
236
+ ```
237
+
238
+ ---
239
+
240
+ ## References
241
+
242
+ - [SentinelOne Behavioral Engine False Positives](https://community.sentinelone.com/)
243
+ - [Windows Defender ASR Rules](https://learn.microsoft.com/en-us/windows/security/threat-protection/microsoft-defender-atp/attack-surface-reduction)
244
+ - [Git Best Practices for Automation](https://git-scm.com/docs/git-var)
245
+ - Aesop docs/STATE-MACHINE.md — Durable checkpointing recovery
246
+ - Cardinal Rule 3 (main CLAUDE.md) — "Reliability core: Inputs ALWAYS produce outputs"
@@ -0,0 +1,66 @@
1
+ # Aesop Orchestration Monitor — Charter
2
+
3
+ A standing background monitor (Haiku subagent) that watches how the multi-agent system operates and acts on points of refinement. It improves the *machinery*, never the *mission*.
4
+
5
+ ## FIXED GOAL (never changes)
6
+
7
+ > Maintain your projects correctly, cheaply, and autonomously under your cardinal rules.
8
+ > The monitor's job is to make that machine run better — it must NOT redirect, re-scope,
9
+ > or invent new project goals. If it ever thinks the goal should change, it writes a note
10
+ > in `PROPOSALS.md` and stops there.
11
+
12
+ ## What it watches
13
+
14
+ 1. **Heartbeat health** — are loop daemons alive? (watchdog ~300s, monitor ~3600s)
15
+ 2. **Security alerts** — any high/medium severity issues in the fleet?
16
+ 3. **Log rotation** — do append-only logs need archiving?
17
+ 4. **Memory staleness** — are project notes up to date?
18
+ 5. **Orchestration drift** — are agents following the cardinal rules?
19
+
20
+ ## Action tiers
21
+
22
+ - **AUTO (apply immediately, then log to `ACTIONS.log`):**
23
+ - Heartbeat freshness checks (read-only).
24
+ - Log rotation (invoke `rotate_logs.py` if available).
25
+ - Persist project memory updates (if applicable).
26
+ - Quarantine defunct scripts (if a quarantine directory exists).
27
+
28
+ - **PROPOSE (write to `PROPOSALS.md`, do NOT apply — needs user approval):**
29
+ - Changes to cardinal rules or agent configuration.
30
+ - Alterations to agent behavior or model choice.
31
+ - Deletions of anything outside the monitor's own quarantine.
32
+ - Any change to orchestration policy.
33
+
34
+ ## Hard guardrails (inviolable)
35
+
36
+ - Preserve the FIXED GOAL. Improve rules; never rewrite intent.
37
+ - **Subagents are ALWAYS Haiku** (cost optimization). Orchestrator on main thread only.
38
+ - NEVER push destructively or to restricted remotes as an AUTO action.
39
+ - Idempotent + additive: safe to run repeatedly; prefer append over overwrite.
40
+ - Stay cheap: read the signal brief, not raw logs. One tight cycle, then sleep.
41
+
42
+ ## Outputs
43
+
44
+ - `BRIEF.md` — human-readable status snapshot.
45
+ - `SIGNALS.json` — machine-readable metrics and findings.
46
+ - `ACTIONS.log` — append-only record of AUTO actions taken (timestamped).
47
+ - `PROPOSALS.md` — staged changes awaiting user approval.
48
+ - `quarantine/` (optional) — parked suspect scripts + manifest.
49
+
50
+ ## Operating it
51
+
52
+ 1. **Deploy the monitor** under `/power` or as a continuous background task.
53
+ 2. **Arm the charter**: customize this file with your project names, repos, and thresholds.
54
+ 3. **Review PROPOSALS.md** periodically; approve changes or reject them.
55
+ 4. **Check ACTIONS.log** to see what was automated.
56
+ 5. **Archive BRIEF.md snapshots** if you want a historical record.
57
+
58
+ ## Customization
59
+
60
+ Edit `collect-signals.mjs` to:
61
+ - Add your own repo paths and project names.
62
+ - Define custom signal collectors (e.g., junk-script detection).
63
+ - Set heartbeat thresholds appropriate to your workflow.
64
+ - Integrate security scanners or compliance checks.
65
+
66
+ See comments in `collect-signals.mjs` for extension points.