@triedotdev/mcp 1.0.136 → 1.0.138
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 +6 -6
- package/dist/{autonomy-config-QA6ATWLJ.js → autonomy-config-TZ6HF4FA.js} +3 -3
- package/dist/{chat-store-HFOOWZYN.js → chat-store-OJLJCJFI.js} +3 -3
- package/dist/{chunk-DFPVUMVE.js → chunk-23RJT5WT.js} +5 -4
- package/dist/chunk-23RJT5WT.js.map +1 -0
- package/dist/{chunk-4YJ6KLGI.js → chunk-3MUCUZ46.js} +8 -8
- package/dist/chunk-3MUCUZ46.js.map +1 -0
- package/dist/{chunk-6VIMBFUZ.js → chunk-3RRXWX3V.js} +21 -17
- package/dist/chunk-3RRXWX3V.js.map +1 -0
- package/dist/{chunk-WHIQAGB7.js → chunk-4C67GV3O.js} +2 -2
- package/dist/{chunk-WS6OA7H6.js → chunk-4MJ52WBH.js} +2 -3
- package/dist/chunk-4MJ52WBH.js.map +1 -0
- package/dist/{chunk-AJ34GCMD.js → chunk-67GSG2ST.js} +41 -38
- package/dist/chunk-67GSG2ST.js.map +1 -0
- package/dist/{chunk-UHX4462X.js → chunk-6LLH3TBZ.js} +24 -25
- package/dist/chunk-6LLH3TBZ.js.map +1 -0
- package/dist/{chunk-DFHMB44X.js → chunk-D3AS5LY7.js} +6 -10
- package/dist/chunk-D3AS5LY7.js.map +1 -0
- package/dist/{chunk-6OUWNVLX.js → chunk-EDDT4ZIH.js} +8 -8
- package/dist/chunk-EDDT4ZIH.js.map +1 -0
- package/dist/{chunk-Z4DN527J.js → chunk-FG467PDD.js} +156 -39
- package/dist/chunk-FG467PDD.js.map +1 -0
- package/dist/{chunk-T4THB2OR.js → chunk-FOCXXIXY.js} +49 -28
- package/dist/chunk-FOCXXIXY.js.map +1 -0
- package/dist/{goal-validator-PDKYZSNP.js → chunk-GFFUDJMK.js} +97 -40
- package/dist/chunk-GFFUDJMK.js.map +1 -0
- package/dist/{chunk-ZEXMMTIQ.js → chunk-J5EMP4XW.js} +2 -2
- package/dist/{chunk-UHMMANC2.js → chunk-LT6VUZG2.js} +21 -18
- package/dist/chunk-LT6VUZG2.js.map +1 -0
- package/dist/{chunk-55CBWOEZ.js → chunk-QSWUPSLK.js} +2 -2
- package/dist/{chunk-45Y5TLQZ.js → chunk-SH7H3WRU.js} +3 -6
- package/dist/chunk-SH7H3WRU.js.map +1 -0
- package/dist/{chunk-VRLMTOB6.js → chunk-TIMIKBY2.js} +1 -1
- package/dist/chunk-TIMIKBY2.js.map +1 -0
- package/dist/{chunk-POHBQUG7.js → chunk-X3F5QDER.js} +1224 -448
- package/dist/chunk-X3F5QDER.js.map +1 -0
- package/dist/{chunk-O6OTJI3W.js → chunk-Y32FM3MR.js} +2 -2
- package/dist/{chunk-G5PRBQIQ.js → chunk-YOKQ25IW.js} +102 -82
- package/dist/chunk-YOKQ25IW.js.map +1 -0
- package/dist/{chunk-JAKMZI5S.js → chunk-Z2P4WST6.js} +291 -180
- package/dist/chunk-Z2P4WST6.js.map +1 -0
- package/dist/cli/create-agent.js +1 -1
- package/dist/cli/main.js +113 -86
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +19 -19
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/{client-BZHI675W.js → client-JTU5TRLB.js} +3 -3
- package/dist/{codebase-index-CR6Q2HEI.js → codebase-index-FNJ4GCBE.js} +3 -3
- package/dist/{goal-manager-FAK7H4RR.js → goal-manager-6BJQ36AH.js} +7 -8
- package/dist/goal-validator-GISXYANK.js +22 -0
- package/dist/{graph-PAUZ5EMP.js → graph-X2FMRQLG.js} +3 -3
- package/dist/{hypothesis-L5446W36.js → hypothesis-K3KQJOXJ.js} +7 -8
- package/dist/{incident-index-ZCDSJ42L.js → incident-index-BWW2UEY7.js} +3 -3
- package/dist/index.js +343 -288
- package/dist/index.js.map +1 -1
- package/dist/{insight-store-F5KDBY5Y.js → insight-store-A5XXMFD6.js} +6 -6
- package/dist/issue-store-BO5OWLJW.js +32 -0
- package/dist/{output-manager-BOTMXSND.js → output-manager-DZO5LGSG.js} +2 -2
- package/dist/{tiered-storage-QW2G7GSG.js → tiered-storage-VZL7KK64.js} +3 -3
- package/dist/trie-agent-XMSGMD7E.js +26 -0
- package/dist/trie-agent-XMSGMD7E.js.map +1 -0
- package/dist/ui/chat.html +260 -67
- package/dist/ui/goals.html +246 -3
- package/dist/ui/hypotheses.html +248 -5
- package/dist/ui/ledger.html +252 -9
- package/dist/ui/nudges.html +244 -1
- package/package.json +1 -1
- package/dist/chunk-45Y5TLQZ.js.map +0 -1
- package/dist/chunk-4YJ6KLGI.js.map +0 -1
- package/dist/chunk-6OUWNVLX.js.map +0 -1
- package/dist/chunk-6VIMBFUZ.js.map +0 -1
- package/dist/chunk-AJ34GCMD.js.map +0 -1
- package/dist/chunk-DFHMB44X.js.map +0 -1
- package/dist/chunk-DFPVUMVE.js.map +0 -1
- package/dist/chunk-G5PRBQIQ.js.map +0 -1
- package/dist/chunk-JAKMZI5S.js.map +0 -1
- package/dist/chunk-PEJEYWVR.js +0 -135
- package/dist/chunk-PEJEYWVR.js.map +0 -1
- package/dist/chunk-POHBQUG7.js.map +0 -1
- package/dist/chunk-T4THB2OR.js.map +0 -1
- package/dist/chunk-UHMMANC2.js.map +0 -1
- package/dist/chunk-UHX4462X.js.map +0 -1
- package/dist/chunk-VRLMTOB6.js.map +0 -1
- package/dist/chunk-WS6OA7H6.js.map +0 -1
- package/dist/chunk-Z4DN527J.js.map +0 -1
- package/dist/goal-validator-PDKYZSNP.js.map +0 -1
- package/dist/guardian-agent-4RHGIXUD.js +0 -27
- package/dist/ledger-WKVJWHBX.js +0 -17
- /package/dist/{autonomy-config-QA6ATWLJ.js.map → autonomy-config-TZ6HF4FA.js.map} +0 -0
- /package/dist/{chat-store-HFOOWZYN.js.map → chat-store-OJLJCJFI.js.map} +0 -0
- /package/dist/{chunk-WHIQAGB7.js.map → chunk-4C67GV3O.js.map} +0 -0
- /package/dist/{chunk-ZEXMMTIQ.js.map → chunk-J5EMP4XW.js.map} +0 -0
- /package/dist/{chunk-55CBWOEZ.js.map → chunk-QSWUPSLK.js.map} +0 -0
- /package/dist/{chunk-O6OTJI3W.js.map → chunk-Y32FM3MR.js.map} +0 -0
- /package/dist/{client-BZHI675W.js.map → client-JTU5TRLB.js.map} +0 -0
- /package/dist/{codebase-index-CR6Q2HEI.js.map → codebase-index-FNJ4GCBE.js.map} +0 -0
- /package/dist/{goal-manager-FAK7H4RR.js.map → goal-manager-6BJQ36AH.js.map} +0 -0
- /package/dist/{graph-PAUZ5EMP.js.map → goal-validator-GISXYANK.js.map} +0 -0
- /package/dist/{guardian-agent-4RHGIXUD.js.map → graph-X2FMRQLG.js.map} +0 -0
- /package/dist/{hypothesis-L5446W36.js.map → hypothesis-K3KQJOXJ.js.map} +0 -0
- /package/dist/{incident-index-ZCDSJ42L.js.map → incident-index-BWW2UEY7.js.map} +0 -0
- /package/dist/{insight-store-F5KDBY5Y.js.map → insight-store-A5XXMFD6.js.map} +0 -0
- /package/dist/{ledger-WKVJWHBX.js.map → issue-store-BO5OWLJW.js.map} +0 -0
- /package/dist/{output-manager-BOTMXSND.js.map → output-manager-DZO5LGSG.js.map} +0 -0
- /package/dist/{tiered-storage-QW2G7GSG.js.map → tiered-storage-VZL7KK64.js.map} +0 -0
|
@@ -3,175 +3,20 @@ import {
|
|
|
3
3
|
CompactedSummariesIndexSchema,
|
|
4
4
|
IssueIndexSchema,
|
|
5
5
|
safeParseAndValidate
|
|
6
|
-
} from "./chunk-
|
|
7
|
-
import {
|
|
8
|
-
appendIssuesToLedger
|
|
9
|
-
} from "./chunk-PEJEYWVR.js";
|
|
6
|
+
} from "./chunk-4MJ52WBH.js";
|
|
10
7
|
import {
|
|
11
8
|
atomicWriteJSON
|
|
12
9
|
} from "./chunk-43X6JBEM.js";
|
|
13
10
|
import {
|
|
14
11
|
getTrieDirectory,
|
|
15
12
|
getWorkingDirectory
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
|
|
18
|
-
// src/memory/compactor.ts
|
|
19
|
-
import { mkdir, readFile } from "fs/promises";
|
|
20
|
-
import { existsSync } from "fs";
|
|
21
|
-
import { join } from "path";
|
|
22
|
-
async function compactOldIssues(issues, options = {}) {
|
|
23
|
-
const keepDays = options.keepDays ?? 30;
|
|
24
|
-
const minIssues = options.minIssuesToCompact ?? 100;
|
|
25
|
-
const cutoffDate = /* @__PURE__ */ new Date();
|
|
26
|
-
cutoffDate.setDate(cutoffDate.getDate() - keepDays);
|
|
27
|
-
const oldIssues = issues.filter((i) => new Date(i.timestamp) < cutoffDate);
|
|
28
|
-
const recentIssues = issues.filter((i) => new Date(i.timestamp) >= cutoffDate);
|
|
29
|
-
if (oldIssues.length < minIssues) {
|
|
30
|
-
return { summary: null, remaining: issues };
|
|
31
|
-
}
|
|
32
|
-
const summary = buildSummary(oldIssues);
|
|
33
|
-
return { summary, remaining: recentIssues };
|
|
34
|
-
}
|
|
35
|
-
function buildSummary(issues) {
|
|
36
|
-
const sorted = issues.sort(
|
|
37
|
-
(a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
|
|
38
|
-
);
|
|
39
|
-
const bySeverity = {};
|
|
40
|
-
const byAgent = {};
|
|
41
|
-
const patternMap = /* @__PURE__ */ new Map();
|
|
42
|
-
const fileCount = /* @__PURE__ */ new Map();
|
|
43
|
-
for (const issue of issues) {
|
|
44
|
-
bySeverity[issue.severity] = (bySeverity[issue.severity] || 0) + 1;
|
|
45
|
-
byAgent[issue.agent] = (byAgent[issue.agent] || 0) + 1;
|
|
46
|
-
const patternKey = normalizePattern(issue.issue);
|
|
47
|
-
const existing = patternMap.get(patternKey);
|
|
48
|
-
if (existing) {
|
|
49
|
-
existing.count++;
|
|
50
|
-
} else {
|
|
51
|
-
patternMap.set(patternKey, { count: 1, issue });
|
|
52
|
-
}
|
|
53
|
-
const fileName = issue.file.split("/").pop() || issue.file;
|
|
54
|
-
fileCount.set(fileName, (fileCount.get(fileName) || 0) + 1);
|
|
55
|
-
}
|
|
56
|
-
const topPatterns = Array.from(patternMap.entries()).sort((a, b) => b[1].count - a[1].count).slice(0, 10).map(([pattern, data]) => ({
|
|
57
|
-
pattern: pattern.slice(0, 100),
|
|
58
|
-
count: data.count,
|
|
59
|
-
severity: data.issue.severity,
|
|
60
|
-
agent: data.issue.agent,
|
|
61
|
-
exampleFix: data.issue.fix.slice(0, 200)
|
|
62
|
-
}));
|
|
63
|
-
const hotFiles = Array.from(fileCount.entries()).sort((a, b) => b[1] - a[1]).slice(0, 10).map(([file, count]) => ({ file, count }));
|
|
64
|
-
return {
|
|
65
|
-
period: `${sorted[0]?.timestamp.split("T")[0]} to ${sorted[sorted.length - 1]?.timestamp.split("T")[0]}`,
|
|
66
|
-
startDate: sorted[0]?.timestamp || "",
|
|
67
|
-
endDate: sorted[sorted.length - 1]?.timestamp || "",
|
|
68
|
-
totalIssues: issues.length,
|
|
69
|
-
resolvedCount: issues.filter((i) => i.resolved).length,
|
|
70
|
-
bySeverity,
|
|
71
|
-
byAgent,
|
|
72
|
-
topPatterns,
|
|
73
|
-
hotFiles,
|
|
74
|
-
compactedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
function normalizePattern(text) {
|
|
78
|
-
return text.toLowerCase().replace(/`[^`]+`/g, "CODE").replace(/\b\d+\b/g, "N").replace(/["']/g, "").replace(/\s+/g, " ").trim().slice(0, 150);
|
|
79
|
-
}
|
|
80
|
-
async function saveCompactedSummary(summary, projectDir) {
|
|
81
|
-
const memoryDir = join(getTrieDirectory(projectDir), "memory");
|
|
82
|
-
await mkdir(memoryDir, { recursive: true });
|
|
83
|
-
const summaryPath = join(memoryDir, "compacted-summaries.json");
|
|
84
|
-
let summaries = [];
|
|
85
|
-
try {
|
|
86
|
-
if (existsSync(summaryPath)) {
|
|
87
|
-
const content = await readFile(summaryPath, "utf-8");
|
|
88
|
-
const result = safeParseAndValidate(content, CompactedSummariesIndexSchema);
|
|
89
|
-
if (result.success) {
|
|
90
|
-
summaries = result.data;
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
} catch {
|
|
94
|
-
summaries = [];
|
|
95
|
-
}
|
|
96
|
-
summaries.push(summary);
|
|
97
|
-
if (summaries.length > 12) {
|
|
98
|
-
summaries = summaries.slice(-12);
|
|
99
|
-
}
|
|
100
|
-
const backupManager = new BackupManager(summaryPath);
|
|
101
|
-
await backupManager.createBackup();
|
|
102
|
-
await atomicWriteJSON(summaryPath, summaries);
|
|
103
|
-
}
|
|
104
|
-
async function loadCompactedSummaries(projectDir) {
|
|
105
|
-
const summaryPath = join(getTrieDirectory(projectDir), "memory", "compacted-summaries.json");
|
|
106
|
-
try {
|
|
107
|
-
if (existsSync(summaryPath)) {
|
|
108
|
-
const content = await readFile(summaryPath, "utf-8");
|
|
109
|
-
const result = safeParseAndValidate(content, CompactedSummariesIndexSchema);
|
|
110
|
-
if (result.success) {
|
|
111
|
-
return result.data;
|
|
112
|
-
}
|
|
113
|
-
const backupManager = new BackupManager(summaryPath);
|
|
114
|
-
if (await backupManager.recoverFromBackup()) {
|
|
115
|
-
const recovered = await readFile(summaryPath, "utf-8");
|
|
116
|
-
const recoveredResult = safeParseAndValidate(recovered, CompactedSummariesIndexSchema);
|
|
117
|
-
if (recoveredResult.success) {
|
|
118
|
-
return recoveredResult.data;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
} catch {
|
|
123
|
-
}
|
|
124
|
-
return [];
|
|
125
|
-
}
|
|
126
|
-
async function getHistoricalInsights(projectDir) {
|
|
127
|
-
const summaries = await loadCompactedSummaries(projectDir);
|
|
128
|
-
if (summaries.length === 0) {
|
|
129
|
-
return {
|
|
130
|
-
totalHistoricalIssues: 0,
|
|
131
|
-
recurringPatterns: [],
|
|
132
|
-
improvementTrend: "unknown"
|
|
133
|
-
};
|
|
134
|
-
}
|
|
135
|
-
const totalHistoricalIssues = summaries.reduce((sum, s) => sum + s.totalIssues, 0);
|
|
136
|
-
const patternCounts = /* @__PURE__ */ new Map();
|
|
137
|
-
for (const summary of summaries) {
|
|
138
|
-
for (const pattern of summary.topPatterns) {
|
|
139
|
-
const key = pattern.pattern;
|
|
140
|
-
const existing = patternCounts.get(key);
|
|
141
|
-
if (existing) {
|
|
142
|
-
existing.count += pattern.count;
|
|
143
|
-
existing.appearances++;
|
|
144
|
-
} else {
|
|
145
|
-
patternCounts.set(key, { ...pattern, appearances: 1 });
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
const recurringPatterns = Array.from(patternCounts.values()).filter((p) => p.appearances >= 2).sort((a, b) => b.count - a.count).slice(0, 5);
|
|
150
|
-
let improvementTrend = "unknown";
|
|
151
|
-
if (summaries.length >= 2) {
|
|
152
|
-
const recent = summaries.slice(-2);
|
|
153
|
-
const olderCount = recent[0]?.totalIssues || 0;
|
|
154
|
-
const newerCount = recent[1]?.totalIssues || 0;
|
|
155
|
-
if (newerCount < olderCount * 0.8) {
|
|
156
|
-
improvementTrend = "improving";
|
|
157
|
-
} else if (newerCount > olderCount * 1.2) {
|
|
158
|
-
improvementTrend = "declining";
|
|
159
|
-
} else {
|
|
160
|
-
improvementTrend = "stable";
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
return {
|
|
164
|
-
totalHistoricalIssues,
|
|
165
|
-
recurringPatterns,
|
|
166
|
-
improvementTrend
|
|
167
|
-
};
|
|
168
|
-
}
|
|
13
|
+
} from "./chunk-SH7H3WRU.js";
|
|
169
14
|
|
|
170
15
|
// src/memory/issue-store.ts
|
|
171
|
-
import { mkdir as
|
|
172
|
-
import { createHash } from "crypto";
|
|
173
|
-
import { existsSync as
|
|
174
|
-
import { join as
|
|
16
|
+
import { mkdir as mkdir3, writeFile, readFile as readFile3, readdir } from "fs/promises";
|
|
17
|
+
import { createHash as createHash2 } from "crypto";
|
|
18
|
+
import { existsSync as existsSync3 } from "fs";
|
|
19
|
+
import { join as join3 } from "path";
|
|
175
20
|
|
|
176
21
|
// src/memory/bm25.ts
|
|
177
22
|
var BM25Index = class _BM25Index {
|
|
@@ -402,11 +247,254 @@ var BM25Index = class _BM25Index {
|
|
|
402
247
|
}
|
|
403
248
|
};
|
|
404
249
|
|
|
405
|
-
// src/memory/
|
|
406
|
-
|
|
250
|
+
// src/memory/compactor.ts
|
|
251
|
+
import { mkdir, readFile } from "fs/promises";
|
|
252
|
+
import { existsSync } from "fs";
|
|
253
|
+
import { join } from "path";
|
|
254
|
+
async function compactOldIssues(issues, options = {}) {
|
|
255
|
+
const keepDays = options.keepDays ?? 30;
|
|
256
|
+
const minIssues = options.minIssuesToCompact ?? 100;
|
|
257
|
+
const cutoffDate = /* @__PURE__ */ new Date();
|
|
258
|
+
cutoffDate.setDate(cutoffDate.getDate() - keepDays);
|
|
259
|
+
const oldIssues = issues.filter((i) => new Date(i.timestamp) < cutoffDate);
|
|
260
|
+
const recentIssues = issues.filter((i) => new Date(i.timestamp) >= cutoffDate);
|
|
261
|
+
if (oldIssues.length < minIssues) {
|
|
262
|
+
return { summary: null, remaining: issues };
|
|
263
|
+
}
|
|
264
|
+
const summary = buildSummary(oldIssues);
|
|
265
|
+
return { summary, remaining: recentIssues };
|
|
266
|
+
}
|
|
267
|
+
function buildSummary(issues) {
|
|
268
|
+
const sorted = issues.sort(
|
|
269
|
+
(a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
|
|
270
|
+
);
|
|
271
|
+
const bySeverity = {};
|
|
272
|
+
const byAgent = {};
|
|
273
|
+
const patternMap = /* @__PURE__ */ new Map();
|
|
274
|
+
const fileCount = /* @__PURE__ */ new Map();
|
|
275
|
+
for (const issue of issues) {
|
|
276
|
+
bySeverity[issue.severity] = (bySeverity[issue.severity] || 0) + 1;
|
|
277
|
+
byAgent[issue.agent] = (byAgent[issue.agent] || 0) + 1;
|
|
278
|
+
const patternKey = normalizePattern(issue.issue);
|
|
279
|
+
const existing = patternMap.get(patternKey);
|
|
280
|
+
if (existing) {
|
|
281
|
+
existing.count++;
|
|
282
|
+
} else {
|
|
283
|
+
patternMap.set(patternKey, { count: 1, issue });
|
|
284
|
+
}
|
|
285
|
+
const fileName = issue.file.split("/").pop() || issue.file;
|
|
286
|
+
fileCount.set(fileName, (fileCount.get(fileName) || 0) + 1);
|
|
287
|
+
}
|
|
288
|
+
const topPatterns = Array.from(patternMap.entries()).sort((a, b) => b[1].count - a[1].count).slice(0, 10).map(([pattern, data]) => ({
|
|
289
|
+
pattern: pattern.slice(0, 100),
|
|
290
|
+
count: data.count,
|
|
291
|
+
severity: data.issue.severity,
|
|
292
|
+
agent: data.issue.agent,
|
|
293
|
+
exampleFix: data.issue.fix.slice(0, 200)
|
|
294
|
+
}));
|
|
295
|
+
const hotFiles = Array.from(fileCount.entries()).sort((a, b) => b[1] - a[1]).slice(0, 10).map(([file, count]) => ({ file, count }));
|
|
296
|
+
return {
|
|
297
|
+
period: `${sorted[0]?.timestamp.split("T")[0]} to ${sorted[sorted.length - 1]?.timestamp.split("T")[0]}`,
|
|
298
|
+
startDate: sorted[0]?.timestamp || "",
|
|
299
|
+
endDate: sorted[sorted.length - 1]?.timestamp || "",
|
|
300
|
+
totalIssues: issues.length,
|
|
301
|
+
resolvedCount: issues.filter((i) => i.resolved).length,
|
|
302
|
+
bySeverity,
|
|
303
|
+
byAgent,
|
|
304
|
+
topPatterns,
|
|
305
|
+
hotFiles,
|
|
306
|
+
compactedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
307
|
+
};
|
|
308
|
+
}
|
|
309
|
+
function normalizePattern(text) {
|
|
310
|
+
return text.toLowerCase().replace(/`[^`]+`/g, "CODE").replace(/\b\d+\b/g, "N").replace(/["']/g, "").replace(/\s+/g, " ").trim().slice(0, 150);
|
|
311
|
+
}
|
|
312
|
+
async function saveCompactedSummary(summary, projectDir) {
|
|
313
|
+
const memoryDir = join(getTrieDirectory(projectDir), "memory");
|
|
314
|
+
await mkdir(memoryDir, { recursive: true });
|
|
315
|
+
const summaryPath = join(memoryDir, "compacted-summaries.json");
|
|
316
|
+
let summaries = [];
|
|
317
|
+
try {
|
|
318
|
+
if (existsSync(summaryPath)) {
|
|
319
|
+
const content = await readFile(summaryPath, "utf-8");
|
|
320
|
+
const result = safeParseAndValidate(content, CompactedSummariesIndexSchema);
|
|
321
|
+
if (result.success) {
|
|
322
|
+
summaries = result.data;
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
} catch {
|
|
326
|
+
summaries = [];
|
|
327
|
+
}
|
|
328
|
+
summaries.push(summary);
|
|
329
|
+
if (summaries.length > 12) {
|
|
330
|
+
summaries = summaries.slice(-12);
|
|
331
|
+
}
|
|
332
|
+
const backupManager = new BackupManager(summaryPath);
|
|
333
|
+
await backupManager.createBackup();
|
|
334
|
+
await atomicWriteJSON(summaryPath, summaries);
|
|
335
|
+
}
|
|
336
|
+
async function loadCompactedSummaries(projectDir) {
|
|
337
|
+
const summaryPath = join(getTrieDirectory(projectDir), "memory", "compacted-summaries.json");
|
|
338
|
+
try {
|
|
339
|
+
if (existsSync(summaryPath)) {
|
|
340
|
+
const content = await readFile(summaryPath, "utf-8");
|
|
341
|
+
const result = safeParseAndValidate(content, CompactedSummariesIndexSchema);
|
|
342
|
+
if (result.success) {
|
|
343
|
+
return result.data;
|
|
344
|
+
}
|
|
345
|
+
const backupManager = new BackupManager(summaryPath);
|
|
346
|
+
if (await backupManager.recoverFromBackup()) {
|
|
347
|
+
const recovered = await readFile(summaryPath, "utf-8");
|
|
348
|
+
const recoveredResult = safeParseAndValidate(recovered, CompactedSummariesIndexSchema);
|
|
349
|
+
if (recoveredResult.success) {
|
|
350
|
+
return recoveredResult.data;
|
|
351
|
+
}
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
} catch {
|
|
355
|
+
}
|
|
356
|
+
return [];
|
|
357
|
+
}
|
|
358
|
+
async function getHistoricalInsights(projectDir) {
|
|
359
|
+
const summaries = await loadCompactedSummaries(projectDir);
|
|
360
|
+
if (summaries.length === 0) {
|
|
361
|
+
return {
|
|
362
|
+
totalHistoricalIssues: 0,
|
|
363
|
+
recurringPatterns: [],
|
|
364
|
+
improvementTrend: "unknown"
|
|
365
|
+
};
|
|
366
|
+
}
|
|
367
|
+
const totalHistoricalIssues = summaries.reduce((sum, s) => sum + s.totalIssues, 0);
|
|
368
|
+
const patternCounts = /* @__PURE__ */ new Map();
|
|
369
|
+
for (const summary of summaries) {
|
|
370
|
+
for (const pattern of summary.topPatterns) {
|
|
371
|
+
const key = pattern.pattern;
|
|
372
|
+
const existing = patternCounts.get(key);
|
|
373
|
+
if (existing) {
|
|
374
|
+
existing.count += pattern.count;
|
|
375
|
+
existing.appearances++;
|
|
376
|
+
} else {
|
|
377
|
+
patternCounts.set(key, { ...pattern, appearances: 1 });
|
|
378
|
+
}
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
const recurringPatterns = Array.from(patternCounts.values()).filter((p) => p.appearances >= 2).sort((a, b) => b.count - a.count).slice(0, 5);
|
|
382
|
+
let improvementTrend = "unknown";
|
|
383
|
+
if (summaries.length >= 2) {
|
|
384
|
+
const recent = summaries.slice(-2);
|
|
385
|
+
const olderCount = recent[0]?.totalIssues || 0;
|
|
386
|
+
const newerCount = recent[1]?.totalIssues || 0;
|
|
387
|
+
if (newerCount < olderCount * 0.8) {
|
|
388
|
+
improvementTrend = "improving";
|
|
389
|
+
} else if (newerCount > olderCount * 1.2) {
|
|
390
|
+
improvementTrend = "declining";
|
|
391
|
+
} else {
|
|
392
|
+
improvementTrend = "stable";
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
return {
|
|
396
|
+
totalHistoricalIssues,
|
|
397
|
+
recurringPatterns,
|
|
398
|
+
improvementTrend
|
|
399
|
+
};
|
|
400
|
+
}
|
|
401
|
+
|
|
402
|
+
// src/memory/ledger.ts
|
|
403
|
+
import { createHash } from "crypto";
|
|
404
|
+
import { mkdir as mkdir2, readFile as readFile2 } from "fs/promises";
|
|
405
|
+
import { existsSync as existsSync2 } from "fs";
|
|
406
|
+
import { join as join2 } from "path";
|
|
407
|
+
var LEDGER_FILENAME = "ledger.json";
|
|
408
|
+
var GENESIS_HASH = "0".repeat(64);
|
|
409
|
+
var LEDGER_VERSION = 1;
|
|
410
|
+
async function appendIssuesToLedger(issues, workDir) {
|
|
411
|
+
if (issues.length === 0) return null;
|
|
407
412
|
const projectDir = workDir || getWorkingDirectory(void 0, true);
|
|
408
413
|
const memoryDir = join2(getTrieDirectory(projectDir), "memory");
|
|
409
414
|
await mkdir2(memoryDir, { recursive: true });
|
|
415
|
+
const blocks = await loadLedger(projectDir);
|
|
416
|
+
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
417
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
418
|
+
const entries = issues.map((issue) => ({
|
|
419
|
+
id: issue.id,
|
|
420
|
+
hash: issue.hash,
|
|
421
|
+
severity: issue.severity,
|
|
422
|
+
file: issue.file,
|
|
423
|
+
agent: issue.agent,
|
|
424
|
+
timestamp: issue.timestamp
|
|
425
|
+
}));
|
|
426
|
+
const previousBlock = blocks[blocks.length - 1];
|
|
427
|
+
const block = previousBlock && previousBlock.date === today ? previousBlock : createBlock(today, now, previousBlock?.blockHash ?? GENESIS_HASH);
|
|
428
|
+
if (block !== previousBlock) {
|
|
429
|
+
blocks.push(block);
|
|
430
|
+
}
|
|
431
|
+
block.entries = [...block.entries, ...entries];
|
|
432
|
+
block.merkleRoot = computeMerkleRoot(block.entries.map((entry) => entry.hash));
|
|
433
|
+
block.blockHash = computeBlockHash(block.previousHash, block.merkleRoot, block.date, block.version);
|
|
434
|
+
block.updatedAt = now;
|
|
435
|
+
await saveLedger(blocks, projectDir);
|
|
436
|
+
return block;
|
|
437
|
+
}
|
|
438
|
+
function computeMerkleRoot(hashes) {
|
|
439
|
+
if (hashes.length === 0) {
|
|
440
|
+
return sha256("");
|
|
441
|
+
}
|
|
442
|
+
let level = hashes.slice();
|
|
443
|
+
while (level.length > 1) {
|
|
444
|
+
const nextLevel = [];
|
|
445
|
+
for (let i = 0; i < level.length; i += 2) {
|
|
446
|
+
const left = level[i];
|
|
447
|
+
const right = level[i + 1] ?? left;
|
|
448
|
+
nextLevel.push(sha256(`${left}:${right}`));
|
|
449
|
+
}
|
|
450
|
+
level = nextLevel;
|
|
451
|
+
}
|
|
452
|
+
return level[0];
|
|
453
|
+
}
|
|
454
|
+
function computeBlockHash(previousHash, merkleRoot, date, version) {
|
|
455
|
+
return sha256(`${version}:${date}:${previousHash}:${merkleRoot}`);
|
|
456
|
+
}
|
|
457
|
+
function createBlock(date, now, previousHash) {
|
|
458
|
+
return {
|
|
459
|
+
version: LEDGER_VERSION,
|
|
460
|
+
date,
|
|
461
|
+
entries: [],
|
|
462
|
+
previousHash,
|
|
463
|
+
merkleRoot: "",
|
|
464
|
+
blockHash: "",
|
|
465
|
+
createdAt: now,
|
|
466
|
+
updatedAt: now
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
async function loadLedger(projectDir) {
|
|
470
|
+
const ledgerPath = join2(getTrieDirectory(projectDir), "memory", LEDGER_FILENAME);
|
|
471
|
+
try {
|
|
472
|
+
if (!existsSync2(ledgerPath)) return [];
|
|
473
|
+
const content = await readFile2(ledgerPath, "utf-8");
|
|
474
|
+
const parsed = JSON.parse(content);
|
|
475
|
+
if (!Array.isArray(parsed)) return [];
|
|
476
|
+
return parsed;
|
|
477
|
+
} catch {
|
|
478
|
+
return [];
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
async function getLedgerBlocks(workDir) {
|
|
482
|
+
const projectDir = workDir || getWorkingDirectory(void 0, true);
|
|
483
|
+
return loadLedger(projectDir);
|
|
484
|
+
}
|
|
485
|
+
async function saveLedger(blocks, projectDir) {
|
|
486
|
+
const ledgerPath = join2(getTrieDirectory(projectDir), "memory", LEDGER_FILENAME);
|
|
487
|
+
await atomicWriteJSON(ledgerPath, blocks);
|
|
488
|
+
}
|
|
489
|
+
function sha256(input) {
|
|
490
|
+
return createHash("sha256").update(input).digest("hex");
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// src/memory/issue-store.ts
|
|
494
|
+
async function storeIssues(issues, project, workDir) {
|
|
495
|
+
const projectDir = workDir || getWorkingDirectory(void 0, true);
|
|
496
|
+
const memoryDir = join3(getTrieDirectory(projectDir), "memory");
|
|
497
|
+
await mkdir3(memoryDir, { recursive: true });
|
|
410
498
|
const stored = [];
|
|
411
499
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
412
500
|
const seenHashes = /* @__PURE__ */ new Set();
|
|
@@ -528,6 +616,27 @@ async function autoResolveIssues(newIssueHashes, scannedFiles, workDir) {
|
|
|
528
616
|
}
|
|
529
617
|
return { resolved: resolvedCount, stillActive: stillActiveCount };
|
|
530
618
|
}
|
|
619
|
+
async function resolveGoalViolation(file, goalDescription, workDir) {
|
|
620
|
+
const projectDir = workDir || getWorkingDirectory(void 0, true);
|
|
621
|
+
const index = await loadIssueIndex(projectDir);
|
|
622
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
623
|
+
let resolvedCount = 0;
|
|
624
|
+
for (const issue of index) {
|
|
625
|
+
if (issue.resolved) continue;
|
|
626
|
+
if (issue.agent !== "goal-violation") continue;
|
|
627
|
+
const normalizedFile = issue.file.replace(/\\/g, "/");
|
|
628
|
+
const normalizedTarget = file.replace(/\\/g, "/");
|
|
629
|
+
if (normalizedFile === normalizedTarget && issue.issue.includes(`Goal "${goalDescription}"`)) {
|
|
630
|
+
issue.resolved = true;
|
|
631
|
+
issue.resolvedAt = now;
|
|
632
|
+
resolvedCount++;
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
if (resolvedCount > 0) {
|
|
636
|
+
await saveIssueIndex(index, projectDir);
|
|
637
|
+
}
|
|
638
|
+
return resolvedCount;
|
|
639
|
+
}
|
|
531
640
|
function getIssueHash(issue) {
|
|
532
641
|
return hashIssue(issue);
|
|
533
642
|
}
|
|
@@ -636,9 +745,9 @@ async function purgeIssues(strategy, options = {}) {
|
|
|
636
745
|
}
|
|
637
746
|
async function getDailyLogs(workDir) {
|
|
638
747
|
const projectDir = workDir || getWorkingDirectory(void 0, true);
|
|
639
|
-
const memoryDir =
|
|
748
|
+
const memoryDir = join3(getTrieDirectory(projectDir), "memory");
|
|
640
749
|
try {
|
|
641
|
-
if (!
|
|
750
|
+
if (!existsSync3(memoryDir)) return [];
|
|
642
751
|
const files = await readdir(memoryDir);
|
|
643
752
|
return files.filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)).sort().reverse();
|
|
644
753
|
} catch {
|
|
@@ -646,13 +755,13 @@ async function getDailyLogs(workDir) {
|
|
|
646
755
|
}
|
|
647
756
|
}
|
|
648
757
|
async function appendToDailyLog(issues, projectDir) {
|
|
649
|
-
const memoryDir =
|
|
758
|
+
const memoryDir = join3(getTrieDirectory(projectDir), "memory");
|
|
650
759
|
const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
|
|
651
|
-
const logPath =
|
|
760
|
+
const logPath = join3(memoryDir, `${today}.md`);
|
|
652
761
|
let content = "";
|
|
653
762
|
try {
|
|
654
|
-
if (
|
|
655
|
-
content = await
|
|
763
|
+
if (existsSync3(logPath)) {
|
|
764
|
+
content = await readFile3(logPath, "utf-8");
|
|
656
765
|
} else {
|
|
657
766
|
content = `# Issue Log: ${today}
|
|
658
767
|
|
|
@@ -675,10 +784,10 @@ async function appendToDailyLog(issues, projectDir) {
|
|
|
675
784
|
await writeFile(logPath, content);
|
|
676
785
|
}
|
|
677
786
|
async function loadIssueIndex(projectDir) {
|
|
678
|
-
const indexPath =
|
|
787
|
+
const indexPath = join3(getTrieDirectory(projectDir), "memory", "issues.json");
|
|
679
788
|
try {
|
|
680
|
-
if (
|
|
681
|
-
const content = await
|
|
789
|
+
if (existsSync3(indexPath)) {
|
|
790
|
+
const content = await readFile3(indexPath, "utf-8");
|
|
682
791
|
const result = safeParseAndValidate(content, IssueIndexSchema);
|
|
683
792
|
if (result.success) {
|
|
684
793
|
return result.data;
|
|
@@ -687,7 +796,7 @@ async function loadIssueIndex(projectDir) {
|
|
|
687
796
|
const backupManager = new BackupManager(indexPath);
|
|
688
797
|
if (await backupManager.recoverFromBackup()) {
|
|
689
798
|
console.error(" \u2705 Recovered from backup");
|
|
690
|
-
const recovered = await
|
|
799
|
+
const recovered = await readFile3(indexPath, "utf-8");
|
|
691
800
|
const recoveredResult = safeParseAndValidate(recovered, IssueIndexSchema);
|
|
692
801
|
if (recoveredResult.success) {
|
|
693
802
|
return recoveredResult.data;
|
|
@@ -700,8 +809,8 @@ async function loadIssueIndex(projectDir) {
|
|
|
700
809
|
return [];
|
|
701
810
|
}
|
|
702
811
|
async function updateIssueIndex(newIssues, projectDir) {
|
|
703
|
-
const memoryDir =
|
|
704
|
-
await
|
|
812
|
+
const memoryDir = join3(getTrieDirectory(projectDir), "memory");
|
|
813
|
+
await mkdir3(memoryDir, { recursive: true });
|
|
705
814
|
let existing = await loadIssueIndex(projectDir);
|
|
706
815
|
const hashSet = new Set(existing.map((i) => i.hash));
|
|
707
816
|
const toAdd = newIssues.filter((i) => !hashSet.has(i.hash));
|
|
@@ -744,29 +853,31 @@ function intelligentPrune(issues, targetCount) {
|
|
|
744
853
|
return scored.sort((a, b) => b.score - a.score).slice(0, targetCount).map((s) => s.issue);
|
|
745
854
|
}
|
|
746
855
|
async function saveIssueIndex(issues, projectDir) {
|
|
747
|
-
const memoryDir =
|
|
748
|
-
await
|
|
749
|
-
const indexPath =
|
|
856
|
+
const memoryDir = join3(getTrieDirectory(projectDir), "memory");
|
|
857
|
+
await mkdir3(memoryDir, { recursive: true });
|
|
858
|
+
const indexPath = join3(memoryDir, "issues.json");
|
|
750
859
|
const backupManager = new BackupManager(indexPath);
|
|
751
860
|
await backupManager.createBackup();
|
|
752
861
|
await atomicWriteJSON(indexPath, issues);
|
|
753
862
|
}
|
|
754
863
|
function hashIssue(issue) {
|
|
755
864
|
const content = `${issue.issue}|${issue.file}|${issue.severity}|${issue.agent}`;
|
|
756
|
-
return
|
|
865
|
+
return createHash2("sha256").update(content).digest("hex").slice(0, 16);
|
|
757
866
|
}
|
|
758
867
|
|
|
759
868
|
export {
|
|
760
869
|
getHistoricalInsights,
|
|
870
|
+
getLedgerBlocks,
|
|
761
871
|
storeIssues,
|
|
762
872
|
searchIssues,
|
|
763
873
|
findSimilarIssues,
|
|
764
874
|
markIssueResolved,
|
|
765
875
|
autoResolveIssues,
|
|
876
|
+
resolveGoalViolation,
|
|
766
877
|
getIssueHash,
|
|
767
878
|
getMemoryStats,
|
|
768
879
|
getRecentIssues,
|
|
769
880
|
purgeIssues,
|
|
770
881
|
getDailyLogs
|
|
771
882
|
};
|
|
772
|
-
//# sourceMappingURL=chunk-
|
|
883
|
+
//# sourceMappingURL=chunk-Z2P4WST6.js.map
|