@plumpslabs/kuma 2.4.5 → 2.4.7

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.
@@ -1,37 +1,90 @@
1
1
  /**
2
- * 🐻 Kuma MCP — Antigravity Lifecycle Hook
3
- * Intercepts file writes to warn about known gotchas and fragile files.
2
+ * 🐻 Kuma MCP — JIT Gotcha Guard Hook
3
+ * Intercepts file writes/edits in real time to inject active gotcha warnings.
4
4
  */
5
5
  import fs from "node:fs";
6
6
  import path from "node:path";
7
7
 
8
- function runHook() {
9
- try {
10
- const input = process.env.AGY_TOOL_INPUT ? JSON.parse(process.env.AGY_TOOL_INPUT) : {};
11
- const targetFile = input.TargetFile || input.file || "";
8
+ function findGotchasForFile(targetPath) {
9
+ if (!targetPath) return [];
10
+ const results = [];
11
+ const normalized = targetPath.replace(/\\/g, "/");
12
+ const baseName = path.basename(normalized);
12
13
 
13
- if (!targetFile) {
14
- process.stdout.write(JSON.stringify({ decision: "allow" }) + "\n");
15
- return;
16
- }
17
-
18
- const gotchasFile = path.resolve(process.cwd(), ".kuma", "KNOWN_GOTCHAS.md");
19
- if (fs.existsSync(gotchasFile)) {
20
- const content = fs.readFileSync(gotchasFile, "utf-8");
21
- const baseName = path.basename(targetFile);
22
- if (content.includes(baseName) || content.includes(targetFile)) {
23
- process.stdout.write(JSON.stringify({
24
- decision: "allow",
25
- systemMessage: `⚠️ Kuma Gotcha Warning: ${baseName} has recorded gotchas in .kuma/KNOWN_GOTCHAS.md. Review before editing!`
26
- }) + "\n");
27
- return;
14
+ const gotchasMd = path.resolve(process.cwd(), ".kuma", "KNOWN_GOTCHAS.md");
15
+ if (fs.existsSync(gotchasMd)) {
16
+ try {
17
+ const content = fs.readFileSync(gotchasMd, "utf-8");
18
+ const sections = content.split(/(?=^###\s+)/m);
19
+ for (const sec of sections) {
20
+ if (sec.includes(baseName) || sec.includes(normalized)) {
21
+ const firstLine = sec.split("\n")[0].replace(/^###\s+/, "").trim();
22
+ const trapMatch = sec.match(/- \S*\s*\*\*Trap\*\*:\s*([^\n]+)/i) || sec.match(/- \*\*Issue\*\*:\s*([^\n]+)/i);
23
+ const ruleMatch = sec.match(/- \S*\s*\*\*Rule(?:\/Fix)?\*\*:\s*([^\n]+)/i) || sec.match(/- \*\*Workaround\*\*:\s*([^\n]+)/i);
24
+ const trap = trapMatch ? trapMatch[1].trim() : firstLine;
25
+ const rule = ruleMatch ? ruleMatch[1].trim() : "";
26
+ results.push({ file: baseName, trap, rule });
27
+ }
28
28
  }
29
+ } catch {}
30
+ }
31
+ return results;
32
+ }
33
+
34
+ function processPayload(rawInput) {
35
+ let data = {};
36
+ if (rawInput && typeof rawInput === "string") {
37
+ try { data = JSON.parse(rawInput); } catch {}
38
+ } else if (rawInput && typeof rawInput === "object") {
39
+ data = rawInput;
40
+ }
41
+
42
+ const input = data.input || data;
43
+ const targetFile = input.TargetFile || input.targetFile || input.file_path || input.path || input.file || "";
44
+
45
+ if (!targetFile) {
46
+ return { decision: "allow" };
47
+ }
48
+
49
+ const gotchas = findGotchasForFile(targetFile);
50
+ if (gotchas.length > 0) {
51
+ const baseName = path.basename(targetFile);
52
+ const lines = [
53
+ `⚠️ [🐻 Kuma JIT Warning] File "${baseName}" has ${gotchas.length} known gotcha(s):`
54
+ ];
55
+ for (const g of gotchas.slice(0, 3)) {
56
+ lines.push(` • 🪤 Trap: ${g.trap}`);
57
+ if (g.rule) lines.push(` 🛡️ Rule: ${g.rule}`);
29
58
  }
59
+ lines.push("💡 Review before modifying to prevent known regressions.");
30
60
 
31
- process.stdout.write(JSON.stringify({ decision: "allow" }) + "\n");
32
- } catch {
33
- process.stdout.write(JSON.stringify({ decision: "allow" }) + "\n");
61
+ const message = lines.join("\n");
62
+ return {
63
+ decision: "allow",
64
+ systemMessage: message,
65
+ additionalContext: message,
66
+ };
34
67
  }
68
+
69
+ return { decision: "allow" };
35
70
  }
36
71
 
37
- runHook();
72
+ let inputBuffer = "";
73
+ const timer = setTimeout(() => {
74
+ const envInput = process.env.AGY_TOOL_INPUT || process.env.TOOL_INPUT || "";
75
+ const result = processPayload(envInput);
76
+ process.stdout.write(JSON.stringify(result) + "\n");
77
+ process.exit(0);
78
+ }, 150);
79
+
80
+ process.stdin.setEncoding("utf-8");
81
+ process.stdin.on("data", (chunk) => {
82
+ clearTimeout(timer);
83
+ inputBuffer += chunk;
84
+ });
85
+ process.stdin.on("end", () => {
86
+ clearTimeout(timer);
87
+ const result = processPayload(inputBuffer || process.env.AGY_TOOL_INPUT || "");
88
+ process.stdout.write(JSON.stringify(result) + "\n");
89
+ process.exit(0);
90
+ });
package/hooks.json CHANGED
@@ -3,11 +3,11 @@
3
3
  "enabled": true,
4
4
  "PreToolUse": [
5
5
  {
6
- "matcher": "replace_file_content|write_to_file",
6
+ "matcher": "replace_file_content|write_to_file|Edit|Write|MultiEdit|edit_file",
7
7
  "hooks": [
8
8
  {
9
9
  "type": "command",
10
- "command": "node -e \"import('fs').then(fs=>{const p=['hooks/kuma-agy-hooks.js','.agents/hooks/kuma-agy-hooks.js','../hooks/kuma-agy-hooks.js'].find(x=>fs.existsSync(x));if(p)import('./'+p);else process.stdout.write(JSON.stringify({decision:'allow'})+'\\n');}).catch(()=>process.stdout.write(JSON.stringify({decision:'allow'})+'\\n'))\"",
10
+ "command": "node -e \"import('fs').then(fs=>{const p=['hooks/kuma-agy-hooks.js','.agents/hooks/kuma-agy-hooks.js',process.env.HOME+'/.gemini/config/plugins/kuma/hooks/kuma-agy-hooks.js'].find(x=>fs.existsSync(x));if(p)import(p.startsWith('/')?p:'./'+p);else process.stdout.write(JSON.stringify({decision:'allow'})+'\\n');}).catch(()=>process.stdout.write(JSON.stringify({decision:'allow'})+'\\n'))\"",
11
11
  "timeout": 15
12
12
  }
13
13
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@plumpslabs/kuma",
3
- "version": "2.4.5",
3
+ "version": "2.4.7",
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",
package/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://antigravity.google/schemas/v1/plugin.json",
3
3
  "name": "kuma",
4
- "version": "2.4.5",
4
+ "version": "2.4.7",
5
5
  "description": "Safety-first context & orchestration engine for AI coding agents. Shadow memory, gotcha lifecycle, blast radius impact analysis, and test verification.",
6
6
  "author": {
7
7
  "name": "plumpslabs",