@plumpslabs/kuma 2.3.17 → 2.3.19

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 (31) hide show
  1. package/dist/{chunk-3TX6Q37T.js → chunk-3BRBJZ7P.js} +3 -3
  2. package/dist/{chunk-SPHI2BOO.js → chunk-3OHYYXYN.js} +1 -1
  3. package/dist/{chunk-AJ7HHUDW.js → chunk-ABKE45T4.js} +138 -68
  4. package/dist/{chunk-Q2444HWO.js → chunk-FKRSI5U5.js} +1 -1
  5. package/dist/{chunk-RI3DKY62.js → chunk-GFLSAXAH.js} +1 -1
  6. package/dist/{chunk-OJALFQ4H.js → chunk-L7F67KUP.js} +2 -2
  7. package/dist/{chunk-R6B3VUSB.js → chunk-LVKOGXLC.js} +2 -2
  8. package/dist/{chunk-ZKDYTYMS.js → chunk-PRUTTZBS.js} +143 -4
  9. package/dist/{contextDigest-5JXLH56Z.js → contextDigest-QB5XHPXE.js} +3 -3
  10. package/dist/{domainRules-ED6EOFVY.js → domainRules-QLPAQASB.js} +2 -2
  11. package/dist/index.js +141 -51
  12. package/dist/{init-BC7FG4C2.js → init-PL4XL662.js} +1 -1
  13. package/dist/{kumaCheckpoint-XIQWRMGV.js → kumaCheckpoint-J2LDQMEO.js} +2 -2
  14. package/dist/{kumaCodeScanner-QYQUL4W6.js → kumaCodeScanner-J6B2EHGI.js} +7 -10
  15. package/dist/{kumaDb-IC7UX7PU.js → kumaDb-4XZ5S2LH.js} +1 -1
  16. package/dist/{kumaDriftDetector-QBY6OJOO.js → kumaDriftDetector-TOORILSZ.js} +1 -1
  17. package/dist/{kumaGotchas-5HODT5RI.js → kumaGotchas-XRGFFBTA.js} +3 -3
  18. package/dist/{kumaGraph-GUQM75WL.js → kumaGraph-UMXZNGYF.js} +4 -2
  19. package/dist/{kumaMemory-FMOWIODH.js → kumaMemory-FBJMV77G.js} +2 -2
  20. package/dist/{kumaMiner-3RXEOCBP.js → kumaMiner-XJETL7TL.js} +3 -3
  21. package/dist/{kumaPolicyEngine-ORBWL5PT.js → kumaPolicyEngine-2QDJDLM7.js} +2 -2
  22. package/dist/{kumaProgressiveContext-CVSNPY3W.js → kumaProgressiveContext-MWEDRXOH.js} +4 -4
  23. package/dist/{kumaSearch-B5WVYHHD.js → kumaSearch-PV4QTKE7.js} +1 -1
  24. package/dist/{kumaTrajectory-T6DXGOG4.js → kumaTrajectory-7NOAVNG2.js} +2 -2
  25. package/dist/{kumaVerifier-6NTJQU7B.js → kumaVerifier-6YEGC77M.js} +2 -2
  26. package/dist/{kumaVisualize-AFL7STLL.js → kumaVisualize-264OEBGJ.js} +17 -1
  27. package/dist/{safetyAudit-32WSA4Z5.js → safetyAudit-O45SPNTS.js} +2 -2
  28. package/dist/{safetyScore-WU27EOG4.js → safetyScore-TMMRD2MV.js} +5 -5
  29. package/dist/{sessionMemory-4UWA3E5J.js → sessionMemory-YPKVIOMV.js} +1 -1
  30. package/dist/{skillGenerator-GYEDLFZP.js → skillGenerator-PWEJKZNX.js} +7 -5
  31. package/package.json +1 -1
