@plumpslabs/kuma 2.3.7 → 2.3.9
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-GDNAWLHF.js → chunk-3TX6Q37T.js} +89 -2
- package/dist/{chunk-X5TPBDKO.js → chunk-OJALFQ4H.js} +2 -2
- package/dist/chunk-Q2444HWO.js +282 -0
- package/dist/{chunk-BI7KD3SG.js → chunk-R6B3VUSB.js} +2 -2
- package/dist/chunk-RI3DKY62.js +155 -0
- package/dist/{chunk-FOQQ2CSL.js → chunk-SPHI2BOO.js} +1 -1
- package/dist/{chunk-K64NSHBR.js → chunk-ZKDYTYMS.js} +108 -2
- package/dist/contextDigest-5JXLH56Z.js +177 -0
- package/dist/domainRules-ED6EOFVY.js +20 -0
- package/dist/index.js +393 -198
- package/dist/kumaAstValidator-CNM7FHYA.js +150 -0
- package/dist/kumaCheckpoint-XIQWRMGV.js +207 -0
- package/dist/kumaCodeScanner-LFJGPJNH.js +566 -0
- package/dist/kumaContractEngine-KX27T4N7.js +305 -0
- package/dist/{kumaDb-DJUDLYBJ.js → kumaDb-IC7UX7PU.js} +3 -1
- package/dist/kumaDriftDetector-QBY6OJOO.js +237 -0
- package/dist/kumaGotchas-5HODT5RI.js +151 -0
- package/dist/{kumaGraph-35TAIBWD.js → kumaGraph-GUQM75WL.js} +8 -2
- package/dist/{kumaMemory-5SR3TGRL.js → kumaMemory-FMOWIODH.js} +2 -2
- package/dist/{kumaMiner-P5KCUSF7.js → kumaMiner-3RXEOCBP.js} +3 -3
- package/dist/kumaPolicyEngine-ORBWL5PT.js +311 -0
- package/dist/kumaProgressiveContext-CVSNPY3W.js +231 -0
- package/dist/{kumaSearch-LG2OYEJY.js → kumaSearch-B5WVYHHD.js} +1 -1
- package/dist/kumaTrajectory-T6DXGOG4.js +460 -0
- package/dist/{kumaVerifier-LFRNIGSL.js → kumaVerifier-KAYJHR5K.js} +25 -2
- package/dist/{kumaVisualize-ODCWFSUY.js → kumaVisualize-AFL7STLL.js} +1 -1
- package/dist/safetyAudit-32WSA4Z5.js +12 -0
- package/dist/{safetyScore-PJGRRBWP.js → safetyScore-WU27EOG4.js} +5 -5
- package/dist/{sessionMemory-HBBXUSIP.js → sessionMemory-4UWA3E5J.js} +1 -1
- package/package.json +18 -13
- package/packages/ide/studio/dist/index.js +140 -0
- package/packages/ide/studio/public/index.html +500 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getDb,
|
|
3
3
|
saveDb
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-3TX6Q37T.js";
|
|
5
5
|
import {
|
|
6
6
|
getProjectRoot
|
|
7
7
|
} from "./chunk-E2KFPEBT.js";
|
|
@@ -458,7 +458,7 @@ The two nodes may not be connected in the knowledge graph yet. Use more tools to
|
|
|
458
458
|
}
|
|
459
459
|
async function buildFromSessionMemory() {
|
|
460
460
|
try {
|
|
461
|
-
const { sessionMemory } = await import("./sessionMemory-
|
|
461
|
+
const { sessionMemory } = await import("./sessionMemory-4UWA3E5J.js");
|
|
462
462
|
const toolCalls = sessionMemory.getToolCallHistory(50);
|
|
463
463
|
let edgeCount = 0;
|
|
464
464
|
for (const call of toolCalls) {
|
|
@@ -630,6 +630,109 @@ async function codebaseSearchFallback(query, limit = 20) {
|
|
|
630
630
|
}
|
|
631
631
|
}
|
|
632
632
|
}
|
|
633
|
+
async function resolveFederatedNode(uri) {
|
|
634
|
+
try {
|
|
635
|
+
if (!uri.startsWith("kuma://")) {
|
|
636
|
+
return `\u26A0\uFE0F Invalid URI scheme: "${uri.substring(0, 20)}...". Use kuma://project/node-id`;
|
|
637
|
+
}
|
|
638
|
+
const pathPart = uri.replace("kuma://", "");
|
|
639
|
+
const firstSlash = pathPart.indexOf("/");
|
|
640
|
+
if (firstSlash === -1) {
|
|
641
|
+
return `\u26A0\uFE0F Invalid federated URI: "${uri}". Format: kuma://<project>/<node-id>`;
|
|
642
|
+
}
|
|
643
|
+
const projectName = pathPart.substring(0, firstSlash);
|
|
644
|
+
const nodeRef = pathPart.substring(firstSlash + 1);
|
|
645
|
+
const db = await getDb();
|
|
646
|
+
const stmt = db.prepare(`
|
|
647
|
+
SELECT id, type, name, file_path, metadata FROM nodes
|
|
648
|
+
WHERE id = ? OR name LIKE ?
|
|
649
|
+
LIMIT 5
|
|
650
|
+
`);
|
|
651
|
+
stmt.bind([nodeRef, `%${nodeRef}%`]);
|
|
652
|
+
const results = [];
|
|
653
|
+
while (stmt.step()) results.push(stmt.getAsObject());
|
|
654
|
+
stmt.free();
|
|
655
|
+
if (results.length > 0) {
|
|
656
|
+
const lines = [
|
|
657
|
+
`\u{1F517} **Federated Node Resolved** (local)`,
|
|
658
|
+
`\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`,
|
|
659
|
+
`\u{1F4C1} Project: ${projectName}`,
|
|
660
|
+
`\u{1F517} URI: ${uri}`,
|
|
661
|
+
""
|
|
662
|
+
];
|
|
663
|
+
for (const r of results) {
|
|
664
|
+
lines.push(` \u2022 **${r.name}** (${r.type}) \u2014 ${r.file_path || "no path"}`);
|
|
665
|
+
}
|
|
666
|
+
lines.push("", "\u{1F4A1} Federated cross-repo resolution is active. Remote resolution via HTTP coming soon.");
|
|
667
|
+
return lines.join("\n");
|
|
668
|
+
}
|
|
669
|
+
const federatedNodes = await registerFederatedReference(uri, projectName, nodeRef);
|
|
670
|
+
return [
|
|
671
|
+
`\u{1F517} **Federated Reference**`,
|
|
672
|
+
`\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`,
|
|
673
|
+
`\u{1F4C1} Remote project: ${projectName}`,
|
|
674
|
+
`\u{1F517} URI: ${uri}`,
|
|
675
|
+
`\u{1F4CC} Node ref: ${nodeRef}`,
|
|
676
|
+
"",
|
|
677
|
+
`\u{1F4DD} Registered as federated reference for future resolution.`,
|
|
678
|
+
`\u{1F4A1} Remote graph resolution will be available when the target project is reachable.`,
|
|
679
|
+
federatedNodes > 0 ? `\u2705 Created ${federatedNodes} federated node(s) in local graph.` : ""
|
|
680
|
+
].filter(Boolean).join("\n");
|
|
681
|
+
} catch (err) {
|
|
682
|
+
return `\u274C Federated resolution failed: ${err}`;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
async function registerFederatedReference(uri, projectName, nodeRef) {
|
|
686
|
+
try {
|
|
687
|
+
await upsertNode({
|
|
688
|
+
id: `federated::${uri}`,
|
|
689
|
+
type: "module",
|
|
690
|
+
name: `[${projectName}] ${nodeRef}`,
|
|
691
|
+
metadata: {
|
|
692
|
+
federated: true,
|
|
693
|
+
uri,
|
|
694
|
+
project: projectName,
|
|
695
|
+
ref: nodeRef,
|
|
696
|
+
resolved: false
|
|
697
|
+
}
|
|
698
|
+
});
|
|
699
|
+
return 1;
|
|
700
|
+
} catch {
|
|
701
|
+
return 0;
|
|
702
|
+
}
|
|
703
|
+
}
|
|
704
|
+
async function listFederatedReferences() {
|
|
705
|
+
try {
|
|
706
|
+
const db = await getDb();
|
|
707
|
+
const stmt = db.prepare(`
|
|
708
|
+
SELECT id, name, metadata FROM nodes
|
|
709
|
+
WHERE metadata LIKE '%"federated":true%'
|
|
710
|
+
ORDER BY updated_at DESC
|
|
711
|
+
LIMIT 20
|
|
712
|
+
`);
|
|
713
|
+
const results = [];
|
|
714
|
+
while (stmt.step()) results.push(stmt.getAsObject());
|
|
715
|
+
stmt.free();
|
|
716
|
+
if (results.length === 0) {
|
|
717
|
+
return "\u{1F517} **No federated references.** Use kuma_memory({ action: 'federated', uri: 'kuma://project/node-id' }) to add one.";
|
|
718
|
+
}
|
|
719
|
+
const lines = [
|
|
720
|
+
"\u{1F517} **Federated References**",
|
|
721
|
+
"\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",
|
|
722
|
+
""
|
|
723
|
+
];
|
|
724
|
+
for (const r of results) {
|
|
725
|
+
const meta = JSON.parse(r.metadata || "{}");
|
|
726
|
+
lines.push(` \u{1F517} **${r.name}**`);
|
|
727
|
+
lines.push(` URI: ${meta.uri || "unknown"}`);
|
|
728
|
+
lines.push(` Resolved: ${meta.resolved ? "\u2705" : "\u23F3"}`);
|
|
729
|
+
lines.push("");
|
|
730
|
+
}
|
|
731
|
+
return lines.join("\n");
|
|
732
|
+
} catch (err) {
|
|
733
|
+
return `Error: ${err}`;
|
|
734
|
+
}
|
|
735
|
+
}
|
|
633
736
|
async function getGraphStats() {
|
|
634
737
|
try {
|
|
635
738
|
const db = await getDb();
|
|
@@ -850,6 +953,7 @@ export {
|
|
|
850
953
|
detectStaleNodes,
|
|
851
954
|
autoHeal,
|
|
852
955
|
formatHealReport,
|
|
956
|
+
nodeId,
|
|
853
957
|
upsertNode,
|
|
854
958
|
addEdge,
|
|
855
959
|
recordFunctionCall,
|
|
@@ -860,6 +964,8 @@ export {
|
|
|
860
964
|
queryGraph,
|
|
861
965
|
buildFromSessionMemory,
|
|
862
966
|
searchGraph,
|
|
967
|
+
resolveFederatedNode,
|
|
968
|
+
listFederatedReferences,
|
|
863
969
|
getGraphStats,
|
|
864
970
|
analyzeImpact,
|
|
865
971
|
formatImpact,
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getActiveGotchas
|
|
3
|
+
} from "./chunk-Q2444HWO.js";
|
|
4
|
+
import {
|
|
5
|
+
sessionMemory
|
|
6
|
+
} from "./chunk-R6B3VUSB.js";
|
|
7
|
+
import {
|
|
8
|
+
getDb
|
|
9
|
+
} from "./chunk-3TX6Q37T.js";
|
|
10
|
+
import {
|
|
11
|
+
getProjectRoot
|
|
12
|
+
} from "./chunk-E2KFPEBT.js";
|
|
13
|
+
|
|
14
|
+
// src/engine/contextDigest.ts
|
|
15
|
+
import fs from "fs";
|
|
16
|
+
import path from "path";
|
|
17
|
+
function detectTechStack() {
|
|
18
|
+
const root = getProjectRoot();
|
|
19
|
+
const stack = {
|
|
20
|
+
languages: [],
|
|
21
|
+
framework: null,
|
|
22
|
+
database: null,
|
|
23
|
+
testRunner: null,
|
|
24
|
+
packageManager: null,
|
|
25
|
+
monorepo: false
|
|
26
|
+
};
|
|
27
|
+
try {
|
|
28
|
+
const pkgPath = path.join(root, "package.json");
|
|
29
|
+
if (fs.existsSync(pkgPath)) {
|
|
30
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
31
|
+
const deps = { ...pkg.dependencies, ...pkg.devDependencies };
|
|
32
|
+
if (fs.existsSync(path.join(root, "pnpm-lock.yaml"))) stack.packageManager = "pnpm";
|
|
33
|
+
else if (fs.existsSync(path.join(root, "yarn.lock"))) stack.packageManager = "yarn";
|
|
34
|
+
else stack.packageManager = "npm";
|
|
35
|
+
stack.monorepo = !!pkg.workspaces;
|
|
36
|
+
if (deps.next) stack.framework = "Next.js";
|
|
37
|
+
else if (deps.react) stack.framework = "React";
|
|
38
|
+
else if (deps.vue) stack.framework = "Vue";
|
|
39
|
+
else if (deps.express) stack.framework = "Express";
|
|
40
|
+
else if (deps.fastify) stack.framework = "Fastify";
|
|
41
|
+
else if (deps.nest) stack.framework = "NestJS";
|
|
42
|
+
else if (deps["@remix-run/react"]) stack.framework = "Remix";
|
|
43
|
+
else if (deps.svelte) stack.framework = "Svelte";
|
|
44
|
+
else if (deps.angular) stack.framework = "Angular";
|
|
45
|
+
if (deps.prisma) stack.database = "Prisma";
|
|
46
|
+
else if (deps.typeorm) stack.database = "TypeORM";
|
|
47
|
+
else if (deps.mongoose) stack.database = "MongoDB";
|
|
48
|
+
else if (deps.pg || deps["@neondatabase/serverless"]) stack.database = "PostgreSQL";
|
|
49
|
+
else if (deps.redis) stack.database = "Redis";
|
|
50
|
+
else if (deps.better || deps.drizzle) stack.database = "Drizzle";
|
|
51
|
+
if (deps.jest || deps["@jest/core"]) stack.testRunner = "Jest";
|
|
52
|
+
else if (deps.vitest) stack.testRunner = "Vitest";
|
|
53
|
+
else if (deps.mocha) stack.testRunner = "Mocha";
|
|
54
|
+
else if (deps.playwright) stack.testRunner = "Playwright";
|
|
55
|
+
else if (deps.cypress) stack.testRunner = "Cypress";
|
|
56
|
+
if (fs.existsSync(path.join(root, "tsconfig.json"))) stack.languages.push("TypeScript");
|
|
57
|
+
if (deps.typescript) stack.languages.push("TypeScript");
|
|
58
|
+
if (fs.existsSync(path.join(root, "jsconfig.json"))) stack.languages.push("JavaScript");
|
|
59
|
+
if (fs.existsSync(path.join(root, "go.mod"))) stack.languages.push("Go");
|
|
60
|
+
if (fs.existsSync(path.join(root, "Cargo.toml"))) stack.languages.push("Rust");
|
|
61
|
+
if (fs.existsSync(path.join(root, "pyproject.toml"))) stack.languages.push("Python");
|
|
62
|
+
if (fs.existsSync(path.join(root, "Gemfile"))) stack.languages.push("Ruby");
|
|
63
|
+
if (stack.languages.length === 0) stack.languages.push("JavaScript");
|
|
64
|
+
}
|
|
65
|
+
} catch {
|
|
66
|
+
}
|
|
67
|
+
return stack;
|
|
68
|
+
}
|
|
69
|
+
function detectEntryPoints() {
|
|
70
|
+
const root = getProjectRoot();
|
|
71
|
+
const entryPoints = [];
|
|
72
|
+
const candidates = [
|
|
73
|
+
"src/index.ts",
|
|
74
|
+
"src/index.js",
|
|
75
|
+
"src/app.ts",
|
|
76
|
+
"src/app.js",
|
|
77
|
+
"index.ts",
|
|
78
|
+
"index.js",
|
|
79
|
+
"src/main.ts",
|
|
80
|
+
"src/main.js",
|
|
81
|
+
"src/server.ts",
|
|
82
|
+
"src/server.js",
|
|
83
|
+
"app.ts",
|
|
84
|
+
"app.js",
|
|
85
|
+
"pages/index.tsx",
|
|
86
|
+
"pages/index.jsx",
|
|
87
|
+
"src/App.tsx",
|
|
88
|
+
"src/App.js",
|
|
89
|
+
"lib/main.ts",
|
|
90
|
+
"lib/index.ts"
|
|
91
|
+
];
|
|
92
|
+
for (const c of candidates) {
|
|
93
|
+
if (fs.existsSync(path.join(root, c))) {
|
|
94
|
+
entryPoints.push(c);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
try {
|
|
98
|
+
const pkg = JSON.parse(fs.readFileSync(path.join(root, "package.json"), "utf-8"));
|
|
99
|
+
if (pkg.main && fs.existsSync(path.join(root, pkg.main))) {
|
|
100
|
+
if (!entryPoints.includes(pkg.main)) entryPoints.push(pkg.main);
|
|
101
|
+
}
|
|
102
|
+
} catch {
|
|
103
|
+
}
|
|
104
|
+
return entryPoints;
|
|
105
|
+
}
|
|
106
|
+
async function getActiveADRs() {
|
|
107
|
+
try {
|
|
108
|
+
const db = await getDb();
|
|
109
|
+
const stmt = db.prepare(
|
|
110
|
+
"SELECT title FROM decision_log WHERE status = 'active' ORDER BY created_at DESC LIMIT 5"
|
|
111
|
+
);
|
|
112
|
+
const results = [];
|
|
113
|
+
while (stmt.step()) {
|
|
114
|
+
const row = stmt.getAsObject();
|
|
115
|
+
results.push(row.title);
|
|
116
|
+
}
|
|
117
|
+
stmt.free();
|
|
118
|
+
return results;
|
|
119
|
+
} catch {
|
|
120
|
+
return [];
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
async function generateContextDigest() {
|
|
124
|
+
const stack = detectTechStack();
|
|
125
|
+
const entryPoints = detectEntryPoints();
|
|
126
|
+
const adrs = await getActiveADRs();
|
|
127
|
+
const gotchas = getActiveGotchas();
|
|
128
|
+
const summary = sessionMemory.getSummary();
|
|
129
|
+
const lines = [
|
|
130
|
+
"\u{1F4CB} **Kuma Digest** \u2014 <500 token briefing",
|
|
131
|
+
"\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",
|
|
132
|
+
""
|
|
133
|
+
];
|
|
134
|
+
const langStr = stack.languages.join("/");
|
|
135
|
+
const frameworkStr = stack.framework || "\u2014";
|
|
136
|
+
const dbStr = stack.database || "\u2014";
|
|
137
|
+
const testStr = stack.testRunner || "\u2014";
|
|
138
|
+
const pmStr = stack.packageManager || "\u2014";
|
|
139
|
+
lines.push(`\u{1F527} **Stack**: ${langStr} | ${frameworkStr} | ${dbStr} | ${testStr} | ${pmStr}${stack.monorepo ? " (monorepo)" : ""}`);
|
|
140
|
+
lines.push(`\u{1F4C1} **Root**: ${getProjectRoot().split("/").pop() || "?"}`);
|
|
141
|
+
if (entryPoints.length > 0) {
|
|
142
|
+
lines.push(`\u{1F6AA} **Entry**: ${entryPoints.slice(0, 3).join(", ")}`);
|
|
143
|
+
}
|
|
144
|
+
try {
|
|
145
|
+
const ruleFile = path.join(getProjectRoot(), ".kuma", "DOMAIN_RULES.md");
|
|
146
|
+
if (fs.existsSync(ruleFile)) {
|
|
147
|
+
const content = fs.readFileSync(ruleFile, "utf-8");
|
|
148
|
+
const rules = content.split("\n").filter((l) => /^- Rule \d+:?\s*/i.test(l)).map((l) => l.replace(/^- Rule \d+:?\s*/i, "").trim()).filter(Boolean);
|
|
149
|
+
if (rules.length > 0) {
|
|
150
|
+
lines.push(`\u{1F4CB} **Rules**: ${rules.slice(0, 5).join(" | ")}`);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
} catch {
|
|
154
|
+
}
|
|
155
|
+
if (gotchas.length > 0) {
|
|
156
|
+
const critical = gotchas.filter((g) => g.severity === "critical" || g.severity === "high");
|
|
157
|
+
if (critical.length > 0) {
|
|
158
|
+
lines.push(`\u26A0\uFE0F **Gotchas**: ${critical.length} high/critical \u2014 ${critical.slice(0, 3).map((g) => g.filePath).join(", ")}`);
|
|
159
|
+
} else {
|
|
160
|
+
lines.push(`\u26A0\uFE0F **Gotchas**: ${gotchas.length} recorded`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (adrs.length > 0) {
|
|
164
|
+
lines.push(`\u{1F4DD} **ADRs**: ${adrs.slice(0, 3).join(" | ")}`);
|
|
165
|
+
}
|
|
166
|
+
lines.push(`\u{1F3AF} **Goal**: ${summary.currentGoal?.substring(0, 80) || "not set"}`);
|
|
167
|
+
const text = lines.join("\n");
|
|
168
|
+
const estimatedTokens = Math.ceil(text.length / 4);
|
|
169
|
+
if (estimatedTokens > 450) {
|
|
170
|
+
lines.push(`\u{1F4CA} *~${estimatedTokens} tokens, fits under 500 limit*`);
|
|
171
|
+
}
|
|
172
|
+
return lines.join("\n") + "\n\n\u{1F4A1} Use kuma_context({ action: 'sync' }) for full state.";
|
|
173
|
+
}
|
|
174
|
+
export {
|
|
175
|
+
generateContextDigest,
|
|
176
|
+
generateContextDigest as generateDigest
|
|
177
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
appendToLayer,
|
|
3
|
+
checkFileGotchas,
|
|
4
|
+
generateDigest,
|
|
5
|
+
getActiveGotchas,
|
|
6
|
+
getLayersSummary,
|
|
7
|
+
readLayer,
|
|
8
|
+
writeLayer
|
|
9
|
+
} from "./chunk-Q2444HWO.js";
|
|
10
|
+
import "./chunk-R6B3VUSB.js";
|
|
11
|
+
import "./chunk-E2KFPEBT.js";
|
|
12
|
+
export {
|
|
13
|
+
appendToLayer,
|
|
14
|
+
checkFileGotchas,
|
|
15
|
+
generateDigest,
|
|
16
|
+
getActiveGotchas,
|
|
17
|
+
getLayersSummary,
|
|
18
|
+
readLayer,
|
|
19
|
+
writeLayer
|
|
20
|
+
};
|