@triedotdev/mcp 1.0.149 → 1.0.154

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.
Files changed (125) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +150 -36
  3. package/dist/{autonomy-config-ZCOSTMPD.js → autonomy-config-RKLZW4XL.js} +4 -4
  4. package/dist/{chat-store-OJLJCJFI.js → chat-store-O3IJ5PMN.js} +4 -4
  5. package/dist/{chunk-IXO4G4D3.js → chunk-2LAJKFWU.js} +2 -2
  6. package/dist/{chunk-23RJT5WT.js → chunk-3CYMLM35.js} +2 -2
  7. package/dist/{chunk-QH77RQB3.js → chunk-4ZAFQEP6.js} +5 -6
  8. package/dist/chunk-4ZAFQEP6.js.map +1 -0
  9. package/dist/{chunk-SH7H3WRU.js → chunk-7F2R2ITA.js} +4 -4
  10. package/dist/{chunk-SH7H3WRU.js.map → chunk-7F2R2ITA.js.map} +1 -1
  11. package/dist/{chunk-FG467PDD.js → chunk-ALSCZ7WR.js} +2 -2
  12. package/dist/{chunk-YOJGSRZK.js → chunk-CBAMZERA.js} +2 -2
  13. package/dist/{chunk-53KUI7RQ.js → chunk-EMJ7RVWB.js} +38 -13
  14. package/dist/{chunk-53KUI7RQ.js.map → chunk-EMJ7RVWB.js.map} +1 -1
  15. package/dist/{chunk-NKHO34UZ.js → chunk-FTOF3FHT.js} +3 -3
  16. package/dist/{chunk-LD7ZEFNY.js → chunk-FXZAABXO.js} +2 -2
  17. package/dist/{chunk-ZUEAHFSY.js → chunk-HD5H7YSW.js} +313 -61
  18. package/dist/chunk-HD5H7YSW.js.map +1 -0
  19. package/dist/{chunk-APMV77PU.js → chunk-JKEEQAG2.js} +1 -1
  20. package/dist/chunk-JKEEQAG2.js.map +1 -0
  21. package/dist/{chunk-FH335WL5.js → chunk-JYWGYUKX.js} +2 -2
  22. package/dist/{chunk-TIMIKBY2.js → chunk-KLMJKM63.js} +2 -2
  23. package/dist/{chunk-4C67GV3O.js → chunk-KYKADM7P.js} +2 -2
  24. package/dist/{chunk-CU5VDH6F.js → chunk-L4FODDDB.js} +2 -2
  25. package/dist/{chunk-ILGMFND2.js → chunk-LFNH3CSN.js} +4 -4
  26. package/dist/{chunk-GAL7OIYU.js → chunk-LJISDV3A.js} +15 -15
  27. package/dist/{chunk-72KSLD7A.js → chunk-NVZZUUEU.js} +5 -5
  28. package/dist/{chunk-7OJ6JIPL.js → chunk-OVSYTWUU.js} +7 -150
  29. package/dist/chunk-OVSYTWUU.js.map +1 -0
  30. package/dist/{chunk-B2AHQ2IR.js → chunk-OWSGJUUR.js} +12 -12
  31. package/dist/{chunk-HYNDXZAU.js → chunk-QAM5X5HM.js} +1535 -90
  32. package/dist/chunk-QAM5X5HM.js.map +1 -0
  33. package/dist/{chunk-OTQEFXHU.js → chunk-T7UAH7GE.js} +2 -2
  34. package/dist/{chunk-FPEMP54L.js → chunk-UL337UDQ.js} +2 -2
  35. package/dist/{chunk-F4NJ4CBP.js → chunk-WO7CC5FH.js} +2 -2
  36. package/dist/{chunk-5KJ4UJOY.js → chunk-XD2HKZVB.js} +2 -2
  37. package/dist/{chunk-V7AY2EJO.js → chunk-YEQXKKZQ.js} +2 -2
  38. package/dist/{chunk-ZDDE442Q.js → chunk-Z2E7X4WI.js} +8 -8
  39. package/dist/{chunk-ZDDE442Q.js.map → chunk-Z2E7X4WI.js.map} +1 -1
  40. package/dist/cli/create-agent.js +9 -41
  41. package/dist/cli/create-agent.js.map +1 -1
  42. package/dist/cli/main.js +58 -96
  43. package/dist/cli/main.js.map +1 -1
  44. package/dist/cli/yolo-daemon.js +65 -28
  45. package/dist/cli/yolo-daemon.js.map +1 -1
  46. package/dist/{client-INNE2GGZ.js → client-ZHOLZTRW.js} +4 -4
  47. package/dist/{codebase-index-FMIULFZQ.js → codebase-index-N37NDF2A.js} +4 -4
  48. package/dist/{fast-analyzer-CTT3MCPE.js → fast-analyzer-U6URGNQT.js} +6 -6
  49. package/dist/github-ingester-AR5A4RAC.js +11 -0
  50. package/dist/{goal-manager-IGUMDGCA.js → goal-manager-5QDITJKE.js} +8 -8
  51. package/dist/{goal-validator-DV6DRSGF.js → goal-validator-FU5QWDQT.js} +7 -7
  52. package/dist/graph-JO7GG65P.js +10 -0
  53. package/dist/{hypothesis-O72ZLVOW.js → hypothesis-JURDWVDC.js} +8 -8
  54. package/dist/incident-index-7CAXUNTL.js +11 -0
  55. package/dist/index.js +136 -1740
  56. package/dist/index.js.map +1 -1
  57. package/dist/{insight-store-Q62UGMTF.js → insight-store-AMEP5PPF.js} +4 -4
  58. package/dist/{issue-store-4FPABLC6.js → issue-store-RM3XLLKG.js} +5 -5
  59. package/dist/{ledger-43SIVE7X.js → ledger-PLE3C3X4.js} +14 -6
  60. package/dist/linear-ingester-NHFMKJBZ.js +11 -0
  61. package/dist/{output-manager-DZO5LGSG.js → output-manager-FX4V7ERT.js} +3 -3
  62. package/dist/{progress-PQVEM7BR.js → progress-PAYTY7BF.js} +2 -2
  63. package/dist/tiered-storage-3TUUR3L2.js +12 -0
  64. package/dist/trie-agent-QHPS4C5Z.js +27 -0
  65. package/dist/{vibe-code-signatures-ELEWJFGZ.js → vibe-code-signatures-J4GD4JOV.js} +3 -3
  66. package/dist/{vulnerability-signatures-EIJQX2TS.js → vulnerability-signatures-EIKOHFPK.js} +3 -3
  67. package/package.json +4 -6
  68. package/dist/chunk-7OJ6JIPL.js.map +0 -1
  69. package/dist/chunk-APMV77PU.js.map +0 -1
  70. package/dist/chunk-G76DYVGX.js +0 -136
  71. package/dist/chunk-G76DYVGX.js.map +0 -1
  72. package/dist/chunk-HYNDXZAU.js.map +0 -1
  73. package/dist/chunk-QH77RQB3.js.map +0 -1
  74. package/dist/chunk-ZUEAHFSY.js.map +0 -1
  75. package/dist/comprehension-46F7ZNKL.js +0 -821
  76. package/dist/comprehension-46F7ZNKL.js.map +0 -1
  77. package/dist/github-ingester-J2ZFYXVE.js +0 -11
  78. package/dist/graph-J4OGTYCO.js +0 -10
  79. package/dist/incident-index-BWW2UEY7.js +0 -11
  80. package/dist/linear-ingester-JRDQAIAA.js +0 -11
  81. package/dist/tiered-storage-VZL7KK64.js +0 -12
  82. package/dist/trie-agent-ET3DAP5Y.js +0 -27
  83. package/dist/workers/agent-worker.d.ts +0 -2
  84. package/dist/workers/agent-worker.js +0 -28
  85. package/dist/workers/agent-worker.js.map +0 -1
  86. /package/dist/{autonomy-config-ZCOSTMPD.js.map → autonomy-config-RKLZW4XL.js.map} +0 -0
  87. /package/dist/{chat-store-OJLJCJFI.js.map → chat-store-O3IJ5PMN.js.map} +0 -0
  88. /package/dist/{chunk-IXO4G4D3.js.map → chunk-2LAJKFWU.js.map} +0 -0
  89. /package/dist/{chunk-23RJT5WT.js.map → chunk-3CYMLM35.js.map} +0 -0
  90. /package/dist/{chunk-FG467PDD.js.map → chunk-ALSCZ7WR.js.map} +0 -0
  91. /package/dist/{chunk-YOJGSRZK.js.map → chunk-CBAMZERA.js.map} +0 -0
  92. /package/dist/{chunk-NKHO34UZ.js.map → chunk-FTOF3FHT.js.map} +0 -0
  93. /package/dist/{chunk-LD7ZEFNY.js.map → chunk-FXZAABXO.js.map} +0 -0
  94. /package/dist/{chunk-FH335WL5.js.map → chunk-JYWGYUKX.js.map} +0 -0
  95. /package/dist/{chunk-TIMIKBY2.js.map → chunk-KLMJKM63.js.map} +0 -0
  96. /package/dist/{chunk-4C67GV3O.js.map → chunk-KYKADM7P.js.map} +0 -0
  97. /package/dist/{chunk-CU5VDH6F.js.map → chunk-L4FODDDB.js.map} +0 -0
  98. /package/dist/{chunk-ILGMFND2.js.map → chunk-LFNH3CSN.js.map} +0 -0
  99. /package/dist/{chunk-GAL7OIYU.js.map → chunk-LJISDV3A.js.map} +0 -0
  100. /package/dist/{chunk-72KSLD7A.js.map → chunk-NVZZUUEU.js.map} +0 -0
  101. /package/dist/{chunk-B2AHQ2IR.js.map → chunk-OWSGJUUR.js.map} +0 -0
  102. /package/dist/{chunk-OTQEFXHU.js.map → chunk-T7UAH7GE.js.map} +0 -0
  103. /package/dist/{chunk-FPEMP54L.js.map → chunk-UL337UDQ.js.map} +0 -0
  104. /package/dist/{chunk-F4NJ4CBP.js.map → chunk-WO7CC5FH.js.map} +0 -0
  105. /package/dist/{chunk-5KJ4UJOY.js.map → chunk-XD2HKZVB.js.map} +0 -0
  106. /package/dist/{chunk-V7AY2EJO.js.map → chunk-YEQXKKZQ.js.map} +0 -0
  107. /package/dist/{client-INNE2GGZ.js.map → client-ZHOLZTRW.js.map} +0 -0
  108. /package/dist/{codebase-index-FMIULFZQ.js.map → codebase-index-N37NDF2A.js.map} +0 -0
  109. /package/dist/{fast-analyzer-CTT3MCPE.js.map → fast-analyzer-U6URGNQT.js.map} +0 -0
  110. /package/dist/{github-ingester-J2ZFYXVE.js.map → github-ingester-AR5A4RAC.js.map} +0 -0
  111. /package/dist/{goal-manager-IGUMDGCA.js.map → goal-manager-5QDITJKE.js.map} +0 -0
  112. /package/dist/{goal-validator-DV6DRSGF.js.map → goal-validator-FU5QWDQT.js.map} +0 -0
  113. /package/dist/{graph-J4OGTYCO.js.map → graph-JO7GG65P.js.map} +0 -0
  114. /package/dist/{hypothesis-O72ZLVOW.js.map → hypothesis-JURDWVDC.js.map} +0 -0
  115. /package/dist/{incident-index-BWW2UEY7.js.map → incident-index-7CAXUNTL.js.map} +0 -0
  116. /package/dist/{insight-store-Q62UGMTF.js.map → insight-store-AMEP5PPF.js.map} +0 -0
  117. /package/dist/{issue-store-4FPABLC6.js.map → issue-store-RM3XLLKG.js.map} +0 -0
  118. /package/dist/{ledger-43SIVE7X.js.map → ledger-PLE3C3X4.js.map} +0 -0
  119. /package/dist/{linear-ingester-JRDQAIAA.js.map → linear-ingester-NHFMKJBZ.js.map} +0 -0
  120. /package/dist/{output-manager-DZO5LGSG.js.map → output-manager-FX4V7ERT.js.map} +0 -0
  121. /package/dist/{progress-PQVEM7BR.js.map → progress-PAYTY7BF.js.map} +0 -0
  122. /package/dist/{tiered-storage-VZL7KK64.js.map → tiered-storage-3TUUR3L2.js.map} +0 -0
  123. /package/dist/{trie-agent-ET3DAP5Y.js.map → trie-agent-QHPS4C5Z.js.map} +0 -0
  124. /package/dist/{vibe-code-signatures-ELEWJFGZ.js.map → vibe-code-signatures-J4GD4JOV.js.map} +0 -0
  125. /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-23RJT5WT.js";
