kodelyth-ecc 2.4.8 → 2.5.0
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 +62 -0
- package/README.md +8 -0
- package/VERSION +1 -1
- package/bin/kodelyth-ecc.js +40 -0
- package/package.json +1 -1
- package/scripts/cli/menu.js +5 -0
- package/scripts/doctor-health.js +162 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,68 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to Kodelyth ECC are documented here.
|
|
4
4
|
|
|
5
|
+
## v2.5.0 — `kodelythecc doctor` live health check (July 2026)
|
|
6
|
+
|
|
7
|
+
A self-diagnostic that verifies every subsystem is **actually wired and working** — the direct answer to "is it real or dummy?"
|
|
8
|
+
|
|
9
|
+
### Added — `kodelythecc doctor`
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
kodelythecc doctor # human-readable report
|
|
13
|
+
kodelythecc doctor --json # machine-readable, exit 1 if any check fails
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
11 live checks that **exercise** each subsystem instead of just checking a file exists — so it catches the exact class of bug we hit in 2.4.3/2.4.4/2.4.0 (recall crash on stale index, prompt-injection guard silently off, MCP server never registered):
|
|
17
|
+
|
|
18
|
+
| Check | What it actually does |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `binaries` | both `kodelyth-ecc` + `kodelythecc` on PATH |
|
|
21
|
+
| `install-target` | agents/skills/commands/hooks/rules populated in `~/.claude/` |
|
|
22
|
+
| `hooks-registered` | required hook events present in `settings.json` (not just files) |
|
|
23
|
+
| `memory-recall` | **runs a real recall** — must not throw (would have caught the 2.4.3 crash) |
|
|
24
|
+
| `memory-index` | index schema valid or self-healing |
|
|
25
|
+
| `mcp-registered` | ECC MCP entry in Claude Code + Desktop configs (would have caught 2.4.0) |
|
|
26
|
+
| `mcp-server-boots` | spawns the server, confirms it returns a tools list |
|
|
27
|
+
| `prompt-injection` | guard is active, not silently off (would have caught 2.4.4) |
|
|
28
|
+
| `rtk` / `terse` / `codebase-graph` | installed + wired |
|
|
29
|
+
|
|
30
|
+
Each non-pass carries a one-line fix. Wired into `doctor --help` and the interactive menu ("Health check").
|
|
31
|
+
|
|
32
|
+
### Verified
|
|
33
|
+
|
|
34
|
+
- Live on this Mac: **11/11 pass** — "Everything is wired and working."
|
|
35
|
+
- Warn path tested (guard off → warns + shows fix), `--json` exits 1 only on failure
|
|
36
|
+
- 4 new tests in `tests/doctor/health.test.js` including a regression that feeds the foreign index schema and asserts recall self-heals
|
|
37
|
+
- Full suite: 0 failures
|
|
38
|
+
|
|
39
|
+
## v2.4.9 — Phase 4 audit + 6 new feature SVGs (July 2026)
|
|
40
|
+
|
|
41
|
+
Final audit round + the visual gap: the six headline 2.x features had **zero illustrations** in the README or website.
|
|
42
|
+
|
|
43
|
+
### Phase 4 audit — findings
|
|
44
|
+
|
|
45
|
+
- **End-to-end swept every advertised feature** with real invocations: all 9 CLI subcommands, 16 MCP tools, swarm (builds real 4-worker plans), replay (validates args), all 8 parallel commands present, 3 bundles valid. **No dummy features found** — the real bugs were all caught in Phases 1-3.
|
|
46
|
+
- **Adversarial agents assessed** (`secret-hunter`, `backdoor-hunter`, `supply-chain-auditor`): already built with real detection commands (backdoor-hunter has 36, supply-chain-auditor has 8 real jq/npm lockfile-audit sections). No dummy gap like security-reviewer had — honest result, left them alone.
|
|
47
|
+
|
|
48
|
+
### New — 6 feature SVGs (the visual gap)
|
|
49
|
+
|
|
50
|
+
Created on-brand 900×170 illustrations matching the existing `section-*.svg` design system, each with real data and a diagram:
|
|
51
|
+
|
|
52
|
+
- `section-rtk.svg` — input-savings pipeline (raw → RTK filter → compact, 5.1M/64% ledger)
|
|
53
|
+
- `section-terse.svg` — 4-level output-compression dial with before/after
|
|
54
|
+
- `section-codebase.svg` — AST graph nodes + query, 412k vs 3.4k token comparison
|
|
55
|
+
- `section-cli.svg` — interactive menu terminal + arrow keys + update check
|
|
56
|
+
- `section-token-savings.svg` — the three-layer stack combining to −55–65%
|
|
57
|
+
- `section-uninstall.svg` — clean-removal checklist + dry-run
|
|
58
|
+
|
|
59
|
+
All rendered to 8K PNG (37 exports total) and injected into the README's RTK / Terse / Codebase / Interactive-CLI sections.
|
|
60
|
+
|
|
61
|
+
### Verified
|
|
62
|
+
|
|
63
|
+
- 384 tests, 0 failures
|
|
64
|
+
- All 6 SVGs render clean at 8K, no text overflow, on-brand
|
|
65
|
+
- README references the 4 new section SVGs
|
|
66
|
+
|
|
5
67
|
## v2.4.8 — Phase 3: agent polish + token-savings skill (July 2026)
|
|
6
68
|
|
|
7
69
|
Phase 3 of the sequenced plan (audit → routing → skills/agents). Disciplined polish — fixed the one agent with a real actionable gap, added the one skill filling a real gap, and deliberately did **not** pad agents that are already complete.
|
package/README.md
CHANGED
|
@@ -430,6 +430,8 @@ Full reference: [`docs/dashboard.md`](docs/dashboard.md).
|
|
|
430
430
|
|
|
431
431
|
## RTK — Input Token Savings (60-90%)
|
|
432
432
|
|
|
433
|
+
<div align="center"><img src="social/section-rtk.svg" alt="RTK — Input Token Savings (60-90%)" width="900"/></div>
|
|
434
|
+
|
|
433
435
|
[RTK (Rust Token Killer)](https://github.com/rtk-ai/rtk) — Apache-2.0, single Rust binary — intercepts shell commands before they run and filters the output. Common commands like `git status`, `ls`, `cargo test`, `docker ps` return ~80% less text with zero information loss for the LLM.
|
|
434
436
|
|
|
435
437
|
ECC bundles RTK end-to-end:
|
|
@@ -462,6 +464,8 @@ total_saved: 5,107,394 ← 64.1% average reduction
|
|
|
462
464
|
|
|
463
465
|
## Terse Mode — Output Token Savings (40-70%)
|
|
464
466
|
|
|
467
|
+
<div align="center"><img src="social/section-terse.svg" alt="Terse Mode — Output Token Savings (40-70%)" width="900"/></div>
|
|
468
|
+
|
|
465
469
|
RTK compresses input. **Terse mode** compresses output. Together they stack — savings on both sides of every turn.
|
|
466
470
|
|
|
467
471
|
ECC's own implementation, inspired by [Caveman](https://github.com/JuliusBrussee/caveman) (MIT), independently written. Ships as a skill + two slash commands + a deterministic zero-dep memory-file compressor.
|
|
@@ -497,6 +501,8 @@ kodelythecc terse --help
|
|
|
497
501
|
|
|
498
502
|
## Codebase Graph — 158 Languages, Structural Queries
|
|
499
503
|
|
|
504
|
+
<div align="center"><img src="social/section-codebase.svg" alt="Codebase Graph — 158 Languages, Structural Queries" width="900"/></div>
|
|
505
|
+
|
|
500
506
|
Powered by [DeusData/codebase-memory-mcp](https://github.com/DeusData/codebase-memory-mcp) (MIT). AST-parsed knowledge graph via tree-sitter across **158 languages**, Hybrid LSP semantic type resolution for 11 major languages, cross-service HTTP/gRPC/GraphQL linking, 14 MCP tools for structural queries.
|
|
501
507
|
|
|
502
508
|
**Why this matters**: "Who calls `ProcessOrder`?" via file-by-file grep = ~412k tokens. Same question via the graph = ~3.4k tokens. That's a **99% reduction** on structural questions.
|
|
@@ -527,6 +533,8 @@ kodelythecc codebase --help
|
|
|
527
533
|
|
|
528
534
|
## Interactive CLI Menu
|
|
529
535
|
|
|
536
|
+
<div align="center"><img src="social/section-cli.svg" alt="Interactive CLI Menu" width="900"/></div>
|
|
537
|
+
|
|
530
538
|
Type `kodelythecc` alone in a real terminal → arrow-key menu opens.
|
|
531
539
|
|
|
532
540
|
```
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
2.
|
|
1
|
+
2.5.0
|
package/bin/kodelyth-ecc.js
CHANGED
|
@@ -106,6 +106,18 @@ if (args[1] === '--help' || args[1] === '-h') {
|
|
|
106
106
|
kodelyth-ecc dashboard [--port 5747] [--host 127.0.0.1] [--no-open]
|
|
107
107
|
|
|
108
108
|
Tabs: Overview · Token Savings (RTK + Terse) · Memory · Codebase · Evolve · Catalog · Sessions
|
|
109
|
+
`,
|
|
110
|
+
doctor: `
|
|
111
|
+
kodelyth-ecc doctor — live subsystem health check
|
|
112
|
+
|
|
113
|
+
Usage:
|
|
114
|
+
kodelyth-ecc doctor human-readable report
|
|
115
|
+
kodelyth-ecc doctor --json machine-readable (exit 1 if any check fails)
|
|
116
|
+
|
|
117
|
+
Exercises every subsystem for real (not just "file exists"): binaries,
|
|
118
|
+
install target, hook registration, memory recall, MCP registration + boot,
|
|
119
|
+
prompt-injection guard, RTK, Terse, codebase graph. Run it if anything
|
|
120
|
+
feels off — it pinpoints exactly what's not wired and how to fix it.
|
|
109
121
|
`,
|
|
110
122
|
};
|
|
111
123
|
const cmd = args[0];
|
|
@@ -339,6 +351,34 @@ if (args[0] === 'rtk') {
|
|
|
339
351
|
return;
|
|
340
352
|
}
|
|
341
353
|
|
|
354
|
+
// ── Subcommand: doctor (live subsystem health check) ─────────────────────────
|
|
355
|
+
// Usage: kodelythecc doctor [--json]
|
|
356
|
+
if (args[0] === 'doctor') {
|
|
357
|
+
const { run, PASS, WARN, FAIL } = require(path.join(ROOT, 'scripts', 'doctor-health.js'));
|
|
358
|
+
const report = run();
|
|
359
|
+
if (args.includes('--json')) {
|
|
360
|
+
process.stdout.write(JSON.stringify(report, null, 2) + '\n');
|
|
361
|
+
process.exit(report.summary.fail > 0 ? 1 : 0);
|
|
362
|
+
}
|
|
363
|
+
const icon = (s) => (s === PASS ? '\x1b[32m✓\x1b[0m' : s === WARN ? '\x1b[33m!\x1b[0m' : '\x1b[31m✗\x1b[0m');
|
|
364
|
+
const w = (m) => process.stdout.write(m + '\n');
|
|
365
|
+
w('');
|
|
366
|
+
w('\x1b[1mKodelyth ECC — health check\x1b[0m');
|
|
367
|
+
w('─'.repeat(60));
|
|
368
|
+
for (const c of report.checks) {
|
|
369
|
+
w(`${icon(c.status)} \x1b[1m${c.id}\x1b[0m — ${c.detail}`);
|
|
370
|
+
if (c.status !== PASS && c.fix) w(` \x1b[90m→ ${c.fix}\x1b[0m`);
|
|
371
|
+
}
|
|
372
|
+
w('─'.repeat(60));
|
|
373
|
+
const s = report.summary;
|
|
374
|
+
w(`${s.pass} pass · ${s.warn} warn · ${s.fail} fail (of ${s.total} checks)`);
|
|
375
|
+
if (s.fail === 0 && s.warn === 0) w('\x1b[32mEverything is wired and working.\x1b[0m');
|
|
376
|
+
else if (s.fail === 0) w('\x1b[33mWorking, with optional features not yet enabled (warnings above).\x1b[0m');
|
|
377
|
+
else w('\x1b[31mSome subsystems are broken — see fixes above.\x1b[0m');
|
|
378
|
+
w('');
|
|
379
|
+
process.exit(s.fail > 0 ? 1 : 0);
|
|
380
|
+
}
|
|
381
|
+
|
|
342
382
|
// ── Subcommand: uninstall (full ECC removal) ────────────────────────────────
|
|
343
383
|
if (args[0] === 'uninstall') {
|
|
344
384
|
const un = require(path.join(ROOT, 'scripts', 'cli', 'uninstall.js'));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kodelyth-ecc",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.5.0",
|
|
4
4
|
"description": "Production-grade AI coding toolkit — 70 agents (incl. devil-mode adversarial crew), 194 skills, 97 commands, parallel multi-agent commands, semantic intent routing, self-learning memory, and a built-in MCP server (16 tools / 6 prompts / 377 resources) that bridges to Claude Desktop, LangGraph, AutoGen, CrewAI, and OpenAI Agents SDK. Works with Claude Code, Windsurf, Cursor, Codex, Antigravity, OpenCode, Cline, RooCode, Aider, Kimi, and Gemini CLI.",
|
|
5
5
|
"author": "Kodelyth <github.com/sifxprime>",
|
|
6
6
|
"license": "MIT",
|
package/scripts/cli/menu.js
CHANGED
|
@@ -77,6 +77,11 @@ async function buildOptions({ ROOT }) {
|
|
|
77
77
|
hint: 'codebase-memory-mcp (DeusData) — 158 languages, structural queries',
|
|
78
78
|
run: () => runSub(['codebase', 'status']),
|
|
79
79
|
});
|
|
80
|
+
opts.push({
|
|
81
|
+
label: 'Health check (doctor)',
|
|
82
|
+
hint: 'Live check every subsystem is actually wired — catches silent breakage',
|
|
83
|
+
run: () => runSub(['doctor']),
|
|
84
|
+
});
|
|
80
85
|
opts.push({
|
|
81
86
|
label: 'Memory stats (BM25 recall)',
|
|
82
87
|
hint: 'Local BM25 memory — captures, projects, top tags',
|
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
// scripts/doctor-health.js
|
|
2
|
+
// Live subsystem health check — the "is it real or dummy" diagnostic.
|
|
3
|
+
// Each check actually EXERCISES a subsystem (not just "does the file exist"),
|
|
4
|
+
// so it catches the class of bug where a feature is installed + registered but
|
|
5
|
+
// silently broken (recall crash on stale index, prompt-injection guard off,
|
|
6
|
+
// MCP server never registered, etc.).
|
|
7
|
+
//
|
|
8
|
+
// Returns { checks: [{ id, status, detail, fix }], summary }. Zero deps.
|
|
9
|
+
|
|
10
|
+
'use strict';
|
|
11
|
+
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const os = require('os');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
const { execFileSync, spawnSync } = require('child_process');
|
|
16
|
+
|
|
17
|
+
const ROOT = path.join(__dirname, '..');
|
|
18
|
+
const HOME = os.homedir();
|
|
19
|
+
|
|
20
|
+
const PASS = 'pass', WARN = 'warn', FAIL = 'fail';
|
|
21
|
+
|
|
22
|
+
function check(id, fn) {
|
|
23
|
+
try { return { id, ...fn() }; }
|
|
24
|
+
catch (e) { return { id, status: FAIL, detail: e.message, fix: 'unexpected error — file an issue' }; }
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function onPath(bin) {
|
|
28
|
+
try { execFileSync(bin, ['--version'], { stdio: 'ignore' }); return true; }
|
|
29
|
+
catch { return false; }
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ── Individual checks ────────────────────────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
function checkBinaries() {
|
|
35
|
+
const a = onPath('kodelyth-ecc'), b = onPath('kodelythecc');
|
|
36
|
+
if (a && b) return { status: PASS, detail: 'kodelyth-ecc and kodelythecc both on PATH' };
|
|
37
|
+
if (a || b) return { status: WARN, detail: `only ${a ? 'kodelyth-ecc' : 'kodelythecc'} on PATH`, fix: 'reinstall: npm i -g kodelyth-ecc' };
|
|
38
|
+
return { status: WARN, detail: 'neither binary on PATH (running via npx?)', fix: 'npm i -g kodelyth-ecc for the global CLI' };
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function checkInstallTarget() {
|
|
42
|
+
const dir = path.join(HOME, '.claude');
|
|
43
|
+
if (!fs.existsSync(dir)) return { status: WARN, detail: 'no ~/.claude — ECC not installed for Claude Code', fix: 'kodelythecc --target claude-code' };
|
|
44
|
+
const counts = {};
|
|
45
|
+
for (const k of ['agents', 'skills', 'commands', 'hooks', 'rules']) {
|
|
46
|
+
try { counts[k] = fs.readdirSync(path.join(dir, k)).length; } catch { counts[k] = 0; }
|
|
47
|
+
}
|
|
48
|
+
const empty = Object.entries(counts).filter(([, n]) => n === 0).map(([k]) => k);
|
|
49
|
+
if (empty.length) return { status: WARN, detail: `empty: ${empty.join(', ')} (have ${JSON.stringify(counts)})`, fix: 'kodelythecc --target claude-code' };
|
|
50
|
+
return { status: PASS, detail: `agents:${counts.agents} skills:${counts.skills} commands:${counts.commands} hooks:${counts.hooks} rules:${counts.rules}` };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function checkHooksRegistered() {
|
|
54
|
+
const settings = path.join(HOME, '.claude', 'settings.json');
|
|
55
|
+
if (!fs.existsSync(settings)) return { status: WARN, detail: 'no ~/.claude/settings.json', fix: 'kodelythecc --target claude-code' };
|
|
56
|
+
let cfg;
|
|
57
|
+
try { cfg = JSON.parse(fs.readFileSync(settings, 'utf8')); } catch { return { status: FAIL, detail: 'settings.json is not valid JSON', fix: 'repair or reinstall' }; }
|
|
58
|
+
const events = Object.keys(cfg.hooks || {});
|
|
59
|
+
const need = ['UserPromptSubmit', 'Stop', 'SessionStart'];
|
|
60
|
+
const missing = need.filter(e => !events.includes(e));
|
|
61
|
+
if (missing.length) return { status: WARN, detail: `hook events missing: ${missing.join(', ')}`, fix: 'kodelythecc --target claude-code' };
|
|
62
|
+
return { status: PASS, detail: `${events.length} hook events wired: ${events.join(', ')}` };
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function checkMemoryRecall() {
|
|
66
|
+
// The real test: recall must NOT throw on whatever index is on disk.
|
|
67
|
+
// This is the exact bug fixed in 2.4.3 (stale/foreign index schema).
|
|
68
|
+
const store = require(path.join(ROOT, 'scripts', 'memory', 'store.js'));
|
|
69
|
+
const stats = store.stats();
|
|
70
|
+
let recalled;
|
|
71
|
+
try { recalled = store.recall('stripe webhook auth database', { limit: 3, minScore: 0.1 }); }
|
|
72
|
+
catch (e) { return { status: FAIL, detail: `recall threw: ${e.message}`, fix: 'delete ~/.kodelythecc/memory/index.json (self-heals on next run)' }; }
|
|
73
|
+
return { status: PASS, detail: `${stats.total} memories, recall returned ${recalled.length} without error` };
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function checkMemoryIndex() {
|
|
77
|
+
const idx = process.env.KODELYTH_MEMORY_DIR
|
|
78
|
+
? path.join(process.env.KODELYTH_MEMORY_DIR, 'index.json')
|
|
79
|
+
: path.join(HOME, '.kodelythecc', 'memory', 'index.json');
|
|
80
|
+
if (!fs.existsSync(idx)) return { status: PASS, detail: 'no index yet (builds on first capture)' };
|
|
81
|
+
let data;
|
|
82
|
+
try { data = JSON.parse(fs.readFileSync(idx, 'utf8')); } catch { return { status: WARN, detail: 'index.json unreadable — will rebuild', fix: 'harmless; rebuilds on next recall' }; }
|
|
83
|
+
const ok = data && data.tokens && typeof data.tokens === 'object' && typeof data.docCount === 'number';
|
|
84
|
+
if (!ok) return { status: WARN, detail: 'index uses an old schema — will self-heal on next recall', fix: 'harmless; auto-rebuilds' };
|
|
85
|
+
return { status: PASS, detail: `valid BM25 index (${data.docCount} docs)` };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function checkMcpRegistered() {
|
|
89
|
+
try {
|
|
90
|
+
const reg = require(path.join(ROOT, 'scripts', 'mcp', 'register-self.js'));
|
|
91
|
+
const rows = reg.statusAll();
|
|
92
|
+
const present = rows.filter(r => r.present).length;
|
|
93
|
+
const total = rows.length;
|
|
94
|
+
if (present === 0) return { status: WARN, detail: 'ECC MCP server not registered in any client', fix: 'kodelythecc mcp-register' };
|
|
95
|
+
if (present < total) return { status: WARN, detail: `registered in ${present}/${total} clients`, fix: 'kodelythecc mcp-register' };
|
|
96
|
+
return { status: PASS, detail: `registered in ${present}/${total} clients (Claude Code + Desktop)` };
|
|
97
|
+
} catch (e) { return { status: WARN, detail: 'could not read MCP configs: ' + e.message }; }
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function checkMcpBoots() {
|
|
101
|
+
const server = path.join(ROOT, 'scripts', 'mcp', 'server.js');
|
|
102
|
+
if (!fs.existsSync(server)) return { status: FAIL, detail: 'mcp/server.js missing', fix: 'reinstall the package' };
|
|
103
|
+
const req = JSON.stringify({ jsonrpc: '2.0', id: 1, method: 'tools/list', params: {} }) + '\n';
|
|
104
|
+
const r = spawnSync(process.execPath, [server], { input: req, encoding: 'utf8', timeout: 8000 });
|
|
105
|
+
const out = (r.stdout || '');
|
|
106
|
+
const m = out.split('\n').map(l => { try { return JSON.parse(l); } catch { return null; } }).filter(Boolean).find(o => o.result && o.result.tools);
|
|
107
|
+
if (!m) return { status: FAIL, detail: 'MCP server did not return a tools list', fix: 'check node version >=18' };
|
|
108
|
+
return { status: PASS, detail: `MCP server boots, exposes ${m.result.tools.length} tools` };
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function checkPromptInjectionGuard() {
|
|
112
|
+
// The 2.4.4 bug: guard defaulted to off = silent no-op. Verify it's active.
|
|
113
|
+
const mode = String(process.env.KODELYTH_PI_GUARD || 'warn').toLowerCase();
|
|
114
|
+
if (mode === 'off') return { status: WARN, detail: 'prompt-injection guard is OFF (silent)', fix: 'unset KODELYTH_PI_GUARD or set =warn' };
|
|
115
|
+
return { status: PASS, detail: `prompt-injection guard active (mode=${mode})` };
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function checkRtk() {
|
|
119
|
+
if (!onPath('rtk')) return { status: WARN, detail: 'RTK not installed (input savings inactive)', fix: 'kodelythecc rtk install' };
|
|
120
|
+
try {
|
|
121
|
+
const v = execFileSync('rtk', ['--version'], { encoding: 'utf8' }).trim();
|
|
122
|
+
return { status: PASS, detail: `${v} installed`, };
|
|
123
|
+
} catch { return { status: WARN, detail: 'rtk present but --version failed' }; }
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function checkTerse() {
|
|
127
|
+
const skill = path.join(HOME, '.claude', 'skills', 'terse-mode', 'SKILL.md');
|
|
128
|
+
if (!fs.existsSync(skill)) return { status: WARN, detail: 'terse-mode skill not installed', fix: 'kodelythecc terse enable' };
|
|
129
|
+
return { status: PASS, detail: 'terse-mode skill installed (activate with /terse)' };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
function checkCodebaseGraph() {
|
|
133
|
+
if (!onPath('codebase-memory-mcp')) return { status: WARN, detail: 'codebase graph not installed (optional)', fix: 'kodelythecc codebase install' };
|
|
134
|
+
return { status: PASS, detail: 'codebase-memory-mcp installed' };
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// ── Runner ───────────────────────────────────────────────────────────────────
|
|
138
|
+
|
|
139
|
+
function run() {
|
|
140
|
+
const checks = [
|
|
141
|
+
check('binaries', checkBinaries),
|
|
142
|
+
check('install-target', checkInstallTarget),
|
|
143
|
+
check('hooks-registered', checkHooksRegistered),
|
|
144
|
+
check('memory-recall', checkMemoryRecall),
|
|
145
|
+
check('memory-index', checkMemoryIndex),
|
|
146
|
+
check('mcp-registered', checkMcpRegistered),
|
|
147
|
+
check('mcp-server-boots', checkMcpBoots),
|
|
148
|
+
check('prompt-injection', checkPromptInjectionGuard),
|
|
149
|
+
check('rtk', checkRtk),
|
|
150
|
+
check('terse', checkTerse),
|
|
151
|
+
check('codebase-graph', checkCodebaseGraph),
|
|
152
|
+
];
|
|
153
|
+
const summary = {
|
|
154
|
+
total: checks.length,
|
|
155
|
+
pass: checks.filter(c => c.status === PASS).length,
|
|
156
|
+
warn: checks.filter(c => c.status === WARN).length,
|
|
157
|
+
fail: checks.filter(c => c.status === FAIL).length,
|
|
158
|
+
};
|
|
159
|
+
return { checks, summary };
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
module.exports = { run, PASS, WARN, FAIL };
|