kodelyth-ecc 2.25.0 → 2.30.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.
Files changed (43) hide show
  1. package/AGENTS.md +1 -1
  2. package/CHANGELOG.md +189 -0
  3. package/CLAUDE.md +7 -7
  4. package/GITHUB_SETUP.md +3 -3
  5. package/README.md +22 -22
  6. package/VERSION +1 -1
  7. package/agents/super-agent.md +102 -0
  8. package/bin/kodelyth-ecc.js +54 -47
  9. package/bundles/enterprise.md +1 -1
  10. package/bundles/indie-hacker.md +1 -1
  11. package/commands/super-agent.md +47 -0
  12. package/hooks/memory/capture-stop.js +1 -1
  13. package/install.ps1 +14 -3
  14. package/install.sh +17 -4
  15. package/package.json +6 -3
  16. package/rules/common/agent-intent-routing.md +2 -1
  17. package/rules/common/agents.md +1 -1
  18. package/rules/common/self-improvement-workflow.md +1 -1
  19. package/scripts/cli/menu.js +1 -1
  20. package/scripts/hooks/post-bash-command-log.js +4 -11
  21. package/scripts/hooks/session-start.js +13 -0
  22. package/scripts/lib/redact.js +58 -0
  23. package/scripts/lib/state-store/index.js +36 -1
  24. package/scripts/lib/state-store/schema.js +18 -1
  25. package/scripts/lib/target-paths.js +62 -0
  26. package/scripts/mcp/register-self.js +59 -16
  27. package/scripts/memory/cli.js +35 -0
  28. package/scripts/memory/embedding-providers/local-transformers.js +44 -0
  29. package/scripts/memory/embeddings.js +98 -0
  30. package/scripts/memory/pending.js +125 -0
  31. package/scripts/memory/project-id.js +93 -0
  32. package/scripts/memory/store.js +123 -13
  33. package/scripts/super-agent/cli.js +135 -0
  34. package/scripts/super-agent/dag.js +123 -0
  35. package/scripts/super-agent/integrate.js +91 -0
  36. package/scripts/super-agent/orchestrator.js +175 -0
  37. package/scripts/super-agent/state.js +136 -0
  38. package/wiki/Agent-Reference.md +1 -1
  39. package/wiki/FAQ.md +5 -5
  40. package/wiki/Home.md +8 -8
  41. package/wiki/Installation-Guide.md +1 -1
  42. package/wiki/Platform-Support.md +8 -8
  43. package/wiki/Skill-Reference.md +4 -4
@@ -21,6 +21,9 @@ const os = require('os');
21
21
 
22
22
  const ROOT = path.join(__dirname, '..');
23
23
 
24
+ // Where each IDE target reads skills/commands from (used by `terse` install).
25
+ const { getTargetSkillsDir, getTargetCommandsDir } = require(path.join(ROOT, 'scripts', 'lib', 'target-paths.js'));
26
+
24
27
  // Auto-migrate legacy ~/.kodelyth/ → ~/.kodelythecc/ on first run for existing users.
25
28
  // Idempotent; instant no-op if legacy dir is absent or migration marker exists.
26
29
  try { require(path.join(ROOT, 'scripts', 'migrate-legacy.js')).main(); } catch { /* best-effort */ }
