@plumpslabs/kuma 2.3.16 → 2.3.18
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/dist/{chunk-S7BQGNHQ.js → chunk-ZIXY2COZ.js} +148 -41
- package/dist/index.js +61 -9
- package/dist/{init-P3DAC23E.js → init-RUKOPMX6.js} +1 -1
- package/dist/{kumaCodeScanner-LFJGPJNH.js → kumaCodeScanner-2RDHZ5F4.js} +7 -10
- package/dist/{kumaVerifier-KAYJHR5K.js → kumaVerifier-6NTJQU7B.js} +8 -1
- package/dist/{skillGenerator-GYEDLFZP.js → skillGenerator-PWEJKZNX.js} +7 -5
- package/package.json +1 -1
|
@@ -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
|
|
80
|
-
' 6. `kuma_memory({ action: "gotcha" })` \u2014 IMMEDIATELY when bug
|
|
81
|
-
' 7. `kuma_memory({ action: "arch_flow" })` \u2014 IMMEDIATELY after
|
|
82
|
-
' 8. `kuma_memory({ action: "decision" })` \u2014
|
|
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{
|
|
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.",
|
|
@@ -309,20 +311,43 @@ function generateInitMdContent() {
|
|
|
309
311
|
"> \u26A0\uFE0F **Research-only sessions included.** Workflow ini wajib meskipun session hanya membaca/riset tanpa code changes.",
|
|
310
312
|
"",
|
|
311
313
|
"> \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
|
|
314
|
+
"> file, grep a pattern, or trace a flow \u2014 call `research_save` immediately to persist what you learned.",
|
|
313
315
|
"> The knowledge graph accumulates across sessions. The more you use it, the richer it becomes.",
|
|
314
316
|
"",
|
|
315
|
-
"
|
|
316
|
-
"-
|
|
317
|
-
"
|
|
318
|
-
"-
|
|
319
|
-
"",
|
|
320
|
-
"**
|
|
321
|
-
"-
|
|
322
|
-
"-
|
|
323
|
-
"-
|
|
324
|
-
"
|
|
325
|
-
"
|
|
317
|
+
"> \u{1F52C} **Scanner vs Inline Recording:**",
|
|
318
|
+
"> \u2022 Scanner = cold start only. Auto-detects structure in TS/JS/TSX/JSX files during research step 3.",
|
|
319
|
+
"> \u2022 Inline Recording = primary method. You (the agent) record findings as you read/grep/edit.",
|
|
320
|
+
"> \u2022 Non-TS/JS projects (Go, Ruby, Python, Rust, PHP) rely ENTIRELY on inline recording.",
|
|
321
|
+
"",
|
|
322
|
+
"**AUTO-RECORDED (cold start scanner \u2014 TS/JS only):**",
|
|
323
|
+
"- Files, Functions, Classes \u2192 scanned during research step 3",
|
|
324
|
+
"- Imports, Calls, Extends \u2192 scanned edges",
|
|
325
|
+
"- Components, Routes \u2192 scanned when patterns match",
|
|
326
|
+
"",
|
|
327
|
+
"\u{1F534} **MUST RECORD \u2014 High Impact (use MCP):**",
|
|
328
|
+
"- `arch_flow` \u2014 IMMEDIATELY after each flow hop. Saves reading 5-10 files next session.",
|
|
329
|
+
"- `gotcha` \u2014 IMMEDIATELY when bug/quirk found. No re-research needed.",
|
|
330
|
+
"- `decision` \u2014 IMMEDIATELY when choosing. Preserves rationale context.",
|
|
331
|
+
"- `research_save` \u2014 After exploring area. Creates searchable cache + graph file node.",
|
|
332
|
+
"",
|
|
333
|
+
"\u{1F7E2} **SKIP \u2014 Low Impact (agent can grep faster):**",
|
|
334
|
+
"- Function/class nodes \u2192 grep `funcName(` / `class ClassName`",
|
|
335
|
+
"- Component nodes \u2192 glob `**/*ComponentName*`",
|
|
336
|
+
"- Import edges \u2192 check imports directly",
|
|
337
|
+
"- Route nodes \u2192 check router file directly",
|
|
338
|
+
"- Visual graph \u2192 for humans, not AI agents",
|
|
339
|
+
"",
|
|
340
|
+
"**RECORD INLINE \u2014 Focus on high-impact actions:**",
|
|
341
|
+
"- Finished tracing a flow? \u2192 `arch_flow` IMMEDIATELY (saves reading 5-10 files next session)",
|
|
342
|
+
"- Found a bug/quirk? \u2192 `gotcha` IMMEDIATELY (no re-research needed)",
|
|
343
|
+
"- Chose between options? \u2192 `decision` IMMEDIATELY (preserves rationale)",
|
|
344
|
+
"- Explored a new area? \u2192 `research_save` (creates searchable cache)",
|
|
345
|
+
"",
|
|
346
|
+
"**SKIP recording these \u2014 grep/glob is faster:**",
|
|
347
|
+
"- Function/class nodes \u2192 just `grep funcName(` or `grep class ClassName`",
|
|
348
|
+
"- Component/route nodes \u2192 glob directly",
|
|
349
|
+
"- Import edges \u2192 read import statements",
|
|
350
|
+
"- Visual graph \u2192 for humans, not AI",
|
|
326
351
|
"",
|
|
327
352
|
"### STEP 5: Save Research (RECORD INLINE \u2014 After Every Read/Grep)",
|
|
328
353
|
"```",
|
|
@@ -398,6 +423,7 @@ function generateInitMdContent() {
|
|
|
398
423
|
"| `todo` | Persistent todo CRUD | When managing tasks |",
|
|
399
424
|
"| `context` | Inject context notes | Additional notes when needed |",
|
|
400
425
|
"| `domain_rules` | Layer 1: business rules | Record business rules when discovered |",
|
|
426
|
+
"| `add_node` | Create structural nodes (low impact \u2014 grep is faster) | Rarely needed; only for visualize debugging |",
|
|
401
427
|
"| `layers` | Show all 3 layers summary | Overview memory layers |",
|
|
402
428
|
"",
|
|
403
429
|
"### \u{1F6E1}\uFE0F kuma_safety \u2014 Safety & Policy",
|
|
@@ -457,14 +483,15 @@ function generateInitMdContent() {
|
|
|
457
483
|
" 2. kuma_safety \u2192 guard \u2014 Safety check",
|
|
458
484
|
" 3. kuma_context \u2192 research \u2014 Research target area",
|
|
459
485
|
" --- EDIT/READ (use native tools) ---",
|
|
460
|
-
" 5. kuma_memory \u2192 research_save \u2014
|
|
461
|
-
" 6. kuma_memory \u2192 gotcha \u2014
|
|
462
|
-
" 7. kuma_memory \u2192 arch_flow \u2014
|
|
463
|
-
" 8. kuma_memory \u2192 decision \u2014
|
|
486
|
+
" 5. kuma_memory \u2192 research_save \u2014 After exploring area (creates search cache)",
|
|
487
|
+
" 6. kuma_memory \u2192 gotcha \u2014 \u{1F525} IMMEDIATELY when bug found (exponential)",
|
|
488
|
+
" 7. kuma_memory \u2192 arch_flow \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential)",
|
|
489
|
+
" 8. kuma_memory \u2192 decision \u2014 When choosing (preserves rationale)",
|
|
464
490
|
" 9. kuma_safety \u2192 verify \u2014 Run tests / confirm nothing broken",
|
|
465
491
|
" 10. kuma_context \u2192 changes \u2014 Review session activity",
|
|
466
492
|
"",
|
|
467
|
-
"\u{
|
|
493
|
+
"\u{1F525} `arch_flow` + `gotcha` are EXPONENTIAL \u2014 each record saves 5-10 files next session.",
|
|
494
|
+
"\u{1F7E2} SKIP recording function/class/component nodes \u2014 grep/glob is faster.",
|
|
468
495
|
"\u{1F9E0} Graph is persistent \u2014 nodes/edges accumulate across sessions.",
|
|
469
496
|
"",
|
|
470
497
|
"ON DISCOVERY (When needed):",
|
|
@@ -472,8 +499,85 @@ function generateInitMdContent() {
|
|
|
472
499
|
" kuma_memory \u2192 context \u2014 Additional notes",
|
|
473
500
|
" kuma_memory \u2192 todo \u2014 Task management",
|
|
474
501
|
" kuma_memory \u2192 mine \u2014 Historical context",
|
|
502
|
+
" kuma_memory \u2192 add_node \u2014 Manual function/class/component node (for visualize)",
|
|
475
503
|
"```",
|
|
476
504
|
"",
|
|
505
|
+
"## \u{1F9E0} How the Scanner Works",
|
|
506
|
+
"",
|
|
507
|
+
"Kuma's code scanner (`kumaCodeScanner.ts`) uses **lightweight regex-based pattern matching**",
|
|
508
|
+
"for **cold start** \u2014 giving new agents basic project structure on first session.",
|
|
509
|
+
"It is NOT a full AST parser (no Babel/TypeScript compiler dependency).",
|
|
510
|
+
"",
|
|
511
|
+
"**Scope:** TS/JS/TSX/JSX only. Non-TypeScript projects (Go, Ruby, Python, Rust, PHP, etc.)",
|
|
512
|
+
"rely entirely on **AI inline recording** \u2014 the agent records what it discovers as it works.",
|
|
513
|
+
"",
|
|
514
|
+
"**What auto-scanner detects (line-by-line regex, TS/JS only):**",
|
|
515
|
+
"- `function` declarations (named + async + generator)",
|
|
516
|
+
"- Arrow function assignments (`const foo = (...) => ...`)",
|
|
517
|
+
"- Typed arrow functions (`const foo: Type = (...) => ...`)",
|
|
518
|
+
"- Class declarations (includes extends/implements)",
|
|
519
|
+
"- React/Vue components (functions returning JSX)",
|
|
520
|
+
"- API route handlers (Express + Hono patterns)",
|
|
521
|
+
"- Import statements (local file imports only)",
|
|
522
|
+
"- Function calls cross-file (`calls` edges)",
|
|
523
|
+
"- Test files (`.test.`, `.spec.`, `__tests__/`)",
|
|
524
|
+
"",
|
|
525
|
+
"**Known limitations:**",
|
|
526
|
+
"- Regex-based: can miss multi-line constructs or non-standard patterns",
|
|
527
|
+
"- Complex generics or deeply nested syntax may not match",
|
|
528
|
+
"- TypeScript advanced types may be partially parsed",
|
|
529
|
+
"- Scanner runs during `kuma_context research` step 3 (max 200 files)",
|
|
530
|
+
"- If scanner returns 0 structural nodes, the regex patterns didn't match your code style",
|
|
531
|
+
"",
|
|
532
|
+
"**Key principle: Scanner = cold start, Inline Recording = primary.**",
|
|
533
|
+
"The scanner populates initial graph structure. Every subsequent session, the agent's",
|
|
534
|
+
"inline recording (research_save, gotcha, arch_flow, decision) enriches the graph further.",
|
|
535
|
+
"The more you use Kuma, the richer the graph becomes \u2014 persistent across sessions.",
|
|
536
|
+
"",
|
|
537
|
+
"---",
|
|
538
|
+
"",
|
|
539
|
+
"## \u{1F4BE} How to Retrieve Past Research \u2014 research_save \u2192 search",
|
|
540
|
+
"",
|
|
541
|
+
"Kuma stores knowledge in two places. The primary retrieval method for AI agents",
|
|
542
|
+
"is **`search`**, not `visualize`. Visualize is for human debugging, not agent consumption.",
|
|
543
|
+
"",
|
|
544
|
+
"**Flow: research_save \u2192 search (for agents)**",
|
|
545
|
+
'- Save: `kuma_memory({ action: "research_save", scope: "<file or area>", confidence: 0.8 })`',
|
|
546
|
+
'- Retrieve: `kuma_memory({ action: "search", query: "<term>" })`',
|
|
547
|
+
'- Auto-load: `kuma_context({ action: "research", scope: "<area>" })`',
|
|
548
|
+
'- List cache: `kuma_context({ action: "researches" })`',
|
|
549
|
+
"",
|
|
550
|
+
"**Key design:** `research_save` now creates BOTH research cache entries AND",
|
|
551
|
+
"knowledge graph nodes (file + research scope). This means `search` finds",
|
|
552
|
+
"past research even if the graph scanner didn't detect your code style.",
|
|
553
|
+
"",
|
|
554
|
+
"**Quick retrieval tips:**",
|
|
555
|
+
'- `kuma_memory({ action: "search", query: "<term>" })` \u2014 **primary method**. Finds past research + graph nodes + codebase',
|
|
556
|
+
'- `kuma_context({ action: "research", scope: "<area>" })` \u2014 deep 5-step research, auto-loads past cache',
|
|
557
|
+
'- `kuma_context({ action: "init" })` \u2014 shows graph stats + recent research + health score',
|
|
558
|
+
'- `kuma_context({ action: "drift" })` \u2014 check if memories are stale vs actual code',
|
|
559
|
+
'- `kuma_context({ action: "changes" })` \u2014 view session activity log',
|
|
560
|
+
'- `kuma_context({ action: "visualize" })` \u2014 (human debugging) Mermaid diagram of the graph',
|
|
561
|
+
"",
|
|
562
|
+
"---",
|
|
563
|
+
"",
|
|
564
|
+
"## \u{1F52C} How Verification Works",
|
|
565
|
+
"",
|
|
566
|
+
'`kuma_safety({ action: "verify", scope: "<area>" })` \u2014 STEP 9',
|
|
567
|
+
"",
|
|
568
|
+
"**Auto-detection logic:**",
|
|
569
|
+
"1. Checks `package.json` \u2192 `scripts.test` \u2192 uses npm/pnpm/yarn test",
|
|
570
|
+
"2. If no test script, checks for Makefile with `test:` target",
|
|
571
|
+
"3. Falls back to Python (pytest), Rust (cargo test), Go (go test)",
|
|
572
|
+
"4. Last resort: `npx tsc --noEmit` (TypeScript syntax check) or `node -c`",
|
|
573
|
+
"5. If nothing found: returns informative message instead of failing",
|
|
574
|
+
"",
|
|
575
|
+
"**Important:** Verification is NEVER auto-triggered. You must call it explicitly.",
|
|
576
|
+
"The 5-layer safety guard (concurrency lock, rate limiting, staleness cache,",
|
|
577
|
+
"runaway detection, hard timeout) prevents resource exhaustion.",
|
|
578
|
+
"",
|
|
579
|
+
"---",
|
|
580
|
+
"",
|
|
477
581
|
"## \u{1F6AB} What Kuma Does NOT Do (Use Agent Native Tools)",
|
|
478
582
|
"",
|
|
479
583
|
"| Function | Correct Tool |",
|
|
@@ -526,14 +630,15 @@ function handleOpencodeSecondary(root, results) {
|
|
|
526
630
|
' 2. `kuma_kuma_safety({ action: "guard" })` \u2014 Safety check before work',
|
|
527
631
|
' 3. `kuma_kuma_context({ action: "research", scope: "<area>" })` \u2014 Research before editing',
|
|
528
632
|
" 4. *(edit/read using native tools)*",
|
|
529
|
-
' 5. `kuma_kuma_memory({ action: "research_save", ... })` \u2014
|
|
530
|
-
' 6. `kuma_kuma_memory({ action: "gotcha" })` \u2014
|
|
531
|
-
' 7. `kuma_kuma_memory({ action: "arch_flow" })` \u2014
|
|
532
|
-
' 8. `kuma_kuma_memory({ action: "decision" })` \u2014
|
|
633
|
+
' 5. `kuma_kuma_memory({ action: "research_save", ... })` \u2014 After exploring area (creates search cache)',
|
|
634
|
+
' 6. `kuma_kuma_memory({ action: "gotcha" })` \u2014 \u{1F525} IMMEDIATELY when bug found (exponential)',
|
|
635
|
+
' 7. `kuma_kuma_memory({ action: "arch_flow" })` \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential)',
|
|
636
|
+
' 8. `kuma_kuma_memory({ action: "decision" })` \u2014 When choosing (preserves rationale)',
|
|
533
637
|
' 9. `kuma_kuma_safety({ action: "verify", ... })` \u2014 Run tests / confirm nothing broken',
|
|
534
638
|
' 10. `kuma_kuma_context({ action: "changes" })` \u2014 Review session activity',
|
|
535
639
|
"",
|
|
536
|
-
"\u{
|
|
640
|
+
"\u{1F525} `arch_flow` + `gotcha` = EXPONENTIAL value. Each record saves 5-10 files next session.",
|
|
641
|
+
"\u{1F7E2} SKIP recording function/class/component nodes \u2014 grep/glob is faster.",
|
|
537
642
|
"\u{1F9E0} Graph is persistent \u2014 nodes/edges accumulate across sessions.",
|
|
538
643
|
"",
|
|
539
644
|
"\u26A0\uFE0F **OpenCode platform note:** Tool names are prefixed with `kuma_kuma_*`",
|
|
@@ -657,14 +762,15 @@ function getCombinedAgentsMd(selectedTypes) {
|
|
|
657
762
|
' 2. `[kuma_]safety({ action: "guard" })` \u2014 Safety check before editing',
|
|
658
763
|
' 3. `[kuma_]context({ action: "research", scope: "<area>" })` \u2014 Research before editing',
|
|
659
764
|
" 4. *(edit/read using native tools)*",
|
|
660
|
-
' 5. `[kuma_]memory({ action: "research_save", ... })` \u2014
|
|
661
|
-
' 6. `[kuma_]memory({ action: "gotcha" })` \u2014
|
|
662
|
-
' 7. `[kuma_]memory({ action: "arch_flow" })` \u2014
|
|
663
|
-
' 8. `[kuma_]memory({ action: "decision" })` \u2014
|
|
765
|
+
' 5. `[kuma_]memory({ action: "research_save", ... })` \u2014 After exploring area (creates search cache)',
|
|
766
|
+
' 6. `[kuma_]memory({ action: "gotcha" })` \u2014 \u{1F525} IMMEDIATELY when bug found (exponential)',
|
|
767
|
+
' 7. `[kuma_]memory({ action: "arch_flow" })` \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential)',
|
|
768
|
+
' 8. `[kuma_]memory({ action: "decision" })` \u2014 When choosing (preserves rationale)',
|
|
664
769
|
' 9. `[kuma_]safety({ action: "verify", ... })` \u2014 Run tests / confirm nothing broken',
|
|
665
770
|
' 10. `[kuma_]context({ action: "changes" })` \u2014 Review session activity',
|
|
666
771
|
"",
|
|
667
|
-
"\u{
|
|
772
|
+
"\u{1F525} `arch_flow` + `gotcha` = EXPONENTIAL value. Each record saves 5-10 files next session.",
|
|
773
|
+
"\u{1F7E2} SKIP recording function/class/component nodes \u2014 grep/glob is faster.",
|
|
668
774
|
"\u{1F9E0} Graph is persistent \u2014 nodes/edges accumulate across sessions.",
|
|
669
775
|
"",
|
|
670
776
|
"\u26D4 Do NOT skip steps 5-10 after research \u2014 even if no code was changed.",
|
|
@@ -874,15 +980,16 @@ function handleQuickrefGeneration(root, results) {
|
|
|
874
980
|
' 2. `kuma_safety({ action: "guard" })` \u2014 Safety check',
|
|
875
981
|
' 3. `kuma_context({ action: "research", scope: "<area>" })` \u2014 Research',
|
|
876
982
|
" 4. *(edit/read using native tools)*",
|
|
877
|
-
' 5. `kuma_memory({ action: "research_save", ... })` \u2014
|
|
878
|
-
' 6. `kuma_memory({ action: "gotcha" })` \u2014
|
|
879
|
-
' 7. `kuma_memory({ action: "arch_flow" })` \u2014
|
|
880
|
-
' 8. `kuma_memory({ action: "decision" })` \u2014
|
|
881
|
-
' 9. `kuma_safety({ action: "verify", ... })` \u2014
|
|
882
|
-
' 10. `kuma_context({ action: "changes" })` \u2014 Review
|
|
883
|
-
"",
|
|
884
|
-
"\u{
|
|
885
|
-
"\u{
|
|
983
|
+
' 5. `kuma_memory({ action: "research_save", ... })` \u2014 After exploring area (creates search cache)',
|
|
984
|
+
' 6. `kuma_memory({ action: "gotcha" })` \u2014 \u{1F525} IMMEDIATELY when bug found (exponential)',
|
|
985
|
+
' 7. `kuma_memory({ action: "arch_flow" })` \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential)',
|
|
986
|
+
' 8. `kuma_memory({ action: "decision" })` \u2014 When choosing (preserves rationale)',
|
|
987
|
+
' 9. `kuma_safety({ action: "verify", ... })` \u2014 Run tests / confirm nothing broken',
|
|
988
|
+
' 10. `kuma_context({ action: "changes" })` \u2014 Review session activity',
|
|
989
|
+
"",
|
|
990
|
+
"\u{1F525} `arch_flow` + `gotcha` = EXPONENTIAL value. Each record saves 5-10 files next session.",
|
|
991
|
+
"\u{1F7E2} SKIP recording function/class/component nodes \u2014 grep/glob is faster.",
|
|
992
|
+
"\u{1F9E0} Graph is persistent \u2014 nodes/edges accumulate across sessions.",
|
|
886
993
|
"",
|
|
887
994
|
"\u26D4 Steps 5-10 are mandatory even for research-only sessions!",
|
|
888
995
|
"",
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
ALL_CONFIG_TYPES,
|
|
9
9
|
formatInitResults,
|
|
10
10
|
runInit
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-ZIXY2COZ.js";
|
|
12
12
|
import {
|
|
13
13
|
formatDecisionTemplate,
|
|
14
14
|
getProactiveMemories,
|
|
@@ -336,7 +336,7 @@ async function handleResearch(params) {
|
|
|
336
336
|
lines.push(" \u26A0\uFE0F Graph query failed");
|
|
337
337
|
}
|
|
338
338
|
try {
|
|
339
|
-
const { scanCodebase } = await import("./kumaCodeScanner-
|
|
339
|
+
const { scanCodebase } = await import("./kumaCodeScanner-2RDHZ5F4.js");
|
|
340
340
|
const scanResult = await scanCodebase({ scope, maxFiles: 100 });
|
|
341
341
|
if (scanResult.nodeCount > 0 || scanResult.edgeCount > 0) {
|
|
342
342
|
lines.push(` \u{1F52C} Auto-scanned ${scanResult.filesScanned} files \u2192 ${scanResult.nodeCount} nodes, ${scanResult.edgeCount} edges`);
|
|
@@ -670,7 +670,13 @@ var MEMORY_ALIASES = {
|
|
|
670
670
|
// Skills synonyms
|
|
671
671
|
"skills": "skills",
|
|
672
672
|
"distilled-skills": "skills",
|
|
673
|
-
"skill-list": "skills"
|
|
673
|
+
"skill-list": "skills",
|
|
674
|
+
// Add node synonyms
|
|
675
|
+
"add_node": "add_node",
|
|
676
|
+
"add-node": "add_node",
|
|
677
|
+
"node": "add_node",
|
|
678
|
+
"create-node": "add_node",
|
|
679
|
+
"record-node": "add_node"
|
|
674
680
|
};
|
|
675
681
|
async function handleMemory(params) {
|
|
676
682
|
const rawAction = params.action || "session";
|
|
@@ -716,6 +722,8 @@ async function handleMemory(params) {
|
|
|
716
722
|
return handleTrajectoryList(params);
|
|
717
723
|
case "skills":
|
|
718
724
|
return handleSkillsList(params);
|
|
725
|
+
case "add_node":
|
|
726
|
+
return handleAddNode(params);
|
|
719
727
|
default:
|
|
720
728
|
return `Unknown action "${action}".`;
|
|
721
729
|
}
|
|
@@ -754,6 +762,17 @@ async function handleResearchSave(params) {
|
|
|
754
762
|
validatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
755
763
|
});
|
|
756
764
|
await saveResearchCache(scope, record, void 0, params.confidence);
|
|
765
|
+
try {
|
|
766
|
+
const { upsertNode, nodeId } = await import("./kumaGraph-GUQM75WL.js");
|
|
767
|
+
await upsertNode({ id: nodeId("file", scope), type: "file", name: scope });
|
|
768
|
+
await upsertNode({
|
|
769
|
+
id: `research::${scope}`,
|
|
770
|
+
type: "variable",
|
|
771
|
+
name: `research:${scope}`,
|
|
772
|
+
metadata: { confidence: params.confidence || 0.8 }
|
|
773
|
+
});
|
|
774
|
+
} catch {
|
|
775
|
+
}
|
|
757
776
|
try {
|
|
758
777
|
const researchDir = path2.join(getProjectRoot(), ".kuma", "research");
|
|
759
778
|
if (!fs2.existsSync(researchDir)) fs2.mkdirSync(researchDir, { recursive: true });
|
|
@@ -955,6 +974,39 @@ async function handleSkillsList(_params) {
|
|
|
955
974
|
const { listDistilledSkills } = await import("./kumaTrajectory-T6DXGOG4.js");
|
|
956
975
|
return await listDistilledSkills();
|
|
957
976
|
}
|
|
977
|
+
async function handleAddNode(params) {
|
|
978
|
+
const type = params.title;
|
|
979
|
+
const name = params.content;
|
|
980
|
+
const filePath = params.scope;
|
|
981
|
+
if (!type || !name) {
|
|
982
|
+
return "\u26A0\uFE0F `title` (node type: function/class/component/file/api_route/test) and `content` (node name) required.\nExample: kuma_memory({ action: 'add_node', title: 'function', content: 'sendMessage', scope: 'ChatService.ts' })";
|
|
983
|
+
}
|
|
984
|
+
const validTypes = ["function", "class", "component", "file", "api_route", "test"];
|
|
985
|
+
if (!validTypes.includes(type)) {
|
|
986
|
+
return `\u26A0\uFE0F Invalid type "${type}". Valid types: ${validTypes.join(", ")}`;
|
|
987
|
+
}
|
|
988
|
+
try {
|
|
989
|
+
const { upsertNode, nodeId, addEdge } = await import("./kumaGraph-GUQM75WL.js");
|
|
990
|
+
const nodeIdStr = filePath ? `${type}::${filePath}::${name}` : nodeId(type, name);
|
|
991
|
+
await upsertNode({
|
|
992
|
+
id: nodeIdStr,
|
|
993
|
+
type,
|
|
994
|
+
name,
|
|
995
|
+
filePath
|
|
996
|
+
});
|
|
997
|
+
if (filePath) {
|
|
998
|
+
const fileNodeId = nodeId("file", filePath);
|
|
999
|
+
await upsertNode({ id: fileNodeId, type: "file", name: filePath });
|
|
1000
|
+
try {
|
|
1001
|
+
await addEdge({ sourceId: fileNodeId, targetId: nodeIdStr, type: "contains" });
|
|
1002
|
+
} catch {
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
return `\u2705 Node created: **${name}** (${type})${filePath ? ` \u2014 ${filePath}` : ""}`;
|
|
1006
|
+
} catch (err) {
|
|
1007
|
+
return `\u274C Failed to create node: ${err}`;
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
958
1010
|
async function handleLayersSummary(_params) {
|
|
959
1011
|
const { getLayersSummary } = await import("./domainRules-ED6EOFVY.js");
|
|
960
1012
|
return getLayersSummary();
|
|
@@ -2149,7 +2201,7 @@ async function handleVerify(params) {
|
|
|
2149
2201
|
}
|
|
2150
2202
|
_lastVerifyCall = now;
|
|
2151
2203
|
sessionMemory.recordToolCall("kuma_safety_verify", { scope: params.scope || params.filePath });
|
|
2152
|
-
const { runAutoVerification } = await import("./kumaVerifier-
|
|
2204
|
+
const { runAutoVerification } = await import("./kumaVerifier-6NTJQU7B.js");
|
|
2153
2205
|
return await runAutoVerification({
|
|
2154
2206
|
scope: params.scope || params.filePath,
|
|
2155
2207
|
force: params.force,
|
|
@@ -2190,9 +2242,9 @@ function registerAllTools(server) {
|
|
|
2190
2242
|
);
|
|
2191
2243
|
server.tool(
|
|
2192
2244
|
"kuma_memory",
|
|
2193
|
-
"**Call
|
|
2245
|
+
"**Call after research/editing** (including research-only). Record what matters, skip what doesn't.\n\n\u{1F534} MUST RECORD \u2014 High Impact (saves agent time next session):\n\u2022 STEP 5: `research_save` \u2014 every read/grep that finds new files. Creates searchable cache.\n\u2022 STEP 6: `gotcha` \u2014 IMMEDIATELY when you discover bugs/quirks. No re-research.\n\u2022 STEP 7: `arch_flow` \u2014 IMMEDIATELY after EACH flow hop. Saves reading 5-10 files.\n\u2022 STEP 8: `decision` \u2014 IMMEDIATELY when choosing between options. Preserves rationale.\n\n\u{1F7E2} SKIP using MCP (agent native tools are faster):\n\u2022 Function/class nodes \u2192 grep\n\u2022 Component/route nodes \u2192 glob or check directly\n\u2022 Import edges \u2192 read imports directly\n\u2022 Visual graph \u2192 for humans, not AI agents\n\nOther actions: session, heal, search, changes, benchmark, layers.",
|
|
2194
2246
|
{
|
|
2195
|
-
action: z.enum(["decision", "mine", "research_save", "session", "heal", "search", "changes", "todo", "context", "benchmark", "decision_log", "domain_rules", "arch_flow", "gotcha", "layers", "federated", "gen_test", "trajectory", "skills"]).describe("Memory action: decision=ADR, mine=mine git log & comments, research_save=save, session=summary, heal=repair, search=search, changes=log, todo=manage todos, context=inject notes, benchmark=capture/diff, decision_log=manage decisions, domain_rules=Layer 1 business rules (Issue #17), arch_flow=Layer 2 architecture flow (Issue #17), gotcha=Layer 3 known gotchas (Issue #17/#21), layers=all 3 layers summary, federated=resolve federated kuma:// URI (Issue #27), gen_test=generate test from trajectory (Issue #28), trajectory=list trajectories, skills=list distilled skills"),
|
|
2247
|
+
action: z.enum(["decision", "mine", "research_save", "session", "heal", "search", "changes", "todo", "context", "benchmark", "decision_log", "domain_rules", "arch_flow", "gotcha", "layers", "federated", "gen_test", "trajectory", "skills", "add_node"]).describe("Memory action: decision=ADR, mine=mine git log & comments, research_save=save (creates file + graph node), session=summary, heal=repair, search=search, changes=log, todo=manage todos, context=inject notes, benchmark=capture/diff, decision_log=manage decisions, domain_rules=Layer 1 business rules (Issue #17), arch_flow=Layer 2 architecture flow (Issue #17), gotcha=Layer 3 known gotchas (Issue #17/#21), layers=all 3 layers summary, federated=resolve federated kuma:// URI (Issue #27), gen_test=generate test from trajectory (Issue #28), trajectory=list trajectories, skills=list distilled skills, add_node=manually create function/class/component structural nodes"),
|
|
2196
2248
|
scope: z.string().optional().describe("Scope for research_save/search/todo/context/mine/federated"),
|
|
2197
2249
|
query: z.string().optional().describe("Search query for search action"),
|
|
2198
2250
|
content: z.string().optional().describe("Content/notes for research_save / context"),
|
|
@@ -2362,7 +2414,7 @@ async function main() {
|
|
|
2362
2414
|
console.error("");
|
|
2363
2415
|
let killedCount = 0;
|
|
2364
2416
|
try {
|
|
2365
|
-
const { getRunningVerificationPid } = await import("./kumaVerifier-
|
|
2417
|
+
const { getRunningVerificationPid } = await import("./kumaVerifier-6NTJQU7B.js");
|
|
2366
2418
|
const pid = getRunningVerificationPid();
|
|
2367
2419
|
if (pid) {
|
|
2368
2420
|
try {
|
|
@@ -2571,7 +2623,7 @@ async function main() {
|
|
|
2571
2623
|
});
|
|
2572
2624
|
(async () => {
|
|
2573
2625
|
try {
|
|
2574
|
-
const { generateInitMdContent } = await import("./init-
|
|
2626
|
+
const { generateInitMdContent } = await import("./init-RUKOPMX6.js");
|
|
2575
2627
|
const fs7 = await import("fs");
|
|
2576
2628
|
const path7 = await import("path");
|
|
2577
2629
|
const initMdPath = path7.resolve(process.cwd(), ".kuma/init.md");
|
|
@@ -2588,7 +2640,7 @@ async function main() {
|
|
|
2588
2640
|
(async () => {
|
|
2589
2641
|
try {
|
|
2590
2642
|
const { detectAgent, getSkillPath, getAgentLabel } = await import("./agentDetector-YOWQVJFR.js");
|
|
2591
|
-
const { generateSkill, getSecondaryFiles } = await import("./skillGenerator-
|
|
2643
|
+
const { generateSkill, getSecondaryFiles } = await import("./skillGenerator-PWEJKZNX.js");
|
|
2592
2644
|
const fs7 = await import("fs");
|
|
2593
2645
|
const path7 = await import("path");
|
|
2594
2646
|
const detection = detectAgent();
|
|
@@ -21,17 +21,18 @@ function getRoot() {
|
|
|
21
21
|
return _cachedRoot;
|
|
22
22
|
}
|
|
23
23
|
var FUNCTION_DECL_RE = /(?:export\s+)?(?:async\s+)?function\s*(?:\*\s*)?(\w+)\s*\(/g;
|
|
24
|
-
var ARROW_FN_RE = /(?:export\s+)?(?:const|let|var)\s+(\w+)\s
|
|
25
|
-
var TYPED_ARROW_RE = /(?:export\s+)?(?:const|let|var)\s+(\w+)\s*:\s*(?:\w+(?:<[^>]*>)?)?\s*=\s*(?:async\s*)?\(/g;
|
|
24
|
+
var ARROW_FN_RE = /(?:export\s+)?(?:const|let|var)\s+(\w+)\s*[=:]\s*(?:async\s*)?(?:<[^>]+>\s*)?(?:\([\s\S]*?\)|\w+)\s*(?::\s*\w+(?:<[^>]*>)?)?\s*=>/g;
|
|
25
|
+
var TYPED_ARROW_RE = /(?:export\s+)?(?:const|let|var)\s+(\w+)\s*:\s*(?:\w+(?:<[^>]*>)?)?\s*=\s*(?:async\s*)?(?:<[^>]+>\s*)?\(/g;
|
|
26
26
|
var CLASS_RE = /(?:export\s+)?(?:abstract\s+)?class\s+(\w+)(?:\s+extends\s+(\w+))?(?:\s+implements\s+([\w,\s]+))?/g;
|
|
27
27
|
var IMPORT_RE = /import\s+(?:\{([^}]*)\}\s+from\s+)?(?:\w+\s+from\s+)?(?:\*\s+as\s+\w+\s+from\s+)?['"]([^'"]+)['"]/g;
|
|
28
28
|
var JSX_RETURN_RE = /return\s*\(?\s*</;
|
|
29
29
|
var JSX_ELEMENT_RE = /<([A-Z]\w+)[\s/>]/g;
|
|
30
|
+
var JSX_IMPLICIT_RE = /=>\s*(?:\(\s*)?</;
|
|
30
31
|
var EXPRESS_ROUTE_RE = /\.(get|post|put|delete|patch)\s*\(\s*['"]([^'"]+)['"]\s*,\s*(\w+)/g;
|
|
31
32
|
var HONO_ROUTE_RE = /c\.(get|post|put|delete|patch)\s*\(\s*['"]([^'"]+)['"]/g;
|
|
32
|
-
var TEST_PATTERNS = [".test.", ".spec.", "__tests__", "/test/"];
|
|
33
33
|
var EXPORT_RE = /export\s+(?:default\s+)?(\w+)/g;
|
|
34
34
|
var CALL_RE = /(\w+)\s*\(/g;
|
|
35
|
+
var TEST_PATTERNS = [".test.", ".spec.", "__tests__", "/test/"];
|
|
35
36
|
var knownComponents = /* @__PURE__ */ new Set();
|
|
36
37
|
var knownFunctions = /* @__PURE__ */ new Set();
|
|
37
38
|
var symbolLocations = /* @__PURE__ */ new Map();
|
|
@@ -236,11 +237,9 @@ function parseFile(filePath, content) {
|
|
|
236
237
|
}
|
|
237
238
|
}
|
|
238
239
|
}
|
|
239
|
-
const JSX_IMPLICIT_RE = /=>\s*(?:\(\s*)?</;
|
|
240
240
|
if (hasJSX) {
|
|
241
241
|
for (const fn of [...result.functions]) {
|
|
242
242
|
const fnStartLine = fn.line - 1;
|
|
243
|
-
const fnLine = lines[fnStartLine];
|
|
244
243
|
const endLine = Math.min(fnStartLine + 50, lines.length);
|
|
245
244
|
let isComponent = false;
|
|
246
245
|
for (let i = fnStartLine; i < endLine; i++) {
|
|
@@ -249,12 +248,10 @@ function parseFile(filePath, content) {
|
|
|
249
248
|
break;
|
|
250
249
|
}
|
|
251
250
|
}
|
|
252
|
-
if (!isComponent && JSX_IMPLICIT_RE.test(
|
|
253
|
-
if (!isComponent &&
|
|
251
|
+
if (!isComponent && JSX_IMPLICIT_RE.test(lines[fnStartLine])) isComponent = true;
|
|
252
|
+
if (!isComponent && fnStartLine + 1 < endLine) {
|
|
254
253
|
const nextLine = lines[fnStartLine + 1].trim();
|
|
255
|
-
if (nextLine.startsWith("<") || nextLine.startsWith("(") || nextLine.startsWith("<>"))
|
|
256
|
-
isComponent = true;
|
|
257
|
-
}
|
|
254
|
+
if (nextLine.startsWith("<") || nextLine.startsWith("(") || nextLine.startsWith("<>")) isComponent = true;
|
|
258
255
|
}
|
|
259
256
|
if (isComponent) {
|
|
260
257
|
result.components.push({ name: fn.name, line: fn.line });
|
|
@@ -93,7 +93,14 @@ function detectTestRunner(root = process.cwd()) {
|
|
|
93
93
|
if (fs.existsSync(path.join(root, "pytest.ini")) || fs.existsSync(path.join(root, "pyproject.toml"))) return { runner: "pytest", baseCommand: "pytest" };
|
|
94
94
|
if (fs.existsSync(path.join(root, "Cargo.toml"))) return { runner: "cargo", baseCommand: "cargo test" };
|
|
95
95
|
if (fs.existsSync(path.join(root, "go.mod"))) return { runner: "go", baseCommand: "go test ./..." };
|
|
96
|
-
if (fs.existsSync(path.join(root, "Makefile")))
|
|
96
|
+
if (fs.existsSync(path.join(root, "Makefile"))) {
|
|
97
|
+
try {
|
|
98
|
+
const makefileContent = fs.readFileSync(path.join(root, "Makefile"), "utf-8");
|
|
99
|
+
const hasTestTarget = /^test:/m.test(makefileContent) || /^\s+test:/.test(makefileContent);
|
|
100
|
+
if (hasTestTarget) return { runner: "make", baseCommand: "make test" };
|
|
101
|
+
} catch {
|
|
102
|
+
}
|
|
103
|
+
}
|
|
97
104
|
if (fs.existsSync(path.join(root, "package.json"))) {
|
|
98
105
|
try {
|
|
99
106
|
const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf-8"));
|
|
@@ -10,14 +10,16 @@ var BOOTSTRAP = [
|
|
|
10
10
|
' 2. `kuma_safety({ action: "guard" })` \u2014 Safety check before work',
|
|
11
11
|
' 3. `kuma_context({ action: "research", scope: "<area>" })` \u2014 Research before editing',
|
|
12
12
|
" 4. *(edit/read using native tools)*",
|
|
13
|
-
' 5. `kuma_memory({ action: "research_save", ... })` \u2014
|
|
14
|
-
' 6. `kuma_memory({ action: "gotcha" })` \u2014
|
|
15
|
-
' 7. `kuma_memory({ action: "arch_flow" })` \u2014
|
|
16
|
-
' 8. `kuma_memory({ action: "decision" })` \u2014
|
|
13
|
+
' 5. `kuma_memory({ action: "research_save", ... })` \u2014 After exploring area (creates search cache)',
|
|
14
|
+
' 6. `kuma_memory({ action: "gotcha" })` \u2014 \u{1F525} IMMEDIATELY when bug found (exponential value)',
|
|
15
|
+
' 7. `kuma_memory({ action: "arch_flow" })` \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential value)',
|
|
16
|
+
' 8. `kuma_memory({ action: "decision" })` \u2014 When choosing between options (preserves rationale)',
|
|
17
17
|
' 9. `kuma_safety({ action: "verify", ... })` \u2014 Run tests / confirm nothing broken',
|
|
18
18
|
' 10. `kuma_context({ action: "changes" })` \u2014 Review session activity',
|
|
19
19
|
"",
|
|
20
|
-
"\u{
|
|
20
|
+
"\u{1F525} **Power Curve:** `arch_flow` + `gotcha` are EXPONENTIAL \u2014 each record saves 5-10 files next session.",
|
|
21
|
+
" The more you record, the more overpowered the agent becomes. These are the highest-value actions.",
|
|
22
|
+
"\u{1F7E2} **SKIP** recording function/class/component nodes \u2014 grep/glob is faster.",
|
|
21
23
|
"\u{1F9E0} Knowledge graph is persistent \u2014 nodes/edges accumulate across sessions, getting richer over time.",
|
|
22
24
|
"",
|
|
23
25
|
"\u26D4 Do NOT skip steps 5-10 after research \u2014 even if no code was changed.",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plumpslabs/kuma",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.18",
|
|
4
4
|
"description": "Safety-first context & orchestration engine for AI coding agents. MCP server with mandatory research pipeline, knowledge graph, impact analysis, decision memory, and safety guard — works with any MCP client.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|