@plumpslabs/kuma 2.3.7 → 2.3.8
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/README.md +25 -3
- package/dist/{chunk-K64NSHBR.js → chunk-4OB3XMHT.js} +2 -2
- package/dist/chunk-53J56QCQ.js +282 -0
- package/dist/{chunk-FOQQ2CSL.js → chunk-FL2TLLMX.js} +1 -1
- package/dist/{chunk-GDNAWLHF.js → chunk-NAM7SCBT.js} +63 -1
- package/dist/chunk-PTEPJK6M.js +155 -0
- package/dist/{chunk-X5TPBDKO.js → chunk-RTGLQDMI.js} +2 -2
- package/dist/{chunk-BI7KD3SG.js → chunk-SLRRDKQ2.js} +2 -2
- package/dist/contextDigest-4PCK3DSM.js +177 -0
- package/dist/domainRules-LDZPOIGZ.js +20 -0
- package/dist/index.js +184 -177
- package/dist/kumaAstValidator-CNM7FHYA.js +150 -0
- package/dist/{kumaDb-DJUDLYBJ.js → kumaDb-6D53ERFP.js} +1 -1
- package/dist/kumaDriftDetector-OESI5GTC.js +237 -0
- package/dist/kumaGotchas-DU5H6N7X.js +151 -0
- package/dist/{kumaGraph-35TAIBWD.js → kumaGraph-AWP743TJ.js} +2 -2
- package/dist/{kumaMemory-5SR3TGRL.js → kumaMemory-7TCUDVZX.js} +2 -2
- package/dist/{kumaMiner-P5KCUSF7.js → kumaMiner-FFXSRHAO.js} +3 -3
- package/dist/kumaPolicyEngine-S2PXN3C7.js +311 -0
- package/dist/{kumaSearch-LG2OYEJY.js → kumaSearch-QGB4QVXS.js} +1 -1
- package/dist/{kumaVerifier-LFRNIGSL.js → kumaVerifier-ARSGPZAM.js} +25 -2
- package/dist/{kumaVisualize-ODCWFSUY.js → kumaVisualize-TECABHUY.js} +1 -1
- package/dist/safetyAudit-55IVCG5B.js +12 -0
- package/dist/{safetyScore-PJGRRBWP.js → safetyScore-GR5N55CU.js} +5 -5
- package/dist/{sessionMemory-HBBXUSIP.js → sessionMemory-CA34TCPF.js} +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,311 @@
|
|
|
1
|
+
import {
|
|
2
|
+
sessionMemory
|
|
3
|
+
} from "./chunk-SLRRDKQ2.js";
|
|
4
|
+
import {
|
|
5
|
+
getProjectRoot
|
|
6
|
+
} from "./chunk-E2KFPEBT.js";
|
|
7
|
+
|
|
8
|
+
// src/engine/kumaPolicyEngine.ts
|
|
9
|
+
import fs from "fs";
|
|
10
|
+
import path from "path";
|
|
11
|
+
var DEFAULT_POLICY_CONFIG = {
|
|
12
|
+
version: 1,
|
|
13
|
+
name: "Kuma Default Security Policy",
|
|
14
|
+
description: "Default safety policy for AI coding agents",
|
|
15
|
+
rules: [
|
|
16
|
+
{
|
|
17
|
+
id: "block-rm-rf",
|
|
18
|
+
description: "Block recursive force deletion",
|
|
19
|
+
severity: "error",
|
|
20
|
+
patterns: ["rm -rf", "rm -fr", "rm --recursive --force"],
|
|
21
|
+
action: "block",
|
|
22
|
+
requireOverride: true
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
id: "block-git-force-push",
|
|
26
|
+
description: "Block force push to git",
|
|
27
|
+
severity: "error",
|
|
28
|
+
patterns: ["git push --force", "git push -f"],
|
|
29
|
+
action: "block",
|
|
30
|
+
requireOverride: true
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
id: "block-npm-publish",
|
|
34
|
+
description: "Block package publishing",
|
|
35
|
+
severity: "error",
|
|
36
|
+
patterns: ["npm publish", "yarn publish", "pnpm publish"],
|
|
37
|
+
action: "block",
|
|
38
|
+
requireOverride: true
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
id: "block-pipe-to-shell",
|
|
42
|
+
description: "Block curl/wget pipe to shell",
|
|
43
|
+
severity: "error",
|
|
44
|
+
patterns: ["curl | bash", "curl | sh", "wget -O - | bash", "curl | sudo"],
|
|
45
|
+
action: "block",
|
|
46
|
+
requireOverride: true
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
id: "warn-destructive-db",
|
|
50
|
+
description: "Warn about destructive database operations",
|
|
51
|
+
severity: "warning",
|
|
52
|
+
patterns: ["DROP DATABASE", "DROP TABLE", "TRUNCATE", "DELETE FROM"],
|
|
53
|
+
action: "warn"
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
id: "block-prod-deploy",
|
|
57
|
+
description: "Block production deployments without override",
|
|
58
|
+
severity: "error",
|
|
59
|
+
patterns: ["deploy --production", "deploy --prod", "deploy:production"],
|
|
60
|
+
action: "block",
|
|
61
|
+
requireOverride: true
|
|
62
|
+
}
|
|
63
|
+
],
|
|
64
|
+
block_commands: [
|
|
65
|
+
"rm -rf",
|
|
66
|
+
"rm -fr",
|
|
67
|
+
"git push --force",
|
|
68
|
+
"git push -f",
|
|
69
|
+
"npm publish",
|
|
70
|
+
"yarn publish",
|
|
71
|
+
"pnpm publish",
|
|
72
|
+
"curl | bash",
|
|
73
|
+
"curl | sh"
|
|
74
|
+
],
|
|
75
|
+
never_touch: [
|
|
76
|
+
".env",
|
|
77
|
+
".env.local",
|
|
78
|
+
".env.production",
|
|
79
|
+
".env.development",
|
|
80
|
+
"package-lock.json",
|
|
81
|
+
"yarn.lock",
|
|
82
|
+
"pnpm-lock.yaml",
|
|
83
|
+
"node_modules/**"
|
|
84
|
+
]
|
|
85
|
+
};
|
|
86
|
+
function loadPolicyConfig() {
|
|
87
|
+
try {
|
|
88
|
+
const root = getProjectRoot();
|
|
89
|
+
const policyPath = path.join(root, ".kuma", "POLICY.json");
|
|
90
|
+
if (fs.existsSync(policyPath)) {
|
|
91
|
+
const content = fs.readFileSync(policyPath, "utf-8");
|
|
92
|
+
const config = JSON.parse(content);
|
|
93
|
+
return { ...DEFAULT_POLICY_CONFIG, ...config };
|
|
94
|
+
}
|
|
95
|
+
const ymlPath = path.join(root, ".kuma", "policy.yml");
|
|
96
|
+
if (fs.existsSync(ymlPath)) {
|
|
97
|
+
console.error("[PolicyEngine] Found legacy policy.yml \u2014 consider migrating to POLICY.json");
|
|
98
|
+
}
|
|
99
|
+
} catch (err) {
|
|
100
|
+
console.error(`[PolicyEngine] Failed to load policy config: ${err}`);
|
|
101
|
+
}
|
|
102
|
+
return DEFAULT_POLICY_CONFIG;
|
|
103
|
+
}
|
|
104
|
+
function savePolicyConfig(config) {
|
|
105
|
+
try {
|
|
106
|
+
const root = getProjectRoot();
|
|
107
|
+
const policyPath = path.join(root, ".kuma", "POLICY.json");
|
|
108
|
+
const dir = path.dirname(policyPath);
|
|
109
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
110
|
+
fs.writeFileSync(policyPath, JSON.stringify(config, null, 2), "utf-8");
|
|
111
|
+
return `\u2705 Policy config saved to .kuma/POLICY.json (${config.rules.length} rules)`;
|
|
112
|
+
} catch (err) {
|
|
113
|
+
return `\u274C Failed to save policy: ${err}`;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
function evaluateCommand(command) {
|
|
117
|
+
const config = loadPolicyConfig();
|
|
118
|
+
const warnings = [];
|
|
119
|
+
const cmdLower = command.toLowerCase();
|
|
120
|
+
for (const rule of config.rules) {
|
|
121
|
+
const matches = rule.patterns.some((p) => cmdLower.includes(p.toLowerCase()));
|
|
122
|
+
if (!matches) continue;
|
|
123
|
+
if (rule.action === "block" || rule.severity === "error") {
|
|
124
|
+
return {
|
|
125
|
+
allowed: false,
|
|
126
|
+
blockedBy: rule,
|
|
127
|
+
warnings,
|
|
128
|
+
requiresOverride: rule.requireOverride ?? false,
|
|
129
|
+
message: `\u26D4 Policy violation: "${rule.description}" (rule: ${rule.id})`
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
if (rule.action === "warn") {
|
|
133
|
+
warnings.push(rule);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
for (const cmd of config.block_commands || []) {
|
|
137
|
+
if (cmdLower.includes(cmd.toLowerCase())) {
|
|
138
|
+
return {
|
|
139
|
+
allowed: false,
|
|
140
|
+
blockedBy: {
|
|
141
|
+
id: "block-command",
|
|
142
|
+
description: `Blocked command: ${cmd}`,
|
|
143
|
+
severity: "error",
|
|
144
|
+
patterns: [cmd],
|
|
145
|
+
action: "block",
|
|
146
|
+
requireOverride: true
|
|
147
|
+
},
|
|
148
|
+
warnings,
|
|
149
|
+
requiresOverride: true,
|
|
150
|
+
message: `\u26D4 Command matches blocked pattern: "${cmd}"`
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
return {
|
|
155
|
+
allowed: true,
|
|
156
|
+
blockedBy: null,
|
|
157
|
+
warnings,
|
|
158
|
+
requiresOverride: false,
|
|
159
|
+
message: warnings.length > 0 ? `\u26A0\uFE0F Command allowed with ${warnings.length} warning(s)` : "\u2705 Command allowed by policy"
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
function evaluateFilePath(filePath) {
|
|
163
|
+
const config = loadPolicyConfig();
|
|
164
|
+
const filesToCheck = config.never_touch || DEFAULT_POLICY_CONFIG.never_touch || [];
|
|
165
|
+
for (const pattern of filesToCheck) {
|
|
166
|
+
if (matchesGlob(pattern, filePath)) {
|
|
167
|
+
return {
|
|
168
|
+
allowed: false,
|
|
169
|
+
blockedBy: {
|
|
170
|
+
id: "never-touch",
|
|
171
|
+
description: `File matches never_touch pattern: ${pattern}`,
|
|
172
|
+
severity: "error",
|
|
173
|
+
patterns: [pattern],
|
|
174
|
+
action: "block",
|
|
175
|
+
requireOverride: true
|
|
176
|
+
},
|
|
177
|
+
warnings: [],
|
|
178
|
+
requiresOverride: true,
|
|
179
|
+
message: `\u26D4 File "${filePath}" is protected by never_touch policy (pattern: ${pattern}). Use kuma_safety({ action: 'override' }) to bypass.`
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
return {
|
|
184
|
+
allowed: true,
|
|
185
|
+
blockedBy: null,
|
|
186
|
+
warnings: [],
|
|
187
|
+
requiresOverride: false,
|
|
188
|
+
message: "\u2705 File allowed by policy"
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
function evaluateDatabaseAction(action) {
|
|
192
|
+
const cmdLower = action.toLowerCase();
|
|
193
|
+
if ((cmdLower.includes("drop") || cmdLower.includes("truncate")) && (cmdLower.includes("database") || cmdLower.includes("table") || cmdLower.includes("schema"))) {
|
|
194
|
+
return {
|
|
195
|
+
allowed: false,
|
|
196
|
+
blockedBy: {
|
|
197
|
+
id: "block-destructive-db",
|
|
198
|
+
description: "Destructive database operation blocked",
|
|
199
|
+
severity: "error",
|
|
200
|
+
patterns: ["DROP DATABASE", "DROP TABLE", "TRUNCATE", "DELETE FROM"],
|
|
201
|
+
action: "block",
|
|
202
|
+
requireOverride: true
|
|
203
|
+
},
|
|
204
|
+
warnings: [],
|
|
205
|
+
requiresOverride: true,
|
|
206
|
+
message: `\u26D4 Destructive database action blocked: "${action}". Use kuma_safety({ action: 'override' }) with a clear reason.`
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
return {
|
|
210
|
+
allowed: true,
|
|
211
|
+
blockedBy: null,
|
|
212
|
+
warnings: [],
|
|
213
|
+
requiresOverride: false,
|
|
214
|
+
message: "\u2705 Database action allowed by policy"
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
async function processOverride(request) {
|
|
218
|
+
const { recordAudit } = await import("./safetyAudit-55IVCG5B.js");
|
|
219
|
+
await recordAudit({
|
|
220
|
+
timestamp: Math.floor(Date.now() / 1e3),
|
|
221
|
+
toolName: request.toolName,
|
|
222
|
+
action: "policy_override",
|
|
223
|
+
filePath: request.filePath,
|
|
224
|
+
riskLevel: "high",
|
|
225
|
+
policyViolations: 1,
|
|
226
|
+
allowed: true,
|
|
227
|
+
durationMs: 0,
|
|
228
|
+
metadata: {
|
|
229
|
+
override: true,
|
|
230
|
+
reason: request.reason,
|
|
231
|
+
command: request.command
|
|
232
|
+
}
|
|
233
|
+
});
|
|
234
|
+
sessionMemory.recordToolCall("kuma_policy_override", {
|
|
235
|
+
toolName: request.toolName,
|
|
236
|
+
reason: request.reason,
|
|
237
|
+
filePath: request.filePath,
|
|
238
|
+
command: request.command
|
|
239
|
+
});
|
|
240
|
+
return [
|
|
241
|
+
`\u26A0\uFE0F **Policy Override** \u2014 ${request.toolName}`,
|
|
242
|
+
`\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501`,
|
|
243
|
+
"",
|
|
244
|
+
`\u{1F4DD} Reason: ${request.reason}`,
|
|
245
|
+
request.filePath ? `\u{1F4C4} File: ${request.filePath}` : "",
|
|
246
|
+
request.command ? `\u{1F4BB} Command: ${request.command}` : "",
|
|
247
|
+
"",
|
|
248
|
+
"\u{1F534} This override is recorded in the safety audit trail.",
|
|
249
|
+
"\u{1F534} Overrides reduce project safety \u2014 use sparingly."
|
|
250
|
+
].filter(Boolean).join("\n");
|
|
251
|
+
}
|
|
252
|
+
function formatPolicyStatus() {
|
|
253
|
+
const config = loadPolicyConfig();
|
|
254
|
+
const lines = [
|
|
255
|
+
"\u{1F4DC} **Policy-as-Code Engine**",
|
|
256
|
+
"\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501",
|
|
257
|
+
"",
|
|
258
|
+
`\u{1F4CB} Policy: ${config.name}`,
|
|
259
|
+
`\u{1F522} Version: ${config.version}`,
|
|
260
|
+
`\u{1F4DD} Rules: ${config.rules.length}`,
|
|
261
|
+
"",
|
|
262
|
+
"**Rules:**"
|
|
263
|
+
];
|
|
264
|
+
for (const rule of config.rules) {
|
|
265
|
+
const icon = rule.action === "block" ? "\u{1F534}" : rule.action === "warn" ? "\u{1F7E1}" : "\u{1F7E2}";
|
|
266
|
+
const override = rule.requireOverride ? " \u{1F511} override" : "";
|
|
267
|
+
lines.push(` ${icon} [${rule.action}] ${rule.description}${override}`);
|
|
268
|
+
lines.push(` Patterns: ${rule.patterns.slice(0, 3).join(", ")}`);
|
|
269
|
+
}
|
|
270
|
+
const neverTouch = config.never_touch || [];
|
|
271
|
+
if (neverTouch.length > 0) {
|
|
272
|
+
lines.push("", "**Protected Files (never_touch):**");
|
|
273
|
+
for (const p of neverTouch) {
|
|
274
|
+
lines.push(` \u{1F6E1}\uFE0F ${p}`);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return lines.join("\n");
|
|
278
|
+
}
|
|
279
|
+
function matchesGlob(pattern, filePath) {
|
|
280
|
+
const normalizedPattern = pattern.replace(/\\/g, "/");
|
|
281
|
+
const normalizedPath = filePath.replace(/\\/g, "/");
|
|
282
|
+
let regexStr = "^";
|
|
283
|
+
for (let i = 0; i < normalizedPattern.length; i++) {
|
|
284
|
+
const ch = normalizedPattern[i];
|
|
285
|
+
if (ch === "*" && normalizedPattern[i + 1] === "*" && normalizedPattern[i + 2] === "/") {
|
|
286
|
+
regexStr += "(.+/)?";
|
|
287
|
+
i += 2;
|
|
288
|
+
} else if (ch === "*") {
|
|
289
|
+
regexStr += "[^/]*";
|
|
290
|
+
} else if (ch === "?") {
|
|
291
|
+
regexStr += "[^/]";
|
|
292
|
+
} else {
|
|
293
|
+
regexStr += ch.replace(/[.+^${}()|[\]\\]/g, "\\$&");
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
regexStr += "$";
|
|
297
|
+
try {
|
|
298
|
+
return new RegExp(regexStr).test(normalizedPath);
|
|
299
|
+
} catch {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
export {
|
|
304
|
+
evaluateCommand,
|
|
305
|
+
evaluateDatabaseAction,
|
|
306
|
+
evaluateFilePath,
|
|
307
|
+
formatPolicyStatus,
|
|
308
|
+
loadPolicyConfig,
|
|
309
|
+
processOverride,
|
|
310
|
+
savePolicyConfig
|
|
311
|
+
};
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
sessionMemory
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-SLRRDKQ2.js";
|
|
4
4
|
import {
|
|
5
5
|
getLatestVerifications,
|
|
6
6
|
saveVerification
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-NAM7SCBT.js";
|
|
8
8
|
import "./chunk-E2KFPEBT.js";
|
|
9
9
|
|
|
10
10
|
// src/engine/kumaVerifier.ts
|
|
@@ -56,6 +56,24 @@ var _localRunning = false;
|
|
|
56
56
|
var _currentProcess = null;
|
|
57
57
|
var STALE_RESULT_MS = 3e5;
|
|
58
58
|
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
59
|
+
var RUNAWAY_WINDOW_MS = 3e5;
|
|
60
|
+
var RUNAWAY_MAX_CALLS = 3;
|
|
61
|
+
var _verifyCallTimestamps = [];
|
|
62
|
+
function checkRunaway() {
|
|
63
|
+
const now = Date.now();
|
|
64
|
+
while (_verifyCallTimestamps.length > 0 && _verifyCallTimestamps[0] < now - RUNAWAY_WINDOW_MS) {
|
|
65
|
+
_verifyCallTimestamps.shift();
|
|
66
|
+
}
|
|
67
|
+
if (_verifyCallTimestamps.length >= RUNAWAY_MAX_CALLS) {
|
|
68
|
+
const oldestInWindow = _verifyCallTimestamps[0];
|
|
69
|
+
const waitMs = RUNAWAY_WINDOW_MS - (now - oldestInWindow);
|
|
70
|
+
const waitSec = Math.ceil(waitMs / 1e3);
|
|
71
|
+
return `\u26D4 **Runaway protection active** \u2014 ${RUNAWAY_MAX_CALLS}+ verify calls in the last 5 minutes. Please wait ${waitSec}s before trying again.
|
|
72
|
+
\u{1F4A1} This prevents resource exhaustion (CPU/RAM) from uncontrolled test spawning.`;
|
|
73
|
+
}
|
|
74
|
+
_verifyCallTimestamps.push(now);
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
59
77
|
function getRunningVerificationPid() {
|
|
60
78
|
return _currentProcess?.pid ?? null;
|
|
61
79
|
}
|
|
@@ -126,6 +144,11 @@ async function runAutoVerification(options = {}) {
|
|
|
126
144
|
const timeoutMs = options.timeoutMs || DEFAULT_TIMEOUT_MS;
|
|
127
145
|
const denial = checkAllowed(root);
|
|
128
146
|
if (denial) return denial;
|
|
147
|
+
const runawayBlock = checkRunaway();
|
|
148
|
+
if (runawayBlock) {
|
|
149
|
+
releaseFileLock(root);
|
|
150
|
+
return runawayBlock;
|
|
151
|
+
}
|
|
129
152
|
try {
|
|
130
153
|
if (!options.force) {
|
|
131
154
|
const cached = await checkStaleness(scope);
|
|
@@ -2,10 +2,10 @@ import {
|
|
|
2
2
|
getGitDiffStat,
|
|
3
3
|
getSessionStats,
|
|
4
4
|
getUnresolvedCount
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-FL2TLLMX.js";
|
|
6
6
|
import {
|
|
7
7
|
sessionMemory
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-SLRRDKQ2.js";
|
|
9
9
|
import "./chunk-E2KFPEBT.js";
|
|
10
10
|
|
|
11
11
|
// src/engine/safetyScore.ts
|
|
@@ -60,7 +60,7 @@ async function computeSafetyScore(inputGoal) {
|
|
|
60
60
|
totalScore += 20;
|
|
61
61
|
}
|
|
62
62
|
try {
|
|
63
|
-
const { getDb } = await import("./kumaDb-
|
|
63
|
+
const { getDb } = await import("./kumaDb-6D53ERFP.js");
|
|
64
64
|
const db = await getDb();
|
|
65
65
|
const nodeCount = db.exec("SELECT COUNT(*) as c FROM nodes")[0]?.values[0][0] ?? 0;
|
|
66
66
|
const edgeCount = db.exec("SELECT COUNT(*) as c FROM edges")[0]?.values[0][0] ?? 0;
|
|
@@ -91,7 +91,7 @@ async function computeSafetyScore(inputGoal) {
|
|
|
91
91
|
totalScore += 5;
|
|
92
92
|
}
|
|
93
93
|
try {
|
|
94
|
-
const { getDb } = await import("./kumaDb-
|
|
94
|
+
const { getDb } = await import("./kumaDb-6D53ERFP.js");
|
|
95
95
|
const db = await getDb();
|
|
96
96
|
const researchCount = db.exec("SELECT COUNT(*) as c FROM research_cache")[0]?.values[0][0] ?? 0;
|
|
97
97
|
checks.push({
|
|
@@ -116,7 +116,7 @@ async function computeSafetyScore(inputGoal) {
|
|
|
116
116
|
const hasRunTests = stats.hasRunTests;
|
|
117
117
|
let latestVerif = null;
|
|
118
118
|
try {
|
|
119
|
-
const { getLatestVerifications } = await import("./kumaDb-
|
|
119
|
+
const { getLatestVerifications } = await import("./kumaDb-6D53ERFP.js");
|
|
120
120
|
const verifs = await getLatestVerifications(1);
|
|
121
121
|
if (verifs.length > 0) latestVerif = verifs[0];
|
|
122
122
|
} catch {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@plumpslabs/kuma",
|
|
3
|
-
"version": "2.3.
|
|
3
|
+
"version": "2.3.8",
|
|
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",
|