@plumpslabs/kuma 2.3.23 → 2.3.24

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/index.js CHANGED
@@ -8866,33 +8866,24 @@ function handleQuickrefGeneration(root, results) {
8866
8866
  const content = [
8867
8867
  "# Kuma Quick Reference",
8868
8868
  "",
8869
- "_(Auto-generated by `kuma init` \u2014 simplified workflow cheat sheet)_",
8869
+ "## Lean Mode (default \u2014 for speed)",
8870
+ "1. `init` \u2192 edit \u2192 record (if needed)",
8870
8871
  "",
8871
- "## Every Session (Mandatory \u2014 including research-only)",
8872
+ "## Standard Mode (for safety)",
8873
+ "1. `init` \u2192 `guard` \u2192 `research` \u2192 edit \u2192 `record` \u2192 `verify`",
8872
8874
  "",
8873
- ' 1. `kuma_context({ action: "init" })` \u2014 Load context',
8874
- ' 2. `kuma_safety({ action: "guard" })` \u2014 Safety check',
8875
- ' 3. `kuma_context({ action: "research", scope: "<area>" })` \u2014 Research',
8876
- " 4. *(edit/read using native tools)*",
8877
- ' 5. `kuma_memory({ action: "research_save", ... })` \u2014 After exploring area (creates search cache)',
8878
- ' 6. `kuma_memory({ action: "gotcha" })` \u2014 \u{1F525} IMMEDIATELY when bug found (exponential)',
8879
- ' 7. `kuma_memory({ action: "arch_flow" })` \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential)',
8880
- ' 8. `kuma_memory({ action: "decision" })` \u2014 When choosing (preserves rationale)',
8881
- ' 9. `kuma_safety({ action: "verify", ... })` \u2014 Run tests / confirm nothing broken',
8882
- ' 10. `kuma_context({ action: "changes" })` \u2014 Review session activity',
8883
- "",
8884
- "\u{1F525} `arch_flow` + `gotcha` = EXPONENTIAL value. Each record saves 5-10 files next session.",
8885
- "\u{1F7E2} SKIP recording function/class/component nodes \u2014 grep/glob is faster.",
8886
- "\u{1F9E0} Graph is persistent \u2014 nodes/edges accumulate across sessions.",
8875
+ "## Full Mode (for complex changes)",
8876
+ "1. `init` \u2192 `guard` \u2192 `research` \u2192 `impact` \u2192 edit \u2192 `record` \u2192 `verify` \u2192 `changes`",
8887
8877
  "",
8888
- "\u26D4 Steps 5-10 are mandatory even for research-only sessions!",
8878
+ "## Record Rules",
8879
+ "- **MUST:** decision, gotcha",
8880
+ "- **SKIP:** function, class, import, route",
8889
8881
  "",
8890
8882
  "## Platform Tool Names",
8883
+ "- OpenCode / Antigravity: `kuma_kuma_*`",
8884
+ "- Others: `kuma_*`",
8891
8885
  "",
8892
- "- **OpenCode:** Use `kuma_kuma_*` prefix (e.g. `kuma_kuma_context`)",
8893
- "- **Other platforms:** Use `kuma_*` directly (e.g. `kuma_context`)",
8894
- "",
8895
- "\u{1F4D6} Full rules: `.kuma/init.md`",
8886
+ "\u{1F4D6} Full: `.kuma/init.md` | \u{1F4CA} Modes: `.kuma/MODE.md` | \u{1F7E2} Skip: `.kuma/SKIP_RULES.md`",
8896
8887
  "_Generated by Kuma MCP - https://github.com/plumpslabs/kuma_"
8897
8888
  ].join("\n");
8898
8889
  try {
@@ -8904,11 +8895,9 @@ function handleQuickrefGeneration(root, results) {
8904
8895
  results.push({ type: "claude", filePath: ".kuma/quickref.md", action: "skipped" });
8905
8896
  return;
8906
8897
  }
8907
- results.push({ type: "claude", filePath: ".kuma/quickref.md", action: "skipped" });
8908
- } else {
8909
- fs24.writeFileSync(quickrefPath, content, "utf-8");
8910
- results.push({ type: "claude", filePath: ".kuma/quickref.md", action: "created" });
8911
8898
  }
8899
+ fs24.writeFileSync(quickrefPath, content, "utf-8");
8900
+ results.push({ type: "claude", filePath: ".kuma/quickref.md", action: "created" });
8912
8901
  } catch (err) {
8913
8902
  results.push({
8914
8903
  type: "claude",
@@ -8918,6 +8907,150 @@ function handleQuickrefGeneration(root, results) {
8918
8907
  });
8919
8908
  }
8920
8909
  }