@@ -141,7 +144,7 @@ if (args[1] === '--help' || args[1] === '-h') {
141
144
 
142
145
  // ── Subcommand: mcp (start MCP server over stdio) ────────────────────────────
143
146
  // Usage: npx kodelyth-ecc mcp
144
- // Exposes 70 agents, 196 skills, 103 commands, the routing rule, and the local
147
+ // Exposes 71 agents, 196 skills, 104 commands, the routing rule, and the local
145
148
  // memory store to any MCP-compatible client (Claude Desktop, LangGraph, etc.).
146
149
  if (args[0] === 'mcp') {
147
150
  // Hand off entirely to the MCP server — it owns stdio from here on.
@@ -419,11 +422,49 @@ if (args[0] === 'memory') {
419
422
  w(`Top tags: ${s.topTags.slice(0, 8).map(t => t[0] + '(' + t[1] + ')').join(', ')}`);
420
423
  process.exit(0);
421
424
  }
422
- process.stderr.write('unknown memory subcommand. try: capture | recall | list | stats\n');
425
+ // Auto-capture review queue: the Stop hook auto-queues candidates; these are
426
+ // the consent gate that turns them into stored memories.
427
+ if (sub === 'list-pending' || sub === 'review-pending') {
428
+ const pending = require(path.join(ROOT, 'scripts', 'memory', 'pending.js'));
429
+ const items = pending.listPending();
430
+ if (!items.length) { w('No memory candidates pending review.'); process.exit(0); }
431
+ w(`${items.length} candidate(s) pending review:`);
432
+ for (const c of items) w(` [${c.id}] (score ${c.score ?? '-'}) ${(c.problem || '').slice(0, 70)}`);
433
+ w('Confirm: kodelythecc memory promote-pending <id|all> · drop: kodelythecc memory discard-pending <id|all>');
434
+ process.exit(0);
435
+ }
436
+ if (sub === 'promote-pending') {
437
+ const pending = require(path.join(ROOT, 'scripts', 'memory', 'pending.js'));
438
+ const sel = rest.find(a => !a.startsWith('--')) || 'all';
439
+ const stored = pending.promotePending(sel);
440
+ if (!stored.length) { w('Nothing promoted (no matching pending candidate).'); process.exit(0); }
441
+ w(`✓ stored ${stored.length} memor${stored.length === 1 ? 'y' : 'ies'}:`);
442
+ for (const m of stored) w(` ${m.id} ${(m.problem || '').slice(0, 60)}`);
443
+ process.exit(0);
444
+ }
445
+ if (sub === 'discard-pending') {
446
+ const pending = require(path.join(ROOT, 'scripts', 'memory', 'pending.js'));
447
+ const sel = rest.find(a => !a.startsWith('--')) || 'all';
448
+ w(`Discarded ${pending.discardPending(sel)} pending candidate(s).`);
449
+ process.exit(0);
450
+ }
451
+ process.stderr.write('unknown memory subcommand. try: capture | recall | list | stats | list-pending | promote-pending | discard-pending\n');
423
452
  process.exit(2);
424
453
  } catch (e) { process.stderr.write(`[memory] ${e.message}\n`); process.exit(1); }
425
454
  }
426
455
 
456
+ // ── Subcommand: super-agent (autonomous orchestrator driver) ─────────────────
457
+ // Arena-style state machine: it does not run agents, it tells the driving LLM
458
+ // what to do next. start → plan → step… → integrate → verify → done, resumable.
459
+ // kodelythecc super-agent start --goal "<objective>" [--token-cap N] [--step-cap N]
460
+ // kodelythecc super-agent next|status|list <id> ; plan/step/integrate/verify to advance
461
+ if (args[0] === 'super-agent' || args[0] === 'superagent') {
462
+ try {
463
+ require(path.join(ROOT, 'scripts', 'super-agent', 'cli.js')).main(args.slice(1));
464
+ process.exit(0);
465
+ } catch (e) { process.stderr.write(`[super-agent] ${e.message}\n`); process.exit(1); }
466
+ }
467
+
427
468
  // ── Subcommand: god / evil / arena (the adversarial arena) ──────────────────
428
469
  // Usage:
429
470
  // kodelythecc god --task "<task>" [--json] plan a GOD-mode build
@@ -716,10 +757,11 @@ if (args[0] === 'doctor') {
716
757
  let update;
717
758
  try {
718
759
  const { cachedCheck } = require(path.join(ROOT, 'scripts', 'cli', 'update-check.js'));
719
- const vf = path.join(ROOT, 'VERSION');
720
- const current = fs.existsSync(vf)
721
- ? fs.readFileSync(vf, 'utf8').trim()
722
- : require(path.join(ROOT, 'package.json')).version;
760
+ // package.json is the source of truth for an npm package; VERSION is only a
761
+ // fallback. (They drifted once and the CLI reported a stale version.)
762
+ let current;
763
+ try { current = require(path.join(ROOT, 'package.json')).version; }
764
+ catch { try { current = fs.readFileSync(path.join(ROOT, 'VERSION'), 'utf8').trim(); } catch { /* leave undefined */ } }
723
765
  update = cachedCheck(current) || undefined;
724
766
  } catch { /* never let a version hint break the health check */ }
725
767
 
@@ -929,43 +971,8 @@ if (args[0] === 'terse') {
929
971
  }
930
972
  }
931
973
 
