@matt82198/aesop 0.1.0-beta.4 → 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 +46 -5
- package/README.md +57 -1
- package/aesop.config.example.json +8 -1
- package/bin/CLAUDE.md +30 -2
- package/bin/cli.js +286 -73
- package/daemons/CLAUDE.md +4 -1
- package/daemons/run-watchdog.sh +5 -2
- package/docs/RELEASING.md +159 -0
- package/docs/archive/README.md +3 -0
- package/docs/{spikes → archive/spikes}/tiered-cognition/README.md +1 -3
- 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 +23 -0
- package/mcp/CLAUDE.md +213 -0
- package/mcp/package.json +26 -0
- package/mcp/server.mjs +543 -0
- package/monitor/CHARTER.md +76 -110
- package/monitor/collect-signals.mjs +85 -0
- package/package.json +4 -1
- package/scan/fleet-scan.example.mjs +292 -0
- package/skills/healthcheck/SKILL.md +44 -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 +30 -149
- package/tools/__pycache__/alert_bridge.cpython-314.pyc +0 -0
- package/tools/__pycache__/ci_merge_wait.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__/metrics_gate.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/alert_bridge.py +449 -0
- package/tools/ci_merge_wait.py +121 -8
- package/tools/fleet_prompt_extractor.py +134 -0
- package/tools/healthcheck.py +296 -0
- package/tools/secret_scan.py +8 -1
- package/tools/self_stats.py +509 -0
- package/tools/session_usage_summary.py +198 -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 +361 -542
- package/tools/verify_submit_encoding.py +12 -4
- package/ui/CLAUDE.md +57 -41
- 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 +9 -5
- package/ui/api/__pycache__/submit.cpython-314.pyc +0 -0
- package/ui/api/submit.py +44 -5
- package/ui/collectors.py +184 -35
- package/ui/config.py +9 -0
- package/ui/cost.py +260 -0
- package/ui/csrf.py +7 -3
- package/ui/handler.py +254 -4
- package/ui/render.py +26 -6
- package/ui/sse.py +16 -1
- 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/ui/templates/dashboard.html +0 -1202
- /package/docs/{spikes → archive/spikes}/tiered-cognition/ACTIVATION.md +0 -0
- /package/docs/{spikes → archive/spikes}/tiered-cognition/DESIGN.md +0 -0
- /package/docs/{spikes → archive/spikes}/tiered-cognition/FINDINGS.md +0 -0
- /package/docs/{spikes → archive/spikes}/tiered-cognition/aesop-cognition.example.md +0 -0
- /package/docs/{spikes → archive/spikes}/tiered-cognition/force-model-policy.merged.mjs +0 -0
- /package/docs/{spikes → archive/spikes}/tiered-cognition/strip-tools-hook.mjs +0 -0
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Case Study: Portfolio Site Build with Aesop
|
|
2
|
+
|
|
3
|
+
## What Happened (Timeline)
|
|
4
|
+
|
|
5
|
+
| Time | Event | Duration |
|
|
6
|
+
|------|-------|----------|
|
|
7
|
+
| 17:09 | User prompt: "build me a portfolio site" | — |
|
|
8
|
+
| 17:09–17:20 | 6 discovery scouts (GitHub API, Medium, LinkedIn, Reddit ×2, Playwright fallback, repo deep-dive) run in parallel; 4 ranked decision points surfaced | 11 min |
|
|
9
|
+
| 17:20–17:24 | User answers 4 prioritization questions | 4 min |
|
|
10
|
+
| 17:24–17:36 | 10 Haiku agents (scaffold + 8 section builders on file-disjoint Astro components + integrator) execute | 12 min |
|
|
11
|
+
| 17:36–17:37 | 9th section added from late Reddit data; Astro build green in 914ms | 1 min |
|
|
12
|
+
| 17:37–17:40 | Playwright screenshot proof round 1: CSS 404 detected (styles linked as `/src/` instead of `/dist/`) | 3 min |
|
|
13
|
+
| 17:40–17:42 | Repair agent fixes CSS paths; proof round 2 validates fix | 2 min |
|
|
14
|
+
| 17:42–17:48 | GitHub agent: secret-scan (10,066 files clean), create public repo, merge PR #1 | 6 min |
|
|
15
|
+
| 18:04 | GitHub Pages deployed and live at https://matt82198.github.io/ (verified 200 status) | **55 min total** |
|
|
16
|
+
|
|
17
|
+
## The Architecture
|
|
18
|
+
|
|
19
|
+
**Parallel discovery with verified facts only**: Six independent scouts (HTTP fallback to Playwright for bot-blocked sites) collected portfolio inspiration, ranked by relevance; each returned structured data on a single contract. No hallucination—every section claim traces to a source.
|
|
20
|
+
|
|
21
|
+
**File-disjoint fan-out**: 8 section agents each owned one `.astro` component with zero file overlap; no merge conflicts, no serialization bottleneck. Integrator assembled in 12 minutes.
|
|
22
|
+
|
|
23
|
+
**Proof-driven QA**: Screenshot verification caught a real ship-blocker—styles in dist/ referenced `/src/` paths that vanished at build time. No visual inspection could have found this; Playwright proved it was broken, repair proved it was fixed.
|
|
24
|
+
|
|
25
|
+
**Gated ship**: Secret-scan gate (10,066 files) ran before public repo creation; zero credentials leaked. PR merged, Pages deploy triggered, liveness confirmed.
|
|
26
|
+
|
|
27
|
+
**Orchestrator final-catch**: Fable verified theme coherence across 9 sections after assembly; caught one color inconsistency and one missing accent variant before ship.
|
|
28
|
+
|
|
29
|
+
## What Failed (and Was Caught)
|
|
30
|
+
|
|
31
|
+
The site rendered unstyled in production. Astro build succeeded locally (914ms), but the distributed `.astro` component agents—writing styles inline—used `import` statements pointing to source paths. After minification and bundling into `/dist/`, those paths no longer existed. The site shipped with no CSS.
|
|
32
|
+
|
|
33
|
+
Playwright screenshot automation caught this in production-like conditions (rendering against the compiled bundle). A repair agent updated path resolution, regenerated the build, and Playwright proved the fix before merge. This is not a testing infrastructure story—this is proof automation as a first-class gate.
|
|
34
|
+
|
|
35
|
+
## Numbers
|
|
36
|
+
|
|
37
|
+
- **Wall-clock time**: 55 minutes (first prompt to live site)
|
|
38
|
+
- **Total agents used**: ~30 (6 scouts, 10 builders, 1 repair, 1 GitHub ops, 3 proof/integration, 9 audits)
|
|
39
|
+
- **Build fleet**: 10 Haiku agents (scaffold + 8 section builders + integrator)
|
|
40
|
+
- **Build time**: 12 minutes (including inter-agent coordination)
|
|
41
|
+
- **Sections delivered**: 9
|
|
42
|
+
- **Proof rounds**: 2 (CSS 404 caught in round 1; fix validated in round 2)
|
|
43
|
+
- **Ship-blockers caught**: 1 (CSS 404)
|
|
44
|
+
- **Files secret-scanned**: 10,066 (0 issues)
|
|
45
|
+
- **Subagent tokens**: ~328K
|
|
46
|
+
- **PR**: #1, merged
|
|
47
|
+
- **Deploy**: GitHub Pages, live 200 status
|
|
48
|
+
|
|
49
|
+
## How to Reproduce
|
|
50
|
+
|
|
51
|
+
1. Fork this repo or set up Aesop in your environment.
|
|
52
|
+
2. Run the [buildsystem skill](/skills/CLAUDE.md) for a portfolio project.
|
|
53
|
+
3. Provide 4–6 source URLs or inspiration topics; Aesop will dispatch 6 discovery scouts.
|
|
54
|
+
4. Approve the ranked backlog (user decision round).
|
|
55
|
+
5. Aesop dispatches the 10-agent build workflow in parallel on Astro or your framework.
|
|
56
|
+
6. Screenshot proof runs automatically; Aesop fixes any visual defects and re-proves.
|
|
57
|
+
7. Secret-scan gate runs; if clean, Aesop creates the public repo and merges the PR.
|
|
58
|
+
8. Pages (or your host) deploys automatically.
|
|
59
|
+
|
|
60
|
+
The 55-minute bound is achievable when discovery sources are web-accessible (not gated PDFs) and the component schema is well-defined (Astro's `.astro` files are ideal; monolithic templates require serialization).
|
|
61
|
+
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_source": "Populated by orchestrator at wave close via fleet telemetry aggregation",
|
|
3
|
+
"_updated": "Awaiting orchestrator population",
|
|
4
|
+
"total_sessions": null,
|
|
5
|
+
"total_turns": null,
|
|
6
|
+
"total_user_prompts": null,
|
|
7
|
+
"max_tokens_single_turn": null,
|
|
8
|
+
"cumulative_agent_runs": null,
|
|
9
|
+
"cumulative_tokens": null,
|
|
10
|
+
"total_coding_hours": null
|
|
11
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# Fleet-Ops Analysis Summary — Cycle N
|
|
2
|
+
|
|
3
|
+
**Generated:** YYYY-MM-DDTHH:MM:SSZ
|
|
4
|
+
|
|
5
|
+
## Top Failure Modes (cumulative this session)
|
|
6
|
+
|
|
7
|
+
| Category | Count | Severity | Notes |
|
|
8
|
+
|----------|-------|----------|-------|
|
|
9
|
+
| [FAILURE_MODE_NAME] | 0 | [HIGH/MED/LOW] | Brief description of failure pattern, root cause hypothesis, and reference to any related recommendations or PRs. |
|
|
10
|
+
| | | | |
|
|
11
|
+
| | | | |
|
|
12
|
+
|
|
13
|
+
## Token Spend Summary
|
|
14
|
+
|
|
15
|
+
Brief summary of session token spend patterns:
|
|
16
|
+
- [Agent/component type]: ~XXXk tokens — brief observation
|
|
17
|
+
- Heavy [category]: XXXk — specific tasks or drivers
|
|
18
|
+
- Typical [operation type]: XXk-XXXk; [context or pattern]
|
|
19
|
+
|
|
20
|
+
Include observations about:
|
|
21
|
+
- Which domains consumed the most tokens
|
|
22
|
+
- Whether spend is aligned with task scope
|
|
23
|
+
- Any unexpected patterns or efficiency issues
|
|
24
|
+
|
|
25
|
+
## Notes
|
|
26
|
+
|
|
27
|
+
(Optional section for additional context, anomalies, or deferred investigations)
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Fleet-Ops Recommendations — machinery fixes for wave open
|
|
2
|
+
|
|
3
|
+
Rolling, append-only list maintained by the orchestration/fleet-ops monitor.
|
|
4
|
+
The buildsystem skill reads this at every wave open (Phase 0.3). Mark items
|
|
5
|
+
ADOPTED/REJECTED/IN-PROGRESS with wave number when actioned; do not delete rows.
|
|
6
|
+
|
|
7
|
+
| # | Date | Source | Severity | Recommendation | Status |
|
|
8
|
+
|---|------|--------|----------|----------------|--------|
|
|
9
|
+
| 1 | YYYY-MM-DD | [source/agent/session phase] | [HIGH/MED/LOW] | Clear, actionable recommendation describing the problem, suggested fix, and rationale. Include specific file paths or component names where applicable. | OPEN |
|
|
10
|
+
| 2 | YYYY-MM-DD | [source/agent/session phase] | [HIGH/MED/LOW] | Second example recommendation with similar detail level. Link to related findings if applicable. | OPEN |
|
|
11
|
+
| | | | | | |
|
|
12
|
+
|
|
13
|
+
## How to Use This Template
|
|
14
|
+
|
|
15
|
+
1. **Record findings at wave close:** The orchestration monitor appends new rows for every machinery issue or systemic improvement identified.
|
|
16
|
+
2. **Mark status transitions:** When a recommendation is adopted (wave-N or PR reference), update Status to `ADOPTED wave-N`. For rejected items, mark `REJECTED wave-N` with brief rationale.
|
|
17
|
+
3. **Track implementation:** Use Status column to indicate OPEN (unactioned), IN-PROGRESS (wave-X, assigned to agent/owner), ADOPTED (implemented, wave-Y), or REJECTED (not pursued, wave-Y).
|
|
18
|
+
4. **Preserve history:** Never delete rows — the log is append-only. This creates an auditable trail for machinery decisions.
|
|
19
|
+
|
|
20
|
+
## Notes
|
|
21
|
+
|
|
22
|
+
- **Source field:** Where did this insight come from? (session coordinator, CI failure, agent forensics, monitor signal, PR review, etc.)
|
|
23
|
+
- **Severity:** HIGH = blocks reliable operation or impacts multiple waves; MED = worth addressing in near term; LOW = nice-to-have optimization.
|
|
24
|
+
- **Implementation scope:** Recommendations should be specific enough for a developer to act on, but can span multiple waves if complex.
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# Orchestration Refinement Proposals — Action Log
|
|
2
|
+
|
|
3
|
+
Actioned proposals moved from PROPOSALS.md (grounded in signals from YYYY-MM-DD). Per standing order, move decided entries here with date and outcome.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## ACCEPTED-IMPLEMENTED — YYYY-MM-DD
|
|
8
|
+
|
|
9
|
+
### 1. [Proposal Title]
|
|
10
|
+
|
|
11
|
+
**Outcome:** [Brief description of what was implemented, where code/docs changed, wave number if applicable, and verification of completion.]
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## IN-PROGRESS — YYYY-MM-DD
|
|
16
|
+
|
|
17
|
+
### 1. [Proposal Title]
|
|
18
|
+
|
|
19
|
+
**Status:** IN-PROGRESS (wave-N, [assigned-agent or owner])
|
|
20
|
+
**Rationale:** [Why this proposal was accepted and what timeline/dependencies exist.]
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## DEFERRED — YYYY-MM-DD
|
|
25
|
+
|
|
26
|
+
### 1. [Proposal Title]
|
|
27
|
+
|
|
28
|
+
**Status:** DEFERRED ([reason: blocked-by/low-priority/waiting-for-data])
|
|
29
|
+
**Rationale:** [Why this proposal was deferred, under what conditions it might be reconsidered.]
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
33
|
+
## REJECTED — YYYY-MM-DD
|
|
34
|
+
|
|
35
|
+
### 1. [Proposal Title]
|
|
36
|
+
|
|
37
|
+
**Status:** REJECTED (wave-N, [reason])
|
|
38
|
+
**Rationale:** [Explanation of rejection, any alternatives considered, and future implications.]
|
|
39
|
+
|
|
40
|
+
---
|
|
41
|
+
|
|
42
|
+
## No further action required (MONITORING ONGOING)
|
|
43
|
+
|
|
44
|
+
### 1. [Proposal Title]
|
|
45
|
+
|
|
46
|
+
**Status:** MONITORING
|
|
47
|
+
[Brief note on what is being tracked and how the team will know if action becomes necessary.]
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
## How to Use This Template
|
|
52
|
+
|
|
53
|
+
1. **Capture proposals:** When orchestration/monitor/coordinator identifies a potential process or machinery improvement, record it in a staging PROPOSALS.md file with date, source, and rationale.
|
|
54
|
+
2. **Move to log on decision:** Once a proposal is decided (ACCEPTED/REJECTED/DEFERRED), move the entry here with date and outcome.
|
|
55
|
+
3. **Track implementation:** Use status sections (ACCEPTED-IMPLEMENTED, IN-PROGRESS, DEFERRED, REJECTED) to organize proposals by lifecycle stage.
|
|
56
|
+
4. **Preserve history:** Keep all entries, do not delete. This creates an auditable trail of organizational decisions and learning.
|
|
57
|
+
5. **Link to execution:** When implemented, reference the wave number or PR. When in-progress, name the owner.
|
|
58
|
+
|
|
59
|
+
## Key Fields
|
|
60
|
+
|
|
61
|
+
- **Proposal Title:** Concise statement of the proposed change or investigation.
|
|
62
|
+
- **Outcome/Status:** What happened as a result (implemented, rejected, deferred, monitoring).
|
|
63
|
+
- **Rationale:** Why this decision was made, dependencies, or conditions for change.
|
|
64
|
+
- **Wave/PR/Agent:** Link to the work that carried out the decision (if applicable).
|
package/hooks/CLAUDE.md
CHANGED
|
@@ -30,6 +30,29 @@ Runs on `git push` via `.git/hooks/pre-push` symlink or copy.
|
|
|
30
30
|
- See `docs/HOOK-INSTALL.md` for symlink (Linux/macOS/Git Bash) and copy (Windows) methods
|
|
31
31
|
- Test with `bash hooks/pre-push-policy.sh --test` before org distribution
|
|
32
32
|
|
|
33
|
+
## Hook: hooks/claude/force-model-policy.mjs
|
|
34
|
+
|
|
35
|
+
Claude Code hook enforcing subagent Haiku dispatch (cost optimization).
|
|
36
|
+
|
|
37
|
+
**Trigger**: On skill invocation or task delegation from main orchestrator thread. Examines Claude API request and enforces model constraint.
|
|
38
|
+
|
|
39
|
+
**Policy**:
|
|
40
|
+
- **Main orchestrator** (Fable/Opus on primary): no override (uses native model)
|
|
41
|
+
- **Subagent dispatch** (fleet workers): **enforce Haiku** (claude-haiku-4-5-*). Exit 1 on non-Haiku model request.
|
|
42
|
+
- **Specialists** (typed dispatches): Pin model to Haiku in the dispatch call; hook validates + blocks if violated.
|
|
43
|
+
|
|
44
|
+
**Logging**:
|
|
45
|
+
- On policy violation: log to `state/SECURITY-ALERTS.log` with timestamp, model-name, worker-id, and reason.
|
|
46
|
+
- No alerts on compliant requests.
|
|
47
|
+
|
|
48
|
+
**Self-Test**:
|
|
49
|
+
- `node hooks/claude/force-model-policy.mjs --test` validates:
|
|
50
|
+
1. Haiku model allowed on subagents
|
|
51
|
+
2. Non-Haiku (e.g., Opus) blocked on subagents
|
|
52
|
+
3. Orchestrator not subject to policy
|
|
53
|
+
4. JSON logging format is valid
|
|
54
|
+
- Exit 0 = all pass; exit 1 = any fail
|
|
55
|
+
|
|
33
56
|
## Invariants
|
|
34
57
|
|
|
35
58
|
- POSIX sh compatible, CRLF-safe (no line continuations)
|
package/mcp/CLAUDE.md
ADDED
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
# mcp/ — Read-Only Fleet State MCP Server
|
|
2
|
+
|
|
3
|
+
**Purpose**: Expose Aesop fleet operational status as a Model Context Protocol (MCP) server for Claude Code and other MCP clients.
|
|
4
|
+
|
|
5
|
+
## Server
|
|
6
|
+
|
|
7
|
+
**File**: `server.mjs` — Stdio-transport MCP server implementing the JSON-RPC 2.0 protocol.
|
|
8
|
+
|
|
9
|
+
**Configuration**:
|
|
10
|
+
- `AESOP_ROOT` environment variable or `--root <path>` command-line flag (no hardcoded paths)
|
|
11
|
+
- `AESOP_STATE_ROOT` environment variable for state directory override (default: `AESOP_ROOT/state`)
|
|
12
|
+
- `AESOP_TRANSCRIPTS_ROOT` environment variable for transcript directory override (default: `~/.claude/projects`)
|
|
13
|
+
- Reads `aesop.config.json` from AESOP_ROOT for optional config file overrides
|
|
14
|
+
|
|
15
|
+
**Launch**:
|
|
16
|
+
```bash
|
|
17
|
+
node mcp/server.mjs [--root /path/to/aesop]
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
The server reads from stdin, writes JSON-RPC responses to stdout. Suitable for direct MCP integration or debugging via manual JSON-RPC frames.
|
|
21
|
+
|
|
22
|
+
## Tools
|
|
23
|
+
|
|
24
|
+
All tools are **strictly read-only**: no state mutations, no file writes, no shell-outs except the minimal dash-extra.mjs passthrough for fleet_agents.
|
|
25
|
+
|
|
26
|
+
### fleet_status
|
|
27
|
+
|
|
28
|
+
**Description**: Get fleet operational status — daemon heartbeats, monitor heartbeat, orchestrator activity, alert count.
|
|
29
|
+
|
|
30
|
+
**Input**: No arguments.
|
|
31
|
+
|
|
32
|
+
**Output** (JSON):
|
|
33
|
+
```json
|
|
34
|
+
{
|
|
35
|
+
"watchdog": {
|
|
36
|
+
"alive": "ALIVE" | "STALE",
|
|
37
|
+
"age_seconds": <bucketed>,
|
|
38
|
+
"threshold_seconds": 300
|
|
39
|
+
},
|
|
40
|
+
"monitor": {
|
|
41
|
+
"alive": "ALIVE" | "STALE",
|
|
42
|
+
"age_seconds": <bucketed>,
|
|
43
|
+
"threshold_seconds": 3600
|
|
44
|
+
},
|
|
45
|
+
"orchestrator": <parsed orchestrator-status.json> or null,
|
|
46
|
+
"alerts": {
|
|
47
|
+
"count": <int>,
|
|
48
|
+
"sample_lines": [<last 3 unreviewed lines>]
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
**Missing files**: If a file doesn't exist, the corresponding field is `null`. The response never crashes; missing state files are reported gracefully with `absent` markers where applicable.
|
|
54
|
+
|
|
55
|
+
### fleet_agents
|
|
56
|
+
|
|
57
|
+
**Description**: List active Claude agents from transcript directory. Invokes `dash-extra.mjs --json` with environment variables for path portability.
|
|
58
|
+
|
|
59
|
+
**Input**: No arguments.
|
|
60
|
+
|
|
61
|
+
**Output** (JSON):
|
|
62
|
+
```json
|
|
63
|
+
{
|
|
64
|
+
"absent": <bool>,
|
|
65
|
+
"agents": [
|
|
66
|
+
{
|
|
67
|
+
"project": <string>,
|
|
68
|
+
"taskLabel": <string>,
|
|
69
|
+
"promptFull": <string>,
|
|
70
|
+
"runtimeSeconds": <int>,
|
|
71
|
+
"tokensUsed": <int>,
|
|
72
|
+
"startedAt": <ISO string>,
|
|
73
|
+
"lastActivity": <ISO string>
|
|
74
|
+
},
|
|
75
|
+
...
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
**Design notes**:
|
|
81
|
+
- Passes through `dash-extra.mjs --json` output (no reimplementation).
|
|
82
|
+
- Timeout: 5 seconds. On timeout or error, returns empty agents list.
|
|
83
|
+
- Environment variables (`AESOP_ROOT`, `AESOP_STATE_ROOT`, `AESOP_TRANSCRIPTS_ROOT`) are set before invoking dash-extra to ensure portable transcript discovery.
|
|
84
|
+
|
|
85
|
+
### fleet_tracker
|
|
86
|
+
|
|
87
|
+
**Description**: Get fleet work items from `tracker.json`, grouped by lane.
|
|
88
|
+
|
|
89
|
+
**Input**: No arguments.
|
|
90
|
+
|
|
91
|
+
**Output** (JSON):
|
|
92
|
+
```json
|
|
93
|
+
{
|
|
94
|
+
"absent": <bool>,
|
|
95
|
+
"by_lane": {
|
|
96
|
+
"ranked": [
|
|
97
|
+
{
|
|
98
|
+
"id": <string>,
|
|
99
|
+
"title": <string>,
|
|
100
|
+
"priority": "P0" | "P1" | "P2",
|
|
101
|
+
"status": "todo" | "in-progress" | "done",
|
|
102
|
+
"tags": [<string>, ...]
|
|
103
|
+
},
|
|
104
|
+
...
|
|
105
|
+
],
|
|
106
|
+
"in-progress": [ ... ],
|
|
107
|
+
"done": [ ... ],
|
|
108
|
+
...
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
**Lanes**: Each lane is optional and present only if items exist in it. Common lanes: `ranked`, `proposed`, `in-progress`, `done`.
|
|
114
|
+
|
|
115
|
+
### fleet_cost
|
|
116
|
+
|
|
117
|
+
**Description**: Get per-model token usage totals from the fleet outcomes ledger (`state/ledger/OUTCOMES-LEDGER.md`).
|
|
118
|
+
|
|
119
|
+
**Input**: No arguments.
|
|
120
|
+
|
|
121
|
+
**Output** (JSON):
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"absent": <bool>,
|
|
125
|
+
"by_model": {
|
|
126
|
+
"claude-haiku-4": {
|
|
127
|
+
"tokens_in": <int>,
|
|
128
|
+
"tokens_out": <int>,
|
|
129
|
+
"total_tokens": <int>,
|
|
130
|
+
"count": <int>
|
|
131
|
+
},
|
|
132
|
+
"claude-opus": { ... },
|
|
133
|
+
...
|
|
134
|
+
},
|
|
135
|
+
"total_tokens_in": <int>,
|
|
136
|
+
"total_tokens_out": <int>
|
|
137
|
+
}
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Design notes**:
|
|
141
|
+
- Parses markdown table rows from the ledger file.
|
|
142
|
+
- Reports **token counts only** — no invented dollar figures.
|
|
143
|
+
- Gracefully handles missing or malformed lines (skips with no error).
|
|
144
|
+
|
|
145
|
+
## MCP Integration
|
|
146
|
+
|
|
147
|
+
### Claude Code (claude.json)
|
|
148
|
+
|
|
149
|
+
To register the server in Claude Code:
|
|
150
|
+
|
|
151
|
+
```json
|
|
152
|
+
{
|
|
153
|
+
"mcp": {
|
|
154
|
+
"aesop-fleet": {
|
|
155
|
+
"command": "node",
|
|
156
|
+
"args": [
|
|
157
|
+
"/path/to/aesop/mcp/server.mjs",
|
|
158
|
+
"--root",
|
|
159
|
+
"/path/to/aesop"
|
|
160
|
+
],
|
|
161
|
+
"env": {
|
|
162
|
+
"AESOP_ROOT": "/path/to/aesop"
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### Portable Setup
|
|
170
|
+
|
|
171
|
+
For portable configuration (no hardcoded user paths), use environment variables:
|
|
172
|
+
|
|
173
|
+
```bash
|
|
174
|
+
export AESOP_ROOT=/path/to/aesop
|
|
175
|
+
export AESOP_STATE_ROOT=/path/to/state # optional override
|
|
176
|
+
export AESOP_TRANSCRIPTS_ROOT=/path/to/transcripts # optional override
|
|
177
|
+
node /path/to/aesop/mcp/server.mjs
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
Or use the `--root` flag:
|
|
181
|
+
|
|
182
|
+
```bash
|
|
183
|
+
node /path/to/aesop/mcp/server.mjs --root /path/to/aesop
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Invariants & Guarantees
|
|
187
|
+
|
|
188
|
+
1. **Strictly read-only**: All tools are read-only. Zero state mutations, zero file writes.
|
|
189
|
+
2. **No shell execution** (except dash-extra.mjs invocation with timeout): Minimizes surface area for injection or performance issues.
|
|
190
|
+
3. **Graceful degradation**: Missing state files → empty results with `absent: true` markers, never a crash.
|
|
191
|
+
4. **No external dependencies**: Plain Node.js (no npm packages). Server.mjs uses only stdlib modules: `fs`, `path`, `os`, `child_process`, `readline`.
|
|
192
|
+
5. **JSON-RPC 2.0 compliant**: Standard request/response format with proper error codes.
|
|
193
|
+
6. **Portable paths**: All paths resolved from AESOP_ROOT, AESOP_STATE_ROOT, AESOP_TRANSCRIPTS_ROOT env vars or config file. No hardcoded paths like `/home/user/aesop`.
|
|
194
|
+
|
|
195
|
+
## Testing
|
|
196
|
+
|
|
197
|
+
See `tests/mcp-fleet.test.mjs` for end-to-end tests:
|
|
198
|
+
- Spawn server over stdio
|
|
199
|
+
- Drive JSON-RPC initialize + tools/list + tools/call round-trips
|
|
200
|
+
- Validate read-only behavior (no state mutations after calls)
|
|
201
|
+
- Verify fixture isolation (temp state root)
|
|
202
|
+
|
|
203
|
+
Run:
|
|
204
|
+
```bash
|
|
205
|
+
npm test # or
|
|
206
|
+
node tests/mcp-fleet.test.mjs
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## Files
|
|
210
|
+
|
|
211
|
+
- **server.mjs** — Main MCP server implementation (stdio, JSON-RPC 2.0)
|
|
212
|
+
- **package.json** — Minimal metadata; no external dependencies
|
|
213
|
+
- **CLAUDE.md** — This file
|
package/mcp/package.json
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "aesop-fleet-mcp",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Read-only MCP server for Aesop fleet state (heartbeats, agents, tracker, costs)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "server.mjs",
|
|
7
|
+
"bin": {
|
|
8
|
+
"aesop-fleet": "server.mjs"
|
|
9
|
+
},
|
|
10
|
+
"scripts": {
|
|
11
|
+
"start": "node server.mjs",
|
|
12
|
+
"start:root": "node server.mjs --root .."
|
|
13
|
+
},
|
|
14
|
+
"keywords": [
|
|
15
|
+
"mcp",
|
|
16
|
+
"model-context-protocol",
|
|
17
|
+
"orchestration",
|
|
18
|
+
"aesop"
|
|
19
|
+
],
|
|
20
|
+
"author": "Anthropic",
|
|
21
|
+
"license": "MIT",
|
|
22
|
+
"dependencies": {},
|
|
23
|
+
"engines": {
|
|
24
|
+
"node": ">=18.0.0"
|
|
25
|
+
}
|
|
26
|
+
}
|