8910
+ function handleModeMdGeneration(root, results) {
8911
+ const filePath = path24.resolve(root, ".kuma/MODE.md");
8912
+ const content = [
8913
+ "# Adaptive Mode Selector",
8914
+ "",
8915
+ "## Mode Definitions",
8916
+ "",
8917
+ "| Mode | When to Use | Token Cost | Steps |",
8918
+ "|------|-------------|------------|-------|",
8919
+ "| **Lean** (default) | Small fixes, familiar code, hotfixes, < 3 files | ~100 | 3 |",
8920
+ "| **Standard** | New features, unfamiliar modules, 3-10 files | ~300 | 5 |",
8921
+ "| **Full** | Cross-module refactors, architecture changes, > 10 files | ~500 | 7 |",
8922
+ "",
8923
+ "## Auto-Detection Rules",
8924
+ "",
8925
+ "```",
8926
+ "IF file_count < 3 AND area_familiar == true:",
8927
+ ' mode = "lean"',
8928
+ "ELSE IF file_count <= 10 OR area_familiar == false:",
8929
+ ' mode = "standard"',
8930
+ "ELSE IF file_count > 10 OR cross_module == true:",
8931
+ ' mode = "full"',
8932
+ "```",
8933
+ "",
8934
+ "## Mode Behaviors",
8935
+ "",
8936
+ "### Lean Mode (Default)",
8937
+ "- Skip: guard, research, verify, changes",
8938
+ "- Record: only if decision/gotcha explicit",
8939
+ "- Focus: speed, minimal overhead",
8940
+ "",
8941
+ "### Standard Mode",
8942
+ "- Include: guard (before unfamiliar), research (before edit)",
8943
+ "- Record: decision, gotcha, arch_flow (if complex)",
8944
+ "- Focus: safety + knowledge capture",
8945
+ "",
8946
+ "### Full Mode",
8947
+ "- Include: all steps including impact, changes",
8948
+ "- Record: everything valuable",
8949
+ "- Focus: completeness, audit trail",
8950
+ "",
8951
+ "_Generated by Kuma MCP - https://github.com/plumpslabs/kuma_"
8952
+ ].join("\n");
8953
+ try {
8954
+ const dir = path24.dirname(filePath);
8955
+ if (!fs24.existsSync(dir)) fs24.mkdirSync(dir, { recursive: true });
8956
+ if (!fs24.existsSync(filePath)) {
8957
+ fs24.writeFileSync(filePath, content, "utf-8");
8958
+ results.push({ type: "claude", filePath: ".kuma/MODE.md", action: "created" });
8959
+ }
8960
+ } catch (err) {
8961
+ results.push({ type: "claude", filePath: ".kuma/MODE.md", action: "error", error: err instanceof Error ? err.message : String(err) });
8962
+ }
8963
+ }
8964
+ function handleSkipRulesMdGeneration(root, results) {
8965
+ const filePath = path24.resolve(root, ".kuma/SKIP_RULES.md");
8966
+ const content = [
8967
+ "# Skip Rules \u2014 What NOT to Record",
8968
+ "",
8969
+ "## \u{1F7E2} NEVER Record (grep/glob is faster)",
8970
+ "",
8971
+ "| What | Why Skip | Better Tool |",
8972
+ "|------|----------|-------------|",
8973
+ "| Function definitions | `grep funcName(` | Grep |",
8974
+ "| Class definitions | `grep class ClassName` | Grep |",
8975
+ "| Import statements | Read import block | Read |",
8976
+ "| Component definitions | `glob **/*Component*` | Glob |",
8977
+ "| Route definitions | Check router file | Read |",
8978
+ "| Type/interface definitions | `grep interface TypeName` | Grep |",
8979
+ "| Variable/const declarations | `grep const varName` | Grep |",
8980
+ "| Test file locations | `glob **/*.test.*` | Glob |",
8981
+ "",
8982
+ "## \u{1F534} ALWAYS Record (high value)",
8983
+ "",
8984
+ "| What | Why Record | Tool |",
8985
+ "|------|------------|------|",
8986
+ "| Architecture decisions with rationale | Preserves context | `decision` |",
8987
+ "| Bugs/quirks found and fixed | Prevents re-discovery | `gotcha` |",
8988
+ "| Cross-module flow paths | Saves 5-10 files next session | `arch_flow` |",
8989
+ "| Business rules discovered | Domain knowledge | `domain_rules` |",
8990
+ "",
8991
+ "## \u{1F7E1} Record ONLY If Complex",
8992
+ "",
8993
+ "| What | Condition | Tool |",
8994
+ "|------|-----------|------|",
8995
+ "| Research findings | Multi-file exploration (> 3 files) | `research_save` |",
8996
+ "| Architecture flow | Cross-service or > 3 hops | `arch_flow` |",
8997
+ "| Feature definition | High-level feature with owns edges | `feature` |",
8998
+ "",
8999
+ "_Generated by Kuma MCP - https://github.com/plumpslabs/kuma_"
9000
+ ].join("\n");
9001
+ try {
9002
+ const dir = path24.dirname(filePath);
9003
+ if (!fs24.existsSync(dir)) fs24.mkdirSync(dir, { recursive: true });
9004
+ if (!fs24.existsSync(filePath)) {
9005
+ fs24.writeFileSync(filePath, content, "utf-8");
9006
+ results.push({ type: "claude", filePath: ".kuma/SKIP_RULES.md", action: "created" });
9007
+ }
9008
+ } catch (err) {
9009
+ results.push({ type: "claude", filePath: ".kuma/SKIP_RULES.md", action: "error", error: err instanceof Error ? err.message : String(err) });
9010
+ }
9011
+ }
9012
+ function handleStalenessMdGeneration(root, results) {
9013
+ const filePath = path24.resolve(root, ".kuma/STALENESS.md");
9014
+ const content = [
9015
+ "# Auto-Staleness Detection",
9016
+ "",
9017
+ "## Staleness Signals",
9018
+ "",
9019
+ "| Signal | Detection | Action |",
9020
+ "|--------|-----------|--------|",
9021
+ "| File modified after save | Compare file mtime vs research_save timestamp | Mark STALE, skip cache |",
9022
+ "| Git commit touches file | `git log --since` on researched files | Mark STALE, warn |",
9023
+ '| Age > 7 days | Current time - research_save timestamp | Warn: "Cache may be stale" |',
9024
+ "| Age > 30 days | Current time - research_save timestamp | Auto-invalidate, re-read |",
9025
+ "",
9026
+ "## Recovery Protocol",
9027
+ "",
9028
+ "```",
9029
+ "ON stale_detected:",
9030
+ " 1. Skip cached data",
9031
+ " 2. Re-read file from disk",
9032
+ " 3. Update research_save timestamp",
9033
+ " 4. Continue with fresh data",
9034
+ "",
9035
+ "ON search_conflict:",
9036
+ " 1. Prefer recent research (newer timestamp)",
9037
+ " 2. If same age, prefer live file over cache",
9038
+ " 3. Log conflict for review",
9039
+ "```",
9040
+ "",
9041
+ "_Generated by Kuma MCP - https://github.com/plumpslabs/kuma_"
9042
+ ].join("\n");
9043
+ try {
9044
+ const dir = path24.dirname(filePath);
9045
+ if (!fs24.existsSync(dir)) fs24.mkdirSync(dir, { recursive: true });
9046
+ if (!fs24.existsSync(filePath)) {
9047
+ fs24.writeFileSync(filePath, content, "utf-8");
9048
+ results.push({ type: "claude", filePath: ".kuma/STALENESS.md", action: "created" });
9049
+ }
9050
+ } catch (err) {
9051
+ results.push({ type: "claude", filePath: ".kuma/STALENESS.md", action: "error", error: err instanceof Error ? err.message : String(err) });
9052
+ }
9053
+ }
8921
9054
  function handleInitMdGeneration(root, results) {
8922
9055
  const initMdPath = path24.resolve(root, ".kuma/init.md");
8923
9056
  try {
@@ -8944,6 +9077,9 @@ function handleInitMdGeneration(root, results) {
8944
9077
  });
8945
9078
  }