932
- // Normalise alias → canonical target (matches scripts/rtk/index.js).
933
- function _canon(target) {
934
- if (target === 'claude-code') return 'claude-home';
935
- if (target === 'gemini-cli') return 'gemini-home';
936
- if (target === 'cursor') return 'cursor-project';
937
- return target;
938
- }
939
- function getTargetSkillsDir(target) {
940
- const home = os.homedir();
941
- switch (_canon(target)) {
942
- case 'claude-home': return path.join(home, '.claude', 'skills');
943
- case 'cursor-project': return path.join(home, '.cursor', 'skills');
944
- case 'windsurf-home':
945
- case 'windsurf-project': return path.join(home, '.codeium', 'windsurf', 'skills');
946
- case 'antigravity': return path.join(home, '.antigravity', 'skills');
947
- case 'codex-home': return path.join(home, '.codex', 'skills');
948
- case 'gemini-home': return path.join(home, '.gemini', 'skills');
949
- case 'gemini-project': return path.join(process.cwd(), '.gemini', 'skills');
950
- case 'opencode': return path.join(home, '.config', 'opencode', 'skills');
951
- default: return null;
952
- }
953
- }
954
- function getTargetCommandsDir(target) {
955
- const home = os.homedir();
956
- switch (_canon(target)) {
957
- case 'claude-home': return path.join(home, '.claude', 'commands');
958
- case 'cursor-project': return path.join(home, '.cursor', 'commands');
959
- case 'windsurf-home':
960
- case 'windsurf-project': return path.join(home, '.codeium', 'windsurf', 'commands');
961
- case 'antigravity': return path.join(home, '.antigravity', 'commands');
962
- case 'codex-home': return path.join(home, '.codex', 'commands');
963
- case 'gemini-home': return path.join(home, '.gemini', 'commands');
964
- case 'gemini-project': return path.join(process.cwd(), '.gemini', 'commands');
965
- case 'opencode': return path.join(home, '.config', 'opencode', 'commands');
966
- default: return null;
967
- }
968
- }
974
+ // getTargetSkillsDir / getTargetCommandsDir are imported at the top of this file
975
+ // from scripts/lib/target-paths.js (shared, unit-tested, mirrors install.sh).
969
976
 
970
977
  // ── Subcommand: route (cost-aware model tier recommendation) ──────────────────
971
978
  // Usage: npx kodelyth-ecc route "<task description>" [--files N] [--agent <name>] [--current <model-id>]
@@ -1825,10 +1832,10 @@ if (args.includes('--help') || args.includes('-h')) {
1825
1832
 
1826
1833
  // ── Version shortcut ──────────────────────────────────────────────────────────
1827
1834
  if (args.includes('--version') || args.includes('-v')) {
1828
- const versionFile = path.join(ROOT, 'VERSION');
1829
- const version = fs.existsSync(versionFile)
1830
- ? fs.readFileSync(versionFile, 'utf8').trim()
1831
- : require(path.join(ROOT, 'package.json')).version;
1835
+ // package.json is canonical for an npm package; VERSION is only a fallback.
1836
+ let version;
1837
+ try { version = require(path.join(ROOT, 'package.json')).version; }
1838
+ catch { try { version = fs.readFileSync(path.join(ROOT, 'VERSION'), 'utf8').trim(); } catch { version = 'unknown'; } }
1832
1839
  console.log(`kodelyth-ecc v${version}`);
1833
1840
  process.exit(0);
1834
1841
  }
@@ -137,7 +137,7 @@ Recommended hooks to enable for SOC 2 / ISO 27001 readiness:
137
137
 
138
138
  ## What This Bundle Surfaces First
139
139
 
140
- You still have all 70 agents — but routing is biased toward:
140
+ You still have all 71 agents — but routing is biased toward:
141
141
 
142
142
  1. **Auditability** — every recommendation comes with rationale
143
143
  2. **Documentation** — every change has a doc impact note
@@ -84,7 +84,7 @@ If you have `/model-route` available, lean on it.
84
84
 
85
85
  ## What This Bundle Skips by Default
86
86
 
87
- You still have access to all 70 agents — these just aren't surfaced first:
87
+ You still have access to all 71 agents — these just aren't surfaced first:
88
88
 
89
89
  - Heavy enterprise agents (`compliance-checker` patterns, `architect-of-architects`)
90
90
  - Most language-specific reviewers if you're TypeScript/Python only — they're there if you need them
@@ -0,0 +1,47 @@
1
+ ---
2
+ name: super-agent
3
+ description: Drive a large objective to completion through the autonomous orchestrator — decompose, dispatch (parallel), integrate branches, verify. Resumable, budget-governed.
4
+ ---
5
+
6
+ # /super-agent
7
+
8
+ Turn one big objective into a finished, verified result by running it through the
9
+ **super-agent** orchestrator — a deterministic, resumable, budget-governed state
10
+ machine (`scripts/super-agent/`).
11
+
12
+ ## Usage
13
+
14
+ ```
15
+ /super-agent <objective> e.g. /super-agent build a rate-limited login API with tests
16
+ /super-agent resume <runId> continue a crashed or earlier run
17
+ ```
18
+
19
+ ## What it does
20
+
21
+ Behaves as the `super-agent` agent and runs the loop:
22
+
23
+ 1. `kodelythecc super-agent start --goal "<objective>" --step-cap <N>` — always with a budget.
24
+ 2. `kodelythecc super-agent next <id>` → perform the action it names:
25
+ - **decompose** → build a dependency DAG with the `blueprint` skill, `… plan <id> --file`.
26
+ - **dispatch** → run each ready step (parallel where independent, each on its own branch), `… step <id> <step> --status done --branch`.
27
+ - **integrate** → conflict-check with `scripts/super-agent/integrate.js`, merge in `mergeOrder`, `… integrate <id>` (or `--conflicts …` to stop).
28
+ - **verify** → run `/verify`, then `… verify <id> --passed|--failed`.
29
+ 3. Repeat until **report**.
30
+
31
+ ## When to use it
32
+
33
+ - A feature or change too large for one pass, that splits into dependent steps.
34
+ - You want parallel execution of independent steps with correct, conflict-checked integration.
35
+ - You want the run to survive a crash and resume.
36
+
37
+ ## When NOT to use it
38
+
39
+ - A single edit, one-file change, or a quick fix — just do it, or use the specific specialist.
40
+ - Something with no real internal dependencies — the swarm (`/swarm`) or a single agent is lighter.
41
+
42
+ ## Guarantees
43
+
44
+ - Nothing is faked: a step that did not succeed is recorded `failed`, and a failed
45
+ dependency stalls the run instead of building on it.
46
+ - The budget cap and integration-conflict stop are honored, never bypassed.
47
+ - `verify --passed` requires the tests/build to actually pass, with evidence.
@@ -70,7 +70,7 @@ function main() {
70
70
  // ── Improvement A: build contextual advisory from session activity ────────
71
71
  const parts = [];
72
72
  if (candidates.length > 0) {
73
- parts.push(`${candidates.length} memory candidate(s) queued — run "/memory review-pending" to confirm`);
73
+ parts.push(`${candidates.length} memory candidate(s) queued — review with "kodelythecc memory list-pending", then "promote-pending <id|all>" to confirm`);
74
74
  }
75
75
  if (hadFileWrites) {
76
76
  parts.push('files written this session — run "/memory save" or "/learn-eval" to save what we learned');
package/install.ps1 CHANGED
@@ -88,7 +88,7 @@ if ($Bundle) {
88
88
  # -- Banner --------------------------------------------------------------------
89
89
  Write-Host ""
90
90
  Write-Host " Kodelyth ECC -- Production-grade AI coding agent toolkit" -ForegroundColor Cyan
91
- Write-Host " 70 agents (8 devil-mode) | 196 skills | 103 commands | 44 hooks | intent routing | local memory" -ForegroundColor Gray
91
+ Write-Host " 71 agents (8 devil-mode) | 196 skills | 104 commands | 44 hooks | intent routing | local memory" -ForegroundColor Gray
92
92
  Write-Host ""
93
93
 
94
94
  # $PSScriptRoot is always the directory containing this .ps1 file,
@@ -155,6 +155,17 @@ switch ($Target) {
155
155
  $HooksDest = ""
156
156
  $RulesDest = "$Dest\rules"
157
157
  }
158
+ "kiro" {
159
+ # Kiro (AWS AI IDE): rules become always-on steering; the full catalog
160
+ # arrives via the MCP server the Node post-install wires into
161
+ # .kiro\settings\mcp.json. MCP-native, so no file dump into steering.
162
+ $Dest = "$(Get-Location)\.kiro"
163
+ $AgentsDest = ""
164
+ $SkillsDest = ""
165
+ $CommandsDest = ""
166
+ $HooksDest = ""
167
+ $RulesDest = "$Dest\steering"
168
+ }
158
169
  "cline" {
159
170
  $Dest = "$(Get-Location)\.clinerules"
160
171
  $AgentsDest = ""
@@ -205,7 +216,7 @@ switch ($Target) {
205
216
  }
206
217
  default {
207
218
  Write-Host "Unknown target: $Target" -ForegroundColor Red
208
- Write-Host "Valid targets: claude-home, windsurf-project, windsurf-home, antigravity, cursor-project, codex-home, opencode, cline, roocode, aider, kimi, gemini-project, gemini-home"
219
+ Write-Host "Valid targets: claude-home, windsurf-project, windsurf-home, antigravity, cursor-project, codex-home, opencode, cline, roocode, aider, kimi, gemini-project, gemini-home, kiro"
209
220
  exit 1
210
221
  }
211
222
  }
@@ -399,7 +410,7 @@ Powered by Kodelyth ECC -- github.com/sifxprime/kodelyth-ecc
399
410
  $geminiText = @'
400
411
  # Kodelyth ECC -- Gemini CLI context
401
412
 
402
- This project uses Kodelyth ECC -- 70 specialist agents, 196 skills, 103 commands, intent routing, and self-learning memory.
413
+ This project uses Kodelyth ECC -- 71 specialist agents, 196 skills, 104 commands, intent routing, and self-learning memory.
403
414
 
404
415
  The full toolkit is installed under this directory:
405
416
 
package/install.sh CHANGED
@@ -47,7 +47,7 @@ echo -e "${RED}${BOLD} ║ DANGER LEVEL: GOD TIER · NOT FOR JUNIOR DEV
47
47
  echo -e "${RED}${BOLD} ╚══════════════════════════════════════════════════════════════╝${RESET}"
48
48
  echo ""
49
49
  echo -e "${BOLD} Kodelyth ECC — The most dangerous AI coding toolkit on the planet${RESET}"
50
- echo -e "${CYAN} 70 specialist agents (8 devil-mode) · 196 skills · 103 commands · 44 hooks · intent routing · compound memory${RESET}"
50
+ echo -e "${CYAN} 71 specialist agents (8 devil-mode) · 196 skills · 104 commands · 44 hooks · intent routing · compound memory${RESET}"
51
51
  echo -e "${CYAN} Any language · Any framework · Any scale · 300B-level quality${RESET}"
52
52
  echo ""
53
53
  echo -e " github.com/sifxprime/kodelyth-ecc"
@@ -359,9 +359,22 @@ case "$TARGET" in
359
359
  RULES_DEST="$DEST/rules"
360
360
  INSTALL_MODE="user"
361
361
  ;;
362
+ kiro|kiro-project)
363
+ # Kiro (AWS AI IDE). Rules become always-on steering docs; the full catalog
364
+ # (agents, skills, commands, memory) arrives via the MCP server the Node
365
+ # post-install wires into .kiro/settings/mcp.json. Kiro is MCP-native, so we
366
+ # do not dump 266 agent/skill files into steering — that is what MCP is for.
367
+ DEST="$(pwd)/.kiro"
368
+ AGENTS_DEST=""
369
+ SKILLS_DEST=""
370
+ COMMANDS_DEST=""
371
+ HOOKS_DEST=""
372
+ RULES_DEST="$DEST/steering"
373
+ INSTALL_MODE="project"
374
+ ;;
362
375
  *)
363
376
  echo -e "${RED}Unknown target: $TARGET${RESET}"
364
- echo "Valid targets: claude-home (aka claude-code), antigravity, cursor-project, windsurf-project, windsurf-home, codex-home, opencode, cline, roocode, aider, kimi, gemini-project, gemini-home"
377
+ echo "Valid targets: claude-home (aka claude-code), antigravity, cursor-project, windsurf-project, windsurf-home, codex-home, opencode, cline, roocode, aider, kimi, gemini-project, gemini-home, kiro"
365
378
  exit 1
366
379
  ;;
367
380
  esac
@@ -653,7 +666,7 @@ AIDER_EOF
653
666
  cat > "$GEMINI_FILE" <<'GEMINI_EOF'
654
667
  # Kodelyth ECC — Gemini CLI context
655
668
 
656
- This project uses Kodelyth ECC — 70 specialist agents, 196 skills, 103 commands, intent routing, and self-learning memory.
669
+ This project uses Kodelyth ECC — 71 specialist agents, 196 skills, 104 commands, intent routing, and self-learning memory.
657
670
 
658
671
  The full toolkit is installed under this directory:
659
672
 
@@ -778,7 +791,7 @@ case "$TARGET" in
778
791
  echo -e "${BOLD} Cline (VS Code) — what to do now:${RESET}"
779
792
  echo ""
780
793
  echo " Open the project in VS Code with Cline installed."
781
- echo " Cline auto-loads .clinerules/ — all 70 agents, rules, and commands as markdown context."
794
+ echo " Cline auto-loads .clinerules/ — all 71 agents, rules, and commands as markdown context."
782
795
  echo " Ask: 'use debug-detective' / 'review my code' / 'devil mode the codebase'"
783
796
  ;;
784
797
  roocode)
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "kodelyth-ecc",
3
- "version": "2.25.0",
4
- "description": "Production-grade AI coding toolkit — 70 agents (incl. devil-mode adversarial crew), 196 skills, 103 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 on macOS, Linux and Windows with Claude Code, Windsurf, Cursor, Codex, Antigravity, OpenCode, Cline, RooCode, Aider, Kimi, and Gemini CLI.",
3
+ "version": "2.30.0",
4
+ "description": "Production-grade AI coding toolkit — 71 agents (incl. devil-mode adversarial crew), 196 skills, 104 commands, parallel multi-agent commands, semantic intent routing, self-learning memory, and a built-in MCP server (16 tools / 6 prompts / 389 resources) that bridges to Claude Desktop, LangGraph, AutoGen, CrewAI, and OpenAI Agents SDK. Works on macOS, Linux and Windows with Claude Code, Windsurf, Cursor, Codex, Antigravity, OpenCode, Cline, RooCode, Aider, Kimi, Gemini CLI, and Kiro.",
5
5
  "author": "Kodelyth <github.com/sifxprime>",
6
6
  "license": "MIT",
7
7
  "repository": {
@@ -75,7 +75,10 @@
75
75
  "portability": "node scripts/portability/scan.js agents commands skills hooks rules scripts"
76
76
  },
77
77
  "optionalDependencies": {
78
- "@modelcontextprotocol/sdk": "^1.0.4"
78
+ "@modelcontextprotocol/sdk": "^1.0.4",
79
+ "sql.js": "^1.8.0",
80
+ "@xenova/transformers": "^2.17.2",
81
+ "ajv": "^8.12.0"
79
82
  },
80
83
  "engines": {
81
84
  "node": ">=18.0.0"
@@ -66,7 +66,8 @@ Beyond the 10 priority tiers below, watch for these newer signals — they map t
66
66
  | "record this decision" / "write an ADR" / "architecture decision record" | `codebase-memory-mcp` via `manage_adr` |
67
67
  | "remove ECC" / "uninstall kodelythecc" / "clean this up" | Suggest `kodelythecc uninstall --dry-run` |
68
68
  | "how much did I save" / "show my token savings" / "RTK stats" | `kodelythecc dashboard` OR `kodelythecc rtk gain` |
69
- | "install for another IDE" / "add to Cursor / Windsurf / Antigravity" | `kodelythecc --target <ide>` |
69
+ | "install for another IDE" / "add to Cursor / Windsurf / Antigravity / Kiro" | `kodelythecc --target <ide>` |
70
+ | "orchestrate this" / "build the whole X end-to-end" / "autonomously build" / "break this big goal into steps and build it" / "run it until it's done" | `super-agent` (the autonomous orchestrator) — decompose → dispatch (parallel) → integrate → verify, resumable + budget-governed. Not for a single edit. |
70
71
 
71
72
  ### 5. Compound intent → parallel agents
72
73
 
@@ -1,6 +1,6 @@
1
1
  # Agent Orchestration
2
2
 
3
- 70 specialist agents are available. Intent routing is always-on — describe your problem in plain words and the right agent is invoked automatically. You can also invoke explicitly: `use <agent-name>`.
3
+ 71 specialist agents are available. Intent routing is always-on — describe your problem in plain words and the right agent is invoked automatically. You can also invoke explicitly: `use <agent-name>`.
4
4
 
5
5
  ## Kodelyth Exclusives
6
6
 
@@ -124,7 +124,7 @@ ECC uses three compounding memory layers — together they make Claude increasin
124
124
  - Example: "Last time you had a CORS issue in Express, you added this middleware..."
125
125
 
126
126
  ### Layer 3 — Intent Routing (`rules/common/agent-intent-routing.md`)
127
- - Always-on. 70 specialists. Zero setup.
127
+ - Always-on. 71 specialists. Zero setup.
128
128
  - Routes your message to the right expert from the first word
129
129
  - No agent names needed — just describe the problem
130
130
 
@@ -144,7 +144,7 @@ async function pickIdeAndInstall(ROOT) {
144
144
  const targets = [
145
145
  'claude-code', 'cursor-project', 'windsurf-home', 'windsurf-project',
146
146
  'antigravity', 'codex-home', 'opencode', 'cline', 'roocode',
147
- 'gemini-home', 'gemini-project', 'kimi', 'aider',
147
+ 'gemini-home', 'gemini-project', 'kimi', 'aider', 'kiro',
148
148
  ];
149
149
  const chosen = await pick('Pick an IDE to install for', targets);
150
150
  if (chosen == null) return main();
@@ -4,6 +4,7 @@
4
4
  const fs = require('fs');
5
5
  const os = require('os');
6
6
  const path = require('path');
7
+ const { redact } = require('../lib/redact');
7
8
 
8
9
  const MAX_STDIN = 1024 * 1024;
9
10
  let raw = '';
@@ -20,17 +21,9 @@ const MODE_CONFIG = {
20
21
  };
21
22
 
22
23
  function sanitizeCommand(command) {
23
- return String(command || '')
24
- .replace(/\n/g, ' ')
25
- .replace(/--token[= ][^ ]*/g, '--token=<REDACTED>')
26
- .replace(/Authorization:[: ]*[^ ]*[: ]*[^ ]*/gi, 'Authorization:<REDACTED>')
27
- .replace(/\bAKIA[A-Z0-9]{16}\b/g, '<REDACTED>')
28
- .replace(/\bASIA[A-Z0-9]{16}\b/g, '<REDACTED>')
29
- .replace(/password[= ][^ ]*/gi, 'password=<REDACTED>')
30
- .replace(/\bghp_[A-Za-z0-9_]+\b/g, '<REDACTED>')
31
- .replace(/\bgho_[A-Za-z0-9_]+\b/g, '<REDACTED>')
32
- .replace(/\bghs_[A-Za-z0-9_]+\b/g, '<REDACTED>')
33
- .replace(/\bgithub_pat_[A-Za-z0-9_]+\b/g, '<REDACTED>');
24
+ // Flatten to one log line, then run the shared credential redactor (which now
25
+ // covers more token formats than this hook's old inline list did).
26
+ return redact(String(command || '').replace(/\n/g, ' '));
34
27
  }
35
28
 
36
29
  function appendLine(filePath, line) {
@@ -392,6 +392,19 @@ async function main() {
392
392
  additionalContextParts.push(structuredInstinctSummary);
393
393
  }
394
394
 
395
+ // Surface the auto-capture review queue so candidates the last session proposed
396
+ // are discoverable now, not just at the end of that session. Consent-first:
397
+ // this only points at the review command; nothing is stored without the user
398
+ // running promote-pending.
399
+ try {
400
+ const n = require('../memory/pending').countPending();
401
+ if (n > 0) {
402
+ additionalContextParts.push(
403
+ `${n} memory candidate(s) await review — list with "kodelythecc memory list-pending", confirm with "promote-pending <id|all>".`
404
+ );
405
+ }
406
+ } catch { /* never block session start */ }
407
+
395
408
  // Check for recent session files (last 7 days)
396
409
  const recentSessions = dedupeRecentSessions(sessionSearchDirs);
397
410
 
@@ -0,0 +1,58 @@
1
+ // scripts/lib/redact.js
2
+ //
3
+ // One place to scrub credentials out of text before it is stored or logged.
4
+ // Used by the memory capture path (so a leaked key is never written into
5
+ // memories.jsonl, where it would then be surfaced by recall and injected into a
6
+ // future session) and by the bash-command logger.
7
+ //
8
+ // Two rule families:
9
+ // - High-confidence provider token FORMATS, matched anywhere (prose or a
10
+ // command line) — AWS, GitHub, OpenAI/Anthropic, Stripe, Slack, Google, npm,
11
+ // JWTs, PEM private-key blocks.
12
+ // - Assignment / header forms — `--token=`, `Authorization:`, `password=`,
13
+ // `api_key=`, etc.
14
+ //
15
+ // Every pattern is linear (no nested quantifiers, no adjacent `\s*\s*`) so none
16
+ // can backtrack catastrophically on hostile input — the ReDoS lesson from the
17
+ // prompt-injection guard applies here too.
18
+ 'use strict';
19
+
20
+ const RULES = [
21
+ // ── Provider token formats (match anywhere) ──
22
+ [/-----BEGIN (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----[\s\S]*?-----END (?:RSA |EC |OPENSSH |DSA |PGP )?PRIVATE KEY-----/g, '<REDACTED:private-key>'],
23
+ [/\bAKIA[0-9A-Z]{16}\b/g, '<REDACTED:aws-key>'],
24
+ [/\bASIA[0-9A-Z]{16}\b/g, '<REDACTED:aws-temp-key>'],
25
+ [/\bghp_[A-Za-z0-9]{20,}\b/g, '<REDACTED:github-token>'],
26
+ [/\bgho_[A-Za-z0-9]{20,}\b/g, '<REDACTED:github-token>'],
27
+ [/\bghs_[A-Za-z0-9]{20,}\b/g, '<REDACTED:github-token>'],
28
+ [/\bghr_[A-Za-z0-9]{20,}\b/g, '<REDACTED:github-token>'],
29
+ [/\bgithub_pat_[A-Za-z0-9_]{22,}\b/g, '<REDACTED:github-pat>'],
30
+ [/\bsk-ant-[A-Za-z0-9_-]{20,}/g, '<REDACTED:anthropic-key>'],
31
+ [/\bsk-[A-Za-z0-9_-]{20,}/g, '<REDACTED:openai-key>'],
32
+ [/\b(?:sk|rk|pk)_(?:live|test)_[A-Za-z0-9]{16,}\b/g, '<REDACTED:stripe-key>'],
33
+ [/\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g, '<REDACTED:slack-token>'],
34
+ [/\bAIza[0-9A-Za-z_-]{35}\b/g, '<REDACTED:google-key>'],
35
+ [/\bnpm_[A-Za-z0-9]{36}\b/g, '<REDACTED:npm-token>'],
36
+ [/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\b/g, '<REDACTED:jwt>'],
37
+ // ── Assignment / header forms ──
38
+ [/(--token[= ])\S+/g, '$1<REDACTED>'],
39
+ [/(Authorization:\s*)(?:Bearer\s+)?\S+/gi, '$1<REDACTED>'],
40
+ [/(\bpassword\s*[=:]\s*)\S+/gi, '$1<REDACTED>'],
41
+ [/(\b(?:api[_-]?key|secret|access[_-]?token|auth[_-]?token)\s*[=:]\s*)["']?[A-Za-z0-9\-_.]{8,}["']?/gi, '$1<REDACTED>'],
42
+ ];
43
+
44
+ // Replace any credentials in `text` with labelled placeholders. Non-strings pass
45
+ // through unchanged (null/undefined stay as they are).
46
+ function redact(text) {
47
+ if (typeof text !== 'string') return text;
48
+ let out = text;
49
+ for (const [re, repl] of RULES) out = out.replace(re, repl);
50
+ return out;
51
+ }
52
+
53
+ // True when redaction would change the text — i.e. a credential is present.
54
+ function hasSecret(text) {
55
+ return typeof text === 'string' && redact(text) !== text;
56
+ }
57
+
58
+ module.exports = { redact, hasSecret, RULES };
@@ -3,7 +3,6 @@
3
3
  const fs = require('fs');
4
4
  const os = require('os');
5
5
  const path = require('path');
6
- const initSqlJs = require('sql.js');
7
6
 
8
7
  const { applyMigrations, getAppliedMigrations } = require('./migrations');
9
8
  const { createQueryApi } = require('./queries');
@@ -11,6 +10,40 @@ const { assertValidEntity, validateEntity } = require('./schema');
11
10
 
12
11
  const DEFAULT_STATE_STORE_RELATIVE_PATH = path.join('.claude', 'ecc', 'state.db');
13
12
 
13
+ // sql.js is OPTIONAL. It powers the session store, the status DB, and the
14
+ // skill-evolution tracker — not the core (memory, RTK, Terse, codebase graph),
15
+ // which stay pure-JS and need nothing. It used to be required at module load, so
16
+ // importing state-store threw "Cannot find module 'sql.js'" for every install
17
+ // that did not have it (which, since it was never a declared dependency, was all
18
+ // of them) — before any caller's try/catch could run. Load it lazily and turn a
19
+ // missing module into a clean, catchable error instead of an import-time crash.
20
+ function loadSqlJs() {
21
+ try {
22
+ return require('sql.js');
23
+ } catch (cause) {
24
+ const err = new Error(
25
+ 'SQLite support is unavailable: the optional dependency "sql.js" is not installed. ' +
26
+ 'Install it (npm i sql.js, or reinstall kodelyth-ecc) to enable the session store, ' +
27
+ 'status DB, and skill-evolution tracker. Core memory, RTK, Terse, and the codebase ' +
28
+ 'graph do not need it.'
29
+ );
30
+ err.code = 'ECC_SQLITE_UNAVAILABLE';
31
+ err.cause = cause;
32
+ throw err;
33
+ }
34
+ }
35
+
36
+ // Non-throwing probe for callers and `doctor`: is the optional SQLite layer
37
+ // usable on this install?
38
+ function isSqliteAvailable() {
39
+ try {
40
+ require.resolve('sql.js');
41
+ return true;
42
+ } catch {
43
+ return false;
44
+ }
45
+ }
46
+
14
47
  function resolveStateStorePath(options = {}) {
15
48
  if (options.dbPath) {
16
49
  if (options.dbPath === ':memory:') {
@@ -163,6 +196,7 @@ async function openDatabase(SQL, dbPath) {
163
196
 
164
197
  async function createStateStore(options = {}) {
165
198
  const dbPath = resolveStateStorePath(options);
199
+ const initSqlJs = loadSqlJs();
166
200
  const SQL = await initSqlJs();
167
201
  const db = await openDatabase(SQL, dbPath);
168
202
  const appliedMigrations = applyMigrations(db);
@@ -188,4 +222,5 @@ module.exports = {
188
222
  DEFAULT_STATE_STORE_RELATIVE_PATH,
189
223
  createStateStore,
190
224
  resolveStateStorePath,
225
+ isSqliteAvailable,
191
226
  };
@@ -2,7 +2,11 @@
2
2
 
3
3
  const fs = require('fs');
4
4
  const path = require('path');
5
- const Ajv = require('ajv');
5
+ // `ajv` is loaded lazily inside getAjv(), NOT at module top. It is an OPTIONAL
6
+ // dependency (it validates the optional SQLite state-store's entities), and
7
+ // requiring it here eagerly made importing state-store throw "Cannot find module
8
+ // 'ajv'" on any install without it — which is every default install, and which
9
+ // broke the pre-publish test step in CI. Same bug class as the sql.js one.
6
10
 
7
11
  const SCHEMA_PATH = path.join(__dirname, '..', '..', '..', 'schemas', 'state-store.schema.json');
8
12
 
@@ -33,6 +37,19 @@ function getAjv() {
33
37
  return cachedAjv;
34
38
  }
35
39
 
40
+ let Ajv;
41
+ try {
42
+ Ajv = require('ajv');
43
+ } catch (cause) {
44
+ const err = new Error(
45
+ 'state-store schema validation needs the optional dependency "ajv", which is not installed. ' +
46
+ 'Install it (or reinstall kodelyth-ecc) to enable session-store / status-DB validation.'
47
+ );
48
+ err.code = 'ECC_AJV_UNAVAILABLE';
49
+ err.cause = cause;
50
+ throw err;
51
+ }
52
+
36
53
  cachedAjv = new Ajv({
37
54
  allErrors: true,
38
55
  strict: false,