@triedotdev/mcp 1.0.113 → 1.0.115
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/auto-fix-apply-PCAHWLXF.js +10 -0
- package/dist/autonomy-config-JXB7WCZ2.js +30 -0
- package/dist/chunk-2GIAROBF.js +173 -0
- package/dist/chunk-2GIAROBF.js.map +1 -0
- package/dist/{chunk-33WL3D7A.js → chunk-2SIFK7OW.js} +7 -419
- package/dist/chunk-2SIFK7OW.js.map +1 -0
- package/dist/chunk-43X6JBEM.js +36 -0
- package/dist/chunk-43X6JBEM.js.map +1 -0
- package/dist/chunk-55DOQNHJ.js +772 -0
- package/dist/chunk-55DOQNHJ.js.map +1 -0
- package/dist/chunk-6LXSA2OZ.js +425 -0
- package/dist/chunk-6LXSA2OZ.js.map +1 -0
- package/dist/{chunk-SDS3UVFY.js → chunk-AOFYU6T3.js} +113 -559
- package/dist/chunk-AOFYU6T3.js.map +1 -0
- package/dist/{chunk-6QR6QZIX.js → chunk-D3EXBJE2.js} +25 -658
- package/dist/chunk-D3EXBJE2.js.map +1 -0
- package/dist/chunk-DJ2YAGHK.js +50 -0
- package/dist/chunk-DJ2YAGHK.js.map +1 -0
- package/dist/chunk-DZREHOGW.js +706 -0
- package/dist/chunk-DZREHOGW.js.map +1 -0
- package/dist/chunk-I2GFI3AM.js +340 -0
- package/dist/chunk-I2GFI3AM.js.map +1 -0
- package/dist/chunk-KRH642MT.js +947 -0
- package/dist/chunk-KRH642MT.js.map +1 -0
- package/dist/{chunk-QYOACM2C.js → chunk-MVNJPJBK.js} +22 -252
- package/dist/chunk-MVNJPJBK.js.map +1 -0
- package/dist/chunk-NS2MSZMB.js +394 -0
- package/dist/chunk-NS2MSZMB.js.map +1 -0
- package/dist/chunk-SWSK7ANT.js +340 -0
- package/dist/chunk-SWSK7ANT.js.map +1 -0
- package/dist/chunk-VRLMTOB6.js +566 -0
- package/dist/chunk-VRLMTOB6.js.map +1 -0
- package/dist/chunk-YR4BMGYO.js +130 -0
- package/dist/chunk-YR4BMGYO.js.map +1 -0
- package/dist/chunk-ZV2K6M7T.js +74 -0
- package/dist/chunk-ZV2K6M7T.js.map +1 -0
- package/dist/{chunk-2764KZZQ.js → chunk-ZYKEILVK.js} +451 -1069
- package/dist/chunk-ZYKEILVK.js.map +1 -0
- package/dist/cli/main.js +107 -375
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +18 -8
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/client-7XZHCMD3.js +28 -0
- package/dist/client-7XZHCMD3.js.map +1 -0
- package/dist/{goal-manager-AP4LTE6U.js → goal-manager-LMS6ZJB7.js} +7 -3
- package/dist/goal-manager-LMS6ZJB7.js.map +1 -0
- package/dist/goal-validator-T5HEYBC5.js +186 -0
- package/dist/goal-validator-T5HEYBC5.js.map +1 -0
- package/dist/graph-U5JWSAB5.js +10 -0
- package/dist/graph-U5JWSAB5.js.map +1 -0
- package/dist/guardian-agent-EXP7APLC.js +25 -0
- package/dist/guardian-agent-EXP7APLC.js.map +1 -0
- package/dist/hypothesis-KGC3P54C.js +19 -0
- package/dist/hypothesis-KGC3P54C.js.map +1 -0
- package/dist/incident-index-PNIVT47T.js +11 -0
- package/dist/incident-index-PNIVT47T.js.map +1 -0
- package/dist/index.js +369 -43
- package/dist/index.js.map +1 -1
- package/dist/ledger-SR6OEBLO.js +15 -0
- package/dist/ledger-SR6OEBLO.js.map +1 -0
- package/dist/output-manager-BOTMXSND.js +13 -0
- package/dist/output-manager-BOTMXSND.js.map +1 -0
- package/dist/pattern-discovery-F7LU5K6E.js +8 -0
- package/dist/pattern-discovery-F7LU5K6E.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-2764KZZQ.js.map +0 -1
- package/dist/chunk-33WL3D7A.js.map +0 -1
- package/dist/chunk-6JPPYG7F.js +0 -1813
- package/dist/chunk-6JPPYG7F.js.map +0 -1
- package/dist/chunk-6QR6QZIX.js.map +0 -1
- package/dist/chunk-QYOACM2C.js.map +0 -1
- package/dist/chunk-SDS3UVFY.js.map +0 -1
- package/dist/guardian-agent-XEYNG7RH.js +0 -18
- /package/dist/{goal-manager-AP4LTE6U.js.map → auto-fix-apply-PCAHWLXF.js.map} +0 -0
- /package/dist/{guardian-agent-XEYNG7RH.js.map → autonomy-config-JXB7WCZ2.js.map} +0 -0
package/dist/index.js
CHANGED
|
@@ -19,6 +19,9 @@ import {
|
|
|
19
19
|
projectInfoExists,
|
|
20
20
|
updateProjectSection
|
|
21
21
|
} from "./chunk-TKMV7JKN.js";
|
|
22
|
+
import {
|
|
23
|
+
getAutonomyConfig
|
|
24
|
+
} from "./chunk-I2GFI3AM.js";
|
|
22
25
|
import {
|
|
23
26
|
ExtractionPipeline,
|
|
24
27
|
InteractiveDashboard,
|
|
@@ -32,33 +35,31 @@ import {
|
|
|
32
35
|
TrieQueryContextTool,
|
|
33
36
|
TrieScanTool,
|
|
34
37
|
TrieTellTool,
|
|
35
|
-
getOutputManager,
|
|
36
38
|
getPrompt,
|
|
37
39
|
getSystemPrompt,
|
|
38
40
|
handleCheckpointTool
|
|
39
|
-
} from "./chunk-
|
|
40
|
-
import "./chunk-
|
|
41
|
+
} from "./chunk-ZYKEILVK.js";
|
|
42
|
+
import "./chunk-AOFYU6T3.js";
|
|
43
|
+
import "./chunk-2SIFK7OW.js";
|
|
44
|
+
import "./chunk-DZREHOGW.js";
|
|
45
|
+
import "./chunk-6LXSA2OZ.js";
|
|
41
46
|
import {
|
|
42
47
|
exportToJson,
|
|
43
48
|
formatFriendlyError,
|
|
44
49
|
importFromJson,
|
|
45
50
|
isTrieInitialized,
|
|
46
51
|
runShellCommandSync
|
|
47
|
-
} from "./chunk-
|
|
52
|
+
} from "./chunk-MVNJPJBK.js";
|
|
48
53
|
import {
|
|
49
|
-
ContextGraph,
|
|
50
54
|
findCrossProjectPatterns,
|
|
51
55
|
getGlobalMemoryStats,
|
|
52
|
-
isAIAvailable,
|
|
53
56
|
listTrackedProjects,
|
|
54
|
-
runAIAnalysis,
|
|
55
57
|
searchGlobalPatterns
|
|
56
|
-
} from "./chunk-
|
|
57
|
-
import "./chunk-IXO4G4D3.js";
|
|
58
|
+
} from "./chunk-D3EXBJE2.js";
|
|
58
59
|
import {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
60
|
+
isAIAvailable,
|
|
61
|
+
runAIAnalysis
|
|
62
|
+
} from "./chunk-SWSK7ANT.js";
|
|
62
63
|
import {
|
|
63
64
|
findSimilarIssues,
|
|
64
65
|
getMemoryStats,
|
|
@@ -66,13 +67,28 @@ import {
|
|
|
66
67
|
markIssueResolved,
|
|
67
68
|
purgeIssues,
|
|
68
69
|
searchIssues
|
|
69
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-55DOQNHJ.js";
|
|
71
|
+
import "./chunk-KRH642MT.js";
|
|
72
|
+
import "./chunk-F4NJ4CBP.js";
|
|
73
|
+
import "./chunk-IXO4G4D3.js";
|
|
74
|
+
import {
|
|
75
|
+
ContextGraph
|
|
76
|
+
} from "./chunk-NS2MSZMB.js";
|
|
77
|
+
import "./chunk-2GIAROBF.js";
|
|
78
|
+
import "./chunk-6NLHFIYA.js";
|
|
79
|
+
import "./chunk-ZV2K6M7T.js";
|
|
80
|
+
import {
|
|
81
|
+
getSkillRegistry
|
|
82
|
+
} from "./chunk-G76DYVGX.js";
|
|
83
|
+
import {
|
|
84
|
+
getOutputManager
|
|
85
|
+
} from "./chunk-VRLMTOB6.js";
|
|
86
|
+
import "./chunk-YR4BMGYO.js";
|
|
87
|
+
import "./chunk-43X6JBEM.js";
|
|
70
88
|
import {
|
|
71
89
|
getTrieDirectory,
|
|
72
90
|
getWorkingDirectory
|
|
73
91
|
} from "./chunk-R4AAPFXC.js";
|
|
74
|
-
import "./chunk-F4NJ4CBP.js";
|
|
75
|
-
import "./chunk-6NLHFIYA.js";
|
|
76
92
|
import {
|
|
77
93
|
isInteractiveMode
|
|
78
94
|
} from "./chunk-APMV77PU.js";
|
|
@@ -1120,7 +1136,6 @@ var SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
|
1120
1136
|
]);
|
|
1121
1137
|
var TrieWatchTool = class _TrieWatchTool {
|
|
1122
1138
|
extractionPipeline = null;
|
|
1123
|
-
static DEFAULT_HOURLY_TOKEN_LIMIT = 5e4;
|
|
1124
1139
|
state = {
|
|
1125
1140
|
isRunning: false,
|
|
1126
1141
|
lastScan: /* @__PURE__ */ new Map(),
|
|
@@ -1136,7 +1151,7 @@ var TrieWatchTool = class _TrieWatchTool {
|
|
|
1136
1151
|
tokenBudget: {
|
|
1137
1152
|
used: 0,
|
|
1138
1153
|
windowStart: Date.now(),
|
|
1139
|
-
hourlyLimit:
|
|
1154
|
+
hourlyLimit: 5e4,
|
|
1140
1155
|
scansSaved: 0
|
|
1141
1156
|
},
|
|
1142
1157
|
cleanFiles: /* @__PURE__ */ new Map()
|
|
@@ -1144,6 +1159,9 @@ var TrieWatchTool = class _TrieWatchTool {
|
|
|
1144
1159
|
watchers = /* @__PURE__ */ new Map();
|
|
1145
1160
|
streamingManager = void 0;
|
|
1146
1161
|
dashboard = void 0;
|
|
1162
|
+
lastHypothesisCheck = 0;
|
|
1163
|
+
static HYPOTHESIS_CHECK_INTERVAL_MS = 3e5;
|
|
1164
|
+
// Check every 5 minutes
|
|
1147
1165
|
async execute(args) {
|
|
1148
1166
|
const { action, directory, debounceMs = 1e3 } = args;
|
|
1149
1167
|
switch (action) {
|
|
@@ -1309,6 +1327,8 @@ Detected changes in ${files.length} file(s):`);
|
|
|
1309
1327
|
console.error("");
|
|
1310
1328
|
}
|
|
1311
1329
|
try {
|
|
1330
|
+
const projectPath = getWorkingDirectory(void 0, true);
|
|
1331
|
+
await this.checkGoalViolations(files, projectPath);
|
|
1312
1332
|
if (this.extractionPipeline) {
|
|
1313
1333
|
try {
|
|
1314
1334
|
const fileContents = await Promise.all(
|
|
@@ -1355,8 +1375,12 @@ ${f.content.slice(0, 1e3)}`
|
|
|
1355
1375
|
}
|
|
1356
1376
|
}
|
|
1357
1377
|
}
|
|
1358
|
-
|
|
1359
|
-
|
|
1378
|
+
this.autoScanFiles(files);
|
|
1379
|
+
await this.discoverPatternsFromIssues(projectPath);
|
|
1380
|
+
const now = Date.now();
|
|
1381
|
+
if (now - this.lastHypothesisCheck > _TrieWatchTool.HYPOTHESIS_CHECK_INTERVAL_MS) {
|
|
1382
|
+
this.checkAndGenerateHypotheses(projectPath);
|
|
1383
|
+
this.lastHypothesisCheck = now;
|
|
1360
1384
|
}
|
|
1361
1385
|
if (this.streamingManager) {
|
|
1362
1386
|
for (const file of files) {
|
|
@@ -1385,9 +1409,238 @@ ${f.content.slice(0, 1e3)}`
|
|
|
1385
1409
|
return false;
|
|
1386
1410
|
}
|
|
1387
1411
|
}
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1412
|
+
/**
|
|
1413
|
+
* Check file changes against active user goals
|
|
1414
|
+
* If violations found: record to ledger, nudge user, auto-fix if enabled
|
|
1415
|
+
*/
|
|
1416
|
+
async checkGoalViolations(files, projectPath) {
|
|
1417
|
+
try {
|
|
1418
|
+
const { validateAgainstGoals, recordGoalViolationCaught, recordGoalViolationFixed } = await import("./goal-validator-T5HEYBC5.js");
|
|
1419
|
+
const { appendIssuesToLedger } = await import("./ledger-SR6OEBLO.js");
|
|
1420
|
+
const { getAutonomyConfig: getAutonomyConfig2 } = await import("./autonomy-config-JXB7WCZ2.js");
|
|
1421
|
+
const { applyAutoFix } = await import("./auto-fix-apply-PCAHWLXF.js");
|
|
1422
|
+
const config = await getAutonomyConfig2(projectPath);
|
|
1423
|
+
const outputMgr = getOutputManager();
|
|
1424
|
+
for (const file of files) {
|
|
1425
|
+
try {
|
|
1426
|
+
const content = await readFile3(file, "utf-8");
|
|
1427
|
+
const result = await validateAgainstGoals(file, content, projectPath);
|
|
1428
|
+
if (result.violations.length === 0) {
|
|
1429
|
+
continue;
|
|
1430
|
+
}
|
|
1431
|
+
for (const violation of result.violations) {
|
|
1432
|
+
const relativePath = file.replace(projectPath + "/", "");
|
|
1433
|
+
const issue = {
|
|
1434
|
+
id: `goal-violation-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
1435
|
+
hash: "",
|
|
1436
|
+
file: relativePath,
|
|
1437
|
+
line: violation.line,
|
|
1438
|
+
agent: "goal-validator",
|
|
1439
|
+
severity: violation.severity,
|
|
1440
|
+
issue: violation.description,
|
|
1441
|
+
fix: violation.autoFixable ? "Auto-fixable" : "Manual fix required",
|
|
1442
|
+
category: "goal-violation",
|
|
1443
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1444
|
+
project: basename2(projectPath),
|
|
1445
|
+
resolved: false,
|
|
1446
|
+
resolvedAt: void 0
|
|
1447
|
+
};
|
|
1448
|
+
await appendIssuesToLedger([issue], projectPath);
|
|
1449
|
+
await recordGoalViolationCaught(violation.goal, relativePath, projectPath);
|
|
1450
|
+
const nudgeMessage = `Goal "${violation.goal.description}" violated: ${violation.violation} in ${basename2(file)}:${violation.line || "?"}`;
|
|
1451
|
+
outputMgr.nudge(
|
|
1452
|
+
nudgeMessage,
|
|
1453
|
+
violation.severity === "critical" ? "critical" : "warning",
|
|
1454
|
+
relativePath
|
|
1455
|
+
);
|
|
1456
|
+
this.state.nudges.push({
|
|
1457
|
+
file: basename2(file),
|
|
1458
|
+
message: nudgeMessage,
|
|
1459
|
+
severity: violation.severity === "critical" ? "critical" : "high",
|
|
1460
|
+
timestamp: (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false })
|
|
1461
|
+
});
|
|
1462
|
+
if (!isInteractiveMode()) {
|
|
1463
|
+
console.error(` [!] Goal violation: ${violation.description}`);
|
|
1464
|
+
}
|
|
1465
|
+
if (config.autoFix.enabled && violation.autoFixable && violation.fixAction) {
|
|
1466
|
+
if (!isInteractiveMode()) {
|
|
1467
|
+
console.error(` [*] Auto-fixing...`);
|
|
1468
|
+
}
|
|
1469
|
+
const fixed = await applyAutoFix(violation.fixAction);
|
|
1470
|
+
if (fixed) {
|
|
1471
|
+
await recordGoalViolationFixed(violation.goal, relativePath, projectPath);
|
|
1472
|
+
const fixMessage = `Auto-fixed: ${violation.goal.description} violation in ${basename2(file)}`;
|
|
1473
|
+
outputMgr.nudge(fixMessage, "info", relativePath, 5e3);
|
|
1474
|
+
if (!isInteractiveMode()) {
|
|
1475
|
+
console.error(` [+] Fixed automatically`);
|
|
1476
|
+
}
|
|
1477
|
+
}
|
|
1478
|
+
}
|
|
1479
|
+
}
|
|
1480
|
+
if (this.streamingManager && result.violations.length > 0) {
|
|
1481
|
+
this.streamingManager.reportSignalExtraction({
|
|
1482
|
+
decisions: 0,
|
|
1483
|
+
facts: 0,
|
|
1484
|
+
blockers: result.violations.length,
|
|
1485
|
+
questions: 0
|
|
1486
|
+
});
|
|
1487
|
+
}
|
|
1488
|
+
} catch (error) {
|
|
1489
|
+
outputMgr.log("warn", `Could not validate ${basename2(file)}: ${error}`);
|
|
1490
|
+
}
|
|
1491
|
+
}
|
|
1492
|
+
} catch (error) {
|
|
1493
|
+
getOutputManager().log("warn", `Goal validation error: ${error}`);
|
|
1494
|
+
}
|
|
1495
|
+
}
|
|
1496
|
+
/**
|
|
1497
|
+
* Check and generate hypotheses autonomously
|
|
1498
|
+
* Claude observes patterns and creates new hypotheses to test
|
|
1499
|
+
*/
|
|
1500
|
+
async checkAndGenerateHypotheses(projectPath) {
|
|
1501
|
+
if (!isAIAvailable()) return;
|
|
1502
|
+
try {
|
|
1503
|
+
const { getHypothesisEngine } = await import("./hypothesis-KGC3P54C.js");
|
|
1504
|
+
const { getOutputManager: getOutputManager2 } = await import("./output-manager-BOTMXSND.js");
|
|
1505
|
+
const hypothesisEngine = getHypothesisEngine(projectPath);
|
|
1506
|
+
const recentIssues = Array.from(this.state.issueCache.values()).flat();
|
|
1507
|
+
const patterns = [];
|
|
1508
|
+
const observations = [];
|
|
1509
|
+
if (this.state.nudges.length > 0) {
|
|
1510
|
+
const nudgesByFile = {};
|
|
1511
|
+
for (const nudge of this.state.nudges) {
|
|
1512
|
+
nudgesByFile[nudge.file] = (nudgesByFile[nudge.file] || 0) + 1;
|
|
1513
|
+
}
|
|
1514
|
+
const topFiles = Object.entries(nudgesByFile).sort(([, a], [, b]) => b - a).slice(0, 3);
|
|
1515
|
+
if (topFiles[0] && topFiles[0][1] > 2) {
|
|
1516
|
+
observations.push(`File ${topFiles[0][0]} has ${topFiles[0][1]} repeated issues this session`);
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
if (this.state.nudges.length > 5) {
|
|
1520
|
+
observations.push(`High issue detection rate: ${this.state.nudges.length} violations detected in watch session`);
|
|
1521
|
+
}
|
|
1522
|
+
let generated = await hypothesisEngine.generateHypothesesWithAI({
|
|
1523
|
+
recentIssues,
|
|
1524
|
+
patterns,
|
|
1525
|
+
observations
|
|
1526
|
+
});
|
|
1527
|
+
if (generated.length === 0) {
|
|
1528
|
+
generated = await hypothesisEngine.autoGenerateHypotheses();
|
|
1529
|
+
}
|
|
1530
|
+
for (const hypothesis of generated) {
|
|
1531
|
+
const message = `[New Hypothesis] "${hypothesis.statement}" (${Math.round(hypothesis.confidence * 100)}% confidence)`;
|
|
1532
|
+
getOutputManager2().nudge(
|
|
1533
|
+
message,
|
|
1534
|
+
"info",
|
|
1535
|
+
void 0,
|
|
1536
|
+
1e4
|
|
1537
|
+
);
|
|
1538
|
+
if (!isInteractiveMode()) {
|
|
1539
|
+
console.error(`
|
|
1540
|
+
[?] ${message}`);
|
|
1541
|
+
console.error(` Test: ${hypothesis.testCriteria || "Collecting evidence..."}`);
|
|
1542
|
+
}
|
|
1543
|
+
if (this.streamingManager) {
|
|
1544
|
+
this.streamingManager.reportSignalExtraction({
|
|
1545
|
+
decisions: 0,
|
|
1546
|
+
facts: 0,
|
|
1547
|
+
blockers: 0,
|
|
1548
|
+
questions: 1
|
|
1549
|
+
// Hypotheses are questions to answer
|
|
1550
|
+
});
|
|
1551
|
+
}
|
|
1552
|
+
}
|
|
1553
|
+
if (recentIssues.length > 10) {
|
|
1554
|
+
await hypothesisEngine.updateConfidenceFromOutcomes();
|
|
1555
|
+
}
|
|
1556
|
+
} catch (error) {
|
|
1557
|
+
if (!isInteractiveMode()) {
|
|
1558
|
+
console.error(` [!] Hypothesis check failed: ${error}`);
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
}
|
|
1562
|
+
/**
|
|
1563
|
+
* Discover patterns from accumulated issues
|
|
1564
|
+
* Patterns emerge naturally from your coding workflow
|
|
1565
|
+
*/
|
|
1566
|
+
async discoverPatternsFromIssues(projectPath) {
|
|
1567
|
+
const totalIssues = Array.from(this.state.issueCache.values()).flat().length;
|
|
1568
|
+
if (totalIssues < 5) return;
|
|
1569
|
+
try {
|
|
1570
|
+
const { ContextGraph: ContextGraph2 } = await import("./graph-U5JWSAB5.js");
|
|
1571
|
+
const { IncidentIndex } = await import("./incident-index-PNIVT47T.js");
|
|
1572
|
+
const { TriePatternDiscovery } = await import("./pattern-discovery-F7LU5K6E.js");
|
|
1573
|
+
const graph = new ContextGraph2(projectPath);
|
|
1574
|
+
const incidentIndex = await IncidentIndex.build(graph, projectPath);
|
|
1575
|
+
const discovery = new TriePatternDiscovery(graph, incidentIndex);
|
|
1576
|
+
const hotPatterns = discovery.discoverHotPatterns(2);
|
|
1577
|
+
for (const hot of hotPatterns) {
|
|
1578
|
+
const existingPatterns = await graph.listNodes();
|
|
1579
|
+
const alreadyExists = existingPatterns.some(
|
|
1580
|
+
(n) => n.type === "pattern" && n.data.description?.includes(hot.path)
|
|
1581
|
+
);
|
|
1582
|
+
if (!alreadyExists) {
|
|
1583
|
+
await graph.addNode("pattern", {
|
|
1584
|
+
description: `${hot.type === "directory" ? "Directory" : "File"} hot zone: ${hot.path}`,
|
|
1585
|
+
appliesTo: [hot.path],
|
|
1586
|
+
confidence: Math.min(0.95, hot.confidence),
|
|
1587
|
+
occurrences: hot.incidentCount,
|
|
1588
|
+
firstSeen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1589
|
+
lastSeen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1590
|
+
isAntiPattern: hot.incidentCount >= 3,
|
|
1591
|
+
// 3+ incidents = anti-pattern
|
|
1592
|
+
source: "local"
|
|
1593
|
+
});
|
|
1594
|
+
if (!isInteractiveMode()) {
|
|
1595
|
+
console.error(` [+] Pattern discovered: ${hot.path} (${hot.incidentCount} issues)`);
|
|
1596
|
+
}
|
|
1597
|
+
if (this.streamingManager) {
|
|
1598
|
+
this.streamingManager.reportSignalExtraction({
|
|
1599
|
+
decisions: 0,
|
|
1600
|
+
facts: 1,
|
|
1601
|
+
// Patterns are facts about the codebase
|
|
1602
|
+
blockers: 0,
|
|
1603
|
+
questions: 0
|
|
1604
|
+
});
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1608
|
+
if (totalIssues >= 10) {
|
|
1609
|
+
const coOccurrences = await discovery.discoverCoOccurrences(2);
|
|
1610
|
+
for (const coOcc of coOccurrences.slice(0, 3)) {
|
|
1611
|
+
const desc = `Files break together: ${coOcc.files[0]} + ${coOcc.files[1]}`;
|
|
1612
|
+
const existingPatterns = await graph.listNodes();
|
|
1613
|
+
const alreadyExists = existingPatterns.some(
|
|
1614
|
+
(n) => n.type === "pattern" && n.data.description === desc
|
|
1615
|
+
);
|
|
1616
|
+
if (!alreadyExists) {
|
|
1617
|
+
await graph.addNode("pattern", {
|
|
1618
|
+
description: desc,
|
|
1619
|
+
appliesTo: [...coOcc.files],
|
|
1620
|
+
confidence: Math.min(0.95, coOcc.confidence),
|
|
1621
|
+
occurrences: coOcc.coOccurrences,
|
|
1622
|
+
firstSeen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1623
|
+
lastSeen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1624
|
+
isAntiPattern: coOcc.confidence > 0.7,
|
|
1625
|
+
source: "local"
|
|
1626
|
+
});
|
|
1627
|
+
if (!isInteractiveMode()) {
|
|
1628
|
+
console.error(` [+] Co-occurrence pattern: ${coOcc.files[0]} + ${coOcc.files[1]}`);
|
|
1629
|
+
}
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
}
|
|
1633
|
+
} catch (error) {
|
|
1634
|
+
if (!isInteractiveMode()) {
|
|
1635
|
+
console.error(` [!] Pattern discovery failed: ${error}`);
|
|
1636
|
+
}
|
|
1637
|
+
}
|
|
1638
|
+
}
|
|
1639
|
+
// Defaults -- overridden by config when loaded
|
|
1640
|
+
aiWatcherCooldownMs = 3e4;
|
|
1641
|
+
cleanFileCooldownMs = 3e5;
|
|
1642
|
+
maxFilesPerScan = 5;
|
|
1643
|
+
maxCharsPerFile = 4e3;
|
|
1391
1644
|
/**
|
|
1392
1645
|
* Use the trie (context graph) to score how urgently a file needs scanning.
|
|
1393
1646
|
* Higher score = more worth spending tokens on.
|
|
@@ -1395,7 +1648,7 @@ ${f.content.slice(0, 1e3)}`
|
|
|
1395
1648
|
async scoreScanPriority(file, graph, projectPath) {
|
|
1396
1649
|
let score = 1;
|
|
1397
1650
|
const lastClean = this.state.cleanFiles.get(file);
|
|
1398
|
-
if (lastClean && Date.now() - lastClean <
|
|
1651
|
+
if (lastClean && Date.now() - lastClean < this.cleanFileCooldownMs) {
|
|
1399
1652
|
return 0;
|
|
1400
1653
|
}
|
|
1401
1654
|
const fileNode = await graph.getNode("file", join2(projectPath, file));
|
|
@@ -1424,14 +1677,32 @@ ${f.content.slice(0, 1e3)}`
|
|
|
1424
1677
|
this.state.tokenBudget.used += tokens;
|
|
1425
1678
|
}
|
|
1426
1679
|
/**
|
|
1427
|
-
* AI-powered
|
|
1428
|
-
*
|
|
1680
|
+
* AI-powered watcher -- the primary detection system.
|
|
1681
|
+
*
|
|
1682
|
+
* This is the single AI call that handles:
|
|
1683
|
+
* 1. Code review (bugs, security, logic errors)
|
|
1684
|
+
* 2. Goal violation detection (user-defined quality goals)
|
|
1685
|
+
*
|
|
1686
|
+
* When goals are active, files with goal violations bypass priority scoring
|
|
1687
|
+
* so violations are always caught. Throttled by cooldown + token budget.
|
|
1429
1688
|
*/
|
|
1430
1689
|
async autoScanFiles(files) {
|
|
1431
1690
|
if (!isAIAvailable()) return;
|
|
1432
1691
|
if (this.state.autoScanInProgress) return;
|
|
1433
1692
|
const now = Date.now();
|
|
1434
|
-
if (now - this.state.lastAutoScan <
|
|
1693
|
+
if (now - this.state.lastAutoScan < this.aiWatcherCooldownMs) return;
|
|
1694
|
+
try {
|
|
1695
|
+
const projectPath = getWorkingDirectory(void 0, true);
|
|
1696
|
+
const config = await getAutonomyConfig(projectPath);
|
|
1697
|
+
const wc = config.aiWatcher;
|
|
1698
|
+
if (!wc.enabled) return;
|
|
1699
|
+
this.state.tokenBudget.hourlyLimit = wc.hourlyTokenLimit;
|
|
1700
|
+
this.aiWatcherCooldownMs = wc.scanCooldownSec * 1e3;
|
|
1701
|
+
this.cleanFileCooldownMs = wc.cleanFileCooldownSec * 1e3;
|
|
1702
|
+
this.maxFilesPerScan = wc.maxFilesPerScan;
|
|
1703
|
+
this.maxCharsPerFile = wc.maxCharsPerFile;
|
|
1704
|
+
} catch {
|
|
1705
|
+
}
|
|
1435
1706
|
const remaining = this.getRemainingBudget();
|
|
1436
1707
|
if (remaining < 500) return;
|
|
1437
1708
|
this.state.autoScanInProgress = true;
|
|
@@ -1439,6 +1710,11 @@ ${f.content.slice(0, 1e3)}`
|
|
|
1439
1710
|
try {
|
|
1440
1711
|
const projectPath = getWorkingDirectory(void 0, true);
|
|
1441
1712
|
const graph = new ContextGraph(projectPath);
|
|
1713
|
+
const { getActiveGoals, recordGoalViolationCaught } = await import("./goal-validator-T5HEYBC5.js");
|
|
1714
|
+
const { appendIssuesToLedger } = await import("./ledger-SR6OEBLO.js");
|
|
1715
|
+
const activeGoals = await getActiveGoals(projectPath);
|
|
1716
|
+
const hasGoals = activeGoals.length > 0;
|
|
1717
|
+
if (this.isQuiet() && !hasGoals) return;
|
|
1442
1718
|
const scored = [];
|
|
1443
1719
|
for (const file of files) {
|
|
1444
1720
|
const relativePath = file.replace(projectPath + "/", "");
|
|
@@ -1451,13 +1727,15 @@ ${f.content.slice(0, 1e3)}`
|
|
|
1451
1727
|
}
|
|
1452
1728
|
if (scored.length === 0) return;
|
|
1453
1729
|
scored.sort((a, b) => b.score - a.score);
|
|
1454
|
-
const
|
|
1455
|
-
const
|
|
1730
|
+
const budgetScale = remaining > 2e4 ? 1 : remaining > 1e4 ? 0.6 : 0.4;
|
|
1731
|
+
const maxFiles = Math.max(1, Math.round(this.maxFilesPerScan * budgetScale));
|
|
1732
|
+
const filesToScan = scored.slice(0, maxFiles);
|
|
1733
|
+
const charLimit = Math.round(this.maxCharsPerFile * (remaining > 15e3 ? 1 : 0.5));
|
|
1456
1734
|
const fileContents = await Promise.all(
|
|
1457
|
-
|
|
1735
|
+
filesToScan.map(async ({ file, relativePath }) => {
|
|
1458
1736
|
try {
|
|
1459
1737
|
const content = await readFile3(file, "utf-8");
|
|
1460
|
-
return { path: relativePath, content: content.slice(0,
|
|
1738
|
+
return { path: relativePath, content: content.slice(0, charLimit) };
|
|
1461
1739
|
} catch {
|
|
1462
1740
|
return null;
|
|
1463
1741
|
}
|
|
@@ -1471,22 +1749,37 @@ ${f.content.slice(0, 1e3)}`
|
|
|
1471
1749
|
${f.content}
|
|
1472
1750
|
\`\`\``
|
|
1473
1751
|
).join("\n\n");
|
|
1752
|
+
let goalsSection = "";
|
|
1753
|
+
if (hasGoals) {
|
|
1754
|
+
goalsSection = `
|
|
1755
|
+
USER-DEFINED GOALS (IMPORTANT - check EVERY file against ALL goals):
|
|
1756
|
+
${activeGoals.map((g, i) => ` ${i + 1}. "${g.description}"`).join("\n")}
|
|
1757
|
+
|
|
1758
|
+
Goal violations are HIGH PRIORITY. If a file violates any goal, you MUST report it.
|
|
1759
|
+
`;
|
|
1760
|
+
}
|
|
1474
1761
|
const result = await runAIAnalysis({
|
|
1475
|
-
systemPrompt: `You are a code
|
|
1762
|
+
systemPrompt: `You are a code quality watcher. You review code for two things:
|
|
1476
1763
|
|
|
1477
|
-
|
|
1764
|
+
1. CODE ISSUES: bugs, security vulnerabilities, logic errors, risky patterns
|
|
1765
|
+
2. GOAL VIOLATIONS: check every file against the user's quality goals
|
|
1766
|
+
${goalsSection}
|
|
1767
|
+
Reply ONLY with a JSON array. Each element must have:
|
|
1478
1768
|
- "file": relative file path
|
|
1479
1769
|
- "severity": "critical" | "major" | "minor"
|
|
1480
|
-
- "description": 1-sentence description
|
|
1770
|
+
- "description": 1-sentence description
|
|
1771
|
+
- "isGoalViolation": true if this violates a user goal, false otherwise
|
|
1772
|
+
- "goalIndex": 0-based index of the violated goal (only if isGoalViolation is true)
|
|
1481
1773
|
|
|
1482
|
-
If
|
|
1774
|
+
Be thorough with goal checking. If a goal says "no emojis" and you see an emoji anywhere in the file, report it. If a goal says "no inline styles" and you see a style attribute, report it.
|
|
1483
1775
|
|
|
1484
|
-
|
|
1485
|
-
|
|
1776
|
+
If no issues or violations found, reply with: []
|
|
1777
|
+
Output ONLY the JSON array, no markdown fences, no commentary.`,
|
|
1778
|
+
userPrompt: `Review these changed files:
|
|
1486
1779
|
|
|
1487
1780
|
${filesBlock}`,
|
|
1488
|
-
maxTokens:
|
|
1489
|
-
temperature: 0.
|
|
1781
|
+
maxTokens: 2048,
|
|
1782
|
+
temperature: 0.1
|
|
1490
1783
|
});
|
|
1491
1784
|
if (result.tokensUsed) {
|
|
1492
1785
|
this.recordTokenUsage(result.tokensUsed.input + result.tokensUsed.output);
|
|
@@ -1501,14 +1794,46 @@ ${filesBlock}`,
|
|
|
1501
1794
|
return;
|
|
1502
1795
|
}
|
|
1503
1796
|
const issuedFiles = new Set(issues.map((i) => i.file));
|
|
1504
|
-
for (const { relativePath } of
|
|
1797
|
+
for (const { relativePath } of filesToScan) {
|
|
1505
1798
|
if (!issuedFiles.has(relativePath)) {
|
|
1506
1799
|
this.state.cleanFiles.set(relativePath, Date.now());
|
|
1507
1800
|
}
|
|
1508
1801
|
}
|
|
1509
1802
|
if (issues.length === 0) return;
|
|
1510
|
-
for (const issue of issues.slice(0,
|
|
1803
|
+
for (const issue of issues.slice(0, 10)) {
|
|
1511
1804
|
const severity = issue.severity === "critical" ? "critical" : issue.severity === "major" ? "major" : "minor";
|
|
1805
|
+
if (issue.isGoalViolation && issue.goalIndex != null && issue.goalIndex >= 0 && issue.goalIndex < activeGoals.length) {
|
|
1806
|
+
const goal = activeGoals[issue.goalIndex];
|
|
1807
|
+
const nudgeMsg = `Goal "${goal.description}" violated in ${issue.file}: ${issue.description}`;
|
|
1808
|
+
const ledgerIssue = {
|
|
1809
|
+
id: `goal-ai-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
|
|
1810
|
+
hash: "",
|
|
1811
|
+
file: issue.file,
|
|
1812
|
+
line: void 0,
|
|
1813
|
+
agent: "ai-watcher",
|
|
1814
|
+
severity: severity === "critical" ? "critical" : severity === "major" ? "high" : "medium",
|
|
1815
|
+
issue: nudgeMsg,
|
|
1816
|
+
fix: "Review and fix",
|
|
1817
|
+
category: "goal-violation",
|
|
1818
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1819
|
+
project: basename2(projectPath),
|
|
1820
|
+
resolved: false,
|
|
1821
|
+
resolvedAt: void 0
|
|
1822
|
+
};
|
|
1823
|
+
await appendIssuesToLedger([ledgerIssue], projectPath);
|
|
1824
|
+
await recordGoalViolationCaught(goal, issue.file, projectPath);
|
|
1825
|
+
getOutputManager().nudge(nudgeMsg, "warning", issue.file);
|
|
1826
|
+
this.state.nudges.push({
|
|
1827
|
+
file: basename2(issue.file),
|
|
1828
|
+
message: nudgeMsg,
|
|
1829
|
+
severity: "high",
|
|
1830
|
+
timestamp: (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false })
|
|
1831
|
+
});
|
|
1832
|
+
if (!isInteractiveMode()) {
|
|
1833
|
+
console.error(` [!] Goal violation: ${nudgeMsg}`);
|
|
1834
|
+
}
|
|
1835
|
+
continue;
|
|
1836
|
+
}
|
|
1512
1837
|
const incident = await graph.addNode("incident", {
|
|
1513
1838
|
description: issue.description,
|
|
1514
1839
|
severity,
|
|
@@ -1534,7 +1859,7 @@ ${filesBlock}`,
|
|
|
1534
1859
|
this.state.totalIssuesFound++;
|
|
1535
1860
|
if (severity !== "minor") {
|
|
1536
1861
|
getOutputManager().nudge(
|
|
1537
|
-
|
|
1862
|
+
`${issue.description}`,
|
|
1538
1863
|
severity === "critical" ? "critical" : "warning",
|
|
1539
1864
|
issue.file,
|
|
1540
1865
|
severity === "critical" ? void 0 : 15e3
|
|
@@ -1555,7 +1880,8 @@ ${filesBlock}`,
|
|
|
1555
1880
|
questions: 0
|
|
1556
1881
|
});
|
|
1557
1882
|
}
|
|
1558
|
-
} catch {
|
|
1883
|
+
} catch (error) {
|
|
1884
|
+
getOutputManager().log("warn", `AI watcher error: ${error}`);
|
|
1559
1885
|
} finally {
|
|
1560
1886
|
this.state.autoScanInProgress = false;
|
|
1561
1887
|
}
|
|
@@ -1632,7 +1958,7 @@ Use \`trie_watch start\` to begin autonomous scanning.`
|
|
|
1632
1958
|
).join("\n");
|
|
1633
1959
|
let agencyStatus = "";
|
|
1634
1960
|
try {
|
|
1635
|
-
const { getGuardian } = await import("./guardian-agent-
|
|
1961
|
+
const { getGuardian } = await import("./guardian-agent-EXP7APLC.js");
|
|
1636
1962
|
const trieAgent = getGuardian(getWorkingDirectory(void 0, true));
|
|
1637
1963
|
await trieAgent.initialize();
|
|
1638
1964
|
const status = await trieAgent.getAgencyStatus();
|