8946
9079
  handleQuickrefGeneration(root, results);
9080
+ handleModeMdGeneration(root, results);
9081
+ handleSkipRulesMdGeneration(root, results);
9082
+ handleStalenessMdGeneration(root, results);
8947
9083
  }
8948
9084
  function handleCodewhaleSecondary(root, results) {
8949
9085
  const mcpPath = path24.resolve(root, ".codewhale/mcp.json");
@@ -9681,30 +9817,18 @@ var init_skillGenerator = __esm({
9681
9817
  "use strict";
9682
9818
  BOOTSTRAP = [
9683
9819
  "Kuma MCP tools are available (kuma_context, kuma_memory, kuma_safety).",
9684
- '**Before coding, call `kuma_context({ action: "init" })`** to load project context and session memory.',
9820
+ '**Before coding, call `kuma_context({ action: "init" })`** to load project context.',
9685
9821
  "Project knowledge persists in `.kuma/memories/*.md` across sessions.",
9686
9822
  "",
9687
- "\u26A0\uFE0F **MANDATORY WORKFLOW** \u2014 Follow in order every session (including research-only):",
9823
+ "\u26A1 **ADAPTIVE WORKFLOW (Lean Mode by Default):**",
9824
+ " \u2022 **Lean Mode (Default, < 3 files):** `init` \u2192 edit/read \u2192 record (`decision`/`gotcha` if needed)",
9825
+ " \u2022 **Standard Mode (3-10 files/unfamiliar):** `init` \u2192 `guard` \u2192 `research` \u2192 edit \u2192 `record` \u2192 `verify`",
9826
+ " \u2022 **Full Mode (> 10 files/refactor):** `init` \u2192 `guard` \u2192 `research` \u2192 `impact` \u2192 edit \u2192 `record` \u2192 `verify` \u2192 `changes`",
9688
9827
  "",
9689
- ' 1. `kuma_context({ action: "init" })` \u2014 Load context (START HERE)',
9690
- ' 2. `kuma_safety({ action: "guard" })` \u2014 Safety check before work',
9691
- ' 3. `kuma_context({ action: "research", scope: "<area>" })` \u2014 Research before editing',
9692
- " 4. *(edit/read using native tools)*",
9693
- ' 5. `kuma_memory({ action: "research_save", ... })` \u2014 After exploring area (creates search cache)',
9694
- ' 6. `kuma_memory({ action: "gotcha" })` \u2014 \u{1F525} IMMEDIATELY when bug found (exponential value)',
9695
- ' 7. `kuma_memory({ action: "arch_flow" })` \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential value)',
9696
- ' 8. `kuma_memory({ action: "decision" })` \u2014 When choosing between options (preserves rationale)',
9697
- ' 9. `kuma_safety({ action: "verify", ... })` \u2014 Run tests / confirm nothing broken',
9698
- ' 10. `kuma_context({ action: "changes" })` \u2014 Review session activity',
9699
- "",
9700
- "\u{1F525} **Power Curve:** `arch_flow` + `gotcha` are EXPONENTIAL \u2014 each record saves 5-10 files next session.",
9701
- " The more you record, the more overpowered the agent becomes. These are the highest-value actions.",
9702
- "\u{1F7E2} **SKIP** recording function/class/component nodes \u2014 grep/glob is faster.",
9703
- "\u{1F9E0} Knowledge graph is persistent \u2014 nodes/edges accumulate across sessions, getting richer over time.",
9828
+ "\u{1F534} **MUST RECORD:** `decision` (rationale), `gotcha` (bug/quirk), `arch_flow` (complex flow)",
9829
+ "\u{1F7E2} **SKIP RECORDING:** function, class, import, route (use native grep/glob instead)",
9704
9830
  "",
9705
- "\u26D4 Do NOT skip steps 5-10 after research \u2014 even if no code was changed.",
9706
- "\u{1F5D1}\uFE0F **Delete/Clear:** `delete_node` (delete node/gotcha/todo/decision) | `clear` (wipe entire graph)",
9707
- "\u{1F4D6} Full rules: `.kuma/init.md`",
9831
+ "\u{1F4D6} Full rules & modes: `.kuma/init.md` | `.kuma/MODE.md` | `.kuma/SKIP_RULES.md`",
9708
9832
  "\u{1F9E0} Tools: `kuma_context` | `kuma_memory` | `kuma_safety`"
9709
9833
  ].join("\n");
9710
9834
  BOOTSTRAP_OPENCODE = [
@@ -9712,27 +9836,15 @@ var init_skillGenerator = __esm({
9712
9836
  '**Before coding, call `kuma_kuma_context({ action: "init" })`** to load project context.',
9713
9837
  "Project knowledge persists in `.kuma/memories/*.md` across sessions.",
9714
9838
  "",
9715
- "\u26A0\uFE0F **MANDATORY WORKFLOW** \u2014 Follow in order every session (including research-only):",
9716
- "",
9717
- ' 1. `kuma_kuma_context({ action: "init" })` \u2014 Load context (START HERE)',
9718
- ' 2. `kuma_kuma_safety({ action: "guard" })` \u2014 Safety check before work',
9719
- ' 3. `kuma_kuma_context({ action: "research", scope: "<area>" })` \u2014 Research before editing',
9720
- " 4. *(edit/read using native tools)*",
9721
- ' 5. `kuma_kuma_memory({ action: "research_save", ... })` \u2014 After exploring area (creates search cache)',
9722
- ' 6. `kuma_kuma_memory({ action: "gotcha" })` \u2014 \u{1F525} IMMEDIATELY when bug found (exponential value)',
9723
- ' 7. `kuma_kuma_memory({ action: "arch_flow" })` \u2014 \u{1F525} IMMEDIATELY after each flow hop (exponential value)',
9724
- ' 8. `kuma_kuma_memory({ action: "decision" })` \u2014 When choosing between options (preserves rationale)',
9725
- ' 9. `kuma_kuma_safety({ action: "verify", ... })` \u2014 Run tests / confirm nothing broken',
9726
- ' 10. `kuma_kuma_context({ action: "changes" })` \u2014 Review session activity',
9839
+ "\u26A1 **ADAPTIVE WORKFLOW (Lean Mode by Default):**",
9840
+ ' \u2022 **Lean Mode (Default, < 3 files):** `kuma_kuma_context({ action: "init" })` \u2192 edit/read \u2192 record (`decision`/`gotcha`)',
9841
+ " \u2022 **Standard Mode (3-10 files/unfamiliar):** `init` \u2192 `guard` \u2192 `research` \u2192 edit \u2192 `record` \u2192 `verify`",
9842
+ " \u2022 **Full Mode (> 10 files/refactor):** `init` \u2192 `guard` \u2192 `research` \u2192 `impact` \u2192 edit \u2192 `record` \u2192 `verify` \u2192 `changes`",
9727
9843
  "",
9728
- "\u{1F525} **Power Curve:** `arch_flow` + `gotcha` are EXPONENTIAL \u2014 each record saves 5-10 files next session.",
9729
- " The more you record, the more overpowered the agent becomes. These are the highest-value actions.",
9730
- "\u{1F7E2} **SKIP** recording function/class/component nodes \u2014 grep/glob is faster.",
9731
- "\u{1F9E0} Knowledge graph is persistent \u2014 nodes/edges accumulate across sessions, getting richer over time.",
9844
+ "\u{1F534} **MUST RECORD:** `decision` (rationale), `gotcha` (bug/quirk), `arch_flow` (complex flow)",
9845
+ "\u{1F7E2} **SKIP RECORDING:** function, class, import, route (use native grep/glob instead)",
9732
9846
  "",
9733
- "\u26D4 Do NOT skip steps 5-10 after research \u2014 even if no code was changed.",
9734
- "\u{1F5D1}\uFE0F **Delete/Clear:** `delete_node` (delete node/gotcha/todo/decision) | `clear` (wipe entire graph)",
9735
- "\u{1F4D6} Full rules: `.kuma/init.md`",
9847
+ "\u{1F4D6} Full rules & modes: `.kuma/init.md` | `.kuma/MODE.md` | `.kuma/SKIP_RULES.md`",
9736
9848
  "\u{1F9E0} Tools: `kuma_kuma_context` | `kuma_kuma_memory` | `kuma_kuma_safety`"
9737
9849
  ].join("\n");
9738
9850
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumpslabs/kuma",
3
- "version": "2.3.23",
3
+ "version": "2.3.24",
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",
@@ -234,8 +234,7 @@ header .status .dot.off { background: var(--red); }
234
234
  <div id="graph-container"></div>
235
235
  <div id="search-box"><input id="node-search" type="text" placeholder="Search nodes..." /></div>
236
236
  <div id="graph-controls">
237
- <button onclick="resetGraphFocus()" title="Reset focus"><i data-lucide="x" style="width:12px;height:12px"></i></button>
238
- <button onclick="if(network)network.fit()" title="Fit to viewport"><i data-lucide="maximize-2" style="width:12px;height:12px"></i></button>
237
+ <button onclick="if(network)network.fit()" title="Fit to viewport"><i data-lucide="maximize-2" style="width:12px;height:12px"></i> Fit</button>
239
238
  <div class="ctrl-sep"></div>
240
239
  <button class="depth-btn" data-depth="1" onclick="setDepth(1)">1</button>
241
240
  <button class="depth-btn active" data-depth="2" onclick="setDepth(2)">2</button>
@@ -482,7 +481,7 @@ function renderGraph(data) {
482
481
  stabilization: { iterations: 120, updateInterval: 50, onlyDynamicEdges: false, fit: false },
483
482
  },
484
483
  interaction: { hover: true, tooltipDelay: 300, zoomView: true, dragView: true, dragNodes: true, keyboard: true, multiselect: true, selectable: true, selectConnectedEdges: false },
485
- nodes: { borderWidth: 0, font: { color: '#ffffff', size: 11, face: 'sans-serif', bold: true }, margin: { top: 6, bottom: 6, left: 10, right: 10 }, shapeProperties: { borderRadius: 6 } },
484
+ nodes: { borderWidth: 0, font: { color: '#ffffff', size: 11, face: 'sans-serif' }, margin: { top: 6, bottom: 6, left: 10, right: 10 }, shapeProperties: { borderRadius: 6 } },
486
485
  edges: { smooth: { type: 'continuous', roundness: 0.2 }, width: 1, color: { color: '#4a4a6a', highlight: '#7c3aed' } },
487
486
  configure: { enabled: false },
488
487
  });
@@ -780,7 +779,7 @@ function renderFeatures(data) {
780
779
  var items = data.features || [];
781
780
  var el = document.getElementById("panel-features");
782
781
  if(!el) return;
783
- if(!items.length){el.innerHTML='<div class="empty">No features recorded yet.<br><br>Use:<br><code style="color:var(--accent)">kuma_memory({action:\'feature\', title:\'Auth\'})</code></div>';return;}
782
+ if(!items.length){el.innerHTML='<div class="empty">No features recorded yet.<br><br>Use:<br><code style="color:var(--accent)">kuma_memory</code></div>';return;}
784
783
  el.innerHTML = items.map(function(f){
785
784
  var feat = typeof f === 'string' ? JSON.parse(f) : f;
786
785
  var meta = {};