@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/monitor/CHARTER.md
CHANGED
|
@@ -1,116 +1,103 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Orchestration Refinement Monitor — Charter
|
|
2
2
|
|
|
3
|
-
A standing background monitor (Haiku
|
|
3
|
+
A standing background monitor (Haiku) that watches how the multi-agent system operates and
|
|
4
|
+
acts on points of refinement. It improves the *machinery*, never the *mission*.
|
|
4
5
|
|
|
5
6
|
## FIXED GOAL (never changes)
|
|
7
|
+
> Ship and maintain your projects correctly, cheaply, and autonomously under the cardinal rules
|
|
8
|
+
> (`~/.claude/CLAUDE.md`). The monitor's job is to make that machine run better — it must NOT
|
|
9
|
+
> redirect, re-scope, or invent new project goals. If it ever thinks the goal should change, it
|
|
10
|
+
> writes a note in `PROPOSALS.md` and stops there.
|
|
11
|
+
|
|
12
|
+
## What it watches (via `collect-signals.mjs`, refreshed each cycle)
|
|
13
|
+
1. **Junk-script sprawl** — one-off Python/JS scripts Claude Code writes to temp/scratch/cloud and
|
|
14
|
+
never reuses. Repeated throwaway `.py` to remote agents is a known cost/clutter sink.
|
|
15
|
+
2. **Memory gaps** — projects/decisions/gotchas with no durable memory file; stale or duplicate memories.
|
|
16
|
+
3. **Rule friction** — cardinal-rule violations in recent activity (non-Haiku subagents, main-thread
|
|
17
|
+
big reads, unpushed green work) and rules that are ambiguous, contradicted, or repeatedly ignored.
|
|
18
|
+
4. **Orchestration health** — hung/stale agents, drift, repeated failures, git state across repos.
|
|
6
19
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
20
|
+
## Action tiers
|
|
21
|
+
- **AUTO (apply immediately, then log to `ACTIONS.log`):**
|
|
22
|
+
- Persist/refresh project memory files (one fact each) + update `MEMORY.md` index.
|
|
23
|
+
- Quarantine confirmed-dead one-off scripts: move junk temp `.py`/`.mjs` (older than 24h, not
|
|
24
|
+
referenced by any repo, not the active session's scratchpad) into `orchestration-monitor/quarantine/`
|
|
25
|
+
with a manifest — never delete outright, never touch a live session scratchpad or repo `src/`.
|
|
26
|
+
- Clarifying, non-behavioral edits to a memory/log the monitor owns.
|
|
27
|
+
- **PROPOSE (write to `PROPOSALS.md`, do NOT apply — needs user OK):**
|
|
28
|
+
- Any change to `~/.claude/CLAUDE.md`, `~/.claude/skills/**`, or a project `CLAUDE.md`.
|
|
29
|
+
- Anything that alters agent behavior, model choice, push targets, or goal scope.
|
|
30
|
+
- Deleting anything outside the monitor's own quarantine.
|
|
11
31
|
|
|
12
|
-
##
|
|
32
|
+
## Hard guardrails (inviolable)
|
|
33
|
+
- Preserve the FIXED GOAL. Improve rules; never rewrite intent.
|
|
34
|
+
- Subagents are ALWAYS Haiku (this monitor included). Opus orchestrates on the main thread only.
|
|
35
|
+
- NEVER work around a classifier denial (cross-repo private-source push = exfil; reusing a
|
|
36
|
+
credential meant for another service = credential exploration). If seen, log + propose, don't act.
|
|
37
|
+
- NEVER print secret values. NEVER push to a remote or run a destructive command as an AUTO action.
|
|
38
|
+
- Idempotent + additive: safe to run repeatedly; prefer append/quarantine over overwrite/delete.
|
|
39
|
+
- Stay cheap: read the signal brief, not raw code/logs. One tight cycle, then sleep.
|
|
13
40
|
|
|
14
|
-
|
|
41
|
+
## End-of-day wipe-survival sweep
|
|
15
42
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
43
|
+
The monitor may run `python ~/scripts/eod_sweep.py` in its final cycle of the day.
|
|
44
|
+
This verifies all known git repos are safe (no data loss risk):
|
|
45
|
+
- working trees clean OR dirty-file list logged
|
|
46
|
+
- current branch pushed to origin (ahead-count 0)
|
|
47
|
+
- untracked files not silently .gitignore'd
|
|
48
|
+
- SECURITY-ALERTS.log has no unreviewed HIGH/MED items
|
|
49
|
+
- memory INBOX consumed (0 pending items)
|
|
50
|
+
- no heartbeat file claims a dead loop (>1h stale)
|
|
19
51
|
|
|
20
|
-
|
|
21
|
-
|
|
52
|
+
Output: single verdict line (`EOD-SWEEP: SAFE` or `EOD-SWEEP: AT-RISK — <n> findings`) + one finding per line;
|
|
53
|
+
appends to handoff log. Exit code 0 only if SAFE.
|
|
22
54
|
|
|
23
|
-
|
|
24
|
-
append summary to BRIEF.md ("N memories stale — keeper should re-verify").
|
|
55
|
+
If findings detected, the monitor stages an alert: `EOD-SWEEP AT-RISK — <n> findings` (each finding on bullet).
|
|
25
56
|
|
|
26
|
-
|
|
27
|
-
default 500 lines / 40 KB). If a log exceeds threshold, emit rotation signal (AUTO tier can
|
|
28
|
-
invoke rotate_logs.py if available); append rotation summary to BRIEF.md.
|
|
57
|
+
## Standing checks (trimmed for solo operation)
|
|
29
58
|
|
|
30
|
-
|
|
31
|
-
older than 24 hours, not in a live session directory (avoid false-positives during active work).
|
|
32
|
-
Count total, estimate quarantinable, list oldest. AUTO tier quarantines confirmed junk into
|
|
33
|
-
`monitor/quarantine/` with manifest.
|
|
59
|
+
**KEPT (durable value):**
|
|
34
60
|
|
|
35
|
-
|
|
36
|
-
|
|
61
|
+
1. **Scripts outside `~/scripts`** — flag `.py`/`.mjs`/`.sh` accumulating outside `~/scripts`
|
|
62
|
+
(scratchpads, temp, repo roots). Quarantine per existing tiers; when one looks genuinely reusable,
|
|
63
|
+
suggest promotion to `~/scripts` (indexed in `~/scripts/CLAUDE.md`).
|
|
37
64
|
|
|
38
|
-
|
|
39
|
-
|
|
65
|
+
2. **Remote Python execution = HIGH-tier finding** — any scheduled/cloud agent or workflow that would
|
|
66
|
+
execute Python remotely violates Rule 5 (local-only execution). Flag immediately; never create one.
|
|
40
67
|
|
|
41
|
-
|
|
42
|
-
prompt-signatures (first ~40 chars, lowercased); count occurrences in recent window (last 50 rows).
|
|
43
|
-
Flag any signature appearing >3 times as probable hung-agent loop → rule 6 cap breached.
|
|
44
|
-
Limitation: heuristic may have false positives for intentional similar-task fan-outs.
|
|
68
|
+
3. **Memory freshness** — scan `~/.claude/projects/*/memory/*.md` (excluding INBOX.md, MEMORY.md); emit `staleMemories` signal in SIGNALS.json listing any file >30d old; append to BRIEF.md: "N memories >30d — keeper should re-verify: <names>".
|
|
45
69
|
|
|
46
|
-
|
|
47
|
-
to
|
|
70
|
+
4. **SECURITY ALERT REVIEW LOOP** — on each /power cycle, arm a persistent Monitor tailing
|
|
71
|
+
SECURITY-ALERTS.log filtered to new 'HIGH'/'MED' lines (exclude SUPPRESSED-FP). Each new alert spawns a read-only fleet-auditor agent to classify REAL vs FALSE-POSITIVE (mask any secret: first 4 chars + ***), verdict appended to SECURITY-ALERTS.log as a REVIEW note and, if REAL, surfaced to the user immediately. Rationale: the append-only alert log is only useful if alerts are triaged; unreviewed HIGHs rot into ignored noise.
|
|
48
72
|
|
|
49
|
-
|
|
50
|
-
spawns since last review; emit count in SIGNALS.json + note in BRIEF.md.
|
|
73
|
+
5. **Fleet ledger harvest** — each cycle, run `python ~/scripts/fleet_ledger.py harvest` to scan session task outputs (JSONL format) and append missing agent outcomes to OUTCOMES-LEDGER.md. Tracks last-harvest state in .fleet-ledger-harvest.json sidecar. Deterministic, local-only, append-only; feeds cost analysis and agent respawn detection. Then invoke `python ~/scripts/fleet_ledger.py rotate` to archive old rows if ledger exceeds 200 lines.
|
|
51
74
|
|
|
52
|
-
|
|
75
|
+
6. **Log rotation** — after ledger operations, invoke `python ~/scripts/rotate_logs.py <file> --max-lines 500 --max-kb 40` over: hook-activity.log, SECURITY-ALERTS.log, FLEET-BACKUP.log (BUILDLOG.md at 1000-line threshold — historical record). Emit `logRotations` list in SIGNALS.json and summary line in BRIEF.md.
|
|
53
76
|
|
|
54
|
-
|
|
55
|
-
- Heartbeat freshness checks (read-only).
|
|
56
|
-
- Log rotation (invoke rotate_logs.py if available; fail-open if not).
|
|
57
|
-
- Persist heartbeat write (`.monitor-heartbeat` update after cycle).
|
|
58
|
-
- Quarantine confirmed-junk scripts: move old temp `.py`/`.mjs` (not live session) into
|
|
59
|
-
`monitor/quarantine/` with manifest — never delete outright.
|
|
60
|
-
|
|
61
|
-
- **PROPOSE (write to `PROPOSALS.md`, do NOT apply — needs user approval):**
|
|
62
|
-
- Changes to cardinal rules or agent configuration.
|
|
63
|
-
- Alterations to agent behavior, model choice, or push targets.
|
|
64
|
-
- Deletions of anything outside monitor's own quarantine.
|
|
65
|
-
- Any change to orchestration policy.
|
|
77
|
+
7. **Heartbeat liveness check** — read state/.heartbeats/* (epoch on line 1) + legacy beat files (.monitor-heartbeat, .watchdog-heartbeat, etc.); flag any older than threshold (watchdog 300s, monitor 3600s, others 1800s default) as `staleLoops` signal in SIGNALS.json; append warning to BRIEF.md. Continuous watchdog complement to /power selftest.
|
|
66
78
|
|
|
67
|
-
|
|
79
|
+
8. **Respawn watch (Rule 6 machine-enforcement)** — parse OUTCOMES-LEDGER.md for agent descriptions; normalize each to prompt-signature (first ~40 chars, lowercased, trimmed); count occurrences per signature within recent window (last 50 rows OR since marker in .signal-state.json). Any signature appearing >3 times = probable hung-agent respawn loop → add to `respawnWatch` in SIGNALS.json + warning line in BRIEF.md. *Limitation:* heuristic may have false positives for intentional similar-task fan-outs (e.g., per-file processing with distinct file names in description); BRIEF includes note to manually review flagged signatures. Pure node parsing (no LLM).
|
|
68
80
|
|
|
69
|
-
-
|
|
70
|
-
- **Subagents are ALWAYS Haiku** (cost optimization). Orchestrator on main thread only.
|
|
71
|
-
- NEVER push destructively or to restricted remotes as an AUTO action.
|
|
72
|
-
- NEVER edit cardinal-rules files (CLAUDE.md, skills/, agent configs) — only PROPOSE changes.
|
|
73
|
-
- Idempotent + additive: safe to run repeatedly; prefer append over overwrite.
|
|
74
|
-
- Stay cheap: read the signal brief, not raw logs. One tight cycle, then sleep.
|
|
75
|
-
- Robust to missing files: treat missing dirs/logs as empty, never crash.
|
|
76
|
-
|
|
77
|
-
## Outputs
|
|
78
|
-
|
|
79
|
-
- `BRIEF.md` — human-readable status snapshot (overwrite each cycle).
|
|
80
|
-
- `SIGNALS.json` — machine-readable metrics and findings (overwrite each cycle).
|
|
81
|
-
- `ACTIONS.log` — append-only record of AUTO actions taken (timestamped).
|
|
82
|
-
- `PROPOSALS.md` — staged changes awaiting user approval.
|
|
83
|
-
- `quarantine/` — parked junk scripts + `MANIFEST.tsv` (append-only).
|
|
84
|
-
- `.monitor-heartbeat` — epoch timestamp (line 1) for liveness.
|
|
85
|
-
- `.signal-state.json` — sidecar state (cycle count, seen prompts, etc.).
|
|
86
|
-
|
|
87
|
-
## Operating it
|
|
81
|
+
9. **Semantic prompt review** — each cycle, collect-signals.mjs runs `fleet_prompt_extractor.py` to identify NEW unreviewed agent-spawn prompts (tracks seen-hash state in `.fleet-prompts-seen.json`); count is emitted as `unreviewedPrompts` in SIGNALS.json + noted in BRIEF.md. If count > 0, the monitor agent does semantic review (read each prompt, classify: OK / DRIFT / SUSPICIOUS) and runs `drift_escalator.py` to write verdicts to DRIFT-REVIEW.log + escalate any DRIFT/SUSPICIOUS findings to SECURITY-ALERTS.log + DRIFT-ESCALATIONS.md. This closes the gap: regex fleet-scan is NOT semantic review; LLM judgment gates malformed/off-goal/injection prompts. Completes before any flagged prompt's agent runs.
|
|
88
82
|
|
|
89
|
-
|
|
90
|
-
2. **Customize via config**: populate `aesop.config.json` with your repo paths, thresholds.
|
|
91
|
-
3. **Review PROPOSALS.md** periodically; approve changes or reject them.
|
|
92
|
-
4. **Check ACTIONS.log** to see what was automated.
|
|
93
|
-
5. **Monitor BRIEF.md** for drift signals; respond to findings.
|
|
83
|
+
10. **Mirror refresh cadence (throttled)** — each monitor cycle mirrors scripts and docs to your fleet-ops directory and regenerates asset indexes. If either produces diffs: check `.last-mirror-pr-time` in state/. Only open a PR if >1 hour has passed since last PR; otherwise log silently as no-op to ACTIONS.log with timestamp. Ensures mirrors stay in sync and asset lists reflect tier-1 changes, but prevents PR spam. Pure Python automation; runs in monitor context only.
|
|
94
84
|
|
|
95
|
-
|
|
85
|
+
11. **UI inbox drain (session-independent work queue)** — each cycle, run `python ~/scripts/inbox_drain.py pending` to surface queued submissions that arrived while no session was running. If items exist, write a one-line `QUEUED WORK PENDING` flag to BRIEF.md so an active monitor also surfaces it. This complements /power's inbox drain (step 5); the monitor ensures work doesn't rot in the queue even between sessions.
|
|
96
86
|
|
|
97
|
-
|
|
98
|
-
- Add/remove checks based on your project needs.
|
|
99
|
-
- Configure paths via environment variables (AESOP_ROOT, BRAIN_ROOT, SCRIPTS_ROOT, TEMP_ROOT)
|
|
100
|
-
or load from aesop.config.json.
|
|
101
|
-
- Set heartbeat thresholds appropriate to your workflow.
|
|
102
|
-
- Integrate custom signal collectors (e.g., compliance checks, custom linters).
|
|
87
|
+
**CUT or DEMOTED (no durable value for solo operator):**
|
|
103
88
|
|
|
104
|
-
|
|
105
|
-
|
|
89
|
+
- **Suppression audit** — (CUT) A solo operator watching the dashboard notices suppression count manually; meta-audits add ceremony without signal.
|
|
90
|
+
- **Cost cadence** — (DEMOTED; blocked) Ledger parsing incomplete; once cost meter is proven, restore. For now, flag as blocked in PROPOSALS.md if touched.
|
|
106
91
|
|
|
107
|
-
|
|
92
|
+
**Rationale & changes:**
|
|
108
93
|
|
|
109
|
-
|
|
110
|
-
After cycle completes, update `.monitor-heartbeat` with current epoch.
|
|
94
|
+
The original 12-check charter was ceremony-heavy for a one-person system. Cuts preserve the critical signals (liveness, security triage, hung loops, prompt safety, cost data acquisition) and demote/cut only checks whose value is marginal or already visible to a solo operator. Check #10 was throttled instead of cut because the mirror sync is critical, but PR-per-cycle wastes bandwidth — now it only PRs when changes exist AND at least 1 hour has passed.
|
|
111
95
|
|
|
112
|
-
|
|
96
|
+
Total standing checks: **11** (reflecting genericization; some checks are environment-specific).
|
|
113
97
|
|
|
114
|
-
|
|
115
|
-
-
|
|
116
|
-
-
|
|
98
|
+
## Outputs (all under orchestration-monitor/)
|
|
99
|
+
- `BRIEF.md` / `SIGNALS.json` — the deterministic snapshot (written by the collector).
|
|
100
|
+
- `ACTIONS.log` — append-only record of AUTO actions taken (timestamped).
|
|
101
|
+
- `PROPOSALS.md` — staged rule/behavior changes awaiting user approval.
|
|
102
|
+
- `quarantine/` — parked junk scripts + `MANIFEST.tsv`.
|
|
103
|
+
- `.monitor-heartbeat` — liveness for any dashboard.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# monitor/ — Orchestration monitor
|
|
2
|
+
|
|
3
|
+
**Purpose**: Continuous background signal collector and refinement proposer — watches fleet machinery health deterministically (Node.js, no LLM), emits cycle snapshots, and proposes rule changes via append-only PROPOSALS.md; GOAL IS FIXED (improve machinery, never mission).
|
|
4
|
+
|
|
5
|
+
## Files
|
|
6
|
+
|
|
7
|
+
- **CHARTER.md** — Governance document; defines 10 signal checks (4 of them extended/opt-in), action tiers (AUTO/PROPOSE), outputs, single-instance guard, single-writer discipline. Read-only; behavior changes only via PROPOSALS/behavioral-PR flow.
|
|
8
|
+
- **collect-signals.mjs** — Deterministic signal collector (Node.js built-ins only); emits BRIEF.md + SIGNALS.json each cycle; reads config from env or aesop.config.json.
|
|
9
|
+
- **BRIEF.md** — Human-readable cycle snapshot (heartbeats, git state, memory freshness, log rotation, junk sprawl, stray scripts, security alerts, respawn watch, cost cadence, unreviewed prompts); overwritten each cycle; runtime.
|
|
10
|
+
- **SIGNALS.json** — Machine-readable metrics (same signal keys as BRIEF); JSON; overwritten each cycle; runtime.
|
|
11
|
+
- **PROPOSALS.md** — Structured inbox for user approval (idempotent per signal key, append-only); never edited by monitor after emission; tracks respawn-watch-breach, stray-repo-scripts, security-alerts-high-med, stale-memory-files; gitignored.
|
|
12
|
+
- **ACTIONS.log** — Append-only log of AUTO tier actions taken (heartbeat updates, log rotation invokes, junk quarantine); runtime; gitignored.
|
|
13
|
+
- **.monitor-heartbeat** — Epoch timestamp (line 1) for single-instance liveness check (<300s = skip cycle); runtime; gitignored.
|
|
14
|
+
- **.signal-state.json** — Sidecar state (cycleCount, etc.); runtime; gitignored.
|
|
15
|
+
|
|
16
|
+
## Contracts
|
|
17
|
+
|
|
18
|
+
**Signal keys collected**: heartbeats, git, memory, logs, junk, strayRepo, alerts, respawnWatch, costTick, unreviewedPrompts. Outputs: BRIEF.md (human), SIGNALS.json (machine); both runtime/gitignored. PROPOSALS.md (tracked, append-only); ACTIONS.log (runtime/gitignored).
|
|
19
|
+
|
|
20
|
+
**Extended signals (opt-in, default OFF)**: checks 5 (junk), 6 (strayRepo), 8 (respawnWatch), and 10 (unreviewedPrompts) are extended — disabled by default.
|
|
21
|
+
- Config key: `monitor.extended_signals` (boolean, default `false`) in aesop.config.json.
|
|
22
|
+
- Env override: `AESOP_EXTENDED_SIGNALS` (`'true'` or `'1'` to enable).
|
|
23
|
+
- Precedence: env var > config file > default (false).
|
|
24
|
+
- When disabled, extended checks emit `{"skipped": true}` in SIGNALS.json and BRIEF.md notes them as "extended (off)"; their dirs are not walked. PROPOSE-tier signals for extended checks (respawn-watch-breach, stray-repo-scripts) are only emitted when extended_signals is ON.
|
|
25
|
+
|
|
26
|
+
**AUTO tier actions** (apply immediately, log to ACTIONS.log): heartbeat checks (read-only); log rotation (invoke rotate_logs.py if available, fail-open); heartbeat write (.monitor-heartbeat update); junk script quarantine (move old temp .py/.mjs to monitor/quarantine/ + manifest — only when extended_signals is ON).
|
|
27
|
+
|
|
28
|
+
**PROPOSE tier actions** (write to PROPOSALS.md, await user approval): rule changes, agent config changes, deletions outside monitor/quarantine/, orchestration policy changes.
|
|
29
|
+
|
|
30
|
+
**Idempotency rule**: Proposal emission keyed on signal key (e.g., 'respawn-watch-breach'); only emitted if not already present in PROPOSALS.md (check: `**Signal:** <key>` exists). Idempotent + append-only; safe to run repeatedly.
|
|
31
|
+
|
|
32
|
+
## Invariants & Gotchas
|
|
33
|
+
|
|
34
|
+
- CHARTER.md is authority; monitor logic is faithful to it; never edit CHARTER.md or collect-signals.mjs directly — propose via PROPOSALS.md.
|
|
35
|
+
- Goal is FIXED (improve machinery, never mission); if monitor thinks goal should change, it writes note to PROPOSALS.md and stops.
|
|
36
|
+
- Single-instance guard via .monitor-heartbeat; if <300s old, skip cycle.
|
|
37
|
+
- Single-writer discipline: only monitor writes BRIEF.md, SIGNALS.json, ACTIONS.log, .monitor-heartbeat, .signal-state.json.
|
|
38
|
+
- Config from env (AESOP_ROOT, BRAIN_ROOT, SCRIPTS_ROOT, TEMP_ROOT, AESOP_EXTENDED_SIGNALS) or aesop.config.json; falls back to safe defaults.
|
|
39
|
+
- Robust to missing files; treats missing dirs/logs as empty, never crashes.
|
|
40
|
+
- Node.js only (no Python, no LLM, no cloud); deterministic + cheap.
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"timestamp": "2026-07-12T19:11:11.520Z",
|
|
3
|
+
"cycleCount": 10,
|
|
4
|
+
"heartbeats": {
|
|
5
|
+
"staleCount": 0,
|
|
6
|
+
"details": []
|
|
7
|
+
},
|
|
8
|
+
"git": [],
|
|
9
|
+
"memory": {
|
|
10
|
+
"count": 26,
|
|
11
|
+
"staleMemories": [],
|
|
12
|
+
"staleCount": 0
|
|
13
|
+
},
|
|
14
|
+
"logs": [
|
|
15
|
+
{
|
|
16
|
+
"name": "FLEET-BACKUP.log",
|
|
17
|
+
"exists": true,
|
|
18
|
+
"sizeKb": "1.8",
|
|
19
|
+
"lineCount": 37,
|
|
20
|
+
"needsRotation": false
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
"name": "SECURITY-ALERTS.log",
|
|
24
|
+
"exists": false,
|
|
25
|
+
"sizeKb": 0,
|
|
26
|
+
"lineCount": 0,
|
|
27
|
+
"needsRotation": null
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"name": "ACTIONS.log",
|
|
31
|
+
"exists": true,
|
|
32
|
+
"sizeKb": "0.2",
|
|
33
|
+
"lineCount": 1,
|
|
34
|
+
"needsRotation": false
|
|
35
|
+
}
|
|
36
|
+
],
|
|
37
|
+
"junk": {
|
|
38
|
+
"skipped": true
|
|
39
|
+
},
|
|
40
|
+
"strayRepo": {
|
|
41
|
+
"skipped": true
|
|
42
|
+
},
|
|
43
|
+
"alerts": {
|
|
44
|
+
"count": 0,
|
|
45
|
+
"highMedCount": 0
|
|
46
|
+
},
|
|
47
|
+
"respawnWatch": {
|
|
48
|
+
"skipped": true
|
|
49
|
+
},
|
|
50
|
+
"costTick": null,
|
|
51
|
+
"unreviewedPrompts": {
|
|
52
|
+
"skipped": true
|
|
53
|
+
}
|
|
54
|
+
}
|