3
+ } from "./chunk-3CYMLM35.js";
4
4
  import {
5
5
  getTrieAgent
6
- } from "./chunk-GAL7OIYU.js";
6
+ } from "./chunk-LJISDV3A.js";
7
+ import {
8
+ CodebaseIndex
9
+ } from "./chunk-YEQXKKZQ.js";
7
10
  import {
8
11
  getOutputManager
9
- } from "./chunk-TIMIKBY2.js";
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-53KUI7RQ.js";
23
+ } from "./chunk-EMJ7RVWB.js";
20
24
  import {
21
25
  loadConfig,
22
26
  saveConfig
23
- } from "./chunk-NKHO34UZ.js";
27
+ } from "./chunk-FTOF3FHT.js";
24
28
  import {
25
29
  IncidentIndex
26
- } from "./chunk-4C67GV3O.js";
30
+ } from "./chunk-KYKADM7P.js";
27
31
  import {
28
32
  findCrossProjectPatterns
29
- } from "./chunk-B2AHQ2IR.js";
30
- import {
31
- TieredStorage,
32
- getStorage
33
- } from "./chunk-FG467PDD.js";
33
+ } from "./chunk-OWSGJUUR.js";
34
34
  import {
35
35
  ContextGraph
36
- } from "./chunk-FH335WL5.js";
36
+ } from "./chunk-JYWGYUKX.js";
37
37
  import {
38
38
  measureInitialGoalValue
39
- } from "./chunk-ZDDE442Q.js";
39
+ } from "./chunk-Z2E7X4WI.js";
40
40
  import {
41
41
  getKeyFromKeychain,
42
42
  isAIAvailable,
43
+ runAIAnalysis,
43
44
  runAIWithTools,
44
45
  setAPIKey
45
- } from "./chunk-FPEMP54L.js";
46
+ } from "./chunk-UL337UDQ.js";
46
47
  import {
47
48
  getProjectState
48
- } from "./chunk-CU5VDH6F.js";
49
+ } from "./chunk-L4FODDDB.js";
50
+ import {
51
+ TieredStorage,
52
+ getStorage
53
+ } from "./chunk-ALSCZ7WR.js";
49
54
  import {
55
+ getAutonomyConfig,
50
56
  loadAutonomyConfig,
51
57
  saveAutonomyConfig
52
- } from "./chunk-5KJ4UJOY.js";
58
+ } from "./chunk-XD2HKZVB.js";
53
59
  import {
60
+ storeIssues
61
+ } from "./chunk-4ZAFQEP6.js";
62
+ import {
63
+ getChangedFilesSinceTimestamp,
64
+ getGitChangedFiles,
54
65
  getLedgerBlocks
55
- } from "./chunk-ZUEAHFSY.js";
66
+ } from "./chunk-HD5H7YSW.js";
56
67
  import {
57
68
  getTrieDirectory,
58
69
  getWorkingDirectory
59
- } from "./chunk-SH7H3WRU.js";
70
+ } from "./chunk-7F2R2ITA.js";
60
71
  import {
61
72
  isInteractiveMode
62
- } from "./chunk-APMV77PU.js";
73
+ } from "./chunk-JKEEQAG2.js";
63
74
 
64
75
  // src/utils/streaming.ts
65
76
  var shouldSuppressConsole = () => isInteractiveMode();
@@ -960,13 +971,13 @@ import { Box, Text, useStdout } from "ink";
960
971
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
961
972
  function Header() {
962
973
  const { state } = useDashboard();
963
- const { signalExtraction, watch, alerts } = state;
974
+ const { signalExtraction, watch: watch2, alerts } = state;
964
975
  const { stdout } = useStdout();
965
976
  const cols = stdout?.columns || 80;
966
977
  const narrow = cols < 50;
967
978
  const totalExtracted = signalExtraction.governanceExtracted + signalExtraction.factsExtracted + signalExtraction.blockersExtracted + signalExtraction.questionsExtracted;
968
979
  let status;
969
- if (watch.watching) {
980
+ if (watch2.watching) {
970
981
  status = totalExtracted > 0 ? /* @__PURE__ */ jsxs(Text, { children: [
971
982
  /* @__PURE__ */ jsx2(Text, { color: "green", children: "\u25CF" }),
972
983
  narrow ? "" : " ",
@@ -1194,8 +1205,8 @@ function ConfigDialog({ onClose }) {
1194
1205
  const loadStats = async () => {
1195
1206
  try {
1196
1207
  const workDir = getWorkingDirectory(void 0, true);
1197
- const { CodebaseIndex } = await import("./codebase-index-FMIULFZQ.js");
1198
- const index = new CodebaseIndex(workDir);
1208
+ const { CodebaseIndex: CodebaseIndex2 } = await import("./codebase-index-N37NDF2A.js");
1209
+ const index = new CodebaseIndex2(workDir);
1199
1210
  const stats = index.getStats();
1200
1211
  let lastUpdatedDisplay = "Never";
1201
1212
  if (stats.lastUpdated) {
@@ -1387,8 +1398,8 @@ function ConfigDialog({ onClose }) {
1387
1398
  const loadStats = async () => {
1388
1399
  try {
1389
1400
  const workDir = getWorkingDirectory(void 0, true);
1390
- const { CodebaseIndex } = await import("./codebase-index-FMIULFZQ.js");
1391
- const index = new CodebaseIndex(workDir);
1401
+ const { CodebaseIndex: CodebaseIndex2 } = await import("./codebase-index-N37NDF2A.js");
1402
+ const index = new CodebaseIndex2(workDir);
1392
1403
  const stats = index.getStats();
1393
1404
  setIndexStats({
1394
1405
  fileCount: stats.totalFiles,
@@ -1462,9 +1473,9 @@ function ConfigDialog({ onClose }) {
1462
1473
  }
1463
1474
  async function reindexCodebase() {
1464
1475
  const workDir = getWorkingDirectory(void 0, true);
1465
- const { CodebaseIndex } = await import("./codebase-index-FMIULFZQ.js");
1476
+ const { CodebaseIndex: CodebaseIndex2 } = await import("./codebase-index-N37NDF2A.js");
1466
1477
  const { glob } = await import("glob");
1467
- const index = new CodebaseIndex(workDir);
1478
+ const index = new CodebaseIndex2(workDir);
1468
1479
  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
1480
  const indexFiles = await glob(indexPattern, {
1470
1481
  ignore: ["**/node_modules/**", "**/dist/**", "**/build/**", "**/.git/**", "**/.trie/**", "**/coverage/**"],
@@ -1713,7 +1724,7 @@ function truncate(str, max) {
1713
1724
  }
1714
1725
  function OverviewView() {
1715
1726
  const { state, dispatch } = useDashboard();
1716
- const { progress, signalExtraction, watch, issues, activityLog, activityPage, pendingFixes: pendingFixes2, selectedFixIndex } = state;
1727
+ const { progress, signalExtraction, watch: watch2, issues, activityLog, activityPage, pendingFixes: pendingFixes2, selectedFixIndex } = state;
1717
1728
  const { totalIssues } = progress;
1718
1729
  const { stdout } = useStdout4();
1719
1730
  const cols = stdout?.columns || 80;
@@ -1744,12 +1755,12 @@ function OverviewView() {
1744
1755
  return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
1745
1756
  /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1746
1757
  "Scanned ",
1747
- watch.filesScannedSession,
1758
+ watch2.filesScannedSession,
1748
1759
  " files ",
1749
1760
  elapsed,
1750
1761
  "s"
1751
1762
  ] }),
1752
- watch.watching && signalExtraction.enabled && /* @__PURE__ */ jsxs6(Text6, { wrap: "truncate", children: [
1763
+ watch2.watching && signalExtraction.enabled && /* @__PURE__ */ jsxs6(Text6, { wrap: "truncate", children: [
1753
1764
  /* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
1754
1765
  " Signal extraction",
1755
1766
  !narrow && (signalExtraction.governanceExtracted > 0 || signalExtraction.factsExtracted > 0 || signalExtraction.blockersExtracted > 0) && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
@@ -1925,10 +1936,10 @@ function AgentView() {
1925
1936
  if (!insight) return;
1926
1937
  try {
1927
1938
  const workDir = getWorkingDirectory(void 0, true);
1928
- const { getInsightStore } = await import("./insight-store-Q62UGMTF.js");
1939
+ const { getInsightStore } = await import("./insight-store-AMEP5PPF.js");
1929
1940
  const store = getInsightStore(workDir);
1930
1941
  await store.dismissInsight(insight.id);
1931
- const { getStorage: getStorage2 } = await import("./tiered-storage-VZL7KK64.js");
1942
+ const { getStorage: getStorage2 } = await import("./tiered-storage-3TUUR3L2.js");
1932
1943
  const storage = getStorage2(workDir);
1933
1944
  await storage.dismissNudge(insight.id).catch(() => {
1934
1945
  });
@@ -2144,10 +2155,20 @@ function GoalsView() {
2144
2155
  const goals = agentState.getAllGoals();
2145
2156
  dispatch({
2146
2157
  type: "SET_GOALS",
2147
- goals: goals.map((g) => {
2148
- const base = { id: g.id, description: g.description, type: g.type, target: g.target, currentValue: g.currentValue, startValue: g.startValue, status: g.status, autoGenerated: g.autoGenerated, updatedAt: g.updatedAt, ...g.achievedAt != null ? { achievedAt: g.achievedAt } : {}, ...g.achievedBy != null ? { achievedBy: g.achievedBy } : {}, ...g.category != null ? { category: g.category } : {} };
2149
- return base;
2150
- })
2158
+ goals: goals.map((g) => ({
2159
+ id: g.id,
2160
+ description: g.description,
2161
+ type: g.type,
2162
+ target: g.target,
2163
+ currentValue: g.currentValue,
2164
+ status: g.status,
2165
+ autoGenerated: g.autoGenerated,
2166
+ updatedAt: g.updatedAt,
2167
+ ...g.startValue !== void 0 && { startValue: g.startValue },
2168
+ ...g.achievedAt != null && { achievedAt: g.achievedAt },
2169
+ ...g.achievedBy != null && { achievedBy: g.achievedBy },
2170
+ ...g.category != null && { category: g.category }
2171
+ }))
2151
2172
  });
2152
2173
  } catch (err) {
2153
2174
  }
@@ -2277,7 +2298,7 @@ function GoalsView() {
2277
2298
  dispatch({ type: "SET_GOAL_SCANNING", goalId, progress: "Starting scan..." });
2278
2299
  dispatch({ type: "ADD_ACTIVITY", message: `Scanning goal: ${goalSummary.description}...` });
2279
2300
  dispatch({ type: "SET_GOAL_SCANNING", goalId, progress: "Loading goal configuration..." });
2280
- const { checkFilesForGoalViolations } = await import("./goal-validator-DV6DRSGF.js");
2301
+ const { checkFilesForGoalViolations } = await import("./goal-validator-FU5QWDQT.js");
2281
2302
  const agentState = getProjectState(workDir);
2282
2303
  await agentState.load();
2283
2304
  const fullGoal = agentState.getAllGoals().find((g) => g.id === goalId);
@@ -2388,7 +2409,7 @@ function GoalsView() {
2388
2409
  const sourceLabel = goal.autoGenerated ? "AI" : "you";
2389
2410
  if (isScanning) {
2390
2411
  return /* @__PURE__ */ jsx9(Box8, { borderStyle: "round", borderColor: "cyan", paddingX: 1, children: /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2391
- /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", overflow: "visible", children: [
2412
+ /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", children: [
2392
2413
  /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: "\u27F3 " }),
2393
2414
  /* @__PURE__ */ jsx9(Text8, { color: "cyan", bold: true, children: goal.description })
2394
2415
  ] }),
@@ -2397,7 +2418,7 @@ function GoalsView() {
2397
2418
  ] }) }, goal.id);
2398
2419
  }
2399
2420
  return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2400
- /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", overflow: "visible", children: [
2421
+ /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", children: [
2401
2422
  isSelected ? /* @__PURE__ */ jsx9(Text8, { bold: true, color: "green", children: "> " }) : " ",
2402
2423
  goal.autoGenerated ? /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: "\u25C7" }) : /* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u25CB" }),
2403
2424
  " ",
@@ -2429,7 +2450,7 @@ function GoalsView() {
2429
2450
  /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " Achieved" }),
2430
2451
  achievedGoals.slice(0, 5).map((g) => {
2431
2452
  const byLabel = g.achievedBy === "agent" ? "AI" : "you";
2432
- return /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", overflow: "visible", children: [
2453
+ return /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", children: [
2433
2454
  " ",
2434
2455
  g.achievedBy === "agent" ? /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: "\u25CF" }) : /* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u25CF" }),
2435
2456
  " ",
@@ -2450,7 +2471,7 @@ function GoalsView() {
2450
2471
  otherGoals.length > 0 && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginTop: 1, children: [
2451
2472
  /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " Other" }),
2452
2473
  otherGoals.slice(0, 2).map((g) => {
2453
- return /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", overflow: "visible", children: [
2474
+ return /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", children: [
2454
2475
  " ",
2455
2476
  /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "\u25CB" }),
2456
2477
  " ",
@@ -2475,7 +2496,6 @@ function HypothesesView() {
2475
2496
  const { stdout } = useStdout7();
2476
2497
  const cols = stdout?.columns || 80;
2477
2498
  const narrow = cols < 60;
2478
- const contentWidth = Math.max(20, cols - 4);
2479
2499
  const testing = hypothesesPanel.hypotheses.filter((h) => h.status === "testing");
2480
2500
  const validated = hypothesesPanel.hypotheses.filter((h) => h.status === "validated");
2481
2501
  const invalidated = hypothesesPanel.hypotheses.filter((h) => h.status === "invalidated");
@@ -2553,7 +2573,7 @@ function HypothesesView() {
2553
2573
  dispatch({ type: "SET_HYPOTHESIS_SCANNING", hypothesisId: hypoId, progress: "Gathering evidence..." });
2554
2574
  dispatch({ type: "ADD_ACTIVITY", message: `Testing hypothesis: ${hypo.statement}` });
2555
2575
  dispatch({ type: "SHOW_NOTIFICATION", message: `Gathering evidence for hypothesis...`, severity: "info", autoHideMs: 3e3 });
2556
- const { gatherEvidenceForHypothesis } = await import("./hypothesis-O72ZLVOW.js");
2576
+ const { gatherEvidenceForHypothesis } = await import("./hypothesis-JURDWVDC.js");
2557
2577
  const evidence = await gatherEvidenceForHypothesis(hypoId, workDir, signal);
2558
2578
  scanAbortRef.current = null;
2559
2579
  dispatch({ type: "SET_HYPOTHESIS_SCANNING", hypothesisId: null, progress: "" });
@@ -5861,23 +5881,23 @@ var TrieFixTool = class {
5861
5881
  const pending = getPendingFixes();
5862
5882
  if (pending.length === 0) {
5863
5883
  return {
5864
- content: [{ type: "text", text: "No pending issues. Run trie_scan to detect new issues, or check memory with trie_memory action:recent." }]
5884
+ content: [{ type: "text", text: "No pending issues. Run trie watch to detect new issues, or check memory with trie_memory action:recent." }]
5865
5885
  };
5866
5886
  }
5867
5887
  const issues = pending.map((p) => ({
5868
5888
  id: p.id,
5869
5889
  severity: p.severity ?? "moderate",
5870
- effort: p.effort,
5871
5890
  issue: p.issue,
5872
5891
  fix: p.suggestedFix,
5873
5892
  file: p.file,
5874
5893
  line: p.line,
5875
5894
  confidence: p.confidence,
5876
5895
  autoFixable: p.autoFixable ?? false,
5877
- agent: "trie_scan",
5878
- cwe: p.cwe,
5879
- owasp: p.owasp,
5880
- category: p.category
5896
+ agent: "trie_fix",
5897
+ ...p.effort && { effort: p.effort },
5898
+ ...p.cwe && { cwe: p.cwe },
5899
+ ...p.owasp && { owasp: p.owasp },
5900
+ ...p.category && { category: p.category }
5881
5901
  }));
5882
5902
  const filtered = issueIds && issueIds.length > 0 ? issues.filter((i) => issueIds.includes(i.id)) : issues;
5883
5903
  const workDir = getWorkingDirectory(void 0, true);
@@ -6176,7 +6196,7 @@ trie_fix
6176
6196
 
6177
6197
  ## Workflow
6178
6198
 
6179
- 1. Run \`trie_scan\` to detect issues
6199
+ 1. Run \`trie watch\` to detect issues
6180
6200
  2. Review the issues found
6181
6201
  3. Run \`trie_fix\` to apply fixes
6182
6202
 
@@ -6197,7 +6217,7 @@ The AI will analyze each issue, generate the fix, and you can review before appl
6197
6217
  line: p.line,
6198
6218
  confidence: p.confidence,
6199
6219
  autoFixable: false,
6200
- agent: "trie_scan"
6220
+ agent: "trie_fix"
6201
6221
  }));
6202
6222
  const workDir = getWorkingDirectory(void 0, true);
6203
6223
  const config = await loadAutonomyConfig(workDir);
@@ -6229,14 +6249,14 @@ function getPendingFixes() {
6229
6249
  }
6230
6250
  async function loadPendingFixesFromMemory() {
6231
6251
  try {
6232
- const { getRecentIssues } = await import("./issue-store-4FPABLC6.js");
6252
+ const { getRecentIssues } = await import("./issue-store-RM3XLLKG.js");
6233
6253
  pendingFixes.clear();
6234
6254
  const recentIssues = await getRecentIssues({ limit: 50, includeResolved: false });
6235
6255
  for (const storedIssue of recentIssues) {
6236
6256
  const fix = {
6237
6257
  id: storedIssue.id,
6238
6258
  file: storedIssue.file,
6239
- line: storedIssue.line || 0,
6259
+ line: storedIssue.line ?? 0,
6240
6260
  issue: storedIssue.issue,
6241
6261
  suggestedFix: storedIssue.fix,
6242
6262
  confidence: 0.8,
@@ -6244,8 +6264,7 @@ async function loadPendingFixesFromMemory() {
6244
6264
  status: "pending",
6245
6265
  severity: storedIssue.severity,
6246
6266
  autoFixable: true,
6247
- // Memory issues are generally auto-fixable
6248
- category: storedIssue.category
6267
+ ...storedIssue.category && { category: storedIssue.category }
6249
6268
  };
6250
6269
  pendingFixes.set(fix.id, fix);
6251
6270
  }
@@ -6319,11 +6338,12 @@ var TrieCloudFixTool = class {
6319
6338
  allIssues = await this.resolveIssues(args?.issueIds);
6320
6339
  }
6321
6340
  if (allIssues.length === 0) {
6322
- return this.text("No issues to dispatch. Run trie_scan to detect new issues, or check memory with trie_memory action:recent. For ad-hoc fixes, pass file, issue, and fix.");
6341
+ return this.text("No issues to dispatch. Run trie watch to detect new issues, or check memory with trie_memory action:recent. For ad-hoc fixes, pass file, issue, and fix.");
6323
6342
  }
6324
6343
  const isAdHocMode = args?.file && args?.issue && args?.fix;
6325
6344
  if (isAdHocMode) {
6326
- console.log(`Ad-hoc mode: dispatching single issue (${allIssues[0].file})`);
6345
+ const first = allIssues[0];
6346
+ console.log(`Ad-hoc mode: dispatching single issue (${first?.file ?? "unknown"})`);
6327
6347
  } else {
6328
6348
  console.log(`Memory mode: loaded ${allIssues.length} issue(s) from memory/scan`);
6329
6349
  }
@@ -6333,7 +6353,8 @@ var TrieCloudFixTool = class {
6333
6353
  if (isAdHocMode) {
6334
6354
  lines.push("FIX ROUTING PLAN (ad-hoc single incident mode)");
6335
6355
  lines.push("\u2500".repeat(68));
6336
- lines.push(` ${shortPath2(allIssues[0].file)}:${allIssues[0].line ?? "?"} \u2192 cloud-agent (single incident)`);
6356
+ const firstIssue = allIssues[0];
6357
+ lines.push(` ${shortPath2(firstIssue?.file ?? "")}:${firstIssue?.line ?? "?"} \u2192 cloud-agent (single incident)`);
6337
6358
  lines.push("");
6338
6359
  } else if (forceCloud) {
6339
6360
  lines.push("FIX ROUTING PLAN (forceCloud: bypassing triage)");
@@ -6531,7 +6552,7 @@ var TrieCloudFixTool = class {
6531
6552
  if (pending.length === 0) {
6532
6553
  try {
6533
6554
  console.log("Loading issues from memory...");
6534
- const { getRecentIssues } = await import("./issue-store-4FPABLC6.js");
6555
+ const { getRecentIssues } = await import("./issue-store-RM3XLLKG.js");
6535
6556
  const recentIssues = await getRecentIssues({ limit: 50, includeResolved: false });
6536
6557
  console.log(`Found ${recentIssues.length} recent issues in memory`);
6537
6558
  const memoryIssues = recentIssues.map((storedIssue) => ({
@@ -6540,13 +6561,13 @@ var TrieCloudFixTool = class {
6540
6561
  issue: storedIssue.issue,
6541
6562
  fix: storedIssue.fix,
6542
6563
  file: storedIssue.file,
6543
- line: storedIssue.line,
6564
+ ...storedIssue.line !== void 0 && { line: storedIssue.line },
6544
6565
  confidence: 0.8,
6545
6566
  // Default confidence for memory issues
6546
6567
  autoFixable: true,
6547
6568
  // Memory issues are generally auto-fixable
6548
6569
  agent: storedIssue.agent,
6549
- category: storedIssue.category
6570
+ ...storedIssue.category && { category: storedIssue.category }
6550
6571
  }));
6551
6572
  console.log(`Converted ${memoryIssues.length} memory issues for cloud dispatch`);
6552
6573
  if (issueIds && issueIds.length > 0) {
@@ -6561,17 +6582,17 @@ var TrieCloudFixTool = class {
6561
6582
  const issues = pending.map((p) => ({
6562
6583
  id: p.id,
6563
6584
  severity: p.severity ?? "moderate",
6564
- effort: p.effort,
6565
6585
  issue: p.issue,
6566
6586
  fix: p.suggestedFix,
6567
6587
  file: p.file,
6568
6588
  line: p.line,
6569
6589
  confidence: p.confidence,
6570
6590
  autoFixable: p.autoFixable ?? false,
6571
- agent: "trie_scan",
6572
- cwe: p.cwe,
6573
- owasp: p.owasp,
6574
- category: p.category
6591
+ agent: "trie_fix",
6592
+ ...p.effort && { effort: p.effort },
6593
+ ...p.cwe && { cwe: p.cwe },
6594
+ ...p.owasp && { owasp: p.owasp },
6595
+ ...p.category && { category: p.category }
6575
6596
  }));
6576
6597
  if (issueIds && issueIds.length > 0) {
6577
6598
  return issues.filter((i) => issueIds.includes(i.id));
@@ -6971,7 +6992,7 @@ var TrieQueryContextTool = class {
6971
6992
  }
6972
6993
  if (includeIncidents) {
6973
6994
  try {
6974
- const { ContextGraph: ContextGraph2 } = await import("./graph-J4OGTYCO.js");
6995
+ const { ContextGraph: ContextGraph2 } = await import("./graph-JO7GG65P.js");
6975
6996
  const graph = new ContextGraph2(workDir);
6976
6997
  const allNodes = await graph.listNodes();
6977
6998
  const incidentNodes = allNodes.filter((n) => n.type === "incident");
@@ -8236,7 +8257,7 @@ ${truncated}`;
8236
8257
  const goalId = input.goalId ? String(input.goalId).trim() : void 0;
8237
8258
  try {
8238
8259
  onProgress?.("Loading goals...");
8239
- const { getActiveGoals } = await import("./goal-validator-DV6DRSGF.js");
8260
+ const { getActiveGoals } = await import("./goal-validator-FU5QWDQT.js");
8240
8261
  const agentState = getProjectState(directory);
8241
8262
  await agentState.load();
8242
8263
  const allGoals = await getActiveGoals(directory);
@@ -8245,7 +8266,7 @@ ${truncated}`;
8245
8266
  return goalId ? `No active goal found with ID: ${goalId}` : "No active goals to check. Add goals in the Goals view first.";
8246
8267
  }
8247
8268
  onProgress?.("Scanning codebase for violations...");
8248
- const { analyzeFilesRapidly } = await import("./fast-analyzer-CTT3MCPE.js");
8269
+ const { analyzeFilesRapidly } = await import("./fast-analyzer-U6URGNQT.js");
8249
8270
  const analysisOptions = {
8250
8271
  maxFiles: 50,
8251
8272
  enableSmartBatching: true
@@ -8259,8 +8280,8 @@ ${truncated}`;
8259
8280
  const cacheInfo2 = analysisResult.cacheHitRatio > 0 ? ` (${Math.round(analysisResult.cacheHitRatio * 100)}% cache hit, ${analysisResult.timeMs}ms)` : ` (${analysisResult.timeMs}ms)`;
8260
8281
  return `\u2713 Scan complete! No violations found for ${goalsToCheck.length} goal(s).${cacheInfo2}`;
8261
8282
  }
8262
- const { storeIssues } = await import("./issue-store-4FPABLC6.js");
8263
- const { basename } = await import("path");
8283
+ const { storeIssues: storeIssues2 } = await import("./issue-store-RM3XLLKG.js");
8284
+ const { basename: basename2 } = await import("path");
8264
8285
  const issuesToStore = violations.map((v, i) => ({
8265
8286
  id: `goal-violation-${Date.now()}-${i}`,
8266
8287
  file: v.file,
@@ -8272,7 +8293,7 @@ ${truncated}`;
8272
8293
  confidence: 80,
8273
8294
  autoFixable: false
8274
8295
  }));
8275
- await storeIssues(issuesToStore, basename(directory), directory);
8296
+ await storeIssues2(issuesToStore, basename2(directory), directory);
8276
8297
  let violationsReport = `Found ${violations.length} violation(s):
8277
8298
 
8278
8299
  `;
@@ -8338,7 +8359,7 @@ ${truncated}`;
8338
8359
  }
8339
8360
  try {
8340
8361
  onProgress?.("Gathering evidence for hypothesis...");
8341
- const { gatherEvidenceForHypothesis } = await import("./hypothesis-O72ZLVOW.js");
8362
+ const { gatherEvidenceForHypothesis } = await import("./hypothesis-JURDWVDC.js");
8342
8363
  const evidence = await gatherEvidenceForHypothesis(hypothesisId, directory);
8343
8364
  if (evidence.length === 0) {
8344
8365
  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.`;
@@ -8602,7 +8623,7 @@ function ChatView() {
8602
8623
  const saveChat = async () => {
8603
8624
  try {
8604
8625
  const workDir = getWorkingDirectory(void 0, true);
8605
- const { getChatStore: getChatStore2 } = await import("./chat-store-OJLJCJFI.js");
8626
+ const { getChatStore: getChatStore2 } = await import("./chat-store-O3IJ5PMN.js");
8606
8627
  const store = getChatStore2(workDir);
8607
8628
  const sessionId = await store.saveSession(
8608
8629
  messages,
@@ -8802,10 +8823,18 @@ ${contextBlock}`;
8802
8823
  const goals = agentState.getAllGoals();
8803
8824
  dispatch({
8804
8825
  type: "SET_GOALS",
8805
- goals: goals.map((g) => {
8806
- const base = { id: g.id, description: g.description, type: g.type, target: g.target, currentValue: g.currentValue, startValue: g.startValue, status: g.status, autoGenerated: g.autoGenerated, updatedAt: g.updatedAt, ...g.category != null ? { category: g.category } : {} };
8807
- return base;
8808
- })
8826
+ goals: goals.map((g) => ({
8827
+ id: g.id,
8828
+ description: g.description,
8829
+ type: g.type,
8830
+ target: g.target,
8831
+ currentValue: g.currentValue,
8832
+ status: g.status,
8833
+ autoGenerated: g.autoGenerated,
8834
+ updatedAt: g.updatedAt,
8835
+ ...g.startValue !== void 0 && { startValue: g.startValue },
8836
+ ...g.category != null && { category: g.category }
8837
+ }))
8809
8838
  });
8810
8839
  }
8811
8840
  if (toolNames.has("trie_add_hypothesis") || toolNames.has("trie_test_hypothesis")) {
@@ -9229,7 +9258,7 @@ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
9229
9258
  var MAIN_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent", "chat"];
9230
9259
  async function applyGoalFix(fix, dispatch) {
9231
9260
  try {
9232
- const { runAIAnalysis, isAIAvailable: isAIAvailable2 } = await import("./client-INNE2GGZ.js");
9261
+ const { runAIAnalysis: runAIAnalysis2, isAIAvailable: isAIAvailable2 } = await import("./client-ZHOLZTRW.js");
9233
9262
  if (!isAIAvailable2()) {
9234
9263
  dispatch({ type: "DISMISS_FIX", id: fix.id });
9235
9264
  getOutputManager().nudge("AI not available for fix", "warning");
@@ -9238,7 +9267,7 @@ async function applyGoalFix(fix, dispatch) {
9238
9267
  const projectPath = getWorkingDirectory(void 0, true);
9239
9268
  const fullPath = join3(projectPath, fix.file);
9240
9269
  const content = await readFile4(fullPath, "utf-8");
9241
- const result = await runAIAnalysis({
9270
+ const result = await runAIAnalysis2({
9242
9271
  systemPrompt: `You are a precise code fixer. The user has a quality goal: "${fix.goalDescription}".
9243
9272
  A violation was detected: "${fix.description}"
9244
9273
  Suggested fix: "${fix.suggestedFix}"
@@ -9264,7 +9293,7 @@ ${content}
9264
9293
  fixedContent = fixedContent.replace(/^```\w*\n?/, "").replace(/\n?```$/, "");
9265
9294
  }
9266
9295
  await writeFile2(fullPath, fixedContent, "utf-8");
9267
- const { recordGoalViolationFixed, getActiveGoals } = await import("./goal-validator-DV6DRSGF.js");
9296
+ const { recordGoalViolationFixed, getActiveGoals } = await import("./goal-validator-FU5QWDQT.js");
9268
9297
  const goals = await getActiveGoals(projectPath);
9269
9298
  const matchedGoal = goals.find((g) => g.description === fix.goalDescription);
9270
9299
  if (matchedGoal) {
@@ -9302,7 +9331,7 @@ function DashboardApp({ onReady }) {
9302
9331
  const workDir = getWorkingDirectory(void 0, true);
9303
9332
  await mkdir2(getTrieDirectory(workDir), { recursive: true });
9304
9333
  await writeFile2(configPath, JSON.stringify(stateRef.current.agentConfig, null, 2), "utf-8");
9305
- const { saveAutonomyConfig: saveAutonomyConfig2, loadAutonomyConfig: loadAutonomyConfig2 } = await import("./autonomy-config-ZCOSTMPD.js");
9334
+ const { saveAutonomyConfig: saveAutonomyConfig2, loadAutonomyConfig: loadAutonomyConfig2 } = await import("./autonomy-config-RKLZW4XL.js");
9306
9335
  const autonomy = await loadAutonomyConfig2(workDir);
9307
9336
  autonomy.aiWatcher = stateRef.current.agentConfig.aiWatcher;
9308
9337
  await saveAutonomyConfig2(workDir, autonomy);
@@ -9343,10 +9372,20 @@ function DashboardApp({ onReady }) {
9343
9372
  const goals = agentState.getAllGoals();
9344
9373
  dispatchRef.current({
9345
9374
  type: "SET_GOALS",
9346
- goals: goals.map((g) => {
9347
- const base = { id: g.id, description: g.description, type: g.type, target: g.target, currentValue: g.currentValue, startValue: g.startValue, status: g.status, autoGenerated: g.autoGenerated, updatedAt: g.updatedAt, ...g.achievedAt != null ? { achievedAt: g.achievedAt } : {}, ...g.achievedBy != null ? { achievedBy: g.achievedBy } : {}, ...g.category != null ? { category: g.category } : {} };
9348
- return base;
9349
- })
9375
+ goals: goals.map((g) => ({
9376
+ id: g.id,
9377
+ description: g.description,
9378
+ type: g.type,
9379
+ target: g.target,
9380
+ currentValue: g.currentValue,
9381
+ status: g.status,
9382
+ autoGenerated: g.autoGenerated,
9383
+ updatedAt: g.updatedAt,
9384
+ ...g.startValue !== void 0 && { startValue: g.startValue },
9385
+ ...g.achievedAt != null && { achievedAt: g.achievedAt },
9386
+ ...g.achievedBy != null && { achievedBy: g.achievedBy },
9387
+ ...g.category != null && { category: g.category }
9388
+ }))
9350
9389
  });
9351
9390
  } catch {
9352
9391
  }
@@ -9370,7 +9409,7 @@ function DashboardApp({ onReady }) {
9370
9409
  const loadPersistedNudges = useCallback7(async () => {
9371
9410
  try {
9372
9411
  const workDir = getWorkingDirectory(void 0, true);
9373
- const { getStorage: getStorage2 } = await import("./tiered-storage-VZL7KK64.js");
9412
+ const { getStorage: getStorage2 } = await import("./tiered-storage-3TUUR3L2.js");
9374
9413
  const storage = getStorage2(workDir);
9375
9414
  await storage.initialize();
9376
9415
  const nudges = await storage.queryNudges({ resolved: false, limit: 50 });
@@ -9598,6 +9637,17 @@ var InteractiveDashboard = class {
9598
9637
  updateHandler = null;
9599
9638
  getConfigFn = null;
9600
9639
  async start() {
9640
+ if (!process.stdin.isTTY || typeof process.stdin.setRawMode !== "function") {
9641
+ return;
9642
+ }
9643
+ try {
9644
+ const currentMode = process.stdin.isRaw;
9645
+ if (currentMode === void 0) {
9646
+ return;
9647
+ }
9648
+ } catch {
9649
+ return;
9650
+ }
9601
9651
  this.app = render(
9602
9652
  React11.createElement(App, {
9603
9653
  onReady: (handler, getConfig) => {
@@ -9627,6 +9677,1401 @@ var InteractiveDashboard = class {
9627
9677
  }
9628
9678
  };
9629
9679
 
9680
+ // src/tools/watch.ts
9681
+ import { watch, existsSync as existsSync6, readFileSync as readFileSync2 } from "fs";
9682
+ import { stat, readFile as readFile5 } from "fs/promises";
9683
+ import { join as join4, extname as extname3, basename } from "path";
9684
+ import { createHash as createHash2 } from "crypto";
9685
+ var WATCH_EXTENSIONS = /* @__PURE__ */ new Set([
9686
+ ".ts",
9687
+ ".tsx",
9688
+ ".js",
9689
+ ".jsx",
9690
+ ".mjs",
9691
+ ".vue",
9692
+ ".svelte",
9693
+ ".astro",
9694
+ ".py",
9695
+ ".go",
9696
+ ".rs"
9697
+ ]);
9698
+ var SKIP_DIRS = /* @__PURE__ */ new Set([
9699
+ "node_modules",
9700
+ ".git",
9701
+ "dist",
9702
+ "build",
9703
+ ".next",
9704
+ ".nuxt",
9705
+ "coverage",
9706
+ ".turbo",
9707
+ ".cache"
9708
+ ]);
9709
+ var TrieWatchTool = class _TrieWatchTool {
9710
+ extractionPipeline = null;
9711
+ watchedDirectory = "";
9712
+ codebaseIndex = null;
9713
+ state = {
9714
+ isRunning: false,
9715
+ lastScan: /* @__PURE__ */ new Map(),
9716
+ pendingFiles: /* @__PURE__ */ new Set(),
9717
+ scanDebounceTimer: null,
9718
+ issueCache: /* @__PURE__ */ new Map(),
9719
+ totalIssuesFound: 0,
9720
+ filesScanned: 0,
9721
+ nudgedFiles: /* @__PURE__ */ new Set(),
9722
+ nudges: [],
9723
+ lastAutoScan: 0,
9724
+ autoScanInProgress: false,
9725
+ tokenBudget: {
9726
+ used: 0,
9727
+ windowStart: Date.now(),
9728
+ hourlyLimit: 5e4,
9729
+ scansSaved: 0
9730
+ },
9731
+ cleanFiles: /* @__PURE__ */ new Map()
9732
+ };
9733
+ watchers = /* @__PURE__ */ new Map();
9734
+ streamingManager = void 0;
9735
+ dashboard = void 0;
9736
+ lastHypothesisCheck = 0;
9737
+ pipelineSyncTimer = null;
9738
+ static HYPOTHESIS_CHECK_INTERVAL_MS = 3e5;
9739
+ // Check every 5 minutes
9740
+ static PIPELINE_SYNC_INTERVAL_MS = 30 * 60 * 1e3;
9741
+ // 30 minutes
9742
+ async execute(args) {
9743
+ const { action, directory, debounceMs = 1e3 } = args;
9744
+ switch (action) {
9745
+ case "start":
9746
+ return this.startWatching(getWorkingDirectory(directory), debounceMs);
9747
+ case "stop":
9748
+ return await this.stopWatching();
9749
+ case "status":
9750
+ return await this.getStatus();
9751
+ case "issues":
9752
+ return this.getCurrentIssues();
9753
+ case "nudges":
9754
+ return this.getNudges();
9755
+ default:
9756
+ return {
9757
+ content: [{
9758
+ type: "text",
9759
+ text: `Unknown action: ${action}. Use 'start', 'stop', 'status', or 'issues'.`
9760
+ }]
9761
+ };
9762
+ }
9763
+ }
9764
+ async startWatching(directory, debounceMs) {
9765
+ if (this.state.isRunning) {
9766
+ return {
9767
+ content: [{
9768
+ type: "text",
9769
+ text: "[!] Watch mode is already running. Use `trie_watch stop` to stop it first."
9770
+ }]
9771
+ };
9772
+ }
9773
+ if (!isTrieInitialized(directory)) {
9774
+ return {
9775
+ content: [{
9776
+ type: "text",
9777
+ text: "Trie is not initialized for this project. Run `trie init` first."
9778
+ }]
9779
+ };
9780
+ }
9781
+ const anthropicApiKey = process.env.ANTHROPIC_API_KEY;
9782
+ if (anthropicApiKey) {
9783
+ this.extractionPipeline = new ExtractionPipeline({
9784
+ workingDirectory: directory,
9785
+ anthropicApiKey
9786
+ });
9787
+ await this.extractionPipeline.initialize();
9788
+ }
9789
+ this.codebaseIndex = new CodebaseIndex(directory);
9790
+ this.state.isRunning = true;
9791
+ this.watchedDirectory = directory;
9792
+ this.state.issueCache.clear();
9793
+ this.state.totalIssuesFound = 0;
9794
+ this.state.filesScanned = 0;
9795
+ this.state.nudgedFiles.clear();
9796
+ this.state.nudges = [];
9797
+ try {
9798
+ const storage = getStorage(directory);
9799
+ await storage.initialize();
9800
+ const unresolvedNudges = await storage.queryNudges({ resolved: false });
9801
+ console.debug(`[Watch] Found ${unresolvedNudges.length} unresolved nudges in storage`);
9802
+ for (const nudge of unresolvedNudges) {
9803
+ let mappedSeverity = "high";
9804
+ if (nudge.severity === "critical") {
9805
+ mappedSeverity = "critical";
9806
+ } else if (nudge.severity === "high") {
9807
+ mappedSeverity = "high";
9808
+ }
9809
+ this.state.nudges.push({
9810
+ file: nudge.file || "unknown",
9811
+ // Keep full path, don't use basename
9812
+ message: nudge.message,
9813
+ severity: mappedSeverity,
9814
+ timestamp: new Date(nudge.timestamp).toLocaleTimeString("en-US", { hour12: false })
9815
+ });
9816
+ console.debug(`[Watch] Loaded nudge: ${nudge.message.slice(0, 60)}... (${nudge.severity} -> ${mappedSeverity})`);
9817
+ }
9818
+ if (unresolvedNudges.length > 0) {
9819
+ console.log(`[Watch] \u2713 Loaded ${unresolvedNudges.length} unresolved nudges from storage`);
9820
+ } else {
9821
+ console.debug(`[Watch] No unresolved nudges found in storage`);
9822
+ }
9823
+ } catch (error) {
9824
+ console.error("[Watch] Failed to load nudges from storage:", error);
9825
+ }
9826
+ try {
9827
+ const graph = new ContextGraph(directory);
9828
+ const allNodes = await graph.listNodes();
9829
+ const unresolvedIncidents = allNodes.filter(
9830
+ (n) => n.type === "incident" && !n.data.resolved
9831
+ );
9832
+ console.debug(`[Watch] Found ${unresolvedIncidents.length} unresolved incidents in context graph`);
9833
+ for (const incident of unresolvedIncidents) {
9834
+ const incidentData = incident.data;
9835
+ let mappedSeverity = "high";
9836
+ if (incidentData.severity === "critical") {
9837
+ mappedSeverity = "critical";
9838
+ } else if (incidentData.severity === "major") {
9839
+ mappedSeverity = "critical";
9840
+ } else if (incidentData.severity === "minor") {
9841
+ mappedSeverity = "high";
9842
+ }
9843
+ const edges = await graph.getEdges(incident.id);
9844
+ const linkedFiles = edges.filter((e) => e.type === "causedBy" || e.type === "affects").map((e) => {
9845
+ const node = allNodes.find((n) => n.id === e.to_id || n.id === e.from_id);
9846
+ if (node?.type === "file") {
9847
+ return node.data.path;
9848
+ }
9849
+ return null;
9850
+ }).filter((f) => f !== null);
9851
+ const file = linkedFiles[0] || "unknown";
9852
+ const message = `INCIDENT: ${incidentData.description}`;
9853
+ this.state.nudges.push({
9854
+ file,
9855
+ message,
9856
+ severity: mappedSeverity,
9857
+ timestamp: new Date(incidentData.timestamp).toLocaleTimeString("en-US", { hour12: false })
9858
+ });
9859
+ console.debug(`[Watch] Loaded incident: ${incidentData.description.slice(0, 60)}... (${incidentData.severity} -> ${mappedSeverity})`);
9860
+ }
9861
+ if (unresolvedIncidents.length > 0) {
9862
+ console.log(`[Watch] \u2713 Loaded ${unresolvedIncidents.length} unresolved incidents from context graph`);
9863
+ } else {
9864
+ console.debug(`[Watch] No unresolved incidents found in context graph`);
9865
+ }
9866
+ } catch (error) {
9867
+ console.error("[Watch] Failed to load incidents from context graph:", error);
9868
+ }
9869
+ if (!isInteractiveMode()) {
9870
+ 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");
9871
+ console.error("TRIE AGENT - NOW WATCHING");
9872
+ 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");
9873
+ console.error("Your Trie agent is now watching over your codebase.");
9874
+ console.error("Signal extraction: ENABLED (building governance ledger)");
9875
+ console.error(`Watching: ${directory}`);
9876
+ console.error(`Debounce: ${debounceMs}ms`);
9877
+ console.error("");
9878
+ }
9879
+ if (isInteractiveMode()) {
9880
+ this.streamingManager = new StreamingManager();
9881
+ this.dashboard = new InteractiveDashboard();
9882
+ this.streamingManager.subscribe((update) => this.dashboard?.handleStreamUpdate(update));
9883
+ const outputManager = getOutputManager();
9884
+ outputManager.setMode("tui");
9885
+ outputManager.setStreamingManager(this.streamingManager);
9886
+ await this.dashboard.start();
9887
+ this.streamingManager.reportWatchStatus({ watching: true, directories: 0, debounceMs });
9888
+ } else {
9889
+ getOutputManager().setMode("console");
9890
+ }
9891
+ await this.watchDirectory(directory, debounceMs);
9892
+ await this.watchContextGraph(directory);
9893
+ if (this.streamingManager) {
9894
+ this.streamingManager.reportWatchStatus({
9895
+ watching: true,
9896
+ directories: this.watchers.size,
9897
+ debounceMs
9898
+ });
9899
+ }
9900
+ setTimeout(() => {
9901
+ void this.initialGoalComplianceScan();
9902
+ void this.initialHypothesisGeneration();
9903
+ void this.syncPipelineIntegrations();
9904
+ }, 1e3);
9905
+ this.pipelineSyncTimer = setInterval(() => {
9906
+ void this.syncPipelineIntegrations();
9907
+ }, _TrieWatchTool.PIPELINE_SYNC_INTERVAL_MS);
9908
+ const indexStatus = this.codebaseIndex?.isEmpty() ? "BUILDING (one-time, speeds up goal checks)" : "READY";
9909
+ return {
9910
+ content: [{
9911
+ type: "text",
9912
+ text: `**TRIE AGENT ACTIVATED**
9913
+
9914
+ Your Trie agent is now autonomously watching and learning from your codebase.
9915
+
9916
+ **Watching:** \`${directory}\`
9917
+ **Debounce:** ${debounceMs}ms (waits for you to stop typing)
9918
+ **Signal Extraction:** ${process.env.ANTHROPIC_API_KEY ? "ENABLED" : "LIMITED (set ANTHROPIC_API_KEY for full extraction)"}
9919
+ **Codebase Index:** ${indexStatus}
9920
+
9921
+ ### How the agent works:
9922
+ 1. You write/edit code
9923
+ 2. Agent detects the change
9924
+ 3. Extracts governance, facts, blockers -> stores in ledger
9925
+ 4. Predicts risks based on historical patterns
9926
+ 5. Nudges you if something looks risky
9927
+
9928
+ ### The agent learns:
9929
+ - Every commit builds the governance ledger
9930
+ - \`trie gotcha\` queries the ledger for predictions
9931
+ - \`trie ok\` / \`trie bad\` teach the agent what matters
9932
+
9933
+ ### Commands:
9934
+ - \`trie_watch status\` - See agent status
9935
+ - \`trie_watch stop\` - Stop the agent
9936
+ - \`trie_index status\` - Check codebase index`
9937
+ }]
9938
+ };
9939
+ }
9940
+ shouldSkipPath(filePath) {
9941
+ const parts = filePath.split("/");
9942
+ return parts.some((p) => SKIP_DIRS.has(p) || p.startsWith(".") && p !== ".");
9943
+ }
9944
+ async watchDirectory(dir, debounceMs) {
9945
+ if (!existsSync6(dir)) return;
9946
+ try {
9947
+ const dirStat = await stat(dir);
9948
+ if (!dirStat.isDirectory()) return;
9949
+ const watcher = watch(dir, { persistent: true, recursive: true }, (_eventType, filename) => {
9950
+ if (!filename) return;
9951
+ if (this.shouldSkipPath(filename)) return;
9952
+ const ext = extname3(filename).toLowerCase();
9953
+ if (!WATCH_EXTENSIONS.has(ext)) return;
9954
+ const fullPath = join4(dir, filename);
9955
+ if (!existsSync6(fullPath)) return;
9956
+ this.state.pendingFiles.add(fullPath);
9957
+ if (this.state.scanDebounceTimer) {
9958
+ clearTimeout(this.state.scanDebounceTimer);
9959
+ }
9960
+ this.state.scanDebounceTimer = setTimeout(() => {
9961
+ this.processPendingFiles();
9962
+ }, debounceMs);
9963
+ });
9964
+ watcher.on("error", (err) => {
9965
+ if (!isInteractiveMode()) {
9966
+ console.error(`[!] Watcher error: ${err.message}`);
9967
+ }
9968
+ watcher.close();
9969
+ this.watchers.delete(dir);
9970
+ });
9971
+ this.watchers.set(dir, watcher);
9972
+ if (this.streamingManager) {
9973
+ this.streamingManager.reportWatchStatus({
9974
+ watching: true,
9975
+ directories: 1,
9976
+ debounceMs
9977
+ });
9978
+ }
9979
+ } catch {
9980
+ }
9981
+ }
9982
+ /**
9983
+ * Watch .trie/context.json for incident changes
9984
+ */
9985
+ async watchContextGraph(directory) {
9986
+ const contextPath = join4(getTrieDirectory(directory), "context.json");
9987
+ if (!existsSync6(contextPath)) {
9988
+ console.debug("[Watch] No context.json found, skipping incident watcher");
9989
+ return;
9990
+ }
9991
+ try {
9992
+ const watcher = watch(contextPath, { persistent: true }, async (_eventType, _filename) => {
9993
+ console.debug("[Watch] context.json changed, reloading incidents...");
9994
+ await this.reloadIncidents(directory);
9995
+ });
9996
+ watcher.on("error", (err) => {
9997
+ console.error(`[Watch] Context watcher error: ${err.message}`);
9998
+ watcher.close();
9999
+ });
10000
+ this.watchers.set("context.json", watcher);
10001
+ console.debug("[Watch] \u2713 Watching context.json for incident changes");
10002
+ } catch (error) {
10003
+ console.error("[Watch] Failed to set up context.json watcher:", error);
10004
+ }
10005
+ }
10006
+ /**
10007
+ * Reload incidents from context graph
10008
+ */
10009
+ async reloadIncidents(directory) {
10010
+ try {
10011
+ const graph = new ContextGraph(directory);
10012
+ const allNodes = await graph.listNodes();
10013
+ const unresolvedIncidents = allNodes.filter(
10014
+ (n) => n.type === "incident" && !n.data.resolved
10015
+ );
10016
+ this.state.nudges = this.state.nudges.filter((n) => !n.message.startsWith("INCIDENT:"));
10017
+ for (const incident of unresolvedIncidents) {
10018
+ const incidentData = incident.data;
10019
+ let mappedSeverity = "high";
10020
+ if (incidentData.severity === "critical") {
10021
+ mappedSeverity = "critical";
10022
+ } else if (incidentData.severity === "major") {
10023
+ mappedSeverity = "critical";
10024
+ } else if (incidentData.severity === "minor") {
10025
+ mappedSeverity = "high";
10026
+ }
10027
+ const edges = await graph.getEdges(incident.id);
10028
+ const linkedFiles = edges.filter((e) => e.type === "causedBy" || e.type === "affects").map((e) => {
10029
+ const node = allNodes.find((n) => n.id === e.to_id || n.id === e.from_id);
10030
+ if (node?.type === "file") {
10031
+ return node.data.path;
10032
+ }
10033
+ return null;
10034
+ }).filter((f) => f !== null);
10035
+ const file = linkedFiles[0] || "unknown";
10036
+ const message = `INCIDENT: ${incidentData.description}`;
10037
+ this.state.nudges.push({
10038
+ file,
10039
+ message,
10040
+ severity: mappedSeverity,
10041
+ timestamp: new Date(incidentData.timestamp).toLocaleTimeString("en-US", { hour12: false })
10042
+ });
10043
+ }
10044
+ console.log(`[Watch] \u2713 Reloaded ${unresolvedIncidents.length} unresolved incidents`);
10045
+ } catch (error) {
10046
+ console.error("[Watch] Failed to reload incidents:", error);
10047
+ }
10048
+ }
10049
+ async processPendingFiles() {
10050
+ if (this.state.pendingFiles.size === 0) return;
10051
+ const files = Array.from(this.state.pendingFiles);
10052
+ this.state.pendingFiles.clear();
10053
+ if (!isInteractiveMode()) {
10054
+ console.error(`
10055
+ Detected changes in ${files.length} file(s):`);
10056
+ for (const file of files) {
10057
+ console.error(` - ${basename(file)}`);
10058
+ }
10059
+ console.error("");
10060
+ }
10061
+ try {
10062
+ const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
10063
+ if (this.extractionPipeline) {
10064
+ try {
10065
+ const fileContents = await Promise.all(
10066
+ files.map(async (file) => {
10067
+ try {
10068
+ const content = await readFile5(file, "utf-8");
10069
+ return { file, content };
10070
+ } catch {
10071
+ return null;
10072
+ }
10073
+ })
10074
+ );
10075
+ const validFiles = fileContents.filter((f) => f !== null);
10076
+ if (validFiles.length > 0) {
10077
+ const combinedContent = validFiles.map(
10078
+ (f) => `File: ${basename(f.file)}
10079
+ ${f.content.slice(0, 1e3)}`
10080
+ // First 1KB of each file
10081
+ ).join("\n\n---\n\n");
10082
+ if (!isInteractiveMode()) {
10083
+ console.error("[*] Extracting signals from changes...");
10084
+ }
10085
+ const signal = await this.extractionPipeline.process(combinedContent, {
10086
+ sourceType: "file",
10087
+ sourceId: `watch-${Date.now()}`
10088
+ });
10089
+ if (signal.governance.length > 0 || signal.facts.length > 0 || signal.blockers.length > 0) {
10090
+ const govCount = signal.governance.length;
10091
+ if (!isInteractiveMode()) {
10092
+ console.error(` [+] Extracted: ${govCount} governance, ${signal.facts.length} facts, ${signal.blockers.length} blockers`);
10093
+ }
10094
+ if (this.streamingManager) {
10095
+ this.streamingManager.reportSignalExtraction({
10096
+ governance: govCount,
10097
+ facts: signal.facts.length,
10098
+ blockers: signal.blockers.length,
10099
+ questions: signal.questions.length
10100
+ });
10101
+ }
10102
+ }
10103
+ }
10104
+ } catch (error) {
10105
+ if (!isInteractiveMode()) {
10106
+ console.error(` [!] Signal extraction failed: ${error}`);
10107
+ }
10108
+ }
10109
+ }
10110
+ void this.autoScanFiles(files).catch((err) => {
10111
+ getOutputManager().log("warn", `Auto scan failed: ${err}`);
10112
+ });
10113
+ await this.discoverPatternsFromIssues(projectPath);
10114
+ const now = Date.now();
10115
+ if (now - this.lastHypothesisCheck > _TrieWatchTool.HYPOTHESIS_CHECK_INTERVAL_MS) {
10116
+ this.checkAndGenerateHypotheses(projectPath);
10117
+ this.lastHypothesisCheck = now;
10118
+ }
10119
+ if (this.streamingManager) {
10120
+ const now2 = Date.now();
10121
+ for (const file of files) {
10122
+ const lastReport = this.state.lastScan.get(file) || 0;
10123
+ if (now2 - lastReport > 2e3) {
10124
+ this.streamingManager.reportWatchChange(file);
10125
+ }
10126
+ }
10127
+ }
10128
+ this.state.filesScanned += files.length;
10129
+ for (const file of files) {
10130
+ this.state.lastScan.set(file, Date.now());
10131
+ if (this.codebaseIndex) {
10132
+ const relativePath = file.replace(projectPath + "/", "");
10133
+ void this.codebaseIndex.indexFile(relativePath).then(() => {
10134
+ void this.codebaseIndex?.save();
10135
+ });
10136
+ }
10137
+ }
10138
+ } catch (error) {
10139
+ if (!isInteractiveMode()) {
10140
+ console.error(`Scan error: ${error}`);
10141
+ }
10142
+ }
10143
+ }
10144
+ isQuiet() {
10145
+ const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
10146
+ const quietPath = join4(getTrieDirectory(projectPath), "quiet.json");
10147
+ try {
10148
+ const raw = readFileSync2(quietPath, "utf-8");
10149
+ const data = JSON.parse(raw);
10150
+ const until = new Date(data.until).getTime();
10151
+ return Date.now() < until;
10152
+ } catch {
10153
+ return false;
10154
+ }
10155
+ }
10156
+ /**
10157
+ * Check and generate hypotheses autonomously
10158
+ * Claude observes patterns and creates new hypotheses to test
10159
+ */
10160
+ async checkAndGenerateHypotheses(projectPath) {
10161
+ if (!isAIAvailable()) return;
10162
+ try {
10163
+ const { getHypothesisEngine } = await import("./hypothesis-JURDWVDC.js");
10164
+ const { getOutputManager: getOutputManager2 } = await import("./output-manager-FX4V7ERT.js");
10165
+ const hypothesisEngine = getHypothesisEngine(projectPath);
10166
+ const recentIssues = Array.from(this.state.issueCache.values()).flat();
10167
+ const patterns = [];
10168
+ const observations = [];
10169
+ if (this.state.nudges.length > 0) {
10170
+ const nudgesByFile = {};
10171
+ for (const nudge of this.state.nudges) {
10172
+ nudgesByFile[nudge.file] = (nudgesByFile[nudge.file] || 0) + 1;
10173
+ }
10174
+ const topFiles = Object.entries(nudgesByFile).sort(([, a], [, b]) => b - a).slice(0, 3);
10175
+ if (topFiles[0] && topFiles[0][1] > 2) {
10176
+ observations.push(`File ${topFiles[0][0]} has ${topFiles[0][1]} repeated issues this session`);
10177
+ }
10178
+ }
10179
+ if (this.state.nudges.length > 5) {
10180
+ observations.push(`High issue detection rate: ${this.state.nudges.length} violations detected in watch session`);
10181
+ }
10182
+ let generated = await hypothesisEngine.generateHypothesesWithAI({
10183
+ recentIssues,
10184
+ patterns,
10185
+ observations
10186
+ });
10187
+ if (generated.length === 0) {
10188
+ generated = await hypothesisEngine.autoGenerateHypotheses();
10189
+ }
10190
+ for (const hypothesis of generated) {
10191
+ const message = `[New Hypothesis] "${hypothesis.statement}" (${Math.round(hypothesis.confidence * 100)}% confidence)`;
10192
+ getOutputManager2().nudge(
10193
+ message,
10194
+ "info",
10195
+ void 0,
10196
+ 1e4
10197
+ );
10198
+ if (!isInteractiveMode()) {
10199
+ console.error(`
10200
+ [?] ${message}`);
10201
+ console.error(` Test: ${hypothesis.testCriteria || "Collecting evidence..."}`);
10202
+ }
10203
+ if (this.streamingManager) {
10204
+ this.streamingManager.reportSignalExtraction({
10205
+ governance: 0,
10206
+ facts: 0,
10207
+ blockers: 0,
10208
+ questions: 1
10209
+ // Hypotheses are questions to answer
10210
+ });
10211
+ }
10212
+ }
10213
+ if (recentIssues.length > 10) {
10214
+ await hypothesisEngine.updateConfidenceFromOutcomes();
10215
+ }
10216
+ } catch (error) {
10217
+ if (!isInteractiveMode()) {
10218
+ console.error(` [!] Hypothesis check failed: ${error}`);
10219
+ }
10220
+ }
10221
+ }
10222
+ /**
10223
+ * Discover patterns from accumulated issues
10224
+ * Patterns emerge naturally from your coding workflow
10225
+ */
10226
+ async discoverPatternsFromIssues(projectPath) {
10227
+ const totalIssues = Array.from(this.state.issueCache.values()).flat().length;
10228
+ if (totalIssues < 5) return;
10229
+ try {
10230
+ const { ContextGraph: ContextGraph2 } = await import("./graph-JO7GG65P.js");
10231
+ const { IncidentIndex: IncidentIndex2 } = await import("./incident-index-7CAXUNTL.js");
10232
+ const { TriePatternDiscovery } = await import("./pattern-discovery-F7LU5K6E.js");
10233
+ const graph = new ContextGraph2(projectPath);
10234
+ const incidentIndex = await IncidentIndex2.build(graph, projectPath);
10235
+ const discovery = new TriePatternDiscovery(graph, incidentIndex);
10236
+ const hotPatterns = discovery.discoverHotPatterns(2);
10237
+ for (const hot of hotPatterns) {
10238
+ const existingPatterns = await graph.listNodes();
10239
+ const alreadyExists = existingPatterns.some(
10240
+ (n) => n.type === "pattern" && n.data.description?.includes(hot.path)
10241
+ );
10242
+ if (!alreadyExists) {
10243
+ await graph.addNode("pattern", {
10244
+ description: `${hot.type === "directory" ? "Directory" : "File"} hot zone: ${hot.path}`,
10245
+ appliesTo: [hot.path],
10246
+ confidence: Math.min(0.95, hot.confidence),
10247
+ occurrences: hot.incidentCount,
10248
+ firstSeen: (/* @__PURE__ */ new Date()).toISOString(),
10249
+ lastSeen: (/* @__PURE__ */ new Date()).toISOString(),
10250
+ isAntiPattern: hot.incidentCount >= 3,
10251
+ // 3+ incidents = anti-pattern
10252
+ source: "local"
10253
+ });
10254
+ if (!isInteractiveMode()) {
10255
+ console.error(` [+] Pattern discovered: ${hot.path} (${hot.incidentCount} issues)`);
10256
+ }
10257
+ if (this.streamingManager) {
10258
+ this.streamingManager.reportSignalExtraction({
10259
+ governance: 0,
10260
+ facts: 1,
10261
+ // Patterns are facts about the codebase
10262
+ blockers: 0,
10263
+ questions: 0
10264
+ });
10265
+ }
10266
+ }
10267
+ }
10268
+ if (totalIssues >= 10) {
10269
+ const coOccurrences = await discovery.discoverCoOccurrences(2);
10270
+ for (const coOcc of coOccurrences.slice(0, 3)) {
10271
+ const desc = `Files break together: ${coOcc.files[0]} + ${coOcc.files[1]}`;
10272
+ const existingPatterns = await graph.listNodes();
10273
+ const alreadyExists = existingPatterns.some(
10274
+ (n) => n.type === "pattern" && n.data.description === desc
10275
+ );
10276
+ if (!alreadyExists) {
10277
+ await graph.addNode("pattern", {
10278
+ description: desc,
10279
+ appliesTo: [...coOcc.files],
10280
+ confidence: Math.min(0.95, coOcc.confidence),
10281
+ occurrences: coOcc.coOccurrences,
10282
+ firstSeen: (/* @__PURE__ */ new Date()).toISOString(),
10283
+ lastSeen: (/* @__PURE__ */ new Date()).toISOString(),
10284
+ isAntiPattern: coOcc.confidence > 0.7,
10285
+ source: "local"
10286
+ });
10287
+ if (!isInteractiveMode()) {
10288
+ console.error(` [+] Co-occurrence pattern: ${coOcc.files[0]} + ${coOcc.files[1]}`);
10289
+ }
10290
+ }
10291
+ }
10292
+ }
10293
+ } catch (error) {
10294
+ if (!isInteractiveMode()) {
10295
+ console.error(` [!] Pattern discovery failed: ${error}`);
10296
+ }
10297
+ }
10298
+ }
10299
+ // Defaults -- overridden by config when loaded
10300
+ aiWatcherCooldownMs = 3e4;
10301
+ cleanFileCooldownMs = 3e5;
10302
+ maxFilesPerScan = 5;
10303
+ maxCharsPerFile = 4e3;
10304
+ /**
10305
+ * Use the trie (context graph) to score how urgently a file needs scanning.
10306
+ * Higher score = more worth spending tokens on.
10307
+ */
10308
+ async scoreScanPriority(file, graph, projectPath) {
10309
+ let score = 1;
10310
+ const lastClean = this.state.cleanFiles.get(file);
10311
+ if (lastClean && Date.now() - lastClean < this.cleanFileCooldownMs) {
10312
+ return 0;
10313
+ }
10314
+ const fileNode = await graph.getNode("file", join4(projectPath, file));
10315
+ if (!fileNode) return score;
10316
+ const data = fileNode.data;
10317
+ const riskScores = { critical: 10, high: 6, medium: 2, low: 1 };
10318
+ score += riskScores[data.riskLevel] ?? 1;
10319
+ score += Math.min(data.incidentCount * 3, 12);
10320
+ if (data.changeCount > 10) score += 2;
10321
+ return score;
10322
+ }
10323
+ /**
10324
+ * Roll the token budget window if an hour has passed.
10325
+ * Returns remaining tokens in the current window.
10326
+ */
10327
+ getRemainingBudget() {
10328
+ const budget = this.state.tokenBudget;
10329
+ const elapsed = Date.now() - budget.windowStart;
10330
+ if (elapsed > 36e5) {
10331
+ budget.used = 0;
10332
+ budget.windowStart = Date.now();
10333
+ }
10334
+ return Math.max(0, budget.hourlyLimit - budget.used);
10335
+ }
10336
+ recordTokenUsage(tokens) {
10337
+ this.state.tokenBudget.used += tokens;
10338
+ }
10339
+ /**
10340
+ * AI-powered watcher -- the primary detection system.
10341
+ *
10342
+ * This is the single AI call that handles:
10343
+ * 1. Code review (bugs, security, logic errors)
10344
+ * 2. Goal violation detection (user-defined quality goals)
10345
+ *
10346
+ * When goals are active, files with goal violations bypass priority scoring
10347
+ * so violations are always caught. Throttled by cooldown + token budget.
10348
+ */
10349
+ async autoScanFiles(files) {
10350
+ if (!isAIAvailable()) return;
10351
+ if (this.state.autoScanInProgress) return;
10352
+ const now = Date.now();
10353
+ if (now - this.state.lastAutoScan < this.aiWatcherCooldownMs) return;
10354
+ this.state.autoScanInProgress = true;
10355
+ this.state.lastAutoScan = now;
10356
+ const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
10357
+ try {
10358
+ try {
10359
+ const config = await getAutonomyConfig(projectPath);
10360
+ const wc = config.aiWatcher;
10361
+ if (!wc.enabled) return;
10362
+ this.state.tokenBudget.hourlyLimit = wc.hourlyTokenLimit;
10363
+ this.aiWatcherCooldownMs = wc.scanCooldownSec * 1e3;
10364
+ this.cleanFileCooldownMs = wc.cleanFileCooldownSec * 1e3;
10365
+ this.maxFilesPerScan = wc.maxFilesPerScan;
10366
+ this.maxCharsPerFile = wc.maxCharsPerFile;
10367
+ } catch {
10368
+ }
10369
+ const remaining = this.getRemainingBudget();
10370
+ if (remaining < 500) return;
10371
+ try {
10372
+ const graph = new ContextGraph(projectPath);
10373
+ const { getActiveGoals, recordGoalViolationCaught } = await import("./goal-validator-FU5QWDQT.js");
10374
+ console.debug("[AI Watcher] Loading active goals...");
10375
+ const activeGoals = await getActiveGoals(projectPath);
10376
+ const hasGoals = activeGoals.length > 0;
10377
+ console.debug("[AI Watcher] Goals loaded:", {
10378
+ totalGoals: activeGoals.length,
10379
+ hasGoals,
10380
+ goals: activeGoals.map((g) => ({ id: g.id, description: g.description, status: g.status }))
10381
+ });
10382
+ if (this.isQuiet() && !hasGoals) return;
10383
+ const scored = [];
10384
+ for (const file of files) {
10385
+ const relativePath = file.replace(projectPath + "/", "");
10386
+ const score = await this.scoreScanPriority(relativePath, graph, projectPath);
10387
+ if (hasGoals || score > 0) {
10388
+ scored.push({ file, relativePath, score: Math.max(score, hasGoals ? 1 : 0) });
10389
+ } else {
10390
+ this.state.tokenBudget.scansSaved++;
10391
+ }
10392
+ }
10393
+ if (scored.length === 0) return;
10394
+ scored.sort((a, b) => b.score - a.score);
10395
+ const budgetScale = remaining > 2e4 ? 1 : remaining > 1e4 ? 0.6 : 0.4;
10396
+ const maxFiles = Math.max(1, Math.round(this.maxFilesPerScan * budgetScale));
10397
+ const filesToScan = scored.slice(0, maxFiles);
10398
+ const charLimit = Math.round(this.maxCharsPerFile * (remaining > 15e3 ? 1 : 0.5));
10399
+ const fileContents = await Promise.all(
10400
+ filesToScan.map(async ({ file, relativePath }) => {
10401
+ try {
10402
+ const content = await readFile5(file, "utf-8");
10403
+ return { path: relativePath, content: content.slice(0, charLimit) };
10404
+ } catch {
10405
+ return null;
10406
+ }
10407
+ })
10408
+ );
10409
+ const valid = fileContents.filter(Boolean);
10410
+ if (valid.length === 0) return;
10411
+ const filesBlock = valid.map(
10412
+ (f) => `### ${f.path}
10413
+ \`\`\`
10414
+ ${f.content}
10415
+ \`\`\``
10416
+ ).join("\n\n");
10417
+ let goalsSection = "";
10418
+ if (hasGoals) {
10419
+ goalsSection = `
10420
+ USER-DEFINED GOALS (IMPORTANT - check EVERY file against ALL goals):
10421
+ ${activeGoals.map((g, i) => ` ${i + 1}. "${g.description}"`).join("\n")}
10422
+
10423
+ Goal violations are HIGH PRIORITY. If a file violates any goal, you MUST report it.
10424
+ `;
10425
+ }
10426
+ console.debug("[AI Watcher] Sending files to AI analysis:", {
10427
+ fileCount: valid.length,
10428
+ hasGoals,
10429
+ goalsIncluded: hasGoals,
10430
+ filePaths: valid.map((f) => f.path),
10431
+ goalsSection: goalsSection.slice(0, 200) + (goalsSection.length > 200 ? "..." : "")
10432
+ });
10433
+ const result = await runAIAnalysis({
10434
+ systemPrompt: `You are a code quality watcher. You review code for two things:
10435
+
10436
+ 1. CODE ISSUES: bugs, security vulnerabilities, logic errors, risky patterns
10437
+ 2. GOAL VIOLATIONS: check every file against the user's quality goals
10438
+ ${goalsSection}
10439
+ Reply ONLY with a JSON array. Each element must have:
10440
+ - "file": relative file path
10441
+ - "severity": "critical" | "major" | "minor"
10442
+ - "description": 1-sentence description of what you found
10443
+ - "confidence": number 0-100, how confident you are this is a real issue
10444
+ - "suggestedFix": 1-sentence description of what should change to fix it
10445
+ - "isGoalViolation": true if this violates a user goal, false otherwise
10446
+ - "goalIndex": 0-based index of the violated goal (only if isGoalViolation is true)
10447
+
10448
+ 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.
10449
+
10450
+ If no issues or violations found, reply with: []
10451
+ Output ONLY the JSON array, no markdown fences, no commentary.`,
10452
+ userPrompt: `Review these changed files:
10453
+
10454
+ ${filesBlock}`,
10455
+ maxTokens: 2048,
10456
+ temperature: 0.1
10457
+ });
10458
+ if (result.tokensUsed) {
10459
+ this.recordTokenUsage(result.tokensUsed.input + result.tokensUsed.output);
10460
+ }
10461
+ console.debug("[AI Watcher] AI analysis result:", {
10462
+ success: result.success,
10463
+ contentLength: result.content ? result.content.length : 0,
10464
+ tokensUsed: result.tokensUsed,
10465
+ contentPreview: result.content ? result.content.slice(0, 500) : "null"
10466
+ });
10467
+ if (!result.success || !result.content.trim()) {
10468
+ console.debug("[AI Watcher] AI analysis failed or returned empty content");
10469
+ return;
10470
+ }
10471
+ let issues = [];
10472
+ try {
10473
+ const cleaned = result.content.replace(/```json?\n?|\n?```/g, "").trim();
10474
+ console.debug("[AI Watcher] Parsing AI response:", { cleanedContent: cleaned.slice(0, 300) });
10475
+ issues = JSON.parse(cleaned);
10476
+ if (!Array.isArray(issues)) issues = [];
10477
+ console.debug("[AI Watcher] Parsed issues:", {
10478
+ totalIssues: issues.length,
10479
+ goalViolations: issues.filter((i) => i.isGoalViolation).length,
10480
+ issueTypes: issues.map((i) => ({ file: i.file, isGoalViolation: i.isGoalViolation, goalIndex: i.goalIndex }))
10481
+ });
10482
+ } catch (error) {
10483
+ console.debug("[AI Watcher] Failed to parse AI response:", error);
10484
+ return;
10485
+ }
10486
+ const issuedFiles = new Set(issues.map((i) => i.file));
10487
+ for (const { relativePath } of filesToScan) {
10488
+ if (!issuedFiles.has(relativePath)) {
10489
+ this.state.cleanFiles.set(relativePath, Date.now());
10490
+ }
10491
+ }
10492
+ if (issues.length === 0) return;
10493
+ for (const issue of issues.slice(0, 10)) {
10494
+ const severity = issue.severity === "critical" ? "critical" : issue.severity === "major" ? "major" : "minor";
10495
+ if (issue.isGoalViolation && issue.goalIndex != null && issue.goalIndex >= 0 && issue.goalIndex < activeGoals.length) {
10496
+ const goal = activeGoals[issue.goalIndex];
10497
+ if (!goal) continue;
10498
+ const confidence = Math.min(100, Math.max(0, issue.confidence ?? 80));
10499
+ const fixId = `fix-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
10500
+ console.debug("[AI Watcher] Goal violation detected:", {
10501
+ goalDescription: goal.description,
10502
+ file: issue.file,
10503
+ violation: issue.description,
10504
+ confidence,
10505
+ goalIndex: issue.goalIndex,
10506
+ totalActiveGoals: activeGoals.length
10507
+ });
10508
+ const goalViolationIssue = {
10509
+ id: fixId,
10510
+ file: issue.file,
10511
+ agent: "goal-violation",
10512
+ severity: severity === "critical" ? "critical" : severity === "major" ? "serious" : "moderate",
10513
+ issue: `Goal "${goal.description}" violated: ${issue.description}`,
10514
+ fix: issue.suggestedFix || "Review and fix",
10515
+ category: "goal-violation",
10516
+ confidence,
10517
+ autoFixable: true
10518
+ };
10519
+ await storeIssues([goalViolationIssue], basename(projectPath), projectPath);
10520
+ await recordGoalViolationCaught(goal, issue.file, projectPath);
10521
+ const confidenceStr = `${confidence}%`;
10522
+ const nudgeMsg = `Goal "${goal.description}" violated in ${issue.file}: ${issue.description} [${confidenceStr} confidence]`;
10523
+ console.debug("[AI Watcher] Sending nudge:", {
10524
+ message: nudgeMsg,
10525
+ file: issue.file,
10526
+ severity: "warning"
10527
+ });
10528
+ getOutputManager().nudge(nudgeMsg, "warning", issue.file);
10529
+ await this.persistNudge({
10530
+ message: nudgeMsg,
10531
+ severity: "warning",
10532
+ file: issue.file,
10533
+ category: "quality",
10534
+ goalId: goal.id,
10535
+ priority: 7,
10536
+ suggestedAction: issue.suggestedFix || "Review and fix manually",
10537
+ relatedIssues: [fixId]
10538
+ });
10539
+ if (this.streamingManager) {
10540
+ this.streamingManager.reportPendingFix({
10541
+ id: fixId,
10542
+ file: issue.file,
10543
+ description: issue.description,
10544
+ goalDescription: goal.description,
10545
+ confidence,
10546
+ severity: issue.severity,
10547
+ suggestedFix: issue.suggestedFix || "Remove the violating code"
10548
+ });
10549
+ }
10550
+ if (!isInteractiveMode()) {
10551
+ console.error(` [!] Goal violation (${confidenceStr}): ${issue.description}`);
10552
+ console.error(` Fix: ${issue.suggestedFix || "Review and fix manually"}`);
10553
+ }
10554
+ continue;
10555
+ }
10556
+ const incident = await graph.addNode("incident", {
10557
+ description: issue.description,
10558
+ severity,
10559
+ affectedUsers: null,
10560
+ duration: null,
10561
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
10562
+ resolved: false,
10563
+ resolution: null,
10564
+ fixChangeId: null,
10565
+ reportedVia: "detected"
10566
+ });
10567
+ const filePath = join4(projectPath, issue.file);
10568
+ const fileNode = await graph.getNode("file", filePath);
10569
+ if (fileNode) {
10570
+ await graph.addEdge(fileNode.id, incident.id, "affects");
10571
+ const data = fileNode.data;
10572
+ const newRisk = severity === "critical" ? "critical" : severity === "major" ? "high" : data.riskLevel === "low" ? "medium" : data.riskLevel;
10573
+ await graph.updateNode("file", fileNode.id, {
10574
+ incidentCount: (data.incidentCount ?? 0) + 1,
10575
+ riskLevel: newRisk
10576
+ });
10577
+ }
10578
+ this.state.totalIssuesFound++;
10579
+ if (severity !== "minor") {
10580
+ getOutputManager().nudge(
10581
+ `${issue.description}`,
10582
+ severity === "critical" ? "critical" : "warning",
10583
+ issue.file,
10584
+ severity === "critical" ? void 0 : 15e3
10585
+ );
10586
+ await this.persistNudge({
10587
+ message: issue.description,
10588
+ severity: severity === "critical" ? "critical" : "warning",
10589
+ file: issue.file,
10590
+ category: "quality",
10591
+ priority: severity === "critical" ? 9 : 6,
10592
+ ...issue.suggestedFix && { suggestedAction: issue.suggestedFix }
10593
+ });
10594
+ }
10595
+ }
10596
+ if (this.streamingManager && issues.length > 0) {
10597
+ this.streamingManager.reportSignalExtraction({
10598
+ governance: 0,
10599
+ facts: 0,
10600
+ blockers: issues.length,
10601
+ questions: 0
10602
+ });
10603
+ }
10604
+ } catch (error) {
10605
+ getOutputManager().log("warn", `AI watcher error: ${error}`);
10606
+ }
10607
+ } finally {
10608
+ this.state.autoScanInProgress = false;
10609
+ }
10610
+ }
10611
+ /**
10612
+ * Initial hypothesis generation when watch starts.
10613
+ *
10614
+ * This generates hypotheses from existing patterns and issues to give
10615
+ * users immediate insights about their codebase.
10616
+ */
10617
+ async initialHypothesisGeneration() {
10618
+ if (!isAIAvailable()) {
10619
+ console.debug("[Initial Hypothesis] AI not available, skipping initial hypothesis generation");
10620
+ return;
10621
+ }
10622
+ const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
10623
+ console.debug("[Initial Hypothesis] Starting initial hypothesis generation", { projectPath });
10624
+ try {
10625
+ const { getHypothesisEngine } = await import("./hypothesis-JURDWVDC.js");
10626
+ const hypothesisEngine = getHypothesisEngine(projectPath);
10627
+ console.debug("[Initial Hypothesis] Running AI-powered hypothesis generation...");
10628
+ const generated = await hypothesisEngine.generateHypothesesWithAI({
10629
+ recentIssues: [],
10630
+ // No recent issues yet on startup
10631
+ patterns: [],
10632
+ observations: ["Initial watch session started", "Analyzing codebase for potential patterns"]
10633
+ });
10634
+ console.debug("[Initial Hypothesis] Generated hypotheses on startup:", {
10635
+ count: generated.length,
10636
+ hypotheses: generated.map((h) => ({ statement: h.statement, confidence: h.confidence }))
10637
+ });
10638
+ if (generated.length > 0) {
10639
+ const { getOutputManager: getOutputManager2 } = await import("./output-manager-FX4V7ERT.js");
10640
+ const outputManager = getOutputManager2();
10641
+ for (const hypothesis of generated.slice(0, 2)) {
10642
+ const message = `[Initial Hypothesis] "${hypothesis.statement}" (${Math.round(hypothesis.confidence * 100)}% confidence)`;
10643
+ outputManager.nudge(message, "info", void 0, 1e4);
10644
+ if (!isInteractiveMode()) {
10645
+ console.error(` [?] ${message}`);
10646
+ }
10647
+ }
10648
+ if (this.streamingManager) {
10649
+ this.streamingManager.reportSignalExtraction({
10650
+ governance: 0,
10651
+ facts: 0,
10652
+ blockers: 0,
10653
+ questions: generated.length
10654
+ });
10655
+ }
10656
+ }
10657
+ } catch (error) {
10658
+ console.debug("[Initial Hypothesis] Failed to generate initial hypotheses:", error);
10659
+ }
10660
+ }
10661
+ /**
10662
+ * Initial goal compliance scan when watch starts.
10663
+ *
10664
+ * This checks recently modified files against active goals so the user
10665
+ * gets immediate feedback about goal violations without waiting for files
10666
+ * to be changed.
10667
+ *
10668
+ * Strategy:
10669
+ * 1. Check if there are any active goals - if not, skip
10670
+ * 2. Find recently modified files (last 24 hours OR uncommitted changes)
10671
+ * 3. Filter to watched file types
10672
+ * 4. Run a quick AI scan focused only on goal violations
10673
+ * 5. Nudge the user about any violations found
10674
+ */
10675
+ async initialGoalComplianceScan() {
10676
+ if (!isAIAvailable()) {
10677
+ console.debug("[Initial Scan] AI not available, skipping initial goal compliance scan");
10678
+ return;
10679
+ }
10680
+ const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
10681
+ console.debug("[Initial Scan] Starting initial goal compliance scan", { projectPath });
10682
+ try {
10683
+ const { getActiveGoals, recordGoalViolationCaught } = await import("./goal-validator-FU5QWDQT.js");
10684
+ const activeGoals = await getActiveGoals(projectPath);
10685
+ console.debug("[Initial Scan] Loaded goals for initial scan:", {
10686
+ goalCount: activeGoals.length,
10687
+ goals: activeGoals.map((g) => ({ id: g.id, description: g.description }))
10688
+ });
10689
+ if (activeGoals.length === 0) {
10690
+ console.debug("[Initial Scan] No active goals found, skipping initial scan");
10691
+ return;
10692
+ }
10693
+ if (!isInteractiveMode()) {
10694
+ console.error("[*] Checking recent files against active goals...");
10695
+ }
10696
+ const recentFiles = /* @__PURE__ */ new Set();
10697
+ const uncommittedFiles = await getGitChangedFiles(projectPath);
10698
+ if (uncommittedFiles) {
10699
+ uncommittedFiles.forEach((f) => recentFiles.add(join4(projectPath, f)));
10700
+ }
10701
+ const oneDayAgo = Date.now() - 24 * 60 * 60 * 1e3;
10702
+ const recentChanges = await getChangedFilesSinceTimestamp(projectPath, oneDayAgo);
10703
+ if (recentChanges) {
10704
+ recentChanges.forEach((f) => recentFiles.add(f));
10705
+ }
10706
+ const filesToCheck = Array.from(recentFiles).filter((file) => {
10707
+ const ext = extname3(file).toLowerCase();
10708
+ return WATCH_EXTENSIONS.has(ext) && existsSync6(file);
10709
+ });
10710
+ console.debug("[Initial Scan] Files discovered for initial scan:", {
10711
+ totalRecentFiles: recentFiles.size,
10712
+ filteredFiles: filesToCheck.length,
10713
+ filePaths: filesToCheck.slice(0, 5).map((f) => f.replace(projectPath + "/", "")),
10714
+ // Show first 5
10715
+ watchedExtensions: Array.from(WATCH_EXTENSIONS)
10716
+ });
10717
+ if (filesToCheck.length === 0) {
10718
+ console.debug("[Initial Scan] No recent files found for initial scan");
10719
+ return;
10720
+ }
10721
+ const maxInitialFiles = 10;
10722
+ const filesToScan = filesToCheck.slice(0, maxInitialFiles);
10723
+ if (!isInteractiveMode()) {
10724
+ console.error(` Scanning ${filesToScan.length} recent file(s) against ${activeGoals.length} goal(s)...`);
10725
+ }
10726
+ const maxCharsPerFile = 3e3;
10727
+ const fileContents = await Promise.all(
10728
+ filesToScan.map(async (file) => {
10729
+ try {
10730
+ const content = await readFile5(file, "utf-8");
10731
+ const relativePath = file.replace(projectPath + "/", "");
10732
+ return { path: relativePath, content: content.slice(0, maxCharsPerFile) };
10733
+ } catch {
10734
+ return null;
10735
+ }
10736
+ })
10737
+ );
10738
+ const valid = fileContents.filter(Boolean);
10739
+ if (valid.length === 0) return;
10740
+ const filesBlock = valid.map(
10741
+ (f) => `### ${f.path}
10742
+ \`\`\`
10743
+ ${f.content}
10744
+ \`\`\``
10745
+ ).join("\n\n");
10746
+ const goalsSection = `
10747
+ USER-DEFINED GOALS (check EVERY file against ALL goals):
10748
+ ${activeGoals.map((g, i) => ` ${i + 1}. "${g.description}"`).join("\n")}
10749
+
10750
+ This is an INITIAL SCAN at watch startup. Report ALL goal violations you find.
10751
+ `;
10752
+ const result = await runAIAnalysis({
10753
+ systemPrompt: `You are checking code for GOAL VIOLATIONS ONLY.
10754
+ ${goalsSection}
10755
+ Reply ONLY with a JSON array. Each element must have:
10756
+ - "file": relative file path
10757
+ - "severity": "critical" | "major" | "minor"
10758
+ - "description": 1-sentence description of the goal violation
10759
+ - "confidence": number 0-100, how confident you are this is a violation
10760
+ - "suggestedFix": 1-sentence description of what should change
10761
+ - "isGoalViolation": true (always true for this scan)
10762
+ - "goalIndex": 0-based index of the violated goal
10763
+
10764
+ 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.
10765
+
10766
+ If no violations found, reply with: []
10767
+ Output ONLY the JSON array, no markdown fences, no commentary.`,
10768
+ userPrompt: `Check these files for goal violations:
10769
+
10770
+ ${filesBlock}`,
10771
+ maxTokens: 2048,
10772
+ temperature: 0.1
10773
+ });
10774
+ if (result.tokensUsed) {
10775
+ this.recordTokenUsage(result.tokensUsed.input + result.tokensUsed.output);
10776
+ }
10777
+ if (!result.success || !result.content.trim()) return;
10778
+ let issues = [];
10779
+ try {
10780
+ const parsed = JSON.parse(result.content.trim());
10781
+ issues = Array.isArray(parsed) ? parsed : [];
10782
+ } catch {
10783
+ return;
10784
+ }
10785
+ const issuesToStore = [];
10786
+ let violationsFound = 0;
10787
+ for (const issue of issues) {
10788
+ if (!issue.isGoalViolation || issue.confidence < 40) continue;
10789
+ violationsFound++;
10790
+ if (issue.goalIndex != null && issue.goalIndex >= 0 && issue.goalIndex < activeGoals.length) {
10791
+ const goal = activeGoals[issue.goalIndex];
10792
+ if (!goal) continue;
10793
+ const fixId = `fix-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
10794
+ issuesToStore.push({
10795
+ id: fixId,
10796
+ file: issue.file,
10797
+ agent: "goal-violation",
10798
+ severity: issue.severity === "critical" ? "critical" : issue.severity === "major" ? "serious" : "moderate",
10799
+ issue: `Goal "${goal.description}" violated: ${issue.description}`,
10800
+ fix: issue.suggestedFix || "Review and fix",
10801
+ category: "goal-violation",
10802
+ confidence: issue.confidence,
10803
+ autoFixable: true
10804
+ });
10805
+ await recordGoalViolationCaught(goal, issue.file, projectPath);
10806
+ const confidenceStr = issue.confidence >= 80 ? "high" : issue.confidence >= 60 ? "medium" : "low";
10807
+ const nudgeMsg = `Goal "${goal.description}" violated in ${issue.file}: ${issue.description} [${confidenceStr} confidence]`;
10808
+ getOutputManager().nudge(nudgeMsg, "warning", issue.file);
10809
+ await this.persistNudge({
10810
+ message: nudgeMsg,
10811
+ severity: "warning",
10812
+ file: issue.file,
10813
+ category: "quality",
10814
+ goalId: goal.id,
10815
+ priority: issue.confidence >= 80 ? 8 : issue.confidence >= 60 ? 6 : 4,
10816
+ ...issue.suggestedFix && { suggestedAction: issue.suggestedFix }
10817
+ });
10818
+ }
10819
+ }
10820
+ if (issuesToStore.length > 0) {
10821
+ await storeIssues(issuesToStore, basename(projectPath), projectPath);
10822
+ }
10823
+ if (!isInteractiveMode()) {
10824
+ if (violationsFound > 0) {
10825
+ console.error(` [!] Found ${violationsFound} goal violation(s) in recent files`);
10826
+ } else {
10827
+ console.error(` [\u2713] No goal violations found in recent files`);
10828
+ }
10829
+ }
10830
+ } catch (error) {
10831
+ if (!isInteractiveMode()) {
10832
+ console.error(` [!] Initial goal scan error: ${error}`);
10833
+ }
10834
+ }
10835
+ }
10836
+ async syncPipelineIntegrations() {
10837
+ const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
10838
+ try {
10839
+ const config = await loadConfig();
10840
+ const hasLinear = !!(config.apiKeys?.linear ?? process.env.LINEAR_API_KEY);
10841
+ const hasGithub = !!(config.apiKeys?.github ?? process.env.GITHUB_TOKEN);
10842
+ if (!hasLinear && !hasGithub) return;
10843
+ const graph = new ContextGraph(projectPath);
10844
+ if (hasLinear) {
10845
+ try {
10846
+ const { LinearIngester } = await import("./linear-ingester-NHFMKJBZ.js");
10847
+ const ingester = new LinearIngester(projectPath, graph);
10848
+ await ingester.syncTickets();
10849
+ if (!isInteractiveMode()) {
10850
+ console.error("[Pipeline] Linear tickets synced");
10851
+ }
10852
+ } catch (error) {
10853
+ if (!isInteractiveMode()) {
10854
+ console.error(`[Pipeline] Linear sync failed: ${error}`);
10855
+ }
10856
+ }
10857
+ }
10858
+ if (hasGithub) {
10859
+ try {
10860
+ const { GitHubIngester } = await import("./github-ingester-AR5A4RAC.js");
10861
+ const ingester = new GitHubIngester(graph);
10862
+ const token = await ingester.getApiToken();
10863
+ const repoInfo = ingester.getRepoInfo(projectPath);
10864
+ if (repoInfo) {
10865
+ await ingester.syncPullRequests(repoInfo.owner, repoInfo.name, token);
10866
+ await ingester.syncIssues(repoInfo.owner, repoInfo.name, token);
10867
+ if (!isInteractiveMode()) {
10868
+ console.error("[Pipeline] GitHub PRs/issues synced");
10869
+ }
10870
+ }
10871
+ } catch (error) {
10872
+ if (!isInteractiveMode()) {
10873
+ console.error(`[Pipeline] GitHub sync failed: ${error}`);
10874
+ }
10875
+ }
10876
+ }
10877
+ } catch {
10878
+ }
10879
+ }
10880
+ async stopWatching() {
10881
+ if (!this.state.isRunning) {
10882
+ return {
10883
+ content: [{
10884
+ type: "text",
10885
+ text: "[!] Watch mode is not running."
10886
+ }]
10887
+ };
10888
+ }
10889
+ for (const watcher of this.watchers.values()) {
10890
+ watcher.close();
10891
+ }
10892
+ this.watchers.clear();
10893
+ if (this.extractionPipeline) {
10894
+ this.extractionPipeline.close();
10895
+ this.extractionPipeline = null;
10896
+ }
10897
+ if (this.pipelineSyncTimer) {
10898
+ clearInterval(this.pipelineSyncTimer);
10899
+ this.pipelineSyncTimer = null;
10900
+ }
10901
+ if (this.codebaseIndex) {
10902
+ await this.codebaseIndex.save();
10903
+ this.codebaseIndex = null;
10904
+ }
10905
+ if (this.state.scanDebounceTimer) {
10906
+ clearTimeout(this.state.scanDebounceTimer);
10907
+ }
10908
+ this.state.isRunning = false;
10909
+ if (!isInteractiveMode()) {
10910
+ console.error("\n[*] Watch mode stopped.\n");
10911
+ }
10912
+ if (this.streamingManager) {
10913
+ this.streamingManager.reportWatchStatus({ watching: false, directories: 0 });
10914
+ }
10915
+ const outputManager = getOutputManager();
10916
+ outputManager.clearTUICallbacks();
10917
+ outputManager.setMode("console");
10918
+ if (this.dashboard) {
10919
+ this.dashboard.stop();
10920
+ this.dashboard = void 0;
10921
+ }
10922
+ const budget = this.state.tokenBudget;
10923
+ const tokensK = (budget.used / 1e3).toFixed(1);
10924
+ return {
10925
+ content: [{
10926
+ type: "text",
10927
+ text: `[*] **TRIE AGENT STOPPED**
10928
+
10929
+ ### Session Summary:
10930
+ - Files scanned: ${this.state.filesScanned}
10931
+ - Issues found: ${this.state.totalIssuesFound}
10932
+ - Tokens used: ${tokensK}k / ${(budget.hourlyLimit / 1e3).toFixed(0)}k hourly limit
10933
+ - Scans skipped (trie-throttled): ${budget.scansSaved}
10934
+ - Governance ledger: Updated continuously
10935
+
10936
+ Use \`trie_watch start\` to resume.`
10937
+ }]
10938
+ };
10939
+ }
10940
+ async getStatus() {
10941
+ if (!this.state.isRunning) {
10942
+ return {
10943
+ content: [{
10944
+ type: "text",
10945
+ text: `[*] **Watch Mode Status: STOPPED**
10946
+
10947
+ Use \`trie_watch start\` to begin autonomous scanning.`
10948
+ }]
10949
+ };
10950
+ }
10951
+ const recentScans = Array.from(this.state.lastScan.entries()).sort((a, b) => b[1] - a[1]).slice(0, 5).map(([file, time]) => {
10952
+ const ago = Math.round((Date.now() - time) / 1e3);
10953
+ return `- \`${basename(file)}\` (${ago}s ago)`;
10954
+ }).join("\n");
10955
+ const recentNudges = this.state.nudges.slice(-3).map(
10956
+ (n) => `- ${basename(n.file)} [${n.severity}] @ ${n.timestamp}`
10957
+ ).join("\n");
10958
+ let agencyStatus = "";
10959
+ try {
10960
+ const { getTrieAgent: getTrieAgent2 } = await import("./trie-agent-QHPS4C5Z.js");
10961
+ const trieAgent = getTrieAgent2(this.watchedDirectory || getWorkingDirectory(void 0, true));
10962
+ await trieAgent.initialize();
10963
+ const status = await trieAgent.getAgencyStatus();
10964
+ agencyStatus = `
10965
+ ### [AI] Trie Agent:
10966
+ - **Goals:** ${status.goals.active} active, ${status.goals.completed} completed${status.goals.topGoal ? ` (${status.goals.topGoal.slice(0, 40)}...)` : ""}
10967
+ - **Hypotheses:** ${status.hypotheses.testing} testing, ${status.hypotheses.validated} validated
10968
+ - **Risk Level:** ${status.riskLevel.toUpperCase()}
10969
+ - **Effectiveness:** ${status.effectiveness}%
10970
+ - **Scan Frequency:** ${Math.round(status.scanFrequency / 1e3)}s${status.isQuietHours ? " (quiet hours)" : ""}`;
10971
+ } catch {
10972
+ }
10973
+ const budget = this.state.tokenBudget;
10974
+ const remaining = this.getRemainingBudget();
10975
+ const tokensK = (budget.used / 1e3).toFixed(1);
10976
+ const remainingK = (remaining / 1e3).toFixed(1);
10977
+ return {
10978
+ content: [{
10979
+ type: "text",
10980
+ text: `[*] **WATCH MODE Status: RUNNING**
10981
+
10982
+ ### Stats:
10983
+ - Directories watched: ${this.watchers.size}
10984
+ - Files scanned: ${this.state.filesScanned}
10985
+ - Issues found: ${this.state.totalIssuesFound}
10986
+ - Pending: ${this.state.pendingFiles.size}
10987
+
10988
+ ### Token Budget:
10989
+ - Used: ${tokensK}k / ${(budget.hourlyLimit / 1e3).toFixed(0)}k hourly
10990
+ - Remaining: ${remainingK}k
10991
+ - Scans skipped (trie-throttled): ${budget.scansSaved}
10992
+ ${agencyStatus}
10993
+
10994
+ ### Recently Scanned:
10995
+ ${recentScans || "(none yet)"}
10996
+
10997
+ ### Recent Nudges:
10998
+ ${recentNudges || "(none)"}
10999
+
11000
+ ### Commands:
11001
+ - \`trie_watch issues\` - Get all issues found
11002
+ - \`trie_watch stop\` - Stop watching`
11003
+ }]
11004
+ };
11005
+ }
11006
+ /**
11007
+ * Helper to persist a nudge to both in-memory state and SQL storage
11008
+ */
11009
+ async persistNudge(params) {
11010
+ const timestamp = (/* @__PURE__ */ new Date()).toISOString();
11011
+ const nudgeId = createHash2("sha256").update(`${params.message}|${params.file || ""}|${timestamp}`).digest("hex").slice(0, 16);
11012
+ const nudge = {
11013
+ id: nudgeId,
11014
+ message: params.message,
11015
+ severity: params.severity,
11016
+ timestamp,
11017
+ resolved: false,
11018
+ dismissed: false,
11019
+ priority: params.priority ?? 5,
11020
+ relatedIssues: params.relatedIssues ?? [],
11021
+ metadata: {},
11022
+ ...params.file && { file: params.file },
11023
+ ...params.category && { category: params.category },
11024
+ ...params.goalId && { goalId: params.goalId },
11025
+ ...params.suggestedAction && { suggestedAction: params.suggestedAction }
11026
+ };
11027
+ this.state.nudges.push({
11028
+ file: params.file || "unknown",
11029
+ // Keep full path for consistency with loaded nudges
11030
+ message: params.message,
11031
+ severity: params.severity === "warning" || params.severity === "info" ? "high" : params.severity,
11032
+ timestamp: (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false })
11033
+ });
11034
+ try {
11035
+ const storage = getStorage(this.watchedDirectory);
11036
+ await storage.storeNudge(nudge);
11037
+ console.debug(`[Watch] \u2713 Persisted nudge to storage: ${nudge.message.slice(0, 60)}...`);
11038
+ } catch (error) {
11039
+ console.error("[Watch] Failed to persist nudge to storage:", error);
11040
+ }
11041
+ }
11042
+ getNudges() {
11043
+ return {
11044
+ content: [
11045
+ {
11046
+ type: "text",
11047
+ text: `[#] Recent nudges (${this.state.nudges.length} this session)
11048
+ ` + (this.state.nudges.length ? this.state.nudges.map(
11049
+ (n) => `- ${basename(n.file)} [${n.severity}] @ ${n.timestamp}
11050
+ ${n.message}`
11051
+ ).join("\n") : "(none)")
11052
+ },
11053
+ {
11054
+ type: "json",
11055
+ json: this.state.nudges
11056
+ }
11057
+ ]
11058
+ };
11059
+ }
11060
+ getCurrentIssues() {
11061
+ return {
11062
+ content: [{
11063
+ type: "text",
11064
+ text: `[L] **Issues Found This Session**
11065
+
11066
+ Total issues: ${this.state.totalIssuesFound}
11067
+ Files scanned: ${this.state.filesScanned}
11068
+
11069
+ To get a full report, run \`trie watch\` on your codebase.`
11070
+ }]
11071
+ };
11072
+ }
11073
+ };
11074
+
9630
11075
  export {
9631
11076
  getPrompt,
9632
11077
  getSystemPrompt,
@@ -9634,7 +11079,6 @@ export {
9634
11079
  TrieCloudFixTool,
9635
11080
  TrieExplainTool,
9636
11081
  StreamingManager,
9637
- ExtractionPipeline,
9638
11082
  TrieTellTool,
9639
11083
  TrieFeedbackTool,
9640
11084
  TrieCheckTool,
@@ -9647,6 +11091,7 @@ export {
9647
11091
  handleCheckpointTool,
9648
11092
  TriePipelineTool,
9649
11093
  GitHubBranchesTool,
9650
- InteractiveDashboard
11094
+ InteractiveDashboard,
11095
+ TrieWatchTool
9651
11096
  };
9652
- //# sourceMappingURL=chunk-HYNDXZAU.js.map
11097
+ //# sourceMappingURL=chunk-QAM5X5HM.js.map