@@ -78,7 +78,7 @@ function createSchema(db) {
78
78
  id INTEGER PRIMARY KEY AUTOINCREMENT,
79
79
  source_id TEXT NOT NULL REFERENCES nodes(id),
80
80
  target_id TEXT NOT NULL REFERENCES nodes(id),
81
- type TEXT NOT NULL CHECK(type IN ('calls','imports','defines','tests','routes','implements','extends','depends_on','owns','modified_by','contains','composes')),
81
+ type TEXT NOT NULL CHECK(type IN ('calls','imports','defines','tests','routes','implements','extends','depends_on','owns','modified_by','contains','composes','flows_through','triggers','syncs_with')),
82
82
  weight REAL DEFAULT 1.0,
83
83
  metadata TEXT DEFAULT '{}',
84
84
  created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')),
@@ -87,13 +87,13 @@ function createSchema(db) {
87
87
  try {
88
88
  const schema = db.exec(`SELECT sql FROM sqlite_master WHERE type='table' AND name='edges'`);
89
89
  const edgeSql = schema[0]?.values?.[0]?.[0] || "";
90
- if (edgeSql.includes("contains") === false || edgeSql.includes("composes") === false) {
90
+ if (edgeSql.includes("flows_through") === false) {
91
91
  db.run(`ALTER TABLE edges RENAME TO edges_old`);
92
92
  db.run(`CREATE TABLE IF NOT EXISTS edges (
93
93
  id INTEGER PRIMARY KEY AUTOINCREMENT,
94
94
  source_id TEXT NOT NULL REFERENCES nodes(id),
95
95
  target_id TEXT NOT NULL REFERENCES nodes(id),
96
- type TEXT NOT NULL CHECK(type IN ('calls','imports','defines','tests','routes','implements','extends','depends_on','owns','modified_by','contains','composes')),
96
+ type TEXT NOT NULL CHECK(type IN ('calls','imports','defines','tests','routes','implements','extends','depends_on','owns','modified_by','contains','composes','flows_through','triggers','syncs_with')),
97
97
  weight REAL DEFAULT 1.0,
98
98
  metadata TEXT DEFAULT '{}',
99
99
  created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')),
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  sessionMemory
3
- } from "./chunk-R6B3VUSB.js";
3
+ } from "./chunk-LVKOGXLC.js";
4
4
  import {
5
5
  getProjectRoot
6
6
  } from "./chunk-E2KFPEBT.js";
@@ -76,14 +76,16 @@ var BOOTSTRAP_LINES = [
76
76
  ' 2. `kuma_safety({ action: "guard" })` \u2014 Safety check before work',
77
77
  ' 3. `kuma_context({ action: "research", scope: "<area>" })` \u2014 Research before editing',
78
78
  " 4. *(edit/read using native tools)*",
79
- ' 5. `kuma_memory({ action: "research_save", ... })` \u2014 IMMEDIATELY after every read/grep (inline)',
80
- ' 6. `kuma_memory({ action: "gotcha" })` \u2014 IMMEDIATELY when bug/quirks found (inline)',
81
- ' 7. `kuma_memory({ action: "arch_flow" })` \u2014 IMMEDIATELY after tracing each flow hop (inline)',
82
- ' 8. `kuma_memory({ action: "decision" })` \u2014 IMMEDIATELY when choosing between options (inline)',
79
+ ' 5. `kuma_memory({ action: "research_save", ... })` \u2014 After exploring area (creates search cache)',
80
+ ' 6. `kuma_memory({ action: "gotcha" })` \u2014 \u{1F525} IMMEDIATELY when bug found (exponential value)',
81
+ ' 7. `kuma_memory({ action: "arch_flow" })` \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential value)',
82
+ ' 8. `kuma_memory({ action: "decision" })` \u2014 When choosing between options (preserves rationale)',
83
83
  ' 9. `kuma_safety({ action: "verify", ... })` \u2014 Run tests / confirm nothing broken',
84
84
  ' 10. `kuma_context({ action: "changes" })` \u2014 Review session activity',
85
85
  "",
86
- "\u{1F504} Record findings INLINE as you work \u2014 not just at steps 5-8. Every read/grep = mini research_save.",
86
+ "\u{1F525} **Power Curve:** `arch_flow` + `gotcha` are EXPONENTIAL \u2014 each record saves 5-10 files next session.",
87
+ " The more you record, the more overpowered the agent becomes. These are the highest-value actions.",
88
+ "\u{1F7E2} **SKIP** recording function/class/component nodes \u2014 grep/glob is faster.",
87
89
  "\u{1F9E0} Knowledge graph is persistent \u2014 nodes/edges accumulate across sessions, getting richer over time.",
88
90
  "",
89
91
  "\u26D4 Do NOT skip steps 5-10 after research \u2014 even if no code was changed.",
@@ -119,7 +121,7 @@ function windsurfRulesTemplate() {
119
121
  "",
120
122
  "Windsurf Cascade agent: Kuma MCP tools are installed.",
121
123
  "All behavioral rules are in `.kuma/init.md`.",
122
- "**Before coding, load project context via `kuma_init()`.**",
124
+ '**Before coding, call `kuma_context({ action: "init" })`** to load project context and session memory.',
123
125
  "Project knowledge persists in `.kuma/memories/*.md` across sessions.",
124
126
  "",
125
127
  "Also auto-detected as SKILL.md in `.windsurf/skills/` and `.agents/skills/`."
@@ -153,11 +155,37 @@ function aiderTemplate() {
153
155
  ].join("\n");
154
156
  }
155
157
  function opencodeAgentsMdTemplate() {
158
+ const opencodeLines = [
159
+ "Kuma MCP tools are installed (kuma_kuma_context, kuma_kuma_memory, kuma_kuma_safety).",
160
+ '**Before coding, call `kuma_kuma_context({ action: "init" })`** to load project context.',
161
+ "Project knowledge persists in `.kuma/memories/*.md` across sessions.",
162
+ "",
163
+ "\u26A0\uFE0F **MANDATORY WORKFLOW** \u2014 Follow in order every session (including research-only):",
164
+ "",
165
+ ' 1. `kuma_kuma_context({ action: "init" })` \u2014 Load context (START HERE)',
166
+ ' 2. `kuma_kuma_safety({ action: "guard" })` \u2014 Safety check before work',
167
+ ' 3. `kuma_kuma_context({ action: "research", scope: "<area>" })` \u2014 Research before editing',
168
+ " 4. *(edit/read using native tools)*",
169
+ ' 5. `kuma_kuma_memory({ action: "research_save", ... })` \u2014 After exploring area (creates search cache)',
170
+ ' 6. `kuma_kuma_memory({ action: "gotcha" })` \u2014 \u{1F525} IMMEDIATELY when bug found (exponential value)',
171
+ ' 7. `kuma_kuma_memory({ action: "arch_flow" })` \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential value)',
172
+ ' 8. `kuma_kuma_memory({ action: "decision" })` \u2014 When choosing between options (preserves rationale)',
173
+ ' 9. `kuma_kuma_safety({ action: "verify", ... })` \u2014 Run tests / confirm nothing broken',
174
+ ' 10. `kuma_kuma_context({ action: "changes" })` \u2014 Review session activity',
175
+ "",
176
+ "\u{1F525} **Power Curve:** `arch_flow` + `gotcha` are EXPONENTIAL \u2014 each record saves 5-10 files next session.",
177
+ " The more you record, the more overpowered the agent becomes. These are the highest-value actions.",
178
+ "\u{1F7E2} **SKIP** recording function/class/component nodes \u2014 grep/glob is faster.",
179
+ "\u{1F9E0} Knowledge graph is persistent \u2014 nodes/edges accumulate across sessions, getting richer over time.",
180
+ "",
181
+ "\u26A0\uFE0F **OpenCode platform note:** Tool names use `kuma_kuma_*` prefix",
182
+ " (server name `kuma` + already-prefixed tool name `kuma_context`).",
183
+ ""
184
+ ].join("\n");
156
185
  return [
157
186
  "## Kuma MCP \u2014 OpenCode",
158
187
  "",
159
- KUMA_CORE_INSTRUCTIONS,
160
- "",
188
+ opencodeLines,
161
189
  "\u{1F4D6} Rules: `.kuma/init.md`",
162
190
  "\u{1F9E0} Skill: `.agents/skills/kuma/SKILL.md`"
163
191
  ].join("\n");
@@ -275,6 +303,13 @@ function generateInitMdContent() {
275
303
  "",
276
304
  "---",
277
305
  "",
306
+ "> \u26A0\uFE0F **Platform Tool Names:**",
307
+ '> \u2022 **OpenCode / Antigravity:** Use `kuma_kuma_*` prefix (e.g. `kuma_kuma_context({ action: "init" })`)',
308
+ '> \u2022 **Other platforms (Claude, Cursor, Cline, etc.):** Use `kuma_*` directly (e.g. `kuma_context({ action: "init" })`)',
309
+ "> \u2022 **Replace `kuma_` with `kuma_kuma_` in all examples below if you're on OpenCode.**",
310
+ "",
311
+ "---",
312
+ "",
278
313
  "## \u26A0\uFE0F SESSION WORKFLOW \u2014 Follow Steps in Order",
279
314
  "",
280
315
  "### STEP 1: Init Session (ALWAYS \u2014 Start of Session)",
@@ -309,20 +344,43 @@ function generateInitMdContent() {
309
344
  "> \u26A0\uFE0F **Research-only sessions included.** Workflow ini wajib meskipun session hanya membaca/riset tanpa code changes.",
310
345
  "",
311
346
  "> \u{1F9E0} **Graph Philosophy:** Record findings INLINE as you work, not just at the end. Every time you read a",
312
- "> file, grep a pattern, or trace a flow \u2014 call `research_save` immediately to persist file/func/import nodes.",
347
+ "> file, grep a pattern, or trace a flow \u2014 call `research_save` immediately to persist what you learned.",
313
348
  "> The knowledge graph accumulates across sessions. The more you use it, the richer it becomes.",
314
349
  "",
315
- "**AUTO-RECORDED nodes/edges** (Kuma scanner detects these automatically):",
316
- "- Files, Functions, Classes \u2192 created as graph nodes",
317
- "- Imports, Calls, Extends \u2192 created as graph edges",
318
- "- Variables, Components, Routes \u2192 created when detected",
319
- "",
320
- "**RECORD INLINE \u2014 Don't wait for steps 5-8:**",
321
- "- After EVERY `read` that finds new files \u2192 call `research_save` mini (persist file nodes)",
322
- "- After EVERY `grep` that discovers new functions \u2192 call `research_save` (persist function nodes)",
323
- "- When you discover a bug/quirk \u2192 call `gotcha` IMMEDIATELY (not at step 6)",
324
- "- When you trace a data flow hop \u2192 call `arch_flow` IMMEDIATELY (not at step 7)",
325
- "- When you choose between options \u2192 call `decision` IMMEDIATELY (not at step 8)",
350
+ "> \u{1F52C} **Scanner vs Inline Recording:**",
351
+ "> \u2022 Scanner = cold start only. Auto-detects structure in TS/JS/TSX/JSX files during research step 3.",
352
+ "> \u2022 Inline Recording = primary method. You (the agent) record findings as you read/grep/edit.",
353
+ "> \u2022 Non-TS/JS projects (Go, Ruby, Python, Rust, PHP) rely ENTIRELY on inline recording.",
354
+ "",
355
+ "**AUTO-RECORDED (cold start scanner \u2014 TS/JS only):**",
356
+ "- Files, Functions, Classes \u2192 scanned during research step 3",
357
+ "- Imports, Calls, Extends \u2192 scanned edges",
358
+ "- Components, Routes \u2192 scanned when patterns match",
359
+ "",
360
+ "\u{1F534} **MUST RECORD \u2014 High Impact (use MCP):**",
361
+ "- `arch_flow` \u2014 IMMEDIATELY after each flow hop. Saves reading 5-10 files next session.",
362
+ "- `gotcha` \u2014 IMMEDIATELY when bug/quirk found. No re-research needed.",
363
+ "- `decision` \u2014 IMMEDIATELY when choosing. Preserves rationale context.",
364
+ "- `research_save` \u2014 After exploring area. Creates searchable cache + graph file node.",
365
+ "",
366
+ "\u{1F7E2} **SKIP \u2014 Low Impact (agent can grep faster):**",
367
+ "- Function/class nodes \u2192 grep `funcName(` / `class ClassName`",
368
+ "- Component nodes \u2192 glob `**/*ComponentName*`",
369
+ "- Import edges \u2192 check imports directly",
370
+ "- Route nodes \u2192 check router file directly",
371
+ "- Visual graph \u2192 for humans, not AI agents",
372
+ "",
373
+ "**RECORD INLINE \u2014 Focus on high-impact actions:**",
374
+ "- Finished tracing a flow? \u2192 `arch_flow` IMMEDIATELY (saves reading 5-10 files next session)",
375
+ "- Found a bug/quirk? \u2192 `gotcha` IMMEDIATELY (no re-research needed)",
376
+ "- Chose between options? \u2192 `decision` IMMEDIATELY (preserves rationale)",
377
+ "- Explored a new area? \u2192 `research_save` (creates searchable cache)",
378
+ "",
379
+ "**SKIP recording these \u2014 grep/glob is faster:**",
380
+ "- Function/class nodes \u2192 just `grep funcName(` or `grep class ClassName`",
381
+ "- Component/route nodes \u2192 glob directly",
382
+ "- Import edges \u2192 read import statements",
383
+ "- Visual graph \u2192 for humans, not AI",
326
384
  "",
327
385
  "### STEP 5: Save Research (RECORD INLINE \u2014 After Every Read/Grep)",
328
386
  "```",
@@ -398,6 +456,7 @@ function generateInitMdContent() {
398
456
  "| `todo` | Persistent todo CRUD | When managing tasks |",
399
457
  "| `context` | Inject context notes | Additional notes when needed |",
400
458
  "| `domain_rules` | Layer 1: business rules | Record business rules when discovered |",
459
+ "| `add_node` | Create structural nodes (low impact \u2014 grep is faster) | Rarely needed; only for visualize debugging |",
401
460
  "| `layers` | Show all 3 layers summary | Overview memory layers |",
402
461
  "",
403
462
  "### \u{1F6E1}\uFE0F kuma_safety \u2014 Safety & Policy",
@@ -431,6 +490,8 @@ function generateInitMdContent() {
431
490
  "| \u25B2 `triangle` | route | API routes | AUTO by scanner |",
432
491
  "| \u2B52 `star` | test | Test files/describes | AUTO by scanner |",
433
492
  "| \u{1F4C4} `note` | context | Manual context notes | MANUAL \u2014 kuma_memory context |",
493
+ "| \u{1F3DB}\uFE0F `feature_domain` | FeatureDomain | High-level feature domain anchor | MANUAL \u2014 kuma_memory arch_flow (domain:) |",
494
+ "| \u{1F517} `cross_service_link` | Workflow hop | Cross-service/inter-file flow step | MANUAL \u2014 kuma_memory arch_flow (hops:) |",
434
495
  "| \u{1F3F7}\uFE0F `tag` | domain_rule | Business rules (Layer 1) | MANUAL \u2014 kuma_memory domain_rules |",
435
496
  "| \u{1F500} `flow` | arch_flow | Architecture flows (Layer 2) | MANUAL \u2014 kuma_memory arch_flow |",
436
497
  "| \u26A0\uFE0F `warning` | gotcha | Known gotchas (Layer 3) | MANUAL \u2014 kuma_memory gotcha |",
@@ -457,14 +518,15 @@ function generateInitMdContent() {
457
518
  " 2. kuma_safety \u2192 guard \u2014 Safety check",
458
519
  " 3. kuma_context \u2192 research \u2014 Research target area",
459
520
  " --- EDIT/READ (use native tools) ---",
460
- " 5. kuma_memory \u2192 research_save \u2014 Save findings (inline after every read/grep)",
461
- " 6. kuma_memory \u2192 gotcha \u2014 Record bugs/quirks (inline when found)",
462
- " 7. kuma_memory \u2192 arch_flow \u2014 Record data flow (inline after each hop)",
463
- " 8. kuma_memory \u2192 decision \u2014 Record key decisions (inline when choosing)",
521
+ " 5. kuma_memory \u2192 research_save \u2014 After exploring area (creates search cache)",
522
+ " 6. kuma_memory \u2192 gotcha \u2014 \u{1F525} IMMEDIATELY when bug found (exponential)",
523
+ " 7. kuma_memory \u2192 arch_flow \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential)",
524
+ " 8. kuma_memory \u2192 decision \u2014 When choosing (preserves rationale)",
464
525
  " 9. kuma_safety \u2192 verify \u2014 Run tests / confirm nothing broken",
465
526
  " 10. kuma_context \u2192 changes \u2014 Review session activity",
466
527
  "",
467
- "\u{1F504} Record INLINE as you work \u2014 not just at steps 5-8. Every read/grep = mini research_save.",
528
+ "\u{1F525} `arch_flow` + `gotcha` are EXPONENTIAL \u2014 each record saves 5-10 files next session.",
529
+ "\u{1F7E2} SKIP recording function/class/component nodes \u2014 grep/glob is faster.",
468
530
  "\u{1F9E0} Graph is persistent \u2014 nodes/edges accumulate across sessions.",
469
531
  "",
470
532
  "ON DISCOVERY (When needed):",
@@ -472,14 +534,19 @@ function generateInitMdContent() {
472
534
  " kuma_memory \u2192 context \u2014 Additional notes",
473
535
  " kuma_memory \u2192 todo \u2014 Task management",
474
536
  " kuma_memory \u2192 mine \u2014 Historical context",
537
+ " kuma_memory \u2192 add_node \u2014 Manual function/class/component node (for visualize)",
475
538
  "```",
476
539
  "",
477
540
  "## \u{1F9E0} How the Scanner Works",
478
541
  "",
479
- "Kuma's code scanner (`kumaCodeScanner.ts`) uses **regex-based pattern matching**",
480
- "to detect code structure. It is NOT a full AST parser (no Babel/TypeScript compiler dependency).",
542
+ "Kuma's code scanner (`kumaCodeScanner.ts`) uses **lightweight regex-based pattern matching**",
543
+ "for **cold start** \u2014 giving new agents basic project structure on first session.",
544
+ "It is NOT a full AST parser (no Babel/TypeScript compiler dependency).",
545
+ "",
546
+ "**Scope:** TS/JS/TSX/JSX only. Non-TypeScript projects (Go, Ruby, Python, Rust, PHP, etc.)",
547
+ "rely entirely on **AI inline recording** \u2014 the agent records what it discovers as it works.",
481
548
  "",
482
- "**What it detects (line-by-line regex):**",
549
+ "**What auto-scanner detects (line-by-line regex, TS/JS only):**",
483
550
  "- `function` declarations (named + async + generator)",
484
551
  "- Arrow function assignments (`const foo = (...) => ...`)",
485
552
  "- Typed arrow functions (`const foo: Type = (...) => ...`)",
@@ -491,41 +558,41 @@ function generateInitMdContent() {
491
558
  "- Test files (`.test.`, `.spec.`, `__tests__/`)",
492
559
  "",
493
560
  "**Known limitations:**",
494
- "- Regex-based = can miss multi-line constructs or non-standard patterns",
561
+ "- Regex-based: can miss multi-line constructs or non-standard patterns",
495
562
  "- Complex generics or deeply nested syntax may not match",
496
563
  "- TypeScript advanced types may be partially parsed",
497
- "- Scanner runs automatically during `kuma_context research` step 3",
564
+ "- Scanner runs during `kuma_context research` step 3 (max 200 files)",
498
565
  "- If scanner returns 0 structural nodes, the regex patterns didn't match your code style",
499
566
  "",
500
- "**For richer code analysis:**",
501
- "- Record findings INLINE as you read/grep \u2014 this builds the graph manually",
502
- "- Call `research_save` after exploring files to persist function/class/import nodes",
503
- "- The more you use Kuma, the richer the graph becomes (persistent across sessions)",
567
+ "**Key principle: Scanner = cold start, Inline Recording = primary.**",
568
+ "The scanner populates initial graph structure. Every subsequent session, the agent's",
569
+ "inline recording (research_save, gotcha, arch_flow, decision) enriches the graph further.",
570
+ "The more you use Kuma, the richer the graph becomes \u2014 persistent across sessions.",
504
571
  "",
505
572
  "---",
506
573
  "",
507
- "## \u{1F4BE} How to Read Memory & Search the Graph",
574
+ "## \u{1F4BE} How to Retrieve Past Research \u2014 research_save \u2192 search",
508
575
  "",
509
- "Kuma stores knowledge in two places:",
576
+ "Kuma stores knowledge in two places. The primary retrieval method for AI agents",
577
+ "is **`search`**, not `visualize`. Visualize is for human debugging, not agent consumption.",
510
578
  "",
511
- "**1. Knowledge Graph (SQLite - `.kuma/kuma.db`)**",
512
- "- Nodes: files, functions, classes, components, routes, tests, gotchas, decisions",
513
- "- Edges: imports, calls, extends, contains, composes, routes",
514
- '- Query: `kuma_memory({ action: "search", query: "<term>" })`',
515
- "- Falls back to codebase grep if graph is empty",
579
+ "**Flow: research_save \u2192 search (for agents)**",
580
+ '- Save: `kuma_memory({ action: "research_save", scope: "<file or area>", confidence: 0.8 })`',
581
+ '- Retrieve: `kuma_memory({ action: "search", query: "<term>" })`',
582
+ '- Auto-load: `kuma_context({ action: "research", scope: "<area>" })`',
583
+ '- List cache: `kuma_context({ action: "researches" })`',
516
584
  "",
517
- "**2. Research Cache (SQLite - `.kuma/kuma.db`)**",
518
- '- Saved via `kuma_memory({ action: "research_save", scope: "<area>", confidence: 0.8 })`',
519
- '- List: `kuma_context({ action: "researches" })`',
520
- '- Auto-loaded during `kuma_context({ action: "research", scope: "<area>" })`',
585
+ "**Key design:** `research_save` now creates BOTH research cache entries AND",
586
+ "knowledge graph nodes (file + research scope). This means `search` finds",
587
+ "past research even if the graph scanner didn't detect your code style.",
521
588
  "",
522
- "**Quick memory reading tips:**",
589
+ "**Quick retrieval tips:**",
590
+ '- `kuma_memory({ action: "search", query: "<term>" })` \u2014 **primary method**. Finds past research + graph nodes + codebase',
591
+ '- `kuma_context({ action: "research", scope: "<area>" })` \u2014 deep 5-step research, auto-loads past cache',
523
592
  '- `kuma_context({ action: "init" })` \u2014 shows graph stats + recent research + health score',
524
- '- `kuma_context({ action: "research", scope: "<area>" })` \u2014 deep research with graph query',
525
- '- `kuma_memory({ action: "search", query: "<term>" })` \u2014 search all memories + graph',
526
- '- `kuma_context({ action: "visualize" })` \u2014 Mermaid diagram of the graph',
527
593
  '- `kuma_context({ action: "drift" })` \u2014 check if memories are stale vs actual code',
528
594
  '- `kuma_context({ action: "changes" })` \u2014 view session activity log',
595
+ '- `kuma_context({ action: "visualize" })` \u2014 (human debugging) Mermaid diagram of the graph',
529
596
  "",
530
597
  "---",
531
598
  "",
@@ -598,14 +665,15 @@ function handleOpencodeSecondary(root, results) {
598
665
  ' 2. `kuma_kuma_safety({ action: "guard" })` \u2014 Safety check before work',
599
666
  ' 3. `kuma_kuma_context({ action: "research", scope: "<area>" })` \u2014 Research before editing',
600
667
  " 4. *(edit/read using native tools)*",
601
- ' 5. `kuma_kuma_memory({ action: "research_save", ... })` \u2014 Save findings (inline after every read/grep)',
602
- ' 6. `kuma_kuma_memory({ action: "gotcha" })` \u2014 Record bugs/quirks (inline when found)',
603
- ' 7. `kuma_kuma_memory({ action: "arch_flow" })` \u2014 Record data flow (inline after each hop)',
604
- ' 8. `kuma_kuma_memory({ action: "decision" })` \u2014 Record key decisions (inline when choosing)',
668
+ ' 5. `kuma_kuma_memory({ action: "research_save", ... })` \u2014 After exploring area (creates search cache)',
669
+ ' 6. `kuma_kuma_memory({ action: "gotcha" })` \u2014 \u{1F525} IMMEDIATELY when bug found (exponential)',
670
+ ' 7. `kuma_kuma_memory({ action: "arch_flow" })` \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential)',
671
+ ' 8. `kuma_kuma_memory({ action: "decision" })` \u2014 When choosing (preserves rationale)',
605
672
  ' 9. `kuma_kuma_safety({ action: "verify", ... })` \u2014 Run tests / confirm nothing broken',
606
673
  ' 10. `kuma_kuma_context({ action: "changes" })` \u2014 Review session activity',
607
674
  "",
608
- "\u{1F504} Record findings INLINE as you work \u2014 Every read/grep = mini research_save.",
675
+ "\u{1F525} `arch_flow` + `gotcha` = EXPONENTIAL value. Each record saves 5-10 files next session.",
676
+ "\u{1F7E2} SKIP recording function/class/component nodes \u2014 grep/glob is faster.",
609
677
  "\u{1F9E0} Graph is persistent \u2014 nodes/edges accumulate across sessions.",
610
678
  "",
611
679
  "\u26A0\uFE0F **OpenCode platform note:** Tool names are prefixed with `kuma_kuma_*`",
@@ -729,14 +797,15 @@ function getCombinedAgentsMd(selectedTypes) {
729
797
  ' 2. `[kuma_]safety({ action: "guard" })` \u2014 Safety check before editing',
730
798
  ' 3. `[kuma_]context({ action: "research", scope: "<area>" })` \u2014 Research before editing',
731
799
  " 4. *(edit/read using native tools)*",
732
- ' 5. `[kuma_]memory({ action: "research_save", ... })` \u2014 Save all findings',
733
- ' 6. `[kuma_]memory({ action: "gotcha" })` \u2014 Record bugs/quirks found',
734
- ' 7. `[kuma_]memory({ action: "arch_flow" })` \u2014 Record data flow if mapped',
735
- ' 8. `[kuma_]memory({ action: "decision" })` \u2014 Record key findings/decisions',
800
+ ' 5. `[kuma_]memory({ action: "research_save", ... })` \u2014 After exploring area (creates search cache)',
801
+ ' 6. `[kuma_]memory({ action: "gotcha" })` \u2014 \u{1F525} IMMEDIATELY when bug found (exponential)',
802
+ ' 7. `[kuma_]memory({ action: "arch_flow" })` \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential)',
803
+ ' 8. `[kuma_]memory({ action: "decision" })` \u2014 When choosing (preserves rationale)',
736
804
  ' 9. `[kuma_]safety({ action: "verify", ... })` \u2014 Run tests / confirm nothing broken',
737
805
  ' 10. `[kuma_]context({ action: "changes" })` \u2014 Review session activity',
738
806
  "",
739
- "\u{1F504} Record findings INLINE as you work \u2014 Every read/grep = mini research_save.",
807
+ "\u{1F525} `arch_flow` + `gotcha` = EXPONENTIAL value. Each record saves 5-10 files next session.",
808
+ "\u{1F7E2} SKIP recording function/class/component nodes \u2014 grep/glob is faster.",
740
809
  "\u{1F9E0} Graph is persistent \u2014 nodes/edges accumulate across sessions.",
741
810
  "",
742
811
  "\u26D4 Do NOT skip steps 5-10 after research \u2014 even if no code was changed.",
@@ -946,15 +1015,16 @@ function handleQuickrefGeneration(root, results) {
946
1015
  ' 2. `kuma_safety({ action: "guard" })` \u2014 Safety check',
947
1016
  ' 3. `kuma_context({ action: "research", scope: "<area>" })` \u2014 Research',
948
1017
  " 4. *(edit/read using native tools)*",
949
- ' 5. `kuma_memory({ action: "research_save", ... })` \u2014 Save findings (inline after every read)',
950
- ' 6. `kuma_memory({ action: "gotcha" })` \u2014 Gotchas (inline when found)',
951
- ' 7. `kuma_memory({ action: "arch_flow" })` \u2014 Arch flow (inline after each hop)',
952
- ' 8. `kuma_memory({ action: "decision" })` \u2014 Decision (inline when choosing)',
953
- ' 9. `kuma_safety({ action: "verify", ... })` \u2014 Verify',
954
- ' 10. `kuma_context({ action: "changes" })` \u2014 Review changes',
955
- "",
956
- "\u{1F504} Record INLINE as you work \u2014 Every read/grep = mini research_save.",
957
- "\u{1F9E0} Graph is persistent \u2014 accumulates across sessions.",
1018
+ ' 5. `kuma_memory({ action: "research_save", ... })` \u2014 After exploring area (creates search cache)',
1019
+ ' 6. `kuma_memory({ action: "gotcha" })` \u2014 \u{1F525} IMMEDIATELY when bug found (exponential)',
1020
+ ' 7. `kuma_memory({ action: "arch_flow" })` \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential)',
1021
+ ' 8. `kuma_memory({ action: "decision" })` \u2014 When choosing (preserves rationale)',
1022
+ ' 9. `kuma_safety({ action: "verify", ... })` \u2014 Run tests / confirm nothing broken',
1023
+ ' 10. `kuma_context({ action: "changes" })` \u2014 Review session activity',
1024
+ "",
1025
+ "\u{1F525} `arch_flow` + `gotcha` = EXPONENTIAL value. Each record saves 5-10 files next session.",
1026
+ "\u{1F7E2} SKIP recording function/class/component nodes \u2014 grep/glob is faster.",
1027
+ "\u{1F9E0} Graph is persistent \u2014 nodes/edges accumulate across sessions.",
958
1028
  "",
959
1029
  "\u26D4 Steps 5-10 are mandatory even for research-only sessions!",
960
1030
  "",
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  sessionMemory
3
- } from "./chunk-R6B3VUSB.js";
3
+ } from "./chunk-LVKOGXLC.js";
4
4
  import {
5
5
  getProjectRoot
6
6
  } from "./chunk-E2KFPEBT.js";
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getDb,
3
3
  saveDb
4
- } from "./chunk-3TX6Q37T.js";
4
+ } from "./chunk-3BRBJZ7P.js";
5
5
 
6
6
  // src/engine/safetyAudit.ts
7
7
  var SCHEMA_SQL = `
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  sessionMemory
3
- } from "./chunk-R6B3VUSB.js";
3
+ } from "./chunk-LVKOGXLC.js";
4
4
  import {
5
5
  getProjectRoot
6
6
  } from "./chunk-E2KFPEBT.js";
@@ -82,7 +82,7 @@ function recordDecision(decision) {
82
82
  }
83
83
  async function recordDecisionToGraph(decision) {
84
84
  try {
85
- const { upsertNode, addEdge } = await import("./kumaGraph-GUQM75WL.js");
85
+ const { upsertNode, addEdge } = await import("./kumaGraph-UMXZNGYF.js");
86
86
  const decisionId = `decision::${decision.title.replace(/[^a-zA-Z0-9_\-\s]/g, "").trim().replace(/\s+/g, "-")}`;
87
87
  await upsertNode({
88
88
  id: decisionId,
@@ -320,7 +320,7 @@ No unresolved issues.`;
320
320
  */
321
321
  async autoTrackToDb(toolName, params, timestamp) {
322
322
  try {
323
- const { getDb, saveDb } = await import("./kumaDb-IC7UX7PU.js");
323
+ const { getDb, saveDb } = await import("./kumaDb-4XZ5S2LH.js");
324
324
  const db = await getDb();
325
325
  db.run(
326
326
  `INSERT INTO tool_calls (tool_name, params, success, duration_ms, created_at) VALUES (?, ?, 1, 0, ?)`,
@@ -605,7 +605,7 @@ No unresolved issues.`;
605
605
  this.addModifiedFile(filePath);
606
606
  }
607
607
  try {
608
- const { recordChange } = await import("./kumaDb-IC7UX7PU.js");
608
+ const { recordChange } = await import("./kumaDb-4XZ5S2LH.js");
609
609
  const gitHash = this.getGitHead();
610
610
  await recordChange({ filePath, changeType, symbol, gitCommitHash: gitHash || void 0 });
611
611
  } catch {
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  getDb,
3
3
  saveDb
4
- } from "./chunk-3TX6Q37T.js";
4
+ } from "./chunk-3BRBJZ7P.js";
5
5
  import {
6
6
  getProjectRoot
7
7
  } from "./chunk-E2KFPEBT.js";
@@ -319,6 +319,144 @@ async function recordApiRoute(route, handler) {
319
319
  await upsertNode({ id: handlerId, type: "function", name: handler });
320
320
  await addEdge({ sourceId: routeId, targetId: handlerId, type: "routes" });
321
321
  }
322
+ async function recordDomainFlow(params) {
323
+ let nodeCount = 0;
324
+ let edgeCount = 0;
325
+ try {
326
+ const domainId = nodeId("feature_domain", params.domain);
327
+ await upsertNode({
328
+ id: domainId,
329
+ type: "feature_domain",
330
+ name: params.domain,
331
+ metadata: {
332
+ hops: params.hops.length,
333
+ gotchas: params.gotchas?.length || 0,
334
+ decisions: params.decisions?.length || 0,
335
+ filePaths: params.filePaths || []
336
+ }
337
+ });
338
+ nodeCount++;
339
+ for (let i = 0; i < params.hops.length; i++) {
340
+ const hop = params.hops[i];
341
+ const fromId = nodeId("cross_service_link", `${params.domain}::${hop.from}`);
342
+ await upsertNode({
343
+ id: fromId,
344
+ type: "cross_service_link",
345
+ name: hop.from,
346
+ metadata: {
347
+ domain: params.domain,
348
+ relation: hop.relation,
349
+ description: hop.description || "",
350
+ hopIndex: i
351
+ }
352
+ });
353
+ nodeCount++;
354
+ const toId = nodeId("cross_service_link", `${params.domain}::${hop.to}`);
355
+ await upsertNode({
356
+ id: toId,
357
+ type: "cross_service_link",
358
+ name: hop.to,
359
+ metadata: {
360
+ domain: params.domain,
361
+ relation: hop.relation,
362
+ description: hop.description || "",
363
+ hopIndex: i
364
+ }
365
+ });
366
+ nodeCount++;
367
+ await addEdge({
368
+ sourceId: fromId,
369
+ targetId: toId,
370
+ type: "flows_through",
371
+ metadata: { relation: hop.relation, description: hop.description }
372
+ });
373
+ edgeCount++;
374
+ await addEdge({
375
+ sourceId: domainId,
376
+ targetId: fromId,
377
+ type: "contains",
378
+ metadata: { hopIndex: i }
379
+ });
380
+ edgeCount++;
381
+ await addEdge({
382
+ sourceId: domainId,
383
+ targetId: toId,
384
+ type: "contains",
385
+ metadata: { hopIndex: i }
386
+ });
387
+ edgeCount++;
388
+ }
389
+ if (params.gotchas) {
390
+ for (const gotcha of params.gotchas) {
391
+ const gotchaId = `gotcha::${params.domain}::${gotcha.substring(0, 40)}`;
392
+ try {
393
+ await upsertNode({
394
+ id: gotchaId,
395
+ type: "variable",
396
+ name: `gotcha:${gotcha.substring(0, 60)}`,
397
+ metadata: { domain: params.domain, gotcha, source: "arch_flow" }
398
+ });
399
+ nodeCount++;
400
+ await addEdge({
401
+ sourceId: domainId,
402
+ targetId: gotchaId,
403
+ type: "depends_on",
404
+ metadata: { type: "gotcha" }
405
+ });
406
+ edgeCount++;
407
+ } catch {
408
+ }
409
+ }
410
+ }
411
+ if (params.decisions) {
412
+ for (const decision of params.decisions) {
413
+ const decisionId = `decision::${params.domain}::${decision.substring(0, 40)}`;
414
+ try {
415
+ await upsertNode({
416
+ id: decisionId,
417
+ type: "variable",
418
+ name: `decision:${decision.substring(0, 60)}`,
419
+ metadata: { domain: params.domain, decision, source: "arch_flow" }
420
+ });
421
+ nodeCount++;
422
+ await addEdge({
423
+ sourceId: domainId,
424
+ targetId: decisionId,
425
+ type: "depends_on",
426
+ metadata: { type: "decision" }
427
+ });
428
+ edgeCount++;
429
+ } catch {
430
+ }
431
+ }
432
+ }
433
+ if (params.filePaths) {
434
+ for (const fp of params.filePaths) {
435
+ const fileId = nodeId("file", fp);
436
+ try {
437
+ await upsertNode({
438
+ id: fileId,
439
+ type: "file",
440
+ name: fp
441
+ });
442
+ nodeCount++;
443
+ await addEdge({
444
+ sourceId: domainId,
445
+ targetId: fileId,
446
+ type: "owns",
447
+ metadata: { domain: params.domain }
448
+ });
449
+ edgeCount++;
450
+ } catch {
451
+ }
452
+ }
453
+ }
454
+ return { nodeCount, edgeCount };
455
+ } catch (err) {
456
+ console.error(`[KumaGraph] Failed to record domain flow: ${err}`);
457
+ return { nodeCount, edgeCount };
458
+ }
459
+ }
322
460
  async function queryGraph(params) {
323
461
  try {
324
462
  const db = await getDb();
@@ -353,7 +491,7 @@ Try a different search term or check if the graph has been built by using tools
353
491
  ""
354
492
  ];
355
493
  for (const r of results) {
356
- const typeEmoji = r.type === "function" ? "\u{1F527}" : r.type === "file" ? "\u{1F4C4}" : r.type === "test" ? "\u{1F9EA}" : r.type === "api_route" ? "\u{1F310}" : r.type === "db_table" ? "\u{1F5C4}\uFE0F" : r.type === "class" ? "\u{1F3D7}\uFE0F" : "\u{1F4CC}";
494
+ const typeEmoji = r.type === "function" ? "\u{1F527}" : r.type === "file" ? "\u{1F4C4}" : r.type === "test" ? "\u{1F9EA}" : r.type === "api_route" ? "\u{1F310}" : r.type === "db_table" ? "\u{1F5C4}\uFE0F" : r.type === "class" ? "\u{1F3D7}\uFE0F" : r.type === "feature_domain" ? "\u{1F3DB}\uFE0F" : r.type === "workflow" ? "\u{1F504}" : r.type === "cross_service_link" ? "\u{1F517}" : "\u{1F4CC}";
357
495
  lines.push(`${typeEmoji} **${r.name}** (${r.type})`);
358
496
  if (r.file_path) lines.push(` \u{1F4CD} ${r.file_path}`);
359
497
  }
@@ -458,7 +596,7 @@ The two nodes may not be connected in the knowledge graph yet. Use more tools to
458
596
  }
459
597
  async function buildFromSessionMemory() {
460
598
  try {
461
- const { sessionMemory } = await import("./sessionMemory-4UWA3E5J.js");
599
+ const { sessionMemory } = await import("./sessionMemory-YPKVIOMV.js");
462
600
  const toolCalls = sessionMemory.getToolCallHistory(50);
463
601
  let edgeCount = 0;
464
602
  for (const call of toolCalls) {
@@ -757,7 +895,7 @@ async function getGraphStats() {
757
895
  if (typeCounts.length > 0) {
758
896
  lines.push("**Node Types:**");
759
897
  for (const t of typeCounts) {
760
- const emoji = t.type === "function" ? "\u{1F527}" : t.type === "file" ? "\u{1F4C4}" : t.type === "test" ? "\u{1F9EA}" : t.type === "api_route" ? "\u{1F310}" : t.type === "db_table" ? "\u{1F5C4}\uFE0F" : t.type === "class" ? "\u{1F3D7}\uFE0F" : "\u{1F4CC}";
898
+ const emoji = t.type === "function" ? "\u{1F527}" : t.type === "file" ? "\u{1F4C4}" : t.type === "test" ? "\u{1F9EA}" : t.type === "api_route" ? "\u{1F310}" : t.type === "db_table" ? "\u{1F5C4}\uFE0F" : t.type === "class" ? "\u{1F3D7}\uFE0F" : t.type === "feature_domain" ? "\u{1F3DB}\uFE0F" : t.type === "workflow" ? "\u{1F504}" : t.type === "cross_service_link" ? "\u{1F517}" : "\u{1F4CC}";
761
899
  lines.push(` ${emoji} ${t.type}: ${t.cnt}`);
762
900
  }
763
901
  }
@@ -961,6 +1099,7 @@ export {
961
1099
  recordImport,
962
1100
  recordTestRelation,
963
1101
  recordApiRoute,
1102
+ recordDomainFlow,
964
1103
  queryGraph,
965
1104
  buildFromSessionMemory,
966
1105
  searchGraph,