kodelyth-ecc 1.8.0 → 1.8.2

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.
Files changed (91) hide show
  1. package/CLAUDE.md +1 -1
  2. package/VERSION +1 -1
  3. package/bin/kodelyth-ecc.js +54 -5
  4. package/install.ps1 +30 -13
  5. package/install.sh +11 -4
  6. package/package.json +1 -1
  7. package/rules/common/agent-intent-routing.md +96 -195
  8. package/.github/ISSUE_TEMPLATE/bug_report.md +0 -47
  9. package/.github/ISSUE_TEMPLATE/config.yml +0 -8
  10. package/.github/ISSUE_TEMPLATE/feature_request.md +0 -41
  11. package/.github/ISSUE_TEMPLATE/good_first_issue.md +0 -36
  12. package/.github/ISSUE_TEMPLATE/new_agent.md +0 -52
  13. package/.github/PULL_REQUEST_TEMPLATE.md +0 -53
  14. package/.github/workflows/ci.yml +0 -45
  15. package/.github/workflows/publish.yml +0 -60
  16. package/brand/concepts.svg +0 -109
  17. package/brand/convert.js +0 -161
  18. package/brand/favicon.svg +0 -7
  19. package/brand/fb-cover.svg +0 -34
  20. package/brand/fb-profile.svg +0 -21
  21. package/brand/kodelyth-dark.svg +0 -24
  22. package/brand/kodelyth-light.svg +0 -24
  23. package/brand/kodelyth-mark.svg +0 -20
  24. package/brand/package.json +0 -12
  25. package/docs/dashboard.md +0 -211
  26. package/docs/evolve.md +0 -303
  27. package/docs/mcp-clients.md +0 -167
  28. package/docs/mcp.md +0 -178
  29. package/docs/replay.md +0 -244
  30. package/docs/supply-chain.md +0 -207
  31. package/docs/swarm.md +0 -243
  32. package/skills/skill-comply/tests/test_grader.py +0 -137
  33. package/skills/skill-comply/tests/test_parser.py +0 -90
  34. package/social/card-agents.svg +0 -104
  35. package/social/card-install.svg +0 -58
  36. package/social/card-main.svg +0 -54
  37. package/social/facebook-v150.svg +0 -110
  38. package/social/fb-ad-main.svg +0 -128
  39. package/social/fb-post-features.svg +0 -118
  40. package/social/fb-post-launch.svg +0 -144
  41. package/social/fb-post-platforms.svg +0 -135
  42. package/social/github-social-preview.svg +0 -151
  43. package/social/hype-compound-learning.svg +0 -129
  44. package/social/hype-devil-mode.svg +0 -240
  45. package/social/hype-mcp-server.svg +0 -148
  46. package/social/hype-parallel-agents.svg +0 -162
  47. package/social/hype-stats-hero.svg +0 -138
  48. package/social/og-image.svg +0 -151
  49. package/social/readme-agents.svg +0 -138
  50. package/social/readme-hero.svg +0 -102
  51. package/social/section-agents.svg +0 -69
  52. package/social/section-author.svg +0 -66
  53. package/social/section-dashboard.svg +0 -71
  54. package/social/section-devil.svg +0 -66
  55. package/social/section-hooks.svg +0 -63
  56. package/social/section-install.svg +0 -54
  57. package/social/section-learning.svg +0 -64
  58. package/social/section-mcp.svg +0 -58
  59. package/social/section-memory.svg +0 -69
  60. package/social/section-parallel.svg +0 -84
  61. package/social/section-routing.svg +0 -63
  62. package/social/twitter-threads.md +0 -621
  63. package/social/x-card-agents-grid.svg +0 -120
  64. package/social/x-card-free.svg +0 -71
  65. package/social/x-card-hook.svg +0 -94
  66. package/tests/dashboard/data.test.js +0 -391
  67. package/tests/dashboard/server.test.js +0 -257
  68. package/tests/evolve/analyze.test.js +0 -169
  69. package/tests/evolve/proposals.test.js +0 -173
  70. package/tests/evolve/stats.test.js +0 -167
  71. package/tests/hooks/branch-name-check.test.js +0 -184
  72. package/tests/hooks/smart-suggest.test.js +0 -149
  73. package/tests/hooks/test-reminder.test.js +0 -181
  74. package/tests/mcp/catalog.test.js +0 -98
  75. package/tests/mcp/client.test.js +0 -113
  76. package/tests/mcp/resources-prompts.test.js +0 -70
  77. package/tests/mcp/tools.test.js +0 -159
  78. package/tests/memory/auto-recall.test.js +0 -132
  79. package/tests/memory/instincts.test.js +0 -258
  80. package/tests/memory/store.test.js +0 -203
  81. package/tests/replay/bundle.test.js +0 -181
  82. package/tests/replay/replay.test.js +0 -131
  83. package/tests/router/classify.test.js +0 -164
  84. package/tests/run-all.js +0 -55
  85. package/tests/safety/patterns.test.js +0 -94
  86. package/tests/safety/prompt-injection-guard.test.js +0 -111
  87. package/tests/safety/token-budget.test.js +0 -119
  88. package/tests/supply-chain/manifest.test.js +0 -147
  89. package/tests/supply-chain/sbom.test.js +0 -170
  90. package/tests/supply-chain/verify.test.js +0 -146
  91. package/tests/swarm/build-plan.test.js +0 -188
package/docs/dashboard.md DELETED
@@ -1,211 +0,0 @@
1
- # Local observability dashboard
2
-
3
- > A localhost-only single-page web UI that renders every local data source Kodelyth ECC produces. Zero telemetry. Zero external runtime dependencies. Read-only.
4
-
5
- ---
6
-
7
- ## Why it exists
8
-
9
- ECC produces a lot of local state by default:
10
-
11
- - BM25 memory captures (`~/.kodelyth/memory/`)
12
- - Self-evolving memory signals + proposals (`~/.kodelyth/evolve/`)
13
- - Token-budget hook state (`~/.kodelyth/token-budget/`)
14
- - Swarm/orchestration session dirs (`.orchestration/<session>/`)
15
- - The full catalog of shipped agents / skills / commands / rules / bundles
16
-
17
- The only way to see all of this was to read JSON files by hand or run six different CLI subcommands. The dashboard is the one-glance answer.
18
-
19
- ---
20
-
21
- ## Boot
22
-
23
- ```bash
24
- npx kodelyth-ecc dashboard # default: 127.0.0.1:5747, auto-opens browser
25
- npx kodelyth-ecc dashboard --port 8088 # custom port
26
- npx kodelyth-ecc dashboard --no-open # don't auto-open browser (CI / remote shells)
27
- npx kodelyth-ecc dashboard --host localhost # explicit localhost binding
28
- ```
29
-
30
- Press `Ctrl+C` to stop. The server has no daemon mode by design — it lives only as long as your terminal session.
31
-
32
- ---
33
-
34
- ## Localhost lock
35
-
36
- The dashboard exposes everything the BM25 store and evolve log have ever recorded. Memories may contain code, problem statements, project paths, gotchas. The default bind is `127.0.0.1` and the server **refuses** to start on any other interface unless you explicitly opt out:
37
-
38
- ```bash
39
- KODELYTH_DASHBOARD_ALLOW_REMOTE=1 \
40
- npx kodelyth-ecc dashboard --host 0.0.0.0
41
- ```
42
-
43
- This escape hatch is intentionally inconvenient. Don't use it on a network you don't fully control.
44
-
45
- Without the env var, attempting any non-localhost host produces:
46
-
47
- ```
48
- [dashboard] refusing to bind host=0.0.0.0. Dashboard is localhost-only by default.
49
- To override (UNSAFE — exposes your memory + evolve data), set KODELYTH_DASHBOARD_ALLOW_REMOTE=1.
50
- ```
51
-
52
- ---
53
-
54
- ## What you see
55
-
56
- ### Overview tab
57
-
58
- A wall of stat cards: agents · skills · commands · rules · bundles · captured memories · surfaces · routing misses · pending proposals · swarm sessions. Plus storage paths and a token-budget snapshot.
59
-
60
- ### Memory tab
61
-
62
- - Stats: total / projects / language count / tag classes
63
- - BM25 search box (proxies through `/api/memory/search`)
64
- - Recent captures table with tags + source
65
-
66
- ### Evolve tab
67
-
68
- - Reuse + miss + proposal counts
69
- - Top 10 reused memories with surface count and last-seen
70
- - Top 10 miss clusters with token tags and a sample prompt
71
- - Proposals table with status pills (`pending` / `accepted` / `rejected` / `applied`)
72
-
73
- ### Catalog tab
74
-
75
- - Selector for agents / skills / commands / rules / bundles
76
- - Free-text filter across name, description, tags
77
- - Tabular results with up to 200 entries per page
78
-
79
- ### Sessions tab
80
-
81
- - Lists every swarm session in `.orchestration/`
82
- - Per-session: workers, modified time, expandable detail with `task.md` + `handoff.md` + `status.md` excerpts
83
-
84
- ---
85
-
86
- ## API surface
87
-
88
- The frontend is just a consumer of these endpoints. They're curl-friendly:
89
-
90
- | Endpoint | Returns |
91
- |---|---|
92
- | `GET /api/health` | `{ ok: true, time: <iso> }` — liveness probe |
93
- | `GET /api/overview` | counts + storage paths |
94
- | `GET /api/memory[?limit=N]` | `{ stats, recent }` |
95
- | `GET /api/memory/search?q=…[&limit=N]` | `{ query, results }` |
96
- | `GET /api/evolve[?limit=N]` | `{ reuse, miss, proposals }` |
97
- | `GET /api/catalog?kind=…[&q=…&limit=N]` | `{ kind, counts, items }` (kind ∈ agents/skills/commands/rules/bundles) |
98
- | `GET /api/sessions[?limit=N]` | `{ sessions }` |
99
- | `GET /api/sessions/:name` | `{ session, path, workers }` |
100
- | `GET /api/token-budget` | `{ sessions, total_tokens }` |
101
-
102
- ### Examples
103
-
104
- ```bash
105
- # Last 5 captured memories
106
- curl -s http://127.0.0.1:5747/api/memory?limit=5 | jq '.recent'
107
-
108
- # Search memory for "tailwind v4"
109
- curl -s 'http://127.0.0.1:5747/api/memory/search?q=tailwind+v4' | jq '.results'
110
-
111
- # Pending proposals
112
- curl -s http://127.0.0.1:5747/api/evolve | jq '.proposals[] | select(.status == "pending")'
113
-
114
- # All agents whose tags include "security"
115
- curl -s 'http://127.0.0.1:5747/api/catalog?kind=agents&q=security'
116
- ```
117
-
118
- ---
119
-
120
- ## Hard rules (enforced by the server)
121
-
122
- 1. **GET-only.** Any other method returns `405 method not allowed`. The dashboard CANNOT mutate state.
123
- 2. **Localhost lock.** Non-localhost binds refused without `KODELYTH_DASHBOARD_ALLOW_REMOTE=1`.
124
- 3. **Path-traversal-safe.** Static file resolution is sandboxed under `scripts/dashboard/static/`. `../` and similar are rejected.
125
- 4. **No cache.** Every response carries `Cache-Control: no-store`. Data is always fresh.
126
- 5. **Hardened headers.** `X-Frame-Options: DENY`, `X-Content-Type-Options: nosniff`, `Referrer-Policy: no-referrer` on every response.
127
- 6. **No external assets.** No CDNs, no Google Fonts, no analytics. Works fully offline.
128
- 7. **Defensive aggregation.** Every data-source read is wrapped in try/catch with empty-default fallback. A broken memory store renders empty cards, never a 500.
129
-
130
- ---
131
-
132
- ## Architecture
133
-
134
- ```
135
- scripts/dashboard/
136
- ├── server.js ← HTTP server. Routes API + static files.
137
- ├── data.js ← Pure aggregators. Reads memory + evolve + catalog + sessions + budget.
138
- └── static/
139
- └── index.html ← Single-page UI. Hand-rolled CSS + vanilla JS. No build step.
140
- ```
141
-
142
- ### `data.js`
143
-
144
- Pure functions only. Every aggregator:
145
-
146
- - Accepts its data-source paths as explicit arguments OR uses well-defined env-overridable defaults
147
- - Returns sane empty defaults on failure (never throws)
148
- - Has no global mutable state
149
- - Is unit-testable in isolation
150
-
151
- ### `server.js`
152
-
153
- Uses only Node built-ins:
154
-
155
- - `http` for the listener
156
- - `fs`, `path` for static files
157
- - `child_process.execFileSync` for browser auto-open (`open` / `xdg-open` / `cmd /c start`) — no shell interpolation
158
-
159
- No `express`, no `koa`, no third-party static-file middleware. All hardening is hand-rolled and auditable in ~290 lines.
160
-
161
- ### `index.html`
162
-
163
- - Hand-rolled CSS (no Tailwind, no CDN)
164
- - Vanilla JS with `fetch` → no build step, no transpilation
165
- - Tabs are simple data-attribute toggles
166
- - Lazy-loads each tab's data only when shown
167
- - SSE (`/api/events`) pushes `data-changed` events when watched files change; a `heartbeat` every 10 s keeps the green dot alive without triggering data reloads
168
-
169
- ---
170
-
171
- ## Worked example
172
-
173
- ```bash
174
- $ npx kodelyth-ecc dashboard --port 5747
175
- ✓ Kodelyth ECC dashboard
176
- http://127.0.0.1:5747/
177
- Press Ctrl+C to stop. Localhost only — zero telemetry.
178
- ```
179
-
180
- In another shell:
181
-
182
- ```bash
183
- $ curl -s http://127.0.0.1:5747/api/overview | jq '.catalog'
184
- {
185
- "agents": 70,
186
- "skills": 193,
187
- "commands": 96,
188
- "rules": 14,
189
- "bundles": 3
190
- }
191
- ```
192
-
193
- ---
194
-
195
- ## Composition with other features
196
-
197
- | Feature | Effect on the dashboard |
198
- |---|---|
199
- | **Memory store** | Source of the Memory tab. |
200
- | **Swarm orchestrator** | Source of the Sessions tab. |
201
- | **Token-budget hook** | Source of the budget snapshot card. |
202
- | **Self-evolving memory** | Source of the Evolve tab. Proposals appear automatically as they're generated. |
203
-
204
- ---
205
-
206
- ## See also
207
-
208
- - `skills/observability-dashboard/SKILL.md` — explicit-invocation skill
209
- - `commands/dashboard.md` — `/dashboard` slash command
210
- - `scripts/dashboard/{server,data}.js` — implementation
211
- - `tests/dashboard/` — aggregator + server smoke tests
package/docs/evolve.md DELETED
@@ -1,303 +0,0 @@
1
- # Self-evolving memory
2
-
3
- > Phase 3.4 of the Devil Roadmap. Closes the learning loop on the BM25 memory system. Repeated memory hits become draft skills. Repeated routing misses become proposed routing-rule additions. Nothing is ever auto-applied.
4
-
5
- ---
6
-
7
- ## Why this exists
8
-
9
- ECC already has:
10
-
11
- - A BM25 memory store (`scripts/memory/store.js`)
12
- - An auto-recall hook that surfaces relevant memories on every `UserPromptSubmit`
13
-
14
- What it didn't have, until 3.4: a way for those signals to feed back into the toolkit's own structure. If the same memory keeps getting surfaced across sessions, that memory is doing real work — it should graduate to a `SKILL.md`. If users keep submitting prompts that match no memory at all, that's a routing gap — the routing rule should grow.
15
-
16
- The 3.4 surface formalizes both loops while preserving the **never auto-commit** rule.
17
-
18
- ---
19
-
20
- ## Two signal streams
21
-
22
- ### 1. Memory reuse (→ skill-upgrade proposals)
23
-
24
- Every time `auto-recall.js` surfaces a memory to the user, it bumps a counter:
25
-
26
- ```jsonc
27
- // ~/.kodelyth/evolve/reuse.json
28
- {
29
- "byMemory": {
30
- "<memoryId>": {
31
- "count": 7,
32
- "sessions": ["s1", "s2", "s3", ...],
33
- "projects": ["/path/to/proj-a", "/path/to/proj-b"],
34
- "firstSurfaced": "2026-04-30T...",
35
- "lastSurfaced": "2026-05-10T..."
36
- }
37
- },
38
- "lastUpdated": "2026-05-10T..."
39
- }
40
- ```
41
-
42
- Counter semantics:
43
-
44
- - **Per-memory, per-session**: surfacing the same memory ten times in one session counts ONCE. Matches the existing "never re-surface the same memory twice in a session" rule of `auto-recall.js`.
45
- - **Cross-session**: each fresh session bumps the count by exactly one.
46
- - **Idempotent**: replaying a session does not double-count.
47
-
48
- Default threshold: count ≥ 3 AND sessions ≥ 2 → eligible for skill-upgrade proposal.
49
-
50
- ### 2. Routing misses (→ routing-addition proposals)
51
-
52
- When `shouldRecall(prompt)` is true (substantive prompt, ≥12 chars, ≥2 meaningful tokens, not a slash command) AND BM25 recall returns zero matches, the prompt is logged:
53
-
54
- ```jsonl
55
- // ~/.kodelyth/evolve/routing-misses.jsonl (append-only)
56
- {"hash":"abc...","prompt":"...","tokens":["..."],"session_id":"...","project":"...","recorded_at":"..."}
57
- ```
58
-
59
- Stored prompts are capped at 1000 chars. Top tokens are extracted at write time so analysis is cheap.
60
-
61
- Default threshold: cluster count ≥ 3 AND distinct prompts ≥ 2 → eligible for routing-addition proposal.
62
-
63
- ---
64
-
65
- ## CLI
66
-
67
- ### `kodelyth-ecc evolve stats`
68
-
69
- Snapshot of recorded signals. No proposals generated.
70
-
71
- ```
72
- Kodelyth ECC — self-evolving memory stats
73
- reuse:
74
- memories tracked: 14
75
- total surfaces: 42
76
- last updated: 2026-05-10T17:23:00.000Z
77
- top reused:
78
- • efe17d650917e445 count=7 sessions=5
79
- • a91ce2034d8b1234 count=5 sessions=4
80
- routing misses:
81
- total: 18
82
- unique prompts: 11
83
- top clusters:
84
- • count=4 tokens=[feature, flag, gradual, rollout]
85
- • count=3 tokens=[migration, postgres, downtime, zero]
86
- ```
87
-
88
- ### `kodelyth-ecc evolve analyze`
89
-
90
- Apply thresholds and write proposals. Idempotent — same evidence produces the same proposal ID, so re-running never duplicates.
91
-
92
- | Flag | Default | Effect |
93
- |---|---|---|
94
- | `--reuse-min N` | 3 | minimum total surface count |
95
- | `--reuse-min-sessions N` | 2 | minimum distinct sessions |
96
- | `--miss-min N` | 3 | minimum miss-cluster total |
97
- | `--miss-min-distinct N` | 2 | minimum distinct prompts in cluster |
98
- | `--json` | off | full report instead of pretty summary |
99
-
100
- ### `kodelyth-ecc evolve list [--status pending|accepted|rejected|applied]`
101
-
102
- Show proposals. Filter by status. Pretty output uses ⏸ ✓ ✗ ★ marks for the four states.
103
-
104
- ### `kodelyth-ecc evolve show <id>`
105
-
106
- Print the full proposed file content + evidence. **Always preview before accepting.**
107
-
108
- ### `kodelyth-ecc evolve accept <id> [--root DIR] [--overwrite]`
109
-
110
- Write the proposed `diff` to its `target_path` under `--root`. Refuses to overwrite an existing file unless `--overwrite` is explicit. Marks the proposal `accepted` with the absolute `applied_path` written to the audit trail.
111
-
112
- **The CLI does not stage, does not commit, does not push.** Review the draft, edit, commit by hand.
113
-
114
- ### `kodelyth-ecc evolve reject <id> [--note "..."]`
115
-
116
- Mark a proposal `rejected`. The optional `--note` is preserved in the audit trail for future reference.
117
-
118
- ---
119
-
120
- ## Proposal anatomy
121
-
122
- Both proposal kinds share a structure:
123
-
124
- ```jsonc
125
- {
126
- "id": "skill-2537cb787a", // deterministic over evidence
127
- "type": "skill-upgrade", // or "routing-addition"
128
- "evidence": {
129
- "memoryId": "efe17d650917e445",
130
- "reuseCount": 7,
131
- "sessions": ["s1", "s2", "s3", "s4", "s5"],
132
- "firstSurfaced": "...",
133
- "lastSurfaced": "..."
134
- },
135
- "proposal": {
136
- "kind": "create-skill", // or "add-routing-entry"
137
- "target_path": "skills/<slug>/SKILL.md", // for skill-upgrade
138
- "diff": "<full markdown content>",
139
- "rationale": "Memory '...' surfaced 7x across 5 sessions ..."
140
- },
141
- "status": "pending", // pending | accepted | rejected | applied
142
- "created_at": "...",
143
- "timestamp": "...",
144
- "applied_path": null // set on accept
145
- }
146
- ```
147
-
148
- ### Skill-upgrade diff (sample)
149
-
150
- ```markdown
151
- ---
152
- name: <slug-from-problem>
153
- description: <problem text> (auto-derived from memory <id> after repeated reuse)
154
- origin: kodelyth-evolve
155
- language: typescript
156
- tags:
157
- - <memory tags>
158
- ---
159
-
160
- # Skill: <slug>
161
-
162
- > **Auto-derived draft.** Generated by `kodelyth-ecc evolve` after this memory
163
- > was surfaced repeatedly across multiple sessions. Review, refine, and rename
164
- > before committing.
165
-
166
- ## Problem
167
- <memory.problem>
168
-
169
- ## Approach
170
- <memory.approach>
171
-
172
- ## Gotchas
173
- <memory.gotchas if any>
174
-
175
- ## When to invoke
176
- _Replace this section with explicit trigger conditions._
177
-
178
- ## Origin
179
- - Memory id: `<id>`
180
- - Captured at: <timestamp>
181
- - Auto-promoted by Phase 3.4 self-evolving memory.
182
- ```
183
-
184
- ### Routing-addition diff (sample)
185
-
186
- ```markdown
187
- <!-- proposed addition to rules/common/agent-intent-routing.md -->
188
- <!-- review by hand, decide on tier + agent, then merge -->
189
-
190
- ### TODO-agent — covers prompts about <token>, <token>, <token>
191
-
192
- Trigger if the user mentions `<t1>`, `<t2>`, `<t3>`.
193
-
194
- | Signal | Real human phrasing |
195
- |---|---|
196
- | repeated unrouted prompt cluster | <tokens> |
197
-
198
- **Origin:** Phase 3.4 self-evolving memory — N prompts in this cluster were
199
- submitted with no memory match and (presumably) no specialist routing.
200
-
201
- Recent samples:
202
- - "<sample 1>"
203
- - "<sample 2>"
204
- - "<sample 3>"
205
-
206
- _(Pick the right tier in `rules/common/agent-intent-routing.md` before merging.
207
- Do NOT commit this block as-is — replace `TODO-agent` with the real agent name
208
- and slot under the correct priority tier.)_
209
- ```
210
-
211
- The `TODO-agent` placeholder is intentional. Even if you accept and commit verbatim, the rule won't route any real traffic — it's a no-op until you fill in the agent name.
212
-
213
- ---
214
-
215
- ## Storage layout
216
-
217
- ```
218
- ~/.kodelyth/evolve/ ← override with $KODELYTH_EVOLVE_DIR
219
- ├── reuse.json ← per-memory reuse counters
220
- ├── routing-misses.jsonl ← append-only miss log
221
- └── proposals.jsonl ← append-only proposal events
222
- ```
223
-
224
- `proposals.jsonl` is append-only. Every state transition is a new event. Reading collapses to "latest state per id" while preserving the full history for audit.
225
-
226
- ---
227
-
228
- ## Worked example
229
-
230
- ```bash
231
- # 1) Use ECC normally for a few weeks. The auto-recall hook records signals.
232
- # 2) Eventually run:
233
- $ npx kodelyth-ecc evolve stats
234
- ... shows current signal volume ...
235
-
236
- # 3) Generate proposals.
237
- $ npx kodelyth-ecc evolve analyze
238
- ✓ analyzed signals
239
- reuse entries scanned: 14
240
- miss entries scanned: 11
241
- proposals generated: 3
242
- new proposals (added): 3
243
-
244
- Run 'kodelyth-ecc evolve list' to review.
245
-
246
- # 4) See what's pending.
247
- $ npx kodelyth-ecc evolve list
248
- Kodelyth ECC — self-evolving memory proposals (3)
249
- ⏸ [pending] skill-2537cb787a skill-upgrade
250
- target: skills/tailwind-v4-arbitrary-values/SKILL.md
251
- why: Memory '...' surfaced 7x across 5 sessions ...
252
- ⏸ [pending] route-13d976a554 routing-addition
253
- target: rules/common/agent-intent-routing.md
254
- why: 4 substantive prompts (4 distinct) clustered on tokens [...]
255
-
256
- # 5) Inspect the skill draft.
257
- $ npx kodelyth-ecc evolve show skill-2537cb787a
258
- ... full markdown + evidence ...
259
-
260
- # 6) Accept it. Writes to disk. NEVER commits.
261
- $ npx kodelyth-ecc evolve accept skill-2537cb787a
262
- ✓ accepted skill-2537cb787a
263
- draft written: /path/to/repo/skills/tailwind-v4-arbitrary-values/SKILL.md
264
-
265
- Review the draft. When you're happy with it, commit it.
266
-
267
- # 7) Reject the routing one — already covered.
268
- $ npx kodelyth-ecc evolve reject route-13d976a554 --note "covered by debug-detective"
269
- ✗ rejected route-13d976a554 (note: covered by debug-detective)
270
- ```
271
-
272
- ---
273
-
274
- ## Hard rules
275
-
276
- 1. **NEVER auto-apply.** `accept` writes a draft. The user reviews, edits, commits.
277
- 2. **NEVER overwrite without `--overwrite`.** Even on accept of a stale proposal.
278
- 3. **NEVER block the recall hook.** All evolve recording is wrapped in try/catch and lazy-required.
279
- 4. **NEVER auto-route a `TODO-agent` proposal.** The placeholder is intentional.
280
- 5. **Idempotent IDs.** Stable evidence → stable proposal ID. Re-running `analyze` never duplicates.
281
- 6. **Append-only proposal log.** Every state change is a new event. Full audit trail preserved.
282
-
283
- ---
284
-
285
- ## Composition with other phases
286
-
287
- | Pair | Effect |
288
- |---|---|
289
- | BM25 memory store | Source of reuse signals. |
290
- | `/memory remember` | Manually captured memories that get reused → skill proposals. |
291
- | `rules/common/agent-intent-routing.md` | Direct target for routing-addition proposals. |
292
- | Phase 2.7 swarm | Repeated swarm tasks reusing the same memories → those memories become skills the swarm picker can choose automatically. |
293
- | Phase 2.8 replay | Replay bundles re-trigger reuse signals when the same memory is surfaced again. |
294
- | Phase 2.10 token-budget hook | Promoting memories → skills means cheaper recalls. |
295
-
296
- ---
297
-
298
- ## See also
299
-
300
- - `skills/self-evolving-memory/SKILL.md` — explicit-invocation skill
301
- - `commands/memory-evolve.md` — `/memory-evolve` slash command
302
- - `scripts/evolve/{stats,analyze,proposals}.js` — pure-function implementation
303
- - `hooks/memory/auto-recall.js` — signal capture (Phase 3.4 augmentation)
@@ -1,167 +0,0 @@
1
- # Kodelyth ECC — MCP Client Mode
2
-
3
- The other half of the MCP story. While `npx kodelyth-ecc mcp` (Phase 2.1) **serves** ECC to any MCP-compatible client, MCP client mode lets ECC **consume** any external MCP server — Stripe, GitHub, Postgres, Redis, Brave, Filesystem, Shopify, Sentry, anything.
4
-
5
- > **Phase 2.5 of the [Devil Roadmap](../README.md).** This makes ECC the MCP **hub**, not just a node. Local-only registry. Zero telemetry. Same SDK as the server side.
6
-
7
- ---
8
-
9
- ## Quick start
10
-
11
- ### 1. Register an external MCP server
12
-
13
- ```bash
14
- # Public servers (no env vars needed)
15
- npx kodelyth-ecc mcp-add brave -- npx -y @modelcontextprotocol/server-brave-search
16
- npx kodelyth-ecc mcp-add filesystem -- npx -y @modelcontextprotocol/server-filesystem /Users/me/notes
17
-
18
- # Servers that need credentials
19
- npx kodelyth-ecc mcp-add github \
20
- --env GITHUB_PERSONAL_ACCESS_TOKEN=ghp_... \
21
- --desc "ECC project ops on github" \
22
- -- npx -y @modelcontextprotocol/server-github
23
-
24
- npx kodelyth-ecc mcp-add postgres \
25
- --env DB_URL=postgres://localhost/myapp \
26
- -- npx -y @modelcontextprotocol/server-postgres
27
-
28
- npx kodelyth-ecc mcp-add stripe \
29
- --env STRIPE_API_KEY=sk_... \
30
- -- npx -y @stripe/mcp
31
- ```
32
-
33
- The registry is stored at `~/.kodelyth/mcp-clients.json` (override with `KODELYTH_MCP_CLIENT_DIR`).
34
-
35
- ### 2. Inspect a registered server
36
-
37
- ```bash
38
- npx kodelyth-ecc mcp-list # all registered
39
- npx kodelyth-ecc mcp-tools github # tools the server exposes
40
- npx kodelyth-ecc mcp-resources filesystem # resources
41
- npx kodelyth-ecc mcp-prompts brave # prompts
42
- ```
43
-
44
- ### 3. Call a tool
45
-
46
- ```bash
47
- # No args:
48
- npx kodelyth-ecc mcp-call github list_repos
49
-
50
- # JSON args:
51
- npx kodelyth-ecc mcp-call github create_issue \
52
- --json '{"owner":"sifxprime","repo":"kodelyth-ecc","title":"hi from ECC"}'
53
-
54
- npx kodelyth-ecc mcp-call postgres query \
55
- --json '{"sql":"SELECT count(*) FROM users"}'
56
- ```
57
-
58
- ### 4. Unregister
59
-
60
- ```bash
61
- npx kodelyth-ecc mcp-remove github
62
- ```
63
-
64
- ---
65
-
66
- ## CLI surface
67
-
68
- | Command | Description |
69
- |---|---|
70
- | `mcp-add <name> [--env K=V] [--desc "..."] -- <command> [args...]` | Register an external server. |
71
- | `mcp-list` | List registered servers. |
72
- | `mcp-remove <name>` | Unregister. |
73
- | `mcp-tools <name>` | List tools exposed by the server. |
74
- | `mcp-resources <name>` | List resources. |
75
- | `mcp-prompts <name>` | List prompts. |
76
- | `mcp-call <name> <tool> [--json '{"arg":"value"}']` | Call a tool with JSON arguments. |
77
-
78
- The `--` separator before the command is mandatory in `mcp-add` so the registry can disambiguate flags belonging to ECC from flags meant for the external server.
79
-
80
- ---
81
-
82
- ## Programmatic use
83
-
84
- The same registry powers in-session agent tool calls. Inside an ECC agent or skill, require the client library:
85
-
86
- ```js
87
- const client = require('kodelyth-ecc/scripts/mcp/client.js');
88
-
89
- // Open a stable connection.
90
- const session = await client.connect('github');
91
- const out = await session.client.callTool({
92
- name: 'create_issue',
93
- arguments: { owner: 'sifxprime', repo: 'kodelyth-ecc', title: 'auto-issue' },
94
- });
95
- await session.close();
96
-
97
- // Or one-shot:
98
- const tools = await client.listTools('postgres');
99
- const stats = await client.callTool('redis', 'set', { key: 'k', value: 'v' });
100
- ```
101
-
102
- Every call spawns a fresh stdio subprocess; there's no long-lived process pool. This is intentional — failed servers don't poison subsequent calls, and credentials live only in the per-call env.
103
-
104
- ---
105
-
106
- ## Registry shape
107
-
108
- ```json
109
- {
110
- "servers": {
111
- "github": {
112
- "name": "github",
113
- "command": "npx",
114
- "args": ["-y", "@modelcontextprotocol/server-github"],
115
- "env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "ghp_..." },
116
- "description": "ECC project ops on github",
117
- "added_at": "2026-05-10T10:48:00.690Z"
118
- }
119
- }
120
- }
121
- ```
122
-
123
- You can hand-edit the file. Reserved name patterns: alphanumeric, dash, underscore.
124
-
125
- ---
126
-
127
- ## Pairing with the rest of ECC
128
-
129
- | Pairs with | How |
130
- |---|---|
131
- | **Phase 2.1 — MCP server** | The two halves complete each other. ECC serves to any framework AND consumes from any provider. |
132
- | **Phase 2.10 — prompt-injection-guard** | Tool responses from external MCP servers are scanned for indirect injection on `PostToolUse:mcp__*` (opt in via `KODELYTH_PI_GUARD=warn|block`). |
133
- | **Phase 2.4 — cost-aware model router** | Tool responses are part of the session token-budget when the safety hook is enabled. |
134
- | **kodelyth-memory** | Capture interesting tool responses as memories with `kodelyth-ecc remember "..." --approach "..."`. |
135
-
136
- ---
137
-
138
- ## Privacy & safety
139
-
140
- - **No network egress from this client** — it only spawns subprocesses you registered.
141
- - **Credentials live in the registry file.** Treat `~/.kodelyth/mcp-clients.json` like a secrets file. `chmod 600` is recommended on shared machines.
142
- - **External servers can do whatever the user gives them permission to do** — register only servers you trust.
143
- - **Pair with `prompt-injection-guard`** to scan tool responses for indirect injection before agents act on them.
144
-
145
- ---
146
-
147
- ## Troubleshooting
148
-
149
- **"Kodelyth MCP client requires `@modelcontextprotocol/sdk`"** — run `npm install @modelcontextprotocol/sdk` once, or rerun via `npx -y kodelyth-ecc ...`.
150
-
151
- **"MCP server X is not registered"** — `mcp-list` shows nothing because the registry lives at `~/.kodelyth/mcp-clients.json` (or `$KODELYTH_MCP_CLIENT_DIR`). Re-run `mcp-add`.
152
-
153
- **Server hangs on connect** — the external server probably needs env vars you didn't pass. Re-add with `--env KEY=VAL`.
154
-
155
- **Tool call returns `isError: true`** — the external server rejected the call. Inspect the `content[0].text` for the underlying error message; it's typed exactly as the spec.
156
-
157
- ---
158
-
159
- ## Roadmap interactions
160
-
161
- - **Phase 2.6 — sandbox layer** will wrap external MCP servers in Docker/firejail isolation by default.
162
- - **Phase 2.3 — local dashboard** will show live MCP traffic per registered server (count, latency, errors).
163
- - **Phase 2.9 — SLSA/SBOM** will publish provenance for the ECC server side and let `supply-chain-auditor` verify external server packages.
164
-
165
- ---
166
-
167
- Built into [Kodelyth ECC](../README.md). MIT licensed. PRs welcome.