@triedotdev/mcp 1.0.151 → 1.0.155
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 +34 -6
- package/dist/{autonomy-config-3APNC6QF.js → autonomy-config-RKLZW4XL.js} +4 -4
- package/dist/{chat-store-HMTDL7I2.js → chat-store-O3IJ5PMN.js} +4 -4
- package/dist/{chunk-IXO4G4D3.js → chunk-2LAJKFWU.js} +2 -2
- package/dist/{chunk-F7BMFOZ6.js → chunk-3CYMLM35.js} +2 -2
- package/dist/{chunk-ED7PLRQA.js → chunk-4ZAFQEP6.js} +4 -4
- package/dist/{chunk-4TQQP7JD.js → chunk-7F2R2ITA.js} +2 -2
- package/dist/{chunk-SU3WCAC4.js → chunk-BUA5PQJY.js} +1487 -49
- package/dist/chunk-BUA5PQJY.js.map +1 -0
- package/dist/{chunk-V3O7C2LY.js → chunk-CBAMZERA.js} +2 -2
- package/dist/{chunk-G7Q23IGF.js → chunk-EMJ7RVWB.js} +9 -9
- package/dist/{chunk-TU7D5DEW.js → chunk-FTOF3FHT.js} +3 -3
- package/dist/{chunk-3KZBC3RJ.js → chunk-FXZAABXO.js} +2 -2
- package/dist/{chunk-TWPX6PHF.js → chunk-HD5H7YSW.js} +2 -2
- package/dist/{chunk-APMV77PU.js → chunk-JKEEQAG2.js} +1 -1
- package/dist/chunk-JKEEQAG2.js.map +1 -0
- package/dist/{chunk-TWQPOVRA.js → chunk-JYWGYUKX.js} +2 -2
- package/dist/{chunk-TIMIKBY2.js → chunk-KLMJKM63.js} +2 -2
- package/dist/{chunk-TCNCNWGV.js → chunk-KYKADM7P.js} +2 -2
- package/dist/{chunk-GLY76TSI.js → chunk-L4FODDDB.js} +2 -2
- package/dist/{chunk-JIS2OCZR.js → chunk-LFNH3CSN.js} +4 -4
- package/dist/{chunk-74R4XSFB.js → chunk-NVZZUUEU.js} +5 -5
- package/dist/{chunk-REHKDCI6.js → chunk-OVSYTWUU.js} +2 -2
- package/dist/{chunk-IFBEAOHH.js → chunk-RY57G46E.js} +6 -6
- package/dist/{chunk-ABY2R7OK.js → chunk-T7UAH7GE.js} +2 -2
- package/dist/{chunk-OJXFQRUE.js → chunk-UL337UDQ.js} +2 -2
- package/dist/{chunk-F4NJ4CBP.js → chunk-WO7CC5FH.js} +2 -2
- package/dist/{chunk-4UDBGYI3.js → chunk-X64XFVAY.js} +13 -13
- package/dist/{chunk-QQG42HCI.js → chunk-XD2HKZVB.js} +2 -2
- package/dist/{chunk-LNUMECBJ.js → chunk-XUGUKSKO.js} +10 -2
- package/dist/chunk-XUGUKSKO.js.map +1 -0
- package/dist/{chunk-WOTLY5NA.js → chunk-YEQXKKZQ.js} +2 -2
- package/dist/{chunk-7HYOJ4Q7.js → chunk-Z2E7X4WI.js} +7 -7
- package/dist/cli/create-agent.js +2 -2
- package/dist/cli/main.js +86 -40
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +78 -27
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/{client-5L64D5SQ.js → client-ZHOLZTRW.js} +4 -4
- package/dist/{codebase-index-OOE7OAHP.js → codebase-index-N37NDF2A.js} +4 -4
- package/dist/{fast-analyzer-FMU3X4AZ.js → fast-analyzer-U6URGNQT.js} +6 -6
- package/dist/github-ingester-AR5A4RAC.js +11 -0
- package/dist/{goal-manager-VTBFFYN4.js → goal-manager-5QDITJKE.js} +8 -8
- package/dist/{goal-validator-EM5XVWVC.js → goal-validator-FU5QWDQT.js} +7 -7
- package/dist/graph-JO7GG65P.js +10 -0
- package/dist/{hypothesis-4UPE7KXU.js → hypothesis-JURDWVDC.js} +8 -8
- package/dist/incident-index-7CAXUNTL.js +11 -0
- package/dist/index.js +57 -1466
- package/dist/index.js.map +1 -1
- package/dist/{insight-store-QEEUQR5L.js → insight-store-AMEP5PPF.js} +4 -4
- package/dist/{issue-store-C6XYENE5.js → issue-store-RM3XLLKG.js} +5 -5
- package/dist/{ledger-VNA4DX3Z.js → ledger-PLE3C3X4.js} +4 -4
- package/dist/linear-ingester-NHFMKJBZ.js +11 -0
- package/dist/{output-manager-DZO5LGSG.js → output-manager-FX4V7ERT.js} +3 -3
- package/dist/{progress-PQVEM7BR.js → progress-PAYTY7BF.js} +2 -2
- package/dist/tiered-storage-SQDVZM2M.js +12 -0
- package/dist/trie-agent-TLOJ2UFS.js +27 -0
- package/dist/{vibe-code-signatures-ELEWJFGZ.js → vibe-code-signatures-J4GD4JOV.js} +3 -3
- package/dist/{vulnerability-signatures-EIJQX2TS.js → vulnerability-signatures-EIKOHFPK.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-APMV77PU.js.map +0 -1
- package/dist/chunk-LNUMECBJ.js.map +0 -1
- package/dist/chunk-SU3WCAC4.js.map +0 -1
- package/dist/github-ingester-C66ZRUYC.js +0 -11
- package/dist/graph-26JPZ3DF.js +0 -10
- package/dist/incident-index-H6APJ4S3.js +0 -11
- package/dist/linear-ingester-WIUBWF55.js +0 -11
- package/dist/tiered-storage-P6Z3NV2Q.js +0 -12
- package/dist/trie-agent-GJJJCL6P.js +0 -27
- /package/dist/{autonomy-config-3APNC6QF.js.map → autonomy-config-RKLZW4XL.js.map} +0 -0
- /package/dist/{chat-store-HMTDL7I2.js.map → chat-store-O3IJ5PMN.js.map} +0 -0
- /package/dist/{chunk-IXO4G4D3.js.map → chunk-2LAJKFWU.js.map} +0 -0
- /package/dist/{chunk-F7BMFOZ6.js.map → chunk-3CYMLM35.js.map} +0 -0
- /package/dist/{chunk-ED7PLRQA.js.map → chunk-4ZAFQEP6.js.map} +0 -0
- /package/dist/{chunk-4TQQP7JD.js.map → chunk-7F2R2ITA.js.map} +0 -0
- /package/dist/{chunk-V3O7C2LY.js.map → chunk-CBAMZERA.js.map} +0 -0
- /package/dist/{chunk-G7Q23IGF.js.map → chunk-EMJ7RVWB.js.map} +0 -0
- /package/dist/{chunk-TU7D5DEW.js.map → chunk-FTOF3FHT.js.map} +0 -0
- /package/dist/{chunk-3KZBC3RJ.js.map → chunk-FXZAABXO.js.map} +0 -0
- /package/dist/{chunk-TWPX6PHF.js.map → chunk-HD5H7YSW.js.map} +0 -0
- /package/dist/{chunk-TWQPOVRA.js.map → chunk-JYWGYUKX.js.map} +0 -0
- /package/dist/{chunk-TIMIKBY2.js.map → chunk-KLMJKM63.js.map} +0 -0
- /package/dist/{chunk-TCNCNWGV.js.map → chunk-KYKADM7P.js.map} +0 -0
- /package/dist/{chunk-GLY76TSI.js.map → chunk-L4FODDDB.js.map} +0 -0
- /package/dist/{chunk-JIS2OCZR.js.map → chunk-LFNH3CSN.js.map} +0 -0
- /package/dist/{chunk-74R4XSFB.js.map → chunk-NVZZUUEU.js.map} +0 -0
- /package/dist/{chunk-REHKDCI6.js.map → chunk-OVSYTWUU.js.map} +0 -0
- /package/dist/{chunk-IFBEAOHH.js.map → chunk-RY57G46E.js.map} +0 -0
- /package/dist/{chunk-ABY2R7OK.js.map → chunk-T7UAH7GE.js.map} +0 -0
- /package/dist/{chunk-OJXFQRUE.js.map → chunk-UL337UDQ.js.map} +0 -0
- /package/dist/{chunk-F4NJ4CBP.js.map → chunk-WO7CC5FH.js.map} +0 -0
- /package/dist/{chunk-4UDBGYI3.js.map → chunk-X64XFVAY.js.map} +0 -0
- /package/dist/{chunk-QQG42HCI.js.map → chunk-XD2HKZVB.js.map} +0 -0
- /package/dist/{chunk-WOTLY5NA.js.map → chunk-YEQXKKZQ.js.map} +0 -0
- /package/dist/{chunk-7HYOJ4Q7.js.map → chunk-Z2E7X4WI.js.map} +0 -0
- /package/dist/{client-5L64D5SQ.js.map → client-ZHOLZTRW.js.map} +0 -0
- /package/dist/{codebase-index-OOE7OAHP.js.map → codebase-index-N37NDF2A.js.map} +0 -0
- /package/dist/{fast-analyzer-FMU3X4AZ.js.map → fast-analyzer-U6URGNQT.js.map} +0 -0
- /package/dist/{github-ingester-C66ZRUYC.js.map → github-ingester-AR5A4RAC.js.map} +0 -0
- /package/dist/{goal-manager-VTBFFYN4.js.map → goal-manager-5QDITJKE.js.map} +0 -0
- /package/dist/{goal-validator-EM5XVWVC.js.map → goal-validator-FU5QWDQT.js.map} +0 -0
- /package/dist/{graph-26JPZ3DF.js.map → graph-JO7GG65P.js.map} +0 -0
- /package/dist/{hypothesis-4UPE7KXU.js.map → hypothesis-JURDWVDC.js.map} +0 -0
- /package/dist/{incident-index-H6APJ4S3.js.map → incident-index-7CAXUNTL.js.map} +0 -0
- /package/dist/{insight-store-QEEUQR5L.js.map → insight-store-AMEP5PPF.js.map} +0 -0
- /package/dist/{issue-store-C6XYENE5.js.map → issue-store-RM3XLLKG.js.map} +0 -0
- /package/dist/{ledger-VNA4DX3Z.js.map → ledger-PLE3C3X4.js.map} +0 -0
- /package/dist/{linear-ingester-WIUBWF55.js.map → linear-ingester-NHFMKJBZ.js.map} +0 -0
- /package/dist/{output-manager-DZO5LGSG.js.map → output-manager-FX4V7ERT.js.map} +0 -0
- /package/dist/{progress-PQVEM7BR.js.map → progress-PAYTY7BF.js.map} +0 -0
- /package/dist/{tiered-storage-P6Z3NV2Q.js.map → tiered-storage-SQDVZM2M.js.map} +0 -0
- /package/dist/{trie-agent-GJJJCL6P.js.map → trie-agent-TLOJ2UFS.js.map} +0 -0
- /package/dist/{vibe-code-signatures-ELEWJFGZ.js.map → vibe-code-signatures-J4GD4JOV.js.map} +0 -0
- /package/dist/{vulnerability-signatures-EIJQX2TS.js.map → vulnerability-signatures-EIKOHFPK.js.map} +0 -0
|
@@ -1,65 +1,76 @@
|
|
|
1
1
|
import {
|
|
2
2
|
getChatStore
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-3CYMLM35.js";
|
|
4
4
|
import {
|
|
5
5
|
getTrieAgent
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-X64XFVAY.js";
|
|
7
|
+
import {
|
|
8
|
+
CodebaseIndex
|
|
9
|
+
} from "./chunk-YEQXKKZQ.js";
|
|
7
10
|
import {
|
|
8
11
|
getOutputManager
|
|
9
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-KLMJKM63.js";
|
|
10
13
|
import {
|
|
11
14
|
LearningEngine,
|
|
12
15
|
exportToJson,
|
|
13
16
|
formatFriendlyError,
|
|
14
17
|
getLastCheckpoint,
|
|
18
|
+
isTrieInitialized,
|
|
15
19
|
listCheckpoints,
|
|
16
20
|
perceiveCurrentChanges,
|
|
17
21
|
reasonAboutChangesHumanReadable,
|
|
18
22
|
saveCheckpoint
|
|
19
|
-
} from "./chunk-
|
|
23
|
+
} from "./chunk-EMJ7RVWB.js";
|
|
20
24
|
import {
|
|
21
25
|
loadConfig,
|
|
22
26
|
saveConfig
|
|
23
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-FTOF3FHT.js";
|
|
24
28
|
import {
|
|
25
29
|
IncidentIndex
|
|
26
|
-
} from "./chunk-
|
|
30
|
+
} from "./chunk-KYKADM7P.js";
|
|
27
31
|
import {
|
|
28
32
|
findCrossProjectPatterns
|
|
29
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-RY57G46E.js";
|
|
30
34
|
import {
|
|
31
35
|
ContextGraph
|
|
32
|
-
} from "./chunk-
|
|
36
|
+
} from "./chunk-JYWGYUKX.js";
|
|
33
37
|
import {
|
|
34
38
|
measureInitialGoalValue
|
|
35
|
-
} from "./chunk-
|
|
39
|
+
} from "./chunk-Z2E7X4WI.js";
|
|
36
40
|
import {
|
|
37
41
|
getKeyFromKeychain,
|
|
38
42
|
isAIAvailable,
|
|
43
|
+
runAIAnalysis,
|
|
39
44
|
runAIWithTools,
|
|
40
45
|
setAPIKey
|
|
41
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-UL337UDQ.js";
|
|
42
47
|
import {
|
|
43
48
|
getProjectState
|
|
44
|
-
} from "./chunk-
|
|
49
|
+
} from "./chunk-L4FODDDB.js";
|
|
45
50
|
import {
|
|
46
51
|
TieredStorage,
|
|
47
52
|
getStorage
|
|
48
|
-
} from "./chunk-
|
|
53
|
+
} from "./chunk-XUGUKSKO.js";
|
|
49
54
|
import {
|
|
55
|
+
getAutonomyConfig,
|
|
50
56
|
loadAutonomyConfig,
|
|
51
57
|
saveAutonomyConfig
|
|
52
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-XD2HKZVB.js";
|
|
59
|
+
import {
|
|
60
|
+
storeIssues
|
|
61
|
+
} from "./chunk-4ZAFQEP6.js";
|
|
53
62
|
import {
|
|
63
|
+
getChangedFilesSinceTimestamp,
|
|
64
|
+
getGitChangedFiles,
|
|
54
65
|
getLedgerBlocks
|
|
55
|
-
} from "./chunk-
|
|
66
|
+
} from "./chunk-HD5H7YSW.js";
|
|
56
67
|
import {
|
|
57
68
|
getTrieDirectory,
|
|
58
69
|
getWorkingDirectory
|
|
59
|
-
} from "./chunk-
|
|
70
|
+
} from "./chunk-7F2R2ITA.js";
|
|
60
71
|
import {
|
|
61
72
|
isInteractiveMode
|
|
62
|
-
} from "./chunk-
|
|
73
|
+
} from "./chunk-JKEEQAG2.js";
|
|
63
74
|
|
|
64
75
|
// src/utils/streaming.ts
|
|
65
76
|
var shouldSuppressConsole = () => isInteractiveMode();
|
|
@@ -238,6 +249,12 @@ var StreamingManager = class {
|
|
|
238
249
|
reportSignalExtraction(signals) {
|
|
239
250
|
this.emit("signal_extracted", signals);
|
|
240
251
|
}
|
|
252
|
+
/**
|
|
253
|
+
* Report ledger update (new entries added)
|
|
254
|
+
*/
|
|
255
|
+
reportLedgerUpdate(entryCount, source) {
|
|
256
|
+
this.emit("ledger_updated", { entryCount, source });
|
|
257
|
+
}
|
|
241
258
|
// ============================================
|
|
242
259
|
// Rich Content Events (for TUI panes)
|
|
243
260
|
// ============================================
|
|
@@ -443,6 +460,11 @@ function handleStreamUpdate(state, update) {
|
|
|
443
460
|
}
|
|
444
461
|
break;
|
|
445
462
|
}
|
|
463
|
+
case "ledger_updated": {
|
|
464
|
+
s.memoryTree = { ...s.memoryTree, loaded: false };
|
|
465
|
+
s = addActivity(s, `[L] Ledger updated: ${update.data.entryCount} ${update.data.source} entries`);
|
|
466
|
+
break;
|
|
467
|
+
}
|
|
446
468
|
case "memory":
|
|
447
469
|
if (update.data.action === "saving") s = addActivity(s, "[~] Saving to memory...");
|
|
448
470
|
else if (update.data.action === "saved") s = addActivity(s, `[+] Memory updated: ${update.data.details || "context saved"}`);
|
|
@@ -960,13 +982,13 @@ import { Box, Text, useStdout } from "ink";
|
|
|
960
982
|
import { jsx as jsx2, jsxs } from "react/jsx-runtime";
|
|
961
983
|
function Header() {
|
|
962
984
|
const { state } = useDashboard();
|
|
963
|
-
const { signalExtraction, watch, alerts } = state;
|
|
985
|
+
const { signalExtraction, watch: watch2, alerts } = state;
|
|
964
986
|
const { stdout } = useStdout();
|
|
965
987
|
const cols = stdout?.columns || 80;
|
|
966
988
|
const narrow = cols < 50;
|
|
967
989
|
const totalExtracted = signalExtraction.governanceExtracted + signalExtraction.factsExtracted + signalExtraction.blockersExtracted + signalExtraction.questionsExtracted;
|
|
968
990
|
let status;
|
|
969
|
-
if (
|
|
991
|
+
if (watch2.watching) {
|
|
970
992
|
status = totalExtracted > 0 ? /* @__PURE__ */ jsxs(Text, { children: [
|
|
971
993
|
/* @__PURE__ */ jsx2(Text, { color: "green", children: "\u25CF" }),
|
|
972
994
|
narrow ? "" : " ",
|
|
@@ -1194,8 +1216,8 @@ function ConfigDialog({ onClose }) {
|
|
|
1194
1216
|
const loadStats = async () => {
|
|
1195
1217
|
try {
|
|
1196
1218
|
const workDir = getWorkingDirectory(void 0, true);
|
|
1197
|
-
const { CodebaseIndex } = await import("./codebase-index-
|
|
1198
|
-
const index = new
|
|
1219
|
+
const { CodebaseIndex: CodebaseIndex2 } = await import("./codebase-index-N37NDF2A.js");
|
|
1220
|
+
const index = new CodebaseIndex2(workDir);
|
|
1199
1221
|
const stats = index.getStats();
|
|
1200
1222
|
let lastUpdatedDisplay = "Never";
|
|
1201
1223
|
if (stats.lastUpdated) {
|
|
@@ -1387,8 +1409,8 @@ function ConfigDialog({ onClose }) {
|
|
|
1387
1409
|
const loadStats = async () => {
|
|
1388
1410
|
try {
|
|
1389
1411
|
const workDir = getWorkingDirectory(void 0, true);
|
|
1390
|
-
const { CodebaseIndex } = await import("./codebase-index-
|
|
1391
|
-
const index = new
|
|
1412
|
+
const { CodebaseIndex: CodebaseIndex2 } = await import("./codebase-index-N37NDF2A.js");
|
|
1413
|
+
const index = new CodebaseIndex2(workDir);
|
|
1392
1414
|
const stats = index.getStats();
|
|
1393
1415
|
setIndexStats({
|
|
1394
1416
|
fileCount: stats.totalFiles,
|
|
@@ -1462,9 +1484,9 @@ function ConfigDialog({ onClose }) {
|
|
|
1462
1484
|
}
|
|
1463
1485
|
async function reindexCodebase() {
|
|
1464
1486
|
const workDir = getWorkingDirectory(void 0, true);
|
|
1465
|
-
const { CodebaseIndex } = await import("./codebase-index-
|
|
1487
|
+
const { CodebaseIndex: CodebaseIndex2 } = await import("./codebase-index-N37NDF2A.js");
|
|
1466
1488
|
const { glob } = await import("glob");
|
|
1467
|
-
const index = new
|
|
1489
|
+
const index = new CodebaseIndex2(workDir);
|
|
1468
1490
|
const indexPattern = `${workDir}/**/*.{ts,tsx,js,jsx,mjs,vue,svelte,astro,py,go,rs,java,c,cpp,h,hpp,cs,rb,php,css,scss,html}`;
|
|
1469
1491
|
const indexFiles = await glob(indexPattern, {
|
|
1470
1492
|
ignore: ["**/node_modules/**", "**/dist/**", "**/build/**", "**/.git/**", "**/.trie/**", "**/coverage/**"],
|
|
@@ -1713,7 +1735,7 @@ function truncate(str, max) {
|
|
|
1713
1735
|
}
|
|
1714
1736
|
function OverviewView() {
|
|
1715
1737
|
const { state, dispatch } = useDashboard();
|
|
1716
|
-
const { progress, signalExtraction, watch, issues, activityLog, activityPage, pendingFixes: pendingFixes2, selectedFixIndex } = state;
|
|
1738
|
+
const { progress, signalExtraction, watch: watch2, issues, activityLog, activityPage, pendingFixes: pendingFixes2, selectedFixIndex } = state;
|
|
1717
1739
|
const { totalIssues } = progress;
|
|
1718
1740
|
const { stdout } = useStdout4();
|
|
1719
1741
|
const cols = stdout?.columns || 80;
|
|
@@ -1744,12 +1766,12 @@ function OverviewView() {
|
|
|
1744
1766
|
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
|
|
1745
1767
|
/* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
1746
1768
|
"Scanned ",
|
|
1747
|
-
|
|
1769
|
+
watch2.filesScannedSession,
|
|
1748
1770
|
" files ",
|
|
1749
1771
|
elapsed,
|
|
1750
1772
|
"s"
|
|
1751
1773
|
] }),
|
|
1752
|
-
|
|
1774
|
+
watch2.watching && signalExtraction.enabled && /* @__PURE__ */ jsxs6(Text6, { wrap: "truncate", children: [
|
|
1753
1775
|
/* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
|
|
1754
1776
|
" Signal extraction",
|
|
1755
1777
|
!narrow && (signalExtraction.governanceExtracted > 0 || signalExtraction.factsExtracted > 0 || signalExtraction.blockersExtracted > 0) && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
|
|
@@ -1925,10 +1947,10 @@ function AgentView() {
|
|
|
1925
1947
|
if (!insight) return;
|
|
1926
1948
|
try {
|
|
1927
1949
|
const workDir = getWorkingDirectory(void 0, true);
|
|
1928
|
-
const { getInsightStore } = await import("./insight-store-
|
|
1950
|
+
const { getInsightStore } = await import("./insight-store-AMEP5PPF.js");
|
|
1929
1951
|
const store = getInsightStore(workDir);
|
|
1930
1952
|
await store.dismissInsight(insight.id);
|
|
1931
|
-
const { getStorage: getStorage2 } = await import("./tiered-storage-
|
|
1953
|
+
const { getStorage: getStorage2 } = await import("./tiered-storage-SQDVZM2M.js");
|
|
1932
1954
|
const storage = getStorage2(workDir);
|
|
1933
1955
|
await storage.dismissNudge(insight.id).catch(() => {
|
|
1934
1956
|
});
|
|
@@ -2287,7 +2309,7 @@ function GoalsView() {
|
|
|
2287
2309
|
dispatch({ type: "SET_GOAL_SCANNING", goalId, progress: "Starting scan..." });
|
|
2288
2310
|
dispatch({ type: "ADD_ACTIVITY", message: `Scanning goal: ${goalSummary.description}...` });
|
|
2289
2311
|
dispatch({ type: "SET_GOAL_SCANNING", goalId, progress: "Loading goal configuration..." });
|
|
2290
|
-
const { checkFilesForGoalViolations } = await import("./goal-validator-
|
|
2312
|
+
const { checkFilesForGoalViolations } = await import("./goal-validator-FU5QWDQT.js");
|
|
2291
2313
|
const agentState = getProjectState(workDir);
|
|
2292
2314
|
await agentState.load();
|
|
2293
2315
|
const fullGoal = agentState.getAllGoals().find((g) => g.id === goalId);
|
|
@@ -2562,7 +2584,7 @@ function HypothesesView() {
|
|
|
2562
2584
|
dispatch({ type: "SET_HYPOTHESIS_SCANNING", hypothesisId: hypoId, progress: "Gathering evidence..." });
|
|
2563
2585
|
dispatch({ type: "ADD_ACTIVITY", message: `Testing hypothesis: ${hypo.statement}` });
|
|
2564
2586
|
dispatch({ type: "SHOW_NOTIFICATION", message: `Gathering evidence for hypothesis...`, severity: "info", autoHideMs: 3e3 });
|
|
2565
|
-
const { gatherEvidenceForHypothesis } = await import("./hypothesis-
|
|
2587
|
+
const { gatherEvidenceForHypothesis } = await import("./hypothesis-JURDWVDC.js");
|
|
2566
2588
|
const evidence = await gatherEvidenceForHypothesis(hypoId, workDir, signal);
|
|
2567
2589
|
scanAbortRef.current = null;
|
|
2568
2590
|
dispatch({ type: "SET_HYPOTHESIS_SCANNING", hypothesisId: null, progress: "" });
|
|
@@ -6238,7 +6260,7 @@ function getPendingFixes() {
|
|
|
6238
6260
|
}
|
|
6239
6261
|
async function loadPendingFixesFromMemory() {
|
|
6240
6262
|
try {
|
|
6241
|
-
const { getRecentIssues } = await import("./issue-store-
|
|
6263
|
+
const { getRecentIssues } = await import("./issue-store-RM3XLLKG.js");
|
|
6242
6264
|
pendingFixes.clear();
|
|
6243
6265
|
const recentIssues = await getRecentIssues({ limit: 50, includeResolved: false });
|
|
6244
6266
|
for (const storedIssue of recentIssues) {
|
|
@@ -6541,7 +6563,7 @@ var TrieCloudFixTool = class {
|
|
|
6541
6563
|
if (pending.length === 0) {
|
|
6542
6564
|
try {
|
|
6543
6565
|
console.log("Loading issues from memory...");
|
|
6544
|
-
const { getRecentIssues } = await import("./issue-store-
|
|
6566
|
+
const { getRecentIssues } = await import("./issue-store-RM3XLLKG.js");
|
|
6545
6567
|
const recentIssues = await getRecentIssues({ limit: 50, includeResolved: false });
|
|
6546
6568
|
console.log(`Found ${recentIssues.length} recent issues in memory`);
|
|
6547
6569
|
const memoryIssues = recentIssues.map((storedIssue) => ({
|
|
@@ -6981,7 +7003,7 @@ var TrieQueryContextTool = class {
|
|
|
6981
7003
|
}
|
|
6982
7004
|
if (includeIncidents) {
|
|
6983
7005
|
try {
|
|
6984
|
-
const { ContextGraph: ContextGraph2 } = await import("./graph-
|
|
7006
|
+
const { ContextGraph: ContextGraph2 } = await import("./graph-JO7GG65P.js");
|
|
6985
7007
|
const graph = new ContextGraph2(workDir);
|
|
6986
7008
|
const allNodes = await graph.listNodes();
|
|
6987
7009
|
const incidentNodes = allNodes.filter((n) => n.type === "incident");
|
|
@@ -8246,7 +8268,7 @@ ${truncated}`;
|
|
|
8246
8268
|
const goalId = input.goalId ? String(input.goalId).trim() : void 0;
|
|
8247
8269
|
try {
|
|
8248
8270
|
onProgress?.("Loading goals...");
|
|
8249
|
-
const { getActiveGoals } = await import("./goal-validator-
|
|
8271
|
+
const { getActiveGoals } = await import("./goal-validator-FU5QWDQT.js");
|
|
8250
8272
|
const agentState = getProjectState(directory);
|
|
8251
8273
|
await agentState.load();
|
|
8252
8274
|
const allGoals = await getActiveGoals(directory);
|
|
@@ -8255,7 +8277,7 @@ ${truncated}`;
|
|
|
8255
8277
|
return goalId ? `No active goal found with ID: ${goalId}` : "No active goals to check. Add goals in the Goals view first.";
|
|
8256
8278
|
}
|
|
8257
8279
|
onProgress?.("Scanning codebase for violations...");
|
|
8258
|
-
const { analyzeFilesRapidly } = await import("./fast-analyzer-
|
|
8280
|
+
const { analyzeFilesRapidly } = await import("./fast-analyzer-U6URGNQT.js");
|
|
8259
8281
|
const analysisOptions = {
|
|
8260
8282
|
maxFiles: 50,
|
|
8261
8283
|
enableSmartBatching: true
|
|
@@ -8269,8 +8291,8 @@ ${truncated}`;
|
|
|
8269
8291
|
const cacheInfo2 = analysisResult.cacheHitRatio > 0 ? ` (${Math.round(analysisResult.cacheHitRatio * 100)}% cache hit, ${analysisResult.timeMs}ms)` : ` (${analysisResult.timeMs}ms)`;
|
|
8270
8292
|
return `\u2713 Scan complete! No violations found for ${goalsToCheck.length} goal(s).${cacheInfo2}`;
|
|
8271
8293
|
}
|
|
8272
|
-
const { storeIssues } = await import("./issue-store-
|
|
8273
|
-
const { basename } = await import("path");
|
|
8294
|
+
const { storeIssues: storeIssues2 } = await import("./issue-store-RM3XLLKG.js");
|
|
8295
|
+
const { basename: basename2 } = await import("path");
|
|
8274
8296
|
const issuesToStore = violations.map((v, i) => ({
|
|
8275
8297
|
id: `goal-violation-${Date.now()}-${i}`,
|
|
8276
8298
|
file: v.file,
|
|
@@ -8282,7 +8304,7 @@ ${truncated}`;
|
|
|
8282
8304
|
confidence: 80,
|
|
8283
8305
|
autoFixable: false
|
|
8284
8306
|
}));
|
|
8285
|
-
await
|
|
8307
|
+
await storeIssues2(issuesToStore, basename2(directory), directory);
|
|
8286
8308
|
let violationsReport = `Found ${violations.length} violation(s):
|
|
8287
8309
|
|
|
8288
8310
|
`;
|
|
@@ -8348,7 +8370,7 @@ ${truncated}`;
|
|
|
8348
8370
|
}
|
|
8349
8371
|
try {
|
|
8350
8372
|
onProgress?.("Gathering evidence for hypothesis...");
|
|
8351
|
-
const { gatherEvidenceForHypothesis } = await import("./hypothesis-
|
|
8373
|
+
const { gatherEvidenceForHypothesis } = await import("./hypothesis-JURDWVDC.js");
|
|
8352
8374
|
const evidence = await gatherEvidenceForHypothesis(hypothesisId, directory);
|
|
8353
8375
|
if (evidence.length === 0) {
|
|
8354
8376
|
return `No evidence found for this hypothesis yet. The codebase may not have enough data to validate it \u2014 try running trie_scan_for_goal_violations first to populate issues, or add more context.`;
|
|
@@ -8612,7 +8634,7 @@ function ChatView() {
|
|
|
8612
8634
|
const saveChat = async () => {
|
|
8613
8635
|
try {
|
|
8614
8636
|
const workDir = getWorkingDirectory(void 0, true);
|
|
8615
|
-
const { getChatStore: getChatStore2 } = await import("./chat-store-
|
|
8637
|
+
const { getChatStore: getChatStore2 } = await import("./chat-store-O3IJ5PMN.js");
|
|
8616
8638
|
const store = getChatStore2(workDir);
|
|
8617
8639
|
const sessionId = await store.saveSession(
|
|
8618
8640
|
messages,
|
|
@@ -9247,7 +9269,7 @@ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
|
9247
9269
|
var MAIN_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent", "chat"];
|
|
9248
9270
|
async function applyGoalFix(fix, dispatch) {
|
|
9249
9271
|
try {
|
|
9250
|
-
const { runAIAnalysis, isAIAvailable: isAIAvailable2 } = await import("./client-
|
|
9272
|
+
const { runAIAnalysis: runAIAnalysis2, isAIAvailable: isAIAvailable2 } = await import("./client-ZHOLZTRW.js");
|
|
9251
9273
|
if (!isAIAvailable2()) {
|
|
9252
9274
|
dispatch({ type: "DISMISS_FIX", id: fix.id });
|
|
9253
9275
|
getOutputManager().nudge("AI not available for fix", "warning");
|
|
@@ -9256,7 +9278,7 @@ async function applyGoalFix(fix, dispatch) {
|
|
|
9256
9278
|
const projectPath = getWorkingDirectory(void 0, true);
|
|
9257
9279
|
const fullPath = join3(projectPath, fix.file);
|
|
9258
9280
|
const content = await readFile4(fullPath, "utf-8");
|
|
9259
|
-
const result = await
|
|
9281
|
+
const result = await runAIAnalysis2({
|
|
9260
9282
|
systemPrompt: `You are a precise code fixer. The user has a quality goal: "${fix.goalDescription}".
|
|
9261
9283
|
A violation was detected: "${fix.description}"
|
|
9262
9284
|
Suggested fix: "${fix.suggestedFix}"
|
|
@@ -9282,7 +9304,7 @@ ${content}
|
|
|
9282
9304
|
fixedContent = fixedContent.replace(/^```\w*\n?/, "").replace(/\n?```$/, "");
|
|
9283
9305
|
}
|
|
9284
9306
|
await writeFile2(fullPath, fixedContent, "utf-8");
|
|
9285
|
-
const { recordGoalViolationFixed, getActiveGoals } = await import("./goal-validator-
|
|
9307
|
+
const { recordGoalViolationFixed, getActiveGoals } = await import("./goal-validator-FU5QWDQT.js");
|
|
9286
9308
|
const goals = await getActiveGoals(projectPath);
|
|
9287
9309
|
const matchedGoal = goals.find((g) => g.description === fix.goalDescription);
|
|
9288
9310
|
if (matchedGoal) {
|
|
@@ -9320,7 +9342,7 @@ function DashboardApp({ onReady }) {
|
|
|
9320
9342
|
const workDir = getWorkingDirectory(void 0, true);
|
|
9321
9343
|
await mkdir2(getTrieDirectory(workDir), { recursive: true });
|
|
9322
9344
|
await writeFile2(configPath, JSON.stringify(stateRef.current.agentConfig, null, 2), "utf-8");
|
|
9323
|
-
const { saveAutonomyConfig: saveAutonomyConfig2, loadAutonomyConfig: loadAutonomyConfig2 } = await import("./autonomy-config-
|
|
9345
|
+
const { saveAutonomyConfig: saveAutonomyConfig2, loadAutonomyConfig: loadAutonomyConfig2 } = await import("./autonomy-config-RKLZW4XL.js");
|
|
9324
9346
|
const autonomy = await loadAutonomyConfig2(workDir);
|
|
9325
9347
|
autonomy.aiWatcher = stateRef.current.agentConfig.aiWatcher;
|
|
9326
9348
|
await saveAutonomyConfig2(workDir, autonomy);
|
|
@@ -9398,7 +9420,7 @@ function DashboardApp({ onReady }) {
|
|
|
9398
9420
|
const loadPersistedNudges = useCallback7(async () => {
|
|
9399
9421
|
try {
|
|
9400
9422
|
const workDir = getWorkingDirectory(void 0, true);
|
|
9401
|
-
const { getStorage: getStorage2 } = await import("./tiered-storage-
|
|
9423
|
+
const { getStorage: getStorage2 } = await import("./tiered-storage-SQDVZM2M.js");
|
|
9402
9424
|
const storage = getStorage2(workDir);
|
|
9403
9425
|
await storage.initialize();
|
|
9404
9426
|
const nudges = await storage.queryNudges({ resolved: false, limit: 50 });
|
|
@@ -9626,6 +9648,17 @@ var InteractiveDashboard = class {
|
|
|
9626
9648
|
updateHandler = null;
|
|
9627
9649
|
getConfigFn = null;
|
|
9628
9650
|
async start() {
|
|
9651
|
+
if (!process.stdin.isTTY || typeof process.stdin.setRawMode !== "function") {
|
|
9652
|
+
return;
|
|
9653
|
+
}
|
|
9654
|
+
try {
|
|
9655
|
+
const currentMode = process.stdin.isRaw;
|
|
9656
|
+
if (currentMode === void 0) {
|
|
9657
|
+
return;
|
|
9658
|
+
}
|
|
9659
|
+
} catch {
|
|
9660
|
+
return;
|
|
9661
|
+
}
|
|
9629
9662
|
this.app = render(
|
|
9630
9663
|
React11.createElement(App, {
|
|
9631
9664
|
onReady: (handler, getConfig) => {
|
|
@@ -9655,6 +9688,1411 @@ var InteractiveDashboard = class {
|
|
|
9655
9688
|
}
|
|
9656
9689
|
};
|
|
9657
9690
|
|
|
9691
|
+
// src/tools/watch.ts
|
|
9692
|
+
import { watch, existsSync as existsSync6, readFileSync as readFileSync2 } from "fs";
|
|
9693
|
+
import { stat, readFile as readFile5 } from "fs/promises";
|
|
9694
|
+
import { join as join4, extname as extname3, basename } from "path";
|
|
9695
|
+
import { createHash as createHash2 } from "crypto";
|
|
9696
|
+
var WATCH_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
9697
|
+
".ts",
|
|
9698
|
+
".tsx",
|
|
9699
|
+
".js",
|
|
9700
|
+
".jsx",
|
|
9701
|
+
".mjs",
|
|
9702
|
+
".vue",
|
|
9703
|
+
".svelte",
|
|
9704
|
+
".astro",
|
|
9705
|
+
".py",
|
|
9706
|
+
".go",
|
|
9707
|
+
".rs"
|
|
9708
|
+
]);
|
|
9709
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
9710
|
+
"node_modules",
|
|
9711
|
+
".git",
|
|
9712
|
+
"dist",
|
|
9713
|
+
"build",
|
|
9714
|
+
".next",
|
|
9715
|
+
".nuxt",
|
|
9716
|
+
"coverage",
|
|
9717
|
+
".turbo",
|
|
9718
|
+
".cache"
|
|
9719
|
+
]);
|
|
9720
|
+
var TrieWatchTool = class _TrieWatchTool {
|
|
9721
|
+
extractionPipeline = null;
|
|
9722
|
+
watchedDirectory = "";
|
|
9723
|
+
codebaseIndex = null;
|
|
9724
|
+
state = {
|
|
9725
|
+
isRunning: false,
|
|
9726
|
+
lastScan: /* @__PURE__ */ new Map(),
|
|
9727
|
+
pendingFiles: /* @__PURE__ */ new Set(),
|
|
9728
|
+
scanDebounceTimer: null,
|
|
9729
|
+
issueCache: /* @__PURE__ */ new Map(),
|
|
9730
|
+
totalIssuesFound: 0,
|
|
9731
|
+
filesScanned: 0,
|
|
9732
|
+
nudgedFiles: /* @__PURE__ */ new Set(),
|
|
9733
|
+
nudges: [],
|
|
9734
|
+
lastAutoScan: 0,
|
|
9735
|
+
autoScanInProgress: false,
|
|
9736
|
+
tokenBudget: {
|
|
9737
|
+
used: 0,
|
|
9738
|
+
windowStart: Date.now(),
|
|
9739
|
+
hourlyLimit: 5e4,
|
|
9740
|
+
scansSaved: 0
|
|
9741
|
+
},
|
|
9742
|
+
cleanFiles: /* @__PURE__ */ new Map()
|
|
9743
|
+
};
|
|
9744
|
+
watchers = /* @__PURE__ */ new Map();
|
|
9745
|
+
streamingManager = void 0;
|
|
9746
|
+
dashboard = void 0;
|
|
9747
|
+
lastHypothesisCheck = 0;
|
|
9748
|
+
pipelineSyncTimer = null;
|
|
9749
|
+
static HYPOTHESIS_CHECK_INTERVAL_MS = 3e5;
|
|
9750
|
+
// Check every 5 minutes
|
|
9751
|
+
static PIPELINE_SYNC_INTERVAL_MS = 30 * 60 * 1e3;
|
|
9752
|
+
// 30 minutes
|
|
9753
|
+
async execute(args) {
|
|
9754
|
+
const { action, directory, debounceMs = 1e3 } = args;
|
|
9755
|
+
switch (action) {
|
|
9756
|
+
case "start":
|
|
9757
|
+
return this.startWatching(getWorkingDirectory(directory), debounceMs);
|
|
9758
|
+
case "stop":
|
|
9759
|
+
return await this.stopWatching();
|
|
9760
|
+
case "status":
|
|
9761
|
+
return await this.getStatus();
|
|
9762
|
+
case "issues":
|
|
9763
|
+
return this.getCurrentIssues();
|
|
9764
|
+
case "nudges":
|
|
9765
|
+
return this.getNudges();
|
|
9766
|
+
default:
|
|
9767
|
+
return {
|
|
9768
|
+
content: [{
|
|
9769
|
+
type: "text",
|
|
9770
|
+
text: `Unknown action: ${action}. Use 'start', 'stop', 'status', or 'issues'.`
|
|
9771
|
+
}]
|
|
9772
|
+
};
|
|
9773
|
+
}
|
|
9774
|
+
}
|
|
9775
|
+
async startWatching(directory, debounceMs) {
|
|
9776
|
+
if (this.state.isRunning) {
|
|
9777
|
+
return {
|
|
9778
|
+
content: [{
|
|
9779
|
+
type: "text",
|
|
9780
|
+
text: "[!] Watch mode is already running. Use `trie_watch stop` to stop it first."
|
|
9781
|
+
}]
|
|
9782
|
+
};
|
|
9783
|
+
}
|
|
9784
|
+
if (!isTrieInitialized(directory)) {
|
|
9785
|
+
return {
|
|
9786
|
+
content: [{
|
|
9787
|
+
type: "text",
|
|
9788
|
+
text: "Trie is not initialized for this project. Run `trie init` first."
|
|
9789
|
+
}]
|
|
9790
|
+
};
|
|
9791
|
+
}
|
|
9792
|
+
const anthropicApiKey = process.env.ANTHROPIC_API_KEY;
|
|
9793
|
+
if (anthropicApiKey) {
|
|
9794
|
+
this.extractionPipeline = new ExtractionPipeline({
|
|
9795
|
+
workingDirectory: directory,
|
|
9796
|
+
anthropicApiKey
|
|
9797
|
+
});
|
|
9798
|
+
await this.extractionPipeline.initialize();
|
|
9799
|
+
}
|
|
9800
|
+
this.codebaseIndex = new CodebaseIndex(directory);
|
|
9801
|
+
this.state.isRunning = true;
|
|
9802
|
+
this.watchedDirectory = directory;
|
|
9803
|
+
this.state.issueCache.clear();
|
|
9804
|
+
this.state.totalIssuesFound = 0;
|
|
9805
|
+
this.state.filesScanned = 0;
|
|
9806
|
+
this.state.nudgedFiles.clear();
|
|
9807
|
+
this.state.nudges = [];
|
|
9808
|
+
try {
|
|
9809
|
+
const storage = getStorage(directory);
|
|
9810
|
+
await storage.initialize();
|
|
9811
|
+
const unresolvedNudges = await storage.queryNudges({ resolved: false });
|
|
9812
|
+
console.debug(`[Watch] Found ${unresolvedNudges.length} unresolved nudges in storage`);
|
|
9813
|
+
for (const nudge of unresolvedNudges) {
|
|
9814
|
+
let mappedSeverity = "high";
|
|
9815
|
+
if (nudge.severity === "critical") {
|
|
9816
|
+
mappedSeverity = "critical";
|
|
9817
|
+
} else if (nudge.severity === "high") {
|
|
9818
|
+
mappedSeverity = "high";
|
|
9819
|
+
}
|
|
9820
|
+
this.state.nudges.push({
|
|
9821
|
+
file: nudge.file || "unknown",
|
|
9822
|
+
// Keep full path, don't use basename
|
|
9823
|
+
message: nudge.message,
|
|
9824
|
+
severity: mappedSeverity,
|
|
9825
|
+
timestamp: new Date(nudge.timestamp).toLocaleTimeString("en-US", { hour12: false })
|
|
9826
|
+
});
|
|
9827
|
+
console.debug(`[Watch] Loaded nudge: ${nudge.message.slice(0, 60)}... (${nudge.severity} -> ${mappedSeverity})`);
|
|
9828
|
+
}
|
|
9829
|
+
if (unresolvedNudges.length > 0) {
|
|
9830
|
+
console.log(`[Watch] \u2713 Loaded ${unresolvedNudges.length} unresolved nudges from storage`);
|
|
9831
|
+
} else {
|
|
9832
|
+
console.debug(`[Watch] No unresolved nudges found in storage`);
|
|
9833
|
+
}
|
|
9834
|
+
} catch (error) {
|
|
9835
|
+
console.error("[Watch] Failed to load nudges from storage:", error);
|
|
9836
|
+
}
|
|
9837
|
+
try {
|
|
9838
|
+
const graph = new ContextGraph(directory);
|
|
9839
|
+
const allNodes = await graph.listNodes();
|
|
9840
|
+
const unresolvedIncidents = allNodes.filter(
|
|
9841
|
+
(n) => n.type === "incident" && !n.data.resolved
|
|
9842
|
+
);
|
|
9843
|
+
console.debug(`[Watch] Found ${unresolvedIncidents.length} unresolved incidents in context graph`);
|
|
9844
|
+
for (const incident of unresolvedIncidents) {
|
|
9845
|
+
const incidentData = incident.data;
|
|
9846
|
+
let mappedSeverity = "high";
|
|
9847
|
+
if (incidentData.severity === "critical") {
|
|
9848
|
+
mappedSeverity = "critical";
|
|
9849
|
+
} else if (incidentData.severity === "major") {
|
|
9850
|
+
mappedSeverity = "critical";
|
|
9851
|
+
} else if (incidentData.severity === "minor") {
|
|
9852
|
+
mappedSeverity = "high";
|
|
9853
|
+
}
|
|
9854
|
+
const edges = await graph.getEdges(incident.id);
|
|
9855
|
+
const linkedFiles = edges.filter((e) => e.type === "causedBy" || e.type === "affects").map((e) => {
|
|
9856
|
+
const node = allNodes.find((n) => n.id === e.to_id || n.id === e.from_id);
|
|
9857
|
+
if (node?.type === "file") {
|
|
9858
|
+
return node.data.path;
|
|
9859
|
+
}
|
|
9860
|
+
return null;
|
|
9861
|
+
}).filter((f) => f !== null);
|
|
9862
|
+
const file = linkedFiles[0] || "unknown";
|
|
9863
|
+
const message = `INCIDENT: ${incidentData.description}`;
|
|
9864
|
+
this.state.nudges.push({
|
|
9865
|
+
file,
|
|
9866
|
+
message,
|
|
9867
|
+
severity: mappedSeverity,
|
|
9868
|
+
timestamp: new Date(incidentData.timestamp).toLocaleTimeString("en-US", { hour12: false })
|
|
9869
|
+
});
|
|
9870
|
+
console.debug(`[Watch] Loaded incident: ${incidentData.description.slice(0, 60)}... (${incidentData.severity} -> ${mappedSeverity})`);
|
|
9871
|
+
}
|
|
9872
|
+
if (unresolvedIncidents.length > 0) {
|
|
9873
|
+
console.log(`[Watch] \u2713 Loaded ${unresolvedIncidents.length} unresolved incidents from context graph`);
|
|
9874
|
+
} else {
|
|
9875
|
+
console.debug(`[Watch] No unresolved incidents found in context graph`);
|
|
9876
|
+
}
|
|
9877
|
+
} catch (error) {
|
|
9878
|
+
console.error("[Watch] Failed to load incidents from context graph:", error);
|
|
9879
|
+
}
|
|
9880
|
+
if (!isInteractiveMode()) {
|
|
9881
|
+
console.error("\n\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\u2501\u2501\u2501\u2501\u2501\u2501\u2501");
|
|
9882
|
+
console.error("TRIE AGENT - NOW WATCHING");
|
|
9883
|
+
console.error("\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\u2501\u2501\u2501\u2501\u2501\u2501\u2501\n");
|
|
9884
|
+
console.error("Your Trie agent is now watching over your codebase.");
|
|
9885
|
+
console.error("Signal extraction: ENABLED (building governance ledger)");
|
|
9886
|
+
console.error(`Watching: ${directory}`);
|
|
9887
|
+
console.error(`Debounce: ${debounceMs}ms`);
|
|
9888
|
+
console.error("");
|
|
9889
|
+
}
|
|
9890
|
+
if (isInteractiveMode()) {
|
|
9891
|
+
this.streamingManager = new StreamingManager();
|
|
9892
|
+
this.dashboard = new InteractiveDashboard();
|
|
9893
|
+
this.streamingManager.subscribe((update) => this.dashboard?.handleStreamUpdate(update));
|
|
9894
|
+
const outputManager = getOutputManager();
|
|
9895
|
+
outputManager.setMode("tui");
|
|
9896
|
+
outputManager.setStreamingManager(this.streamingManager);
|
|
9897
|
+
await this.dashboard.start();
|
|
9898
|
+
this.streamingManager.reportWatchStatus({ watching: true, directories: 0, debounceMs });
|
|
9899
|
+
} else {
|
|
9900
|
+
getOutputManager().setMode("console");
|
|
9901
|
+
}
|
|
9902
|
+
await this.watchDirectory(directory, debounceMs);
|
|
9903
|
+
await this.watchContextGraph(directory);
|
|
9904
|
+
if (this.streamingManager) {
|
|
9905
|
+
this.streamingManager.reportWatchStatus({
|
|
9906
|
+
watching: true,
|
|
9907
|
+
directories: this.watchers.size,
|
|
9908
|
+
debounceMs
|
|
9909
|
+
});
|
|
9910
|
+
}
|
|
9911
|
+
setTimeout(() => {
|
|
9912
|
+
void this.initialGoalComplianceScan();
|
|
9913
|
+
void this.initialHypothesisGeneration();
|
|
9914
|
+
void this.syncPipelineIntegrations();
|
|
9915
|
+
}, 1e3);
|
|
9916
|
+
this.pipelineSyncTimer = setInterval(() => {
|
|
9917
|
+
void this.syncPipelineIntegrations();
|
|
9918
|
+
}, _TrieWatchTool.PIPELINE_SYNC_INTERVAL_MS);
|
|
9919
|
+
const indexStatus = this.codebaseIndex?.isEmpty() ? "BUILDING (one-time, speeds up goal checks)" : "READY";
|
|
9920
|
+
return {
|
|
9921
|
+
content: [{
|
|
9922
|
+
type: "text",
|
|
9923
|
+
text: `**TRIE AGENT ACTIVATED**
|
|
9924
|
+
|
|
9925
|
+
Your Trie agent is now autonomously watching and learning from your codebase.
|
|
9926
|
+
|
|
9927
|
+
**Watching:** \`${directory}\`
|
|
9928
|
+
**Debounce:** ${debounceMs}ms (waits for you to stop typing)
|
|
9929
|
+
**Signal Extraction:** ${process.env.ANTHROPIC_API_KEY ? "ENABLED" : "LIMITED (set ANTHROPIC_API_KEY for full extraction)"}
|
|
9930
|
+
**Codebase Index:** ${indexStatus}
|
|
9931
|
+
|
|
9932
|
+
### How the agent works:
|
|
9933
|
+
1. You write/edit code
|
|
9934
|
+
2. Agent detects the change
|
|
9935
|
+
3. Extracts governance, facts, blockers -> stores in ledger
|
|
9936
|
+
4. Predicts risks based on historical patterns
|
|
9937
|
+
5. Nudges you if something looks risky
|
|
9938
|
+
|
|
9939
|
+
### The agent learns:
|
|
9940
|
+
- Every commit builds the governance ledger
|
|
9941
|
+
- \`trie gotcha\` queries the ledger for predictions
|
|
9942
|
+
- \`trie ok\` / \`trie bad\` teach the agent what matters
|
|
9943
|
+
|
|
9944
|
+
### Commands:
|
|
9945
|
+
- \`trie_watch status\` - See agent status
|
|
9946
|
+
- \`trie_watch stop\` - Stop the agent
|
|
9947
|
+
- \`trie_index status\` - Check codebase index`
|
|
9948
|
+
}]
|
|
9949
|
+
};
|
|
9950
|
+
}
|
|
9951
|
+
shouldSkipPath(filePath) {
|
|
9952
|
+
const parts = filePath.split("/");
|
|
9953
|
+
return parts.some((p) => SKIP_DIRS.has(p) || p.startsWith(".") && p !== ".");
|
|
9954
|
+
}
|
|
9955
|
+
async watchDirectory(dir, debounceMs) {
|
|
9956
|
+
if (!existsSync6(dir)) return;
|
|
9957
|
+
try {
|
|
9958
|
+
const dirStat = await stat(dir);
|
|
9959
|
+
if (!dirStat.isDirectory()) return;
|
|
9960
|
+
const watcher = watch(dir, { persistent: true, recursive: true }, (_eventType, filename) => {
|
|
9961
|
+
if (!filename) return;
|
|
9962
|
+
if (this.shouldSkipPath(filename)) return;
|
|
9963
|
+
const ext = extname3(filename).toLowerCase();
|
|
9964
|
+
if (!WATCH_EXTENSIONS.has(ext)) return;
|
|
9965
|
+
const fullPath = join4(dir, filename);
|
|
9966
|
+
if (!existsSync6(fullPath)) return;
|
|
9967
|
+
this.state.pendingFiles.add(fullPath);
|
|
9968
|
+
if (this.state.scanDebounceTimer) {
|
|
9969
|
+
clearTimeout(this.state.scanDebounceTimer);
|
|
9970
|
+
}
|
|
9971
|
+
this.state.scanDebounceTimer = setTimeout(() => {
|
|
9972
|
+
this.processPendingFiles();
|
|
9973
|
+
}, debounceMs);
|
|
9974
|
+
});
|
|
9975
|
+
watcher.on("error", (err) => {
|
|
9976
|
+
if (!isInteractiveMode()) {
|
|
9977
|
+
console.error(`[!] Watcher error: ${err.message}`);
|
|
9978
|
+
}
|
|
9979
|
+
watcher.close();
|
|
9980
|
+
this.watchers.delete(dir);
|
|
9981
|
+
});
|
|
9982
|
+
this.watchers.set(dir, watcher);
|
|
9983
|
+
if (this.streamingManager) {
|
|
9984
|
+
this.streamingManager.reportWatchStatus({
|
|
9985
|
+
watching: true,
|
|
9986
|
+
directories: 1,
|
|
9987
|
+
debounceMs
|
|
9988
|
+
});
|
|
9989
|
+
}
|
|
9990
|
+
} catch {
|
|
9991
|
+
}
|
|
9992
|
+
}
|
|
9993
|
+
/**
|
|
9994
|
+
* Watch .trie/context.json for incident changes
|
|
9995
|
+
*/
|
|
9996
|
+
async watchContextGraph(directory) {
|
|
9997
|
+
const contextPath = join4(getTrieDirectory(directory), "context.json");
|
|
9998
|
+
if (!existsSync6(contextPath)) {
|
|
9999
|
+
console.debug("[Watch] No context.json found, skipping incident watcher");
|
|
10000
|
+
return;
|
|
10001
|
+
}
|
|
10002
|
+
try {
|
|
10003
|
+
const watcher = watch(contextPath, { persistent: true }, async (_eventType, _filename) => {
|
|
10004
|
+
console.debug("[Watch] context.json changed, reloading incidents...");
|
|
10005
|
+
await this.reloadIncidents(directory);
|
|
10006
|
+
});
|
|
10007
|
+
watcher.on("error", (err) => {
|
|
10008
|
+
console.error(`[Watch] Context watcher error: ${err.message}`);
|
|
10009
|
+
watcher.close();
|
|
10010
|
+
});
|
|
10011
|
+
this.watchers.set("context.json", watcher);
|
|
10012
|
+
console.debug("[Watch] \u2713 Watching context.json for incident changes");
|
|
10013
|
+
} catch (error) {
|
|
10014
|
+
console.error("[Watch] Failed to set up context.json watcher:", error);
|
|
10015
|
+
}
|
|
10016
|
+
}
|
|
10017
|
+
/**
|
|
10018
|
+
* Reload incidents from context graph
|
|
10019
|
+
*/
|
|
10020
|
+
async reloadIncidents(directory) {
|
|
10021
|
+
try {
|
|
10022
|
+
const graph = new ContextGraph(directory);
|
|
10023
|
+
const allNodes = await graph.listNodes();
|
|
10024
|
+
const unresolvedIncidents = allNodes.filter(
|
|
10025
|
+
(n) => n.type === "incident" && !n.data.resolved
|
|
10026
|
+
);
|
|
10027
|
+
this.state.nudges = this.state.nudges.filter((n) => !n.message.startsWith("INCIDENT:"));
|
|
10028
|
+
for (const incident of unresolvedIncidents) {
|
|
10029
|
+
const incidentData = incident.data;
|
|
10030
|
+
let mappedSeverity = "high";
|
|
10031
|
+
if (incidentData.severity === "critical") {
|
|
10032
|
+
mappedSeverity = "critical";
|
|
10033
|
+
} else if (incidentData.severity === "major") {
|
|
10034
|
+
mappedSeverity = "critical";
|
|
10035
|
+
} else if (incidentData.severity === "minor") {
|
|
10036
|
+
mappedSeverity = "high";
|
|
10037
|
+
}
|
|
10038
|
+
const edges = await graph.getEdges(incident.id);
|
|
10039
|
+
const linkedFiles = edges.filter((e) => e.type === "causedBy" || e.type === "affects").map((e) => {
|
|
10040
|
+
const node = allNodes.find((n) => n.id === e.to_id || n.id === e.from_id);
|
|
10041
|
+
if (node?.type === "file") {
|
|
10042
|
+
return node.data.path;
|
|
10043
|
+
}
|
|
10044
|
+
return null;
|
|
10045
|
+
}).filter((f) => f !== null);
|
|
10046
|
+
const file = linkedFiles[0] || "unknown";
|
|
10047
|
+
const message = `INCIDENT: ${incidentData.description}`;
|
|
10048
|
+
this.state.nudges.push({
|
|
10049
|
+
file,
|
|
10050
|
+
message,
|
|
10051
|
+
severity: mappedSeverity,
|
|
10052
|
+
timestamp: new Date(incidentData.timestamp).toLocaleTimeString("en-US", { hour12: false })
|
|
10053
|
+
});
|
|
10054
|
+
}
|
|
10055
|
+
console.log(`[Watch] \u2713 Reloaded ${unresolvedIncidents.length} unresolved incidents`);
|
|
10056
|
+
} catch (error) {
|
|
10057
|
+
console.error("[Watch] Failed to reload incidents:", error);
|
|
10058
|
+
}
|
|
10059
|
+
}
|
|
10060
|
+
async processPendingFiles() {
|
|
10061
|
+
if (this.state.pendingFiles.size === 0) return;
|
|
10062
|
+
const files = Array.from(this.state.pendingFiles);
|
|
10063
|
+
this.state.pendingFiles.clear();
|
|
10064
|
+
if (!isInteractiveMode()) {
|
|
10065
|
+
console.error(`
|
|
10066
|
+
Detected changes in ${files.length} file(s):`);
|
|
10067
|
+
for (const file of files) {
|
|
10068
|
+
console.error(` - ${basename(file)}`);
|
|
10069
|
+
}
|
|
10070
|
+
console.error("");
|
|
10071
|
+
}
|
|
10072
|
+
try {
|
|
10073
|
+
const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
|
|
10074
|
+
if (this.extractionPipeline) {
|
|
10075
|
+
try {
|
|
10076
|
+
const fileContents = await Promise.all(
|
|
10077
|
+
files.map(async (file) => {
|
|
10078
|
+
try {
|
|
10079
|
+
const content = await readFile5(file, "utf-8");
|
|
10080
|
+
return { file, content };
|
|
10081
|
+
} catch {
|
|
10082
|
+
return null;
|
|
10083
|
+
}
|
|
10084
|
+
})
|
|
10085
|
+
);
|
|
10086
|
+
const validFiles = fileContents.filter((f) => f !== null);
|
|
10087
|
+
if (validFiles.length > 0) {
|
|
10088
|
+
const combinedContent = validFiles.map(
|
|
10089
|
+
(f) => `File: ${basename(f.file)}
|
|
10090
|
+
${f.content.slice(0, 1e3)}`
|
|
10091
|
+
// First 1KB of each file
|
|
10092
|
+
).join("\n\n---\n\n");
|
|
10093
|
+
if (!isInteractiveMode()) {
|
|
10094
|
+
console.error("[*] Extracting signals from changes...");
|
|
10095
|
+
}
|
|
10096
|
+
const signal = await this.extractionPipeline.process(combinedContent, {
|
|
10097
|
+
sourceType: "file",
|
|
10098
|
+
sourceId: `watch-${Date.now()}`
|
|
10099
|
+
});
|
|
10100
|
+
if (signal.governance.length > 0 || signal.facts.length > 0 || signal.blockers.length > 0) {
|
|
10101
|
+
const govCount = signal.governance.length;
|
|
10102
|
+
if (!isInteractiveMode()) {
|
|
10103
|
+
console.error(` [+] Extracted: ${govCount} governance, ${signal.facts.length} facts, ${signal.blockers.length} blockers`);
|
|
10104
|
+
}
|
|
10105
|
+
if (this.streamingManager) {
|
|
10106
|
+
this.streamingManager.reportSignalExtraction({
|
|
10107
|
+
governance: govCount,
|
|
10108
|
+
facts: signal.facts.length,
|
|
10109
|
+
blockers: signal.blockers.length,
|
|
10110
|
+
questions: signal.questions.length
|
|
10111
|
+
});
|
|
10112
|
+
}
|
|
10113
|
+
}
|
|
10114
|
+
}
|
|
10115
|
+
} catch (error) {
|
|
10116
|
+
if (!isInteractiveMode()) {
|
|
10117
|
+
console.error(` [!] Signal extraction failed: ${error}`);
|
|
10118
|
+
}
|
|
10119
|
+
}
|
|
10120
|
+
} else {
|
|
10121
|
+
if (files.length > 0 && !isInteractiveMode()) {
|
|
10122
|
+
console.debug("[Watch] Signal extraction skipped: ANTHROPIC_API_KEY not set");
|
|
10123
|
+
}
|
|
10124
|
+
}
|
|
10125
|
+
void this.autoScanFiles(files).catch((err) => {
|
|
10126
|
+
getOutputManager().log("warn", `Auto scan failed: ${err}`);
|
|
10127
|
+
});
|
|
10128
|
+
await this.discoverPatternsFromIssues(projectPath);
|
|
10129
|
+
const now = Date.now();
|
|
10130
|
+
if (now - this.lastHypothesisCheck > _TrieWatchTool.HYPOTHESIS_CHECK_INTERVAL_MS) {
|
|
10131
|
+
this.checkAndGenerateHypotheses(projectPath);
|
|
10132
|
+
this.lastHypothesisCheck = now;
|
|
10133
|
+
}
|
|
10134
|
+
if (this.streamingManager) {
|
|
10135
|
+
const now2 = Date.now();
|
|
10136
|
+
for (const file of files) {
|
|
10137
|
+
const lastReport = this.state.lastScan.get(file) || 0;
|
|
10138
|
+
if (now2 - lastReport > 2e3) {
|
|
10139
|
+
this.streamingManager.reportWatchChange(file);
|
|
10140
|
+
}
|
|
10141
|
+
}
|
|
10142
|
+
}
|
|
10143
|
+
this.state.filesScanned += files.length;
|
|
10144
|
+
for (const file of files) {
|
|
10145
|
+
this.state.lastScan.set(file, Date.now());
|
|
10146
|
+
if (this.codebaseIndex) {
|
|
10147
|
+
const relativePath = file.replace(projectPath + "/", "");
|
|
10148
|
+
void this.codebaseIndex.indexFile(relativePath).then(() => {
|
|
10149
|
+
void this.codebaseIndex?.save();
|
|
10150
|
+
});
|
|
10151
|
+
}
|
|
10152
|
+
}
|
|
10153
|
+
} catch (error) {
|
|
10154
|
+
if (!isInteractiveMode()) {
|
|
10155
|
+
console.error(`Scan error: ${error}`);
|
|
10156
|
+
}
|
|
10157
|
+
}
|
|
10158
|
+
}
|
|
10159
|
+
isQuiet() {
|
|
10160
|
+
const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
|
|
10161
|
+
const quietPath = join4(getTrieDirectory(projectPath), "quiet.json");
|
|
10162
|
+
try {
|
|
10163
|
+
const raw = readFileSync2(quietPath, "utf-8");
|
|
10164
|
+
const data = JSON.parse(raw);
|
|
10165
|
+
const until = new Date(data.until).getTime();
|
|
10166
|
+
return Date.now() < until;
|
|
10167
|
+
} catch {
|
|
10168
|
+
return false;
|
|
10169
|
+
}
|
|
10170
|
+
}
|
|
10171
|
+
/**
|
|
10172
|
+
* Check and generate hypotheses autonomously
|
|
10173
|
+
* Claude observes patterns and creates new hypotheses to test
|
|
10174
|
+
*/
|
|
10175
|
+
async checkAndGenerateHypotheses(projectPath) {
|
|
10176
|
+
if (!isAIAvailable()) return;
|
|
10177
|
+
try {
|
|
10178
|
+
const { getHypothesisEngine } = await import("./hypothesis-JURDWVDC.js");
|
|
10179
|
+
const { getOutputManager: getOutputManager2 } = await import("./output-manager-FX4V7ERT.js");
|
|
10180
|
+
const hypothesisEngine = getHypothesisEngine(projectPath);
|
|
10181
|
+
const recentIssues = Array.from(this.state.issueCache.values()).flat();
|
|
10182
|
+
const patterns = [];
|
|
10183
|
+
const observations = [];
|
|
10184
|
+
if (this.state.nudges.length > 0) {
|
|
10185
|
+
const nudgesByFile = {};
|
|
10186
|
+
for (const nudge of this.state.nudges) {
|
|
10187
|
+
nudgesByFile[nudge.file] = (nudgesByFile[nudge.file] || 0) + 1;
|
|
10188
|
+
}
|
|
10189
|
+
const topFiles = Object.entries(nudgesByFile).sort(([, a], [, b]) => b - a).slice(0, 3);
|
|
10190
|
+
if (topFiles[0] && topFiles[0][1] > 2) {
|
|
10191
|
+
observations.push(`File ${topFiles[0][0]} has ${topFiles[0][1]} repeated issues this session`);
|
|
10192
|
+
}
|
|
10193
|
+
}
|
|
10194
|
+
if (this.state.nudges.length > 5) {
|
|
10195
|
+
observations.push(`High issue detection rate: ${this.state.nudges.length} violations detected in watch session`);
|
|
10196
|
+
}
|
|
10197
|
+
let generated = await hypothesisEngine.generateHypothesesWithAI({
|
|
10198
|
+
recentIssues,
|
|
10199
|
+
patterns,
|
|
10200
|
+
observations
|
|
10201
|
+
});
|
|
10202
|
+
if (generated.length === 0) {
|
|
10203
|
+
generated = await hypothesisEngine.autoGenerateHypotheses();
|
|
10204
|
+
}
|
|
10205
|
+
for (const hypothesis of generated) {
|
|
10206
|
+
const message = `[New Hypothesis] "${hypothesis.statement}" (${Math.round(hypothesis.confidence * 100)}% confidence)`;
|
|
10207
|
+
getOutputManager2().nudge(
|
|
10208
|
+
message,
|
|
10209
|
+
"info",
|
|
10210
|
+
void 0,
|
|
10211
|
+
1e4
|
|
10212
|
+
);
|
|
10213
|
+
if (!isInteractiveMode()) {
|
|
10214
|
+
console.error(`
|
|
10215
|
+
[?] ${message}`);
|
|
10216
|
+
console.error(` Test: ${hypothesis.testCriteria || "Collecting evidence..."}`);
|
|
10217
|
+
}
|
|
10218
|
+
if (this.streamingManager) {
|
|
10219
|
+
this.streamingManager.reportSignalExtraction({
|
|
10220
|
+
governance: 0,
|
|
10221
|
+
facts: 0,
|
|
10222
|
+
blockers: 0,
|
|
10223
|
+
questions: 1
|
|
10224
|
+
// Hypotheses are questions to answer
|
|
10225
|
+
});
|
|
10226
|
+
}
|
|
10227
|
+
}
|
|
10228
|
+
if (recentIssues.length > 10) {
|
|
10229
|
+
await hypothesisEngine.updateConfidenceFromOutcomes();
|
|
10230
|
+
}
|
|
10231
|
+
} catch (error) {
|
|
10232
|
+
if (!isInteractiveMode()) {
|
|
10233
|
+
console.error(` [!] Hypothesis check failed: ${error}`);
|
|
10234
|
+
}
|
|
10235
|
+
}
|
|
10236
|
+
}
|
|
10237
|
+
/**
|
|
10238
|
+
* Discover patterns from accumulated issues
|
|
10239
|
+
* Patterns emerge naturally from your coding workflow
|
|
10240
|
+
*/
|
|
10241
|
+
async discoverPatternsFromIssues(projectPath) {
|
|
10242
|
+
const totalIssues = Array.from(this.state.issueCache.values()).flat().length;
|
|
10243
|
+
if (totalIssues < 5) return;
|
|
10244
|
+
try {
|
|
10245
|
+
const { ContextGraph: ContextGraph2 } = await import("./graph-JO7GG65P.js");
|
|
10246
|
+
const { IncidentIndex: IncidentIndex2 } = await import("./incident-index-7CAXUNTL.js");
|
|
10247
|
+
const { TriePatternDiscovery } = await import("./pattern-discovery-F7LU5K6E.js");
|
|
10248
|
+
const graph = new ContextGraph2(projectPath);
|
|
10249
|
+
const incidentIndex = await IncidentIndex2.build(graph, projectPath);
|
|
10250
|
+
const discovery = new TriePatternDiscovery(graph, incidentIndex);
|
|
10251
|
+
const hotPatterns = discovery.discoverHotPatterns(2);
|
|
10252
|
+
for (const hot of hotPatterns) {
|
|
10253
|
+
const existingPatterns = await graph.listNodes();
|
|
10254
|
+
const alreadyExists = existingPatterns.some(
|
|
10255
|
+
(n) => n.type === "pattern" && n.data.description?.includes(hot.path)
|
|
10256
|
+
);
|
|
10257
|
+
if (!alreadyExists) {
|
|
10258
|
+
await graph.addNode("pattern", {
|
|
10259
|
+
description: `${hot.type === "directory" ? "Directory" : "File"} hot zone: ${hot.path}`,
|
|
10260
|
+
appliesTo: [hot.path],
|
|
10261
|
+
confidence: Math.min(0.95, hot.confidence),
|
|
10262
|
+
occurrences: hot.incidentCount,
|
|
10263
|
+
firstSeen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10264
|
+
lastSeen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10265
|
+
isAntiPattern: hot.incidentCount >= 3,
|
|
10266
|
+
// 3+ incidents = anti-pattern
|
|
10267
|
+
source: "local"
|
|
10268
|
+
});
|
|
10269
|
+
if (!isInteractiveMode()) {
|
|
10270
|
+
console.error(` [+] Pattern discovered: ${hot.path} (${hot.incidentCount} issues)`);
|
|
10271
|
+
}
|
|
10272
|
+
if (this.streamingManager) {
|
|
10273
|
+
this.streamingManager.reportSignalExtraction({
|
|
10274
|
+
governance: 0,
|
|
10275
|
+
facts: 1,
|
|
10276
|
+
// Patterns are facts about the codebase
|
|
10277
|
+
blockers: 0,
|
|
10278
|
+
questions: 0
|
|
10279
|
+
});
|
|
10280
|
+
}
|
|
10281
|
+
}
|
|
10282
|
+
}
|
|
10283
|
+
if (totalIssues >= 10) {
|
|
10284
|
+
const coOccurrences = await discovery.discoverCoOccurrences(2);
|
|
10285
|
+
for (const coOcc of coOccurrences.slice(0, 3)) {
|
|
10286
|
+
const desc = `Files break together: ${coOcc.files[0]} + ${coOcc.files[1]}`;
|
|
10287
|
+
const existingPatterns = await graph.listNodes();
|
|
10288
|
+
const alreadyExists = existingPatterns.some(
|
|
10289
|
+
(n) => n.type === "pattern" && n.data.description === desc
|
|
10290
|
+
);
|
|
10291
|
+
if (!alreadyExists) {
|
|
10292
|
+
await graph.addNode("pattern", {
|
|
10293
|
+
description: desc,
|
|
10294
|
+
appliesTo: [...coOcc.files],
|
|
10295
|
+
confidence: Math.min(0.95, coOcc.confidence),
|
|
10296
|
+
occurrences: coOcc.coOccurrences,
|
|
10297
|
+
firstSeen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10298
|
+
lastSeen: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10299
|
+
isAntiPattern: coOcc.confidence > 0.7,
|
|
10300
|
+
source: "local"
|
|
10301
|
+
});
|
|
10302
|
+
if (!isInteractiveMode()) {
|
|
10303
|
+
console.error(` [+] Co-occurrence pattern: ${coOcc.files[0]} + ${coOcc.files[1]}`);
|
|
10304
|
+
}
|
|
10305
|
+
}
|
|
10306
|
+
}
|
|
10307
|
+
}
|
|
10308
|
+
} catch (error) {
|
|
10309
|
+
if (!isInteractiveMode()) {
|
|
10310
|
+
console.error(` [!] Pattern discovery failed: ${error}`);
|
|
10311
|
+
}
|
|
10312
|
+
}
|
|
10313
|
+
}
|
|
10314
|
+
// Defaults -- overridden by config when loaded
|
|
10315
|
+
aiWatcherCooldownMs = 3e4;
|
|
10316
|
+
cleanFileCooldownMs = 3e5;
|
|
10317
|
+
maxFilesPerScan = 5;
|
|
10318
|
+
maxCharsPerFile = 4e3;
|
|
10319
|
+
/**
|
|
10320
|
+
* Use the trie (context graph) to score how urgently a file needs scanning.
|
|
10321
|
+
* Higher score = more worth spending tokens on.
|
|
10322
|
+
*/
|
|
10323
|
+
async scoreScanPriority(file, graph, projectPath) {
|
|
10324
|
+
let score = 1;
|
|
10325
|
+
const lastClean = this.state.cleanFiles.get(file);
|
|
10326
|
+
if (lastClean && Date.now() - lastClean < this.cleanFileCooldownMs) {
|
|
10327
|
+
return 0;
|
|
10328
|
+
}
|
|
10329
|
+
const fileNode = await graph.getNode("file", join4(projectPath, file));
|
|
10330
|
+
if (!fileNode) return score;
|
|
10331
|
+
const data = fileNode.data;
|
|
10332
|
+
const riskScores = { critical: 10, high: 6, medium: 2, low: 1 };
|
|
10333
|
+
score += riskScores[data.riskLevel] ?? 1;
|
|
10334
|
+
score += Math.min(data.incidentCount * 3, 12);
|
|
10335
|
+
if (data.changeCount > 10) score += 2;
|
|
10336
|
+
return score;
|
|
10337
|
+
}
|
|
10338
|
+
/**
|
|
10339
|
+
* Roll the token budget window if an hour has passed.
|
|
10340
|
+
* Returns remaining tokens in the current window.
|
|
10341
|
+
*/
|
|
10342
|
+
getRemainingBudget() {
|
|
10343
|
+
const budget = this.state.tokenBudget;
|
|
10344
|
+
const elapsed = Date.now() - budget.windowStart;
|
|
10345
|
+
if (elapsed > 36e5) {
|
|
10346
|
+
budget.used = 0;
|
|
10347
|
+
budget.windowStart = Date.now();
|
|
10348
|
+
}
|
|
10349
|
+
return Math.max(0, budget.hourlyLimit - budget.used);
|
|
10350
|
+
}
|
|
10351
|
+
recordTokenUsage(tokens) {
|
|
10352
|
+
this.state.tokenBudget.used += tokens;
|
|
10353
|
+
}
|
|
10354
|
+
/**
|
|
10355
|
+
* AI-powered watcher -- the primary detection system.
|
|
10356
|
+
*
|
|
10357
|
+
* This is the single AI call that handles:
|
|
10358
|
+
* 1. Code review (bugs, security, logic errors)
|
|
10359
|
+
* 2. Goal violation detection (user-defined quality goals)
|
|
10360
|
+
*
|
|
10361
|
+
* When goals are active, files with goal violations bypass priority scoring
|
|
10362
|
+
* so violations are always caught. Throttled by cooldown + token budget.
|
|
10363
|
+
*/
|
|
10364
|
+
async autoScanFiles(files) {
|
|
10365
|
+
if (!isAIAvailable()) return;
|
|
10366
|
+
if (this.state.autoScanInProgress) return;
|
|
10367
|
+
const now = Date.now();
|
|
10368
|
+
if (now - this.state.lastAutoScan < this.aiWatcherCooldownMs) return;
|
|
10369
|
+
this.state.autoScanInProgress = true;
|
|
10370
|
+
this.state.lastAutoScan = now;
|
|
10371
|
+
const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
|
|
10372
|
+
try {
|
|
10373
|
+
try {
|
|
10374
|
+
const config = await getAutonomyConfig(projectPath);
|
|
10375
|
+
const wc = config.aiWatcher;
|
|
10376
|
+
if (!wc.enabled) return;
|
|
10377
|
+
this.state.tokenBudget.hourlyLimit = wc.hourlyTokenLimit;
|
|
10378
|
+
this.aiWatcherCooldownMs = wc.scanCooldownSec * 1e3;
|
|
10379
|
+
this.cleanFileCooldownMs = wc.cleanFileCooldownSec * 1e3;
|
|
10380
|
+
this.maxFilesPerScan = wc.maxFilesPerScan;
|
|
10381
|
+
this.maxCharsPerFile = wc.maxCharsPerFile;
|
|
10382
|
+
} catch {
|
|
10383
|
+
}
|
|
10384
|
+
const remaining = this.getRemainingBudget();
|
|
10385
|
+
if (remaining < 500) return;
|
|
10386
|
+
try {
|
|
10387
|
+
const graph = new ContextGraph(projectPath);
|
|
10388
|
+
const { getActiveGoals, recordGoalViolationCaught } = await import("./goal-validator-FU5QWDQT.js");
|
|
10389
|
+
console.debug("[AI Watcher] Loading active goals...");
|
|
10390
|
+
const activeGoals = await getActiveGoals(projectPath);
|
|
10391
|
+
const hasGoals = activeGoals.length > 0;
|
|
10392
|
+
console.debug("[AI Watcher] Goals loaded:", {
|
|
10393
|
+
totalGoals: activeGoals.length,
|
|
10394
|
+
hasGoals,
|
|
10395
|
+
goals: activeGoals.map((g) => ({ id: g.id, description: g.description, status: g.status }))
|
|
10396
|
+
});
|
|
10397
|
+
if (this.isQuiet() && !hasGoals) return;
|
|
10398
|
+
const scored = [];
|
|
10399
|
+
for (const file of files) {
|
|
10400
|
+
const relativePath = file.replace(projectPath + "/", "");
|
|
10401
|
+
const score = await this.scoreScanPriority(relativePath, graph, projectPath);
|
|
10402
|
+
if (hasGoals || score > 0) {
|
|
10403
|
+
scored.push({ file, relativePath, score: Math.max(score, hasGoals ? 1 : 0) });
|
|
10404
|
+
} else {
|
|
10405
|
+
this.state.tokenBudget.scansSaved++;
|
|
10406
|
+
}
|
|
10407
|
+
}
|
|
10408
|
+
if (scored.length === 0) return;
|
|
10409
|
+
scored.sort((a, b) => b.score - a.score);
|
|
10410
|
+
const budgetScale = remaining > 2e4 ? 1 : remaining > 1e4 ? 0.6 : 0.4;
|
|
10411
|
+
const maxFiles = Math.max(1, Math.round(this.maxFilesPerScan * budgetScale));
|
|
10412
|
+
const filesToScan = scored.slice(0, maxFiles);
|
|
10413
|
+
const charLimit = Math.round(this.maxCharsPerFile * (remaining > 15e3 ? 1 : 0.5));
|
|
10414
|
+
const fileContents = await Promise.all(
|
|
10415
|
+
filesToScan.map(async ({ file, relativePath }) => {
|
|
10416
|
+
try {
|
|
10417
|
+
const content = await readFile5(file, "utf-8");
|
|
10418
|
+
return { path: relativePath, content: content.slice(0, charLimit) };
|
|
10419
|
+
} catch {
|
|
10420
|
+
return null;
|
|
10421
|
+
}
|
|
10422
|
+
})
|
|
10423
|
+
);
|
|
10424
|
+
const valid = fileContents.filter(Boolean);
|
|
10425
|
+
if (valid.length === 0) return;
|
|
10426
|
+
const filesBlock = valid.map(
|
|
10427
|
+
(f) => `### ${f.path}
|
|
10428
|
+
\`\`\`
|
|
10429
|
+
${f.content}
|
|
10430
|
+
\`\`\``
|
|
10431
|
+
).join("\n\n");
|
|
10432
|
+
let goalsSection = "";
|
|
10433
|
+
if (hasGoals) {
|
|
10434
|
+
goalsSection = `
|
|
10435
|
+
USER-DEFINED GOALS (IMPORTANT - check EVERY file against ALL goals):
|
|
10436
|
+
${activeGoals.map((g, i) => ` ${i + 1}. "${g.description}"`).join("\n")}
|
|
10437
|
+
|
|
10438
|
+
Goal violations are HIGH PRIORITY. If a file violates any goal, you MUST report it.
|
|
10439
|
+
`;
|
|
10440
|
+
}
|
|
10441
|
+
console.debug("[AI Watcher] Sending files to AI analysis:", {
|
|
10442
|
+
fileCount: valid.length,
|
|
10443
|
+
hasGoals,
|
|
10444
|
+
goalsIncluded: hasGoals,
|
|
10445
|
+
filePaths: valid.map((f) => f.path),
|
|
10446
|
+
goalsSection: goalsSection.slice(0, 200) + (goalsSection.length > 200 ? "..." : "")
|
|
10447
|
+
});
|
|
10448
|
+
const result = await runAIAnalysis({
|
|
10449
|
+
systemPrompt: `You are a code quality watcher. You review code for two things:
|
|
10450
|
+
|
|
10451
|
+
1. CODE ISSUES: bugs, security vulnerabilities, logic errors, risky patterns
|
|
10452
|
+
2. GOAL VIOLATIONS: check every file against the user's quality goals
|
|
10453
|
+
${goalsSection}
|
|
10454
|
+
Reply ONLY with a JSON array. Each element must have:
|
|
10455
|
+
- "file": relative file path
|
|
10456
|
+
- "severity": "critical" | "major" | "minor"
|
|
10457
|
+
- "description": 1-sentence description of what you found
|
|
10458
|
+
- "confidence": number 0-100, how confident you are this is a real issue
|
|
10459
|
+
- "suggestedFix": 1-sentence description of what should change to fix it
|
|
10460
|
+
- "isGoalViolation": true if this violates a user goal, false otherwise
|
|
10461
|
+
- "goalIndex": 0-based index of the violated goal (only if isGoalViolation is true)
|
|
10462
|
+
|
|
10463
|
+
Be thorough with goal checking. If a goal says "no emojis" and you see an emoji anywhere in the file, report it with the exact location. If a goal says "no inline styles" and you see a style attribute, report it.
|
|
10464
|
+
|
|
10465
|
+
If no issues or violations found, reply with: []
|
|
10466
|
+
Output ONLY the JSON array, no markdown fences, no commentary.`,
|
|
10467
|
+
userPrompt: `Review these changed files:
|
|
10468
|
+
|
|
10469
|
+
${filesBlock}`,
|
|
10470
|
+
maxTokens: 2048,
|
|
10471
|
+
temperature: 0.1
|
|
10472
|
+
});
|
|
10473
|
+
if (result.tokensUsed) {
|
|
10474
|
+
this.recordTokenUsage(result.tokensUsed.input + result.tokensUsed.output);
|
|
10475
|
+
}
|
|
10476
|
+
console.debug("[AI Watcher] AI analysis result:", {
|
|
10477
|
+
success: result.success,
|
|
10478
|
+
contentLength: result.content ? result.content.length : 0,
|
|
10479
|
+
tokensUsed: result.tokensUsed,
|
|
10480
|
+
contentPreview: result.content ? result.content.slice(0, 500) : "null"
|
|
10481
|
+
});
|
|
10482
|
+
if (!result.success || !result.content.trim()) {
|
|
10483
|
+
console.debug("[AI Watcher] AI analysis failed or returned empty content");
|
|
10484
|
+
return;
|
|
10485
|
+
}
|
|
10486
|
+
let issues = [];
|
|
10487
|
+
try {
|
|
10488
|
+
const cleaned = result.content.replace(/```json?\n?|\n?```/g, "").trim();
|
|
10489
|
+
console.debug("[AI Watcher] Parsing AI response:", { cleanedContent: cleaned.slice(0, 300) });
|
|
10490
|
+
issues = JSON.parse(cleaned);
|
|
10491
|
+
if (!Array.isArray(issues)) issues = [];
|
|
10492
|
+
console.debug("[AI Watcher] Parsed issues:", {
|
|
10493
|
+
totalIssues: issues.length,
|
|
10494
|
+
goalViolations: issues.filter((i) => i.isGoalViolation).length,
|
|
10495
|
+
issueTypes: issues.map((i) => ({ file: i.file, isGoalViolation: i.isGoalViolation, goalIndex: i.goalIndex }))
|
|
10496
|
+
});
|
|
10497
|
+
} catch (error) {
|
|
10498
|
+
console.debug("[AI Watcher] Failed to parse AI response:", error);
|
|
10499
|
+
return;
|
|
10500
|
+
}
|
|
10501
|
+
const issuedFiles = new Set(issues.map((i) => i.file));
|
|
10502
|
+
for (const { relativePath } of filesToScan) {
|
|
10503
|
+
if (!issuedFiles.has(relativePath)) {
|
|
10504
|
+
this.state.cleanFiles.set(relativePath, Date.now());
|
|
10505
|
+
}
|
|
10506
|
+
}
|
|
10507
|
+
if (issues.length === 0) return;
|
|
10508
|
+
for (const issue of issues.slice(0, 10)) {
|
|
10509
|
+
const severity = issue.severity === "critical" ? "critical" : issue.severity === "major" ? "major" : "minor";
|
|
10510
|
+
if (issue.isGoalViolation && issue.goalIndex != null && issue.goalIndex >= 0 && issue.goalIndex < activeGoals.length) {
|
|
10511
|
+
const goal = activeGoals[issue.goalIndex];
|
|
10512
|
+
if (!goal) continue;
|
|
10513
|
+
const confidence = Math.min(100, Math.max(0, issue.confidence ?? 80));
|
|
10514
|
+
const fixId = `fix-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
10515
|
+
console.debug("[AI Watcher] Goal violation detected:", {
|
|
10516
|
+
goalDescription: goal.description,
|
|
10517
|
+
file: issue.file,
|
|
10518
|
+
violation: issue.description,
|
|
10519
|
+
confidence,
|
|
10520
|
+
goalIndex: issue.goalIndex,
|
|
10521
|
+
totalActiveGoals: activeGoals.length
|
|
10522
|
+
});
|
|
10523
|
+
const goalViolationIssue = {
|
|
10524
|
+
id: fixId,
|
|
10525
|
+
file: issue.file,
|
|
10526
|
+
agent: "goal-violation",
|
|
10527
|
+
severity: severity === "critical" ? "critical" : severity === "major" ? "serious" : "moderate",
|
|
10528
|
+
issue: `Goal "${goal.description}" violated: ${issue.description}`,
|
|
10529
|
+
fix: issue.suggestedFix || "Review and fix",
|
|
10530
|
+
category: "goal-violation",
|
|
10531
|
+
confidence,
|
|
10532
|
+
autoFixable: true
|
|
10533
|
+
};
|
|
10534
|
+
await storeIssues([goalViolationIssue], basename(projectPath), projectPath);
|
|
10535
|
+
await recordGoalViolationCaught(goal, issue.file, projectPath);
|
|
10536
|
+
if (this.streamingManager) {
|
|
10537
|
+
this.streamingManager.reportLedgerUpdate(1, "goal-violation");
|
|
10538
|
+
}
|
|
10539
|
+
const confidenceStr = `${confidence}%`;
|
|
10540
|
+
const nudgeMsg = `Goal "${goal.description}" violated in ${issue.file}: ${issue.description} [${confidenceStr} confidence]`;
|
|
10541
|
+
console.debug("[AI Watcher] Sending nudge:", {
|
|
10542
|
+
message: nudgeMsg,
|
|
10543
|
+
file: issue.file,
|
|
10544
|
+
severity: "warning"
|
|
10545
|
+
});
|
|
10546
|
+
getOutputManager().nudge(nudgeMsg, "warning", issue.file);
|
|
10547
|
+
await this.persistNudge({
|
|
10548
|
+
message: nudgeMsg,
|
|
10549
|
+
severity: "warning",
|
|
10550
|
+
file: issue.file,
|
|
10551
|
+
category: "quality",
|
|
10552
|
+
goalId: goal.id,
|
|
10553
|
+
priority: 7,
|
|
10554
|
+
suggestedAction: issue.suggestedFix || "Review and fix manually",
|
|
10555
|
+
relatedIssues: [fixId]
|
|
10556
|
+
});
|
|
10557
|
+
if (this.streamingManager) {
|
|
10558
|
+
this.streamingManager.reportPendingFix({
|
|
10559
|
+
id: fixId,
|
|
10560
|
+
file: issue.file,
|
|
10561
|
+
description: issue.description,
|
|
10562
|
+
goalDescription: goal.description,
|
|
10563
|
+
confidence,
|
|
10564
|
+
severity: issue.severity,
|
|
10565
|
+
suggestedFix: issue.suggestedFix || "Remove the violating code"
|
|
10566
|
+
});
|
|
10567
|
+
}
|
|
10568
|
+
if (!isInteractiveMode()) {
|
|
10569
|
+
console.error(` [!] Goal violation (${confidenceStr}): ${issue.description}`);
|
|
10570
|
+
console.error(` Fix: ${issue.suggestedFix || "Review and fix manually"}`);
|
|
10571
|
+
}
|
|
10572
|
+
continue;
|
|
10573
|
+
}
|
|
10574
|
+
const incident = await graph.addNode("incident", {
|
|
10575
|
+
description: issue.description,
|
|
10576
|
+
severity,
|
|
10577
|
+
affectedUsers: null,
|
|
10578
|
+
duration: null,
|
|
10579
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
10580
|
+
resolved: false,
|
|
10581
|
+
resolution: null,
|
|
10582
|
+
fixChangeId: null,
|
|
10583
|
+
reportedVia: "detected"
|
|
10584
|
+
});
|
|
10585
|
+
const filePath = join4(projectPath, issue.file);
|
|
10586
|
+
const fileNode = await graph.getNode("file", filePath);
|
|
10587
|
+
if (fileNode) {
|
|
10588
|
+
await graph.addEdge(fileNode.id, incident.id, "affects");
|
|
10589
|
+
const data = fileNode.data;
|
|
10590
|
+
const newRisk = severity === "critical" ? "critical" : severity === "major" ? "high" : data.riskLevel === "low" ? "medium" : data.riskLevel;
|
|
10591
|
+
await graph.updateNode("file", fileNode.id, {
|
|
10592
|
+
incidentCount: (data.incidentCount ?? 0) + 1,
|
|
10593
|
+
riskLevel: newRisk
|
|
10594
|
+
});
|
|
10595
|
+
}
|
|
10596
|
+
this.state.totalIssuesFound++;
|
|
10597
|
+
if (severity !== "minor") {
|
|
10598
|
+
getOutputManager().nudge(
|
|
10599
|
+
`${issue.description}`,
|
|
10600
|
+
severity === "critical" ? "critical" : "warning",
|
|
10601
|
+
issue.file,
|
|
10602
|
+
severity === "critical" ? void 0 : 15e3
|
|
10603
|
+
);
|
|
10604
|
+
await this.persistNudge({
|
|
10605
|
+
message: issue.description,
|
|
10606
|
+
severity: severity === "critical" ? "critical" : "warning",
|
|
10607
|
+
file: issue.file,
|
|
10608
|
+
category: "quality",
|
|
10609
|
+
priority: severity === "critical" ? 9 : 6,
|
|
10610
|
+
...issue.suggestedFix && { suggestedAction: issue.suggestedFix }
|
|
10611
|
+
});
|
|
10612
|
+
}
|
|
10613
|
+
}
|
|
10614
|
+
if (this.streamingManager && issues.length > 0) {
|
|
10615
|
+
this.streamingManager.reportSignalExtraction({
|
|
10616
|
+
governance: 0,
|
|
10617
|
+
facts: 0,
|
|
10618
|
+
blockers: issues.length,
|
|
10619
|
+
questions: 0
|
|
10620
|
+
});
|
|
10621
|
+
}
|
|
10622
|
+
} catch (error) {
|
|
10623
|
+
getOutputManager().log("warn", `AI watcher error: ${error}`);
|
|
10624
|
+
}
|
|
10625
|
+
} finally {
|
|
10626
|
+
this.state.autoScanInProgress = false;
|
|
10627
|
+
}
|
|
10628
|
+
}
|
|
10629
|
+
/**
|
|
10630
|
+
* Initial hypothesis generation when watch starts.
|
|
10631
|
+
*
|
|
10632
|
+
* This generates hypotheses from existing patterns and issues to give
|
|
10633
|
+
* users immediate insights about their codebase.
|
|
10634
|
+
*/
|
|
10635
|
+
async initialHypothesisGeneration() {
|
|
10636
|
+
if (!isAIAvailable()) {
|
|
10637
|
+
console.debug("[Initial Hypothesis] AI not available, skipping initial hypothesis generation");
|
|
10638
|
+
return;
|
|
10639
|
+
}
|
|
10640
|
+
const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
|
|
10641
|
+
console.debug("[Initial Hypothesis] Starting initial hypothesis generation", { projectPath });
|
|
10642
|
+
try {
|
|
10643
|
+
const { getHypothesisEngine } = await import("./hypothesis-JURDWVDC.js");
|
|
10644
|
+
const hypothesisEngine = getHypothesisEngine(projectPath);
|
|
10645
|
+
console.debug("[Initial Hypothesis] Running AI-powered hypothesis generation...");
|
|
10646
|
+
const generated = await hypothesisEngine.generateHypothesesWithAI({
|
|
10647
|
+
recentIssues: [],
|
|
10648
|
+
// No recent issues yet on startup
|
|
10649
|
+
patterns: [],
|
|
10650
|
+
observations: ["Initial watch session started", "Analyzing codebase for potential patterns"]
|
|
10651
|
+
});
|
|
10652
|
+
console.debug("[Initial Hypothesis] Generated hypotheses on startup:", {
|
|
10653
|
+
count: generated.length,
|
|
10654
|
+
hypotheses: generated.map((h) => ({ statement: h.statement, confidence: h.confidence }))
|
|
10655
|
+
});
|
|
10656
|
+
if (generated.length > 0) {
|
|
10657
|
+
const { getOutputManager: getOutputManager2 } = await import("./output-manager-FX4V7ERT.js");
|
|
10658
|
+
const outputManager = getOutputManager2();
|
|
10659
|
+
for (const hypothesis of generated.slice(0, 2)) {
|
|
10660
|
+
const message = `[Initial Hypothesis] "${hypothesis.statement}" (${Math.round(hypothesis.confidence * 100)}% confidence)`;
|
|
10661
|
+
outputManager.nudge(message, "info", void 0, 1e4);
|
|
10662
|
+
if (!isInteractiveMode()) {
|
|
10663
|
+
console.error(` [?] ${message}`);
|
|
10664
|
+
}
|
|
10665
|
+
}
|
|
10666
|
+
if (this.streamingManager) {
|
|
10667
|
+
this.streamingManager.reportSignalExtraction({
|
|
10668
|
+
governance: 0,
|
|
10669
|
+
facts: 0,
|
|
10670
|
+
blockers: 0,
|
|
10671
|
+
questions: generated.length
|
|
10672
|
+
});
|
|
10673
|
+
}
|
|
10674
|
+
}
|
|
10675
|
+
} catch (error) {
|
|
10676
|
+
console.debug("[Initial Hypothesis] Failed to generate initial hypotheses:", error);
|
|
10677
|
+
}
|
|
10678
|
+
}
|
|
10679
|
+
/**
|
|
10680
|
+
* Initial goal compliance scan when watch starts.
|
|
10681
|
+
*
|
|
10682
|
+
* This checks recently modified files against active goals so the user
|
|
10683
|
+
* gets immediate feedback about goal violations without waiting for files
|
|
10684
|
+
* to be changed.
|
|
10685
|
+
*
|
|
10686
|
+
* Strategy:
|
|
10687
|
+
* 1. Check if there are any active goals - if not, skip
|
|
10688
|
+
* 2. Find recently modified files (last 24 hours OR uncommitted changes)
|
|
10689
|
+
* 3. Filter to watched file types
|
|
10690
|
+
* 4. Run a quick AI scan focused only on goal violations
|
|
10691
|
+
* 5. Nudge the user about any violations found
|
|
10692
|
+
*/
|
|
10693
|
+
async initialGoalComplianceScan() {
|
|
10694
|
+
if (!isAIAvailable()) {
|
|
10695
|
+
console.debug("[Initial Scan] AI not available, skipping initial goal compliance scan");
|
|
10696
|
+
return;
|
|
10697
|
+
}
|
|
10698
|
+
const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
|
|
10699
|
+
console.debug("[Initial Scan] Starting initial goal compliance scan", { projectPath });
|
|
10700
|
+
try {
|
|
10701
|
+
const { getActiveGoals, recordGoalViolationCaught } = await import("./goal-validator-FU5QWDQT.js");
|
|
10702
|
+
const activeGoals = await getActiveGoals(projectPath);
|
|
10703
|
+
console.debug("[Initial Scan] Loaded goals for initial scan:", {
|
|
10704
|
+
goalCount: activeGoals.length,
|
|
10705
|
+
goals: activeGoals.map((g) => ({ id: g.id, description: g.description }))
|
|
10706
|
+
});
|
|
10707
|
+
if (activeGoals.length === 0) {
|
|
10708
|
+
console.debug("[Initial Scan] No active goals found, skipping initial scan");
|
|
10709
|
+
return;
|
|
10710
|
+
}
|
|
10711
|
+
if (!isInteractiveMode()) {
|
|
10712
|
+
console.error("[*] Checking recent files against active goals...");
|
|
10713
|
+
}
|
|
10714
|
+
const recentFiles = /* @__PURE__ */ new Set();
|
|
10715
|
+
const uncommittedFiles = await getGitChangedFiles(projectPath);
|
|
10716
|
+
if (uncommittedFiles) {
|
|
10717
|
+
uncommittedFiles.forEach((f) => recentFiles.add(join4(projectPath, f)));
|
|
10718
|
+
}
|
|
10719
|
+
const oneDayAgo = Date.now() - 24 * 60 * 60 * 1e3;
|
|
10720
|
+
const recentChanges = await getChangedFilesSinceTimestamp(projectPath, oneDayAgo);
|
|
10721
|
+
if (recentChanges) {
|
|
10722
|
+
recentChanges.forEach((f) => recentFiles.add(f));
|
|
10723
|
+
}
|
|
10724
|
+
const filesToCheck = Array.from(recentFiles).filter((file) => {
|
|
10725
|
+
const ext = extname3(file).toLowerCase();
|
|
10726
|
+
return WATCH_EXTENSIONS.has(ext) && existsSync6(file);
|
|
10727
|
+
});
|
|
10728
|
+
console.debug("[Initial Scan] Files discovered for initial scan:", {
|
|
10729
|
+
totalRecentFiles: recentFiles.size,
|
|
10730
|
+
filteredFiles: filesToCheck.length,
|
|
10731
|
+
filePaths: filesToCheck.slice(0, 5).map((f) => f.replace(projectPath + "/", "")),
|
|
10732
|
+
// Show first 5
|
|
10733
|
+
watchedExtensions: Array.from(WATCH_EXTENSIONS)
|
|
10734
|
+
});
|
|
10735
|
+
if (filesToCheck.length === 0) {
|
|
10736
|
+
console.debug("[Initial Scan] No recent files found for initial scan");
|
|
10737
|
+
return;
|
|
10738
|
+
}
|
|
10739
|
+
const maxInitialFiles = 10;
|
|
10740
|
+
const filesToScan = filesToCheck.slice(0, maxInitialFiles);
|
|
10741
|
+
if (!isInteractiveMode()) {
|
|
10742
|
+
console.error(` Scanning ${filesToScan.length} recent file(s) against ${activeGoals.length} goal(s)...`);
|
|
10743
|
+
}
|
|
10744
|
+
const maxCharsPerFile = 3e3;
|
|
10745
|
+
const fileContents = await Promise.all(
|
|
10746
|
+
filesToScan.map(async (file) => {
|
|
10747
|
+
try {
|
|
10748
|
+
const content = await readFile5(file, "utf-8");
|
|
10749
|
+
const relativePath = file.replace(projectPath + "/", "");
|
|
10750
|
+
return { path: relativePath, content: content.slice(0, maxCharsPerFile) };
|
|
10751
|
+
} catch {
|
|
10752
|
+
return null;
|
|
10753
|
+
}
|
|
10754
|
+
})
|
|
10755
|
+
);
|
|
10756
|
+
const valid = fileContents.filter(Boolean);
|
|
10757
|
+
if (valid.length === 0) return;
|
|
10758
|
+
const filesBlock = valid.map(
|
|
10759
|
+
(f) => `### ${f.path}
|
|
10760
|
+
\`\`\`
|
|
10761
|
+
${f.content}
|
|
10762
|
+
\`\`\``
|
|
10763
|
+
).join("\n\n");
|
|
10764
|
+
const goalsSection = `
|
|
10765
|
+
USER-DEFINED GOALS (check EVERY file against ALL goals):
|
|
10766
|
+
${activeGoals.map((g, i) => ` ${i + 1}. "${g.description}"`).join("\n")}
|
|
10767
|
+
|
|
10768
|
+
This is an INITIAL SCAN at watch startup. Report ALL goal violations you find.
|
|
10769
|
+
`;
|
|
10770
|
+
const result = await runAIAnalysis({
|
|
10771
|
+
systemPrompt: `You are checking code for GOAL VIOLATIONS ONLY.
|
|
10772
|
+
${goalsSection}
|
|
10773
|
+
Reply ONLY with a JSON array. Each element must have:
|
|
10774
|
+
- "file": relative file path
|
|
10775
|
+
- "severity": "critical" | "major" | "minor"
|
|
10776
|
+
- "description": 1-sentence description of the goal violation
|
|
10777
|
+
- "confidence": number 0-100, how confident you are this is a violation
|
|
10778
|
+
- "suggestedFix": 1-sentence description of what should change
|
|
10779
|
+
- "isGoalViolation": true (always true for this scan)
|
|
10780
|
+
- "goalIndex": 0-based index of the violated goal
|
|
10781
|
+
|
|
10782
|
+
Be thorough. If a goal says "no emojis" and you see ANY emoji in the file, report it. If a goal says "no console.log" and you see console.log, report it.
|
|
10783
|
+
|
|
10784
|
+
If no violations found, reply with: []
|
|
10785
|
+
Output ONLY the JSON array, no markdown fences, no commentary.`,
|
|
10786
|
+
userPrompt: `Check these files for goal violations:
|
|
10787
|
+
|
|
10788
|
+
${filesBlock}`,
|
|
10789
|
+
maxTokens: 2048,
|
|
10790
|
+
temperature: 0.1
|
|
10791
|
+
});
|
|
10792
|
+
if (result.tokensUsed) {
|
|
10793
|
+
this.recordTokenUsage(result.tokensUsed.input + result.tokensUsed.output);
|
|
10794
|
+
}
|
|
10795
|
+
if (!result.success || !result.content.trim()) return;
|
|
10796
|
+
let issues = [];
|
|
10797
|
+
try {
|
|
10798
|
+
const parsed = JSON.parse(result.content.trim());
|
|
10799
|
+
issues = Array.isArray(parsed) ? parsed : [];
|
|
10800
|
+
} catch {
|
|
10801
|
+
return;
|
|
10802
|
+
}
|
|
10803
|
+
const issuesToStore = [];
|
|
10804
|
+
let violationsFound = 0;
|
|
10805
|
+
for (const issue of issues) {
|
|
10806
|
+
if (!issue.isGoalViolation || issue.confidence < 40) continue;
|
|
10807
|
+
violationsFound++;
|
|
10808
|
+
if (issue.goalIndex != null && issue.goalIndex >= 0 && issue.goalIndex < activeGoals.length) {
|
|
10809
|
+
const goal = activeGoals[issue.goalIndex];
|
|
10810
|
+
if (!goal) continue;
|
|
10811
|
+
const fixId = `fix-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
10812
|
+
issuesToStore.push({
|
|
10813
|
+
id: fixId,
|
|
10814
|
+
file: issue.file,
|
|
10815
|
+
agent: "goal-violation",
|
|
10816
|
+
severity: issue.severity === "critical" ? "critical" : issue.severity === "major" ? "serious" : "moderate",
|
|
10817
|
+
issue: `Goal "${goal.description}" violated: ${issue.description}`,
|
|
10818
|
+
fix: issue.suggestedFix || "Review and fix",
|
|
10819
|
+
category: "goal-violation",
|
|
10820
|
+
confidence: issue.confidence,
|
|
10821
|
+
autoFixable: true
|
|
10822
|
+
});
|
|
10823
|
+
await recordGoalViolationCaught(goal, issue.file, projectPath);
|
|
10824
|
+
const confidenceStr = issue.confidence >= 80 ? "high" : issue.confidence >= 60 ? "medium" : "low";
|
|
10825
|
+
const nudgeMsg = `Goal "${goal.description}" violated in ${issue.file}: ${issue.description} [${confidenceStr} confidence]`;
|
|
10826
|
+
getOutputManager().nudge(nudgeMsg, "warning", issue.file);
|
|
10827
|
+
await this.persistNudge({
|
|
10828
|
+
message: nudgeMsg,
|
|
10829
|
+
severity: "warning",
|
|
10830
|
+
file: issue.file,
|
|
10831
|
+
category: "quality",
|
|
10832
|
+
goalId: goal.id,
|
|
10833
|
+
priority: issue.confidence >= 80 ? 8 : issue.confidence >= 60 ? 6 : 4,
|
|
10834
|
+
...issue.suggestedFix && { suggestedAction: issue.suggestedFix }
|
|
10835
|
+
});
|
|
10836
|
+
}
|
|
10837
|
+
}
|
|
10838
|
+
if (issuesToStore.length > 0) {
|
|
10839
|
+
await storeIssues(issuesToStore, basename(projectPath), projectPath);
|
|
10840
|
+
if (this.streamingManager) {
|
|
10841
|
+
this.streamingManager.reportLedgerUpdate(issuesToStore.length, "goal-violation");
|
|
10842
|
+
}
|
|
10843
|
+
}
|
|
10844
|
+
if (!isInteractiveMode()) {
|
|
10845
|
+
if (violationsFound > 0) {
|
|
10846
|
+
console.error(` [!] Found ${violationsFound} goal violation(s) in recent files`);
|
|
10847
|
+
} else {
|
|
10848
|
+
console.error(` [\u2713] No goal violations found in recent files`);
|
|
10849
|
+
}
|
|
10850
|
+
}
|
|
10851
|
+
} catch (error) {
|
|
10852
|
+
if (!isInteractiveMode()) {
|
|
10853
|
+
console.error(` [!] Initial goal scan error: ${error}`);
|
|
10854
|
+
}
|
|
10855
|
+
}
|
|
10856
|
+
}
|
|
10857
|
+
async syncPipelineIntegrations() {
|
|
10858
|
+
const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
|
|
10859
|
+
try {
|
|
10860
|
+
const config = await loadConfig();
|
|
10861
|
+
const hasLinear = !!(config.apiKeys?.linear ?? process.env.LINEAR_API_KEY);
|
|
10862
|
+
const hasGithub = !!(config.apiKeys?.github ?? process.env.GITHUB_TOKEN);
|
|
10863
|
+
if (!hasLinear && !hasGithub) return;
|
|
10864
|
+
const graph = new ContextGraph(projectPath);
|
|
10865
|
+
if (hasLinear) {
|
|
10866
|
+
try {
|
|
10867
|
+
const { LinearIngester } = await import("./linear-ingester-NHFMKJBZ.js");
|
|
10868
|
+
const ingester = new LinearIngester(projectPath, graph);
|
|
10869
|
+
await ingester.syncTickets();
|
|
10870
|
+
if (!isInteractiveMode()) {
|
|
10871
|
+
console.error("[Pipeline] Linear tickets synced");
|
|
10872
|
+
}
|
|
10873
|
+
} catch (error) {
|
|
10874
|
+
if (!isInteractiveMode()) {
|
|
10875
|
+
console.error(`[Pipeline] Linear sync failed: ${error}`);
|
|
10876
|
+
}
|
|
10877
|
+
}
|
|
10878
|
+
}
|
|
10879
|
+
if (hasGithub) {
|
|
10880
|
+
try {
|
|
10881
|
+
const { GitHubIngester } = await import("./github-ingester-AR5A4RAC.js");
|
|
10882
|
+
const ingester = new GitHubIngester(graph);
|
|
10883
|
+
const token = await ingester.getApiToken();
|
|
10884
|
+
const repoInfo = ingester.getRepoInfo(projectPath);
|
|
10885
|
+
if (repoInfo) {
|
|
10886
|
+
await ingester.syncPullRequests(repoInfo.owner, repoInfo.name, token);
|
|
10887
|
+
await ingester.syncIssues(repoInfo.owner, repoInfo.name, token);
|
|
10888
|
+
if (!isInteractiveMode()) {
|
|
10889
|
+
console.error("[Pipeline] GitHub PRs/issues synced");
|
|
10890
|
+
}
|
|
10891
|
+
}
|
|
10892
|
+
} catch (error) {
|
|
10893
|
+
if (!isInteractiveMode()) {
|
|
10894
|
+
console.error(`[Pipeline] GitHub sync failed: ${error}`);
|
|
10895
|
+
}
|
|
10896
|
+
}
|
|
10897
|
+
}
|
|
10898
|
+
} catch {
|
|
10899
|
+
}
|
|
10900
|
+
}
|
|
10901
|
+
async stopWatching() {
|
|
10902
|
+
if (!this.state.isRunning) {
|
|
10903
|
+
return {
|
|
10904
|
+
content: [{
|
|
10905
|
+
type: "text",
|
|
10906
|
+
text: "[!] Watch mode is not running."
|
|
10907
|
+
}]
|
|
10908
|
+
};
|
|
10909
|
+
}
|
|
10910
|
+
for (const watcher of this.watchers.values()) {
|
|
10911
|
+
watcher.close();
|
|
10912
|
+
}
|
|
10913
|
+
this.watchers.clear();
|
|
10914
|
+
if (this.extractionPipeline) {
|
|
10915
|
+
this.extractionPipeline.close();
|
|
10916
|
+
this.extractionPipeline = null;
|
|
10917
|
+
}
|
|
10918
|
+
if (this.pipelineSyncTimer) {
|
|
10919
|
+
clearInterval(this.pipelineSyncTimer);
|
|
10920
|
+
this.pipelineSyncTimer = null;
|
|
10921
|
+
}
|
|
10922
|
+
if (this.codebaseIndex) {
|
|
10923
|
+
await this.codebaseIndex.save();
|
|
10924
|
+
this.codebaseIndex = null;
|
|
10925
|
+
}
|
|
10926
|
+
if (this.state.scanDebounceTimer) {
|
|
10927
|
+
clearTimeout(this.state.scanDebounceTimer);
|
|
10928
|
+
}
|
|
10929
|
+
this.state.isRunning = false;
|
|
10930
|
+
if (!isInteractiveMode()) {
|
|
10931
|
+
console.error("\n[*] Watch mode stopped.\n");
|
|
10932
|
+
}
|
|
10933
|
+
if (this.streamingManager) {
|
|
10934
|
+
this.streamingManager.reportWatchStatus({ watching: false, directories: 0 });
|
|
10935
|
+
}
|
|
10936
|
+
const outputManager = getOutputManager();
|
|
10937
|
+
outputManager.clearTUICallbacks();
|
|
10938
|
+
outputManager.setMode("console");
|
|
10939
|
+
if (this.dashboard) {
|
|
10940
|
+
this.dashboard.stop();
|
|
10941
|
+
this.dashboard = void 0;
|
|
10942
|
+
}
|
|
10943
|
+
const budget = this.state.tokenBudget;
|
|
10944
|
+
const tokensK = (budget.used / 1e3).toFixed(1);
|
|
10945
|
+
return {
|
|
10946
|
+
content: [{
|
|
10947
|
+
type: "text",
|
|
10948
|
+
text: `[*] **TRIE AGENT STOPPED**
|
|
10949
|
+
|
|
10950
|
+
### Session Summary:
|
|
10951
|
+
- Files scanned: ${this.state.filesScanned}
|
|
10952
|
+
- Issues found: ${this.state.totalIssuesFound}
|
|
10953
|
+
- Tokens used: ${tokensK}k / ${(budget.hourlyLimit / 1e3).toFixed(0)}k hourly limit
|
|
10954
|
+
- Scans skipped (trie-throttled): ${budget.scansSaved}
|
|
10955
|
+
- Governance ledger: Updated continuously
|
|
10956
|
+
|
|
10957
|
+
Use \`trie_watch start\` to resume.`
|
|
10958
|
+
}]
|
|
10959
|
+
};
|
|
10960
|
+
}
|
|
10961
|
+
async getStatus() {
|
|
10962
|
+
if (!this.state.isRunning) {
|
|
10963
|
+
return {
|
|
10964
|
+
content: [{
|
|
10965
|
+
type: "text",
|
|
10966
|
+
text: `[*] **Watch Mode Status: STOPPED**
|
|
10967
|
+
|
|
10968
|
+
Use \`trie_watch start\` to begin autonomous scanning.`
|
|
10969
|
+
}]
|
|
10970
|
+
};
|
|
10971
|
+
}
|
|
10972
|
+
const recentScans = Array.from(this.state.lastScan.entries()).sort((a, b) => b[1] - a[1]).slice(0, 5).map(([file, time]) => {
|
|
10973
|
+
const ago = Math.round((Date.now() - time) / 1e3);
|
|
10974
|
+
return `- \`${basename(file)}\` (${ago}s ago)`;
|
|
10975
|
+
}).join("\n");
|
|
10976
|
+
const recentNudges = this.state.nudges.slice(-3).map(
|
|
10977
|
+
(n) => `- ${basename(n.file)} [${n.severity}] @ ${n.timestamp}`
|
|
10978
|
+
).join("\n");
|
|
10979
|
+
let agencyStatus = "";
|
|
10980
|
+
try {
|
|
10981
|
+
const { getTrieAgent: getTrieAgent2 } = await import("./trie-agent-TLOJ2UFS.js");
|
|
10982
|
+
const trieAgent = getTrieAgent2(this.watchedDirectory || getWorkingDirectory(void 0, true));
|
|
10983
|
+
await trieAgent.initialize();
|
|
10984
|
+
const status = await trieAgent.getAgencyStatus();
|
|
10985
|
+
agencyStatus = `
|
|
10986
|
+
### [AI] Trie Agent:
|
|
10987
|
+
- **Goals:** ${status.goals.active} active, ${status.goals.completed} completed${status.goals.topGoal ? ` (${status.goals.topGoal.slice(0, 40)}...)` : ""}
|
|
10988
|
+
- **Hypotheses:** ${status.hypotheses.testing} testing, ${status.hypotheses.validated} validated
|
|
10989
|
+
- **Risk Level:** ${status.riskLevel.toUpperCase()}
|
|
10990
|
+
- **Effectiveness:** ${status.effectiveness}%
|
|
10991
|
+
- **Scan Frequency:** ${Math.round(status.scanFrequency / 1e3)}s${status.isQuietHours ? " (quiet hours)" : ""}`;
|
|
10992
|
+
} catch {
|
|
10993
|
+
}
|
|
10994
|
+
const budget = this.state.tokenBudget;
|
|
10995
|
+
const remaining = this.getRemainingBudget();
|
|
10996
|
+
const tokensK = (budget.used / 1e3).toFixed(1);
|
|
10997
|
+
const remainingK = (remaining / 1e3).toFixed(1);
|
|
10998
|
+
return {
|
|
10999
|
+
content: [{
|
|
11000
|
+
type: "text",
|
|
11001
|
+
text: `[*] **WATCH MODE Status: RUNNING**
|
|
11002
|
+
|
|
11003
|
+
### Stats:
|
|
11004
|
+
- Directories watched: ${this.watchers.size}
|
|
11005
|
+
- Files scanned: ${this.state.filesScanned}
|
|
11006
|
+
- Issues found: ${this.state.totalIssuesFound}
|
|
11007
|
+
- Pending: ${this.state.pendingFiles.size}
|
|
11008
|
+
|
|
11009
|
+
### Token Budget:
|
|
11010
|
+
- Used: ${tokensK}k / ${(budget.hourlyLimit / 1e3).toFixed(0)}k hourly
|
|
11011
|
+
- Remaining: ${remainingK}k
|
|
11012
|
+
- Scans skipped (trie-throttled): ${budget.scansSaved}
|
|
11013
|
+
${agencyStatus}
|
|
11014
|
+
|
|
11015
|
+
### Recently Scanned:
|
|
11016
|
+
${recentScans || "(none yet)"}
|
|
11017
|
+
|
|
11018
|
+
### Recent Nudges:
|
|
11019
|
+
${recentNudges || "(none)"}
|
|
11020
|
+
|
|
11021
|
+
### Commands:
|
|
11022
|
+
- \`trie_watch issues\` - Get all issues found
|
|
11023
|
+
- \`trie_watch stop\` - Stop watching`
|
|
11024
|
+
}]
|
|
11025
|
+
};
|
|
11026
|
+
}
|
|
11027
|
+
/**
|
|
11028
|
+
* Helper to persist a nudge to both in-memory state and SQL storage
|
|
11029
|
+
*/
|
|
11030
|
+
async persistNudge(params) {
|
|
11031
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
11032
|
+
const nudgeId = createHash2("sha256").update(`${params.message}|${params.file || ""}|${timestamp}`).digest("hex").slice(0, 16);
|
|
11033
|
+
const nudge = {
|
|
11034
|
+
id: nudgeId,
|
|
11035
|
+
message: params.message,
|
|
11036
|
+
severity: params.severity,
|
|
11037
|
+
timestamp,
|
|
11038
|
+
resolved: false,
|
|
11039
|
+
dismissed: false,
|
|
11040
|
+
priority: params.priority ?? 5,
|
|
11041
|
+
relatedIssues: params.relatedIssues ?? [],
|
|
11042
|
+
metadata: {},
|
|
11043
|
+
...params.file && { file: params.file },
|
|
11044
|
+
...params.category && { category: params.category },
|
|
11045
|
+
...params.goalId && { goalId: params.goalId },
|
|
11046
|
+
...params.suggestedAction && { suggestedAction: params.suggestedAction }
|
|
11047
|
+
};
|
|
11048
|
+
this.state.nudges.push({
|
|
11049
|
+
file: params.file || "unknown",
|
|
11050
|
+
// Keep full path for consistency with loaded nudges
|
|
11051
|
+
message: params.message,
|
|
11052
|
+
severity: params.severity === "warning" || params.severity === "info" ? "high" : params.severity,
|
|
11053
|
+
timestamp: (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false })
|
|
11054
|
+
});
|
|
11055
|
+
try {
|
|
11056
|
+
const storage = getStorage(this.watchedDirectory);
|
|
11057
|
+
await storage.storeNudge(nudge);
|
|
11058
|
+
console.debug(`[Watch] \u2713 Persisted nudge to storage: ${nudge.message.slice(0, 60)}...`);
|
|
11059
|
+
} catch (error) {
|
|
11060
|
+
console.error("[Watch] Failed to persist nudge to storage:", error);
|
|
11061
|
+
}
|
|
11062
|
+
}
|
|
11063
|
+
getNudges() {
|
|
11064
|
+
return {
|
|
11065
|
+
content: [
|
|
11066
|
+
{
|
|
11067
|
+
type: "text",
|
|
11068
|
+
text: `[#] Recent nudges (${this.state.nudges.length} this session)
|
|
11069
|
+
` + (this.state.nudges.length ? this.state.nudges.map(
|
|
11070
|
+
(n) => `- ${basename(n.file)} [${n.severity}] @ ${n.timestamp}
|
|
11071
|
+
${n.message}`
|
|
11072
|
+
).join("\n") : "(none)")
|
|
11073
|
+
},
|
|
11074
|
+
{
|
|
11075
|
+
type: "json",
|
|
11076
|
+
json: this.state.nudges
|
|
11077
|
+
}
|
|
11078
|
+
]
|
|
11079
|
+
};
|
|
11080
|
+
}
|
|
11081
|
+
getCurrentIssues() {
|
|
11082
|
+
return {
|
|
11083
|
+
content: [{
|
|
11084
|
+
type: "text",
|
|
11085
|
+
text: `[L] **Issues Found This Session**
|
|
11086
|
+
|
|
11087
|
+
Total issues: ${this.state.totalIssuesFound}
|
|
11088
|
+
Files scanned: ${this.state.filesScanned}
|
|
11089
|
+
|
|
11090
|
+
To get a full report, run \`trie watch\` on your codebase.`
|
|
11091
|
+
}]
|
|
11092
|
+
};
|
|
11093
|
+
}
|
|
11094
|
+
};
|
|
11095
|
+
|
|
9658
11096
|
export {
|
|
9659
11097
|
getPrompt,
|
|
9660
11098
|
getSystemPrompt,
|
|
@@ -9662,7 +11100,6 @@ export {
|
|
|
9662
11100
|
TrieCloudFixTool,
|
|
9663
11101
|
TrieExplainTool,
|
|
9664
11102
|
StreamingManager,
|
|
9665
|
-
ExtractionPipeline,
|
|
9666
11103
|
TrieTellTool,
|
|
9667
11104
|
TrieFeedbackTool,
|
|
9668
11105
|
TrieCheckTool,
|
|
@@ -9675,6 +11112,7 @@ export {
|
|
|
9675
11112
|
handleCheckpointTool,
|
|
9676
11113
|
TriePipelineTool,
|
|
9677
11114
|
GitHubBranchesTool,
|
|
9678
|
-
InteractiveDashboard
|
|
11115
|
+
InteractiveDashboard,
|
|
11116
|
+
TrieWatchTool
|
|
9679
11117
|
};
|
|
9680
|
-
//# sourceMappingURL=chunk-
|
|
11118
|
+
//# sourceMappingURL=chunk-BUA5PQJY.js.map
|