@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
package/dist/index.js CHANGED
@@ -1,10 +1,7 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  GitHubIngester
4
- } from "./chunk-YOJGSRZK.js";
5
- import {
6
- CodebaseIndex
7
- } from "./chunk-V7AY2EJO.js";
4
+ } from "./chunk-CBAMZERA.js";
8
5
  import {
9
6
  appendToSection,
10
7
  completeBootstrap,
@@ -22,15 +19,12 @@ import {
22
19
  needsBootstrap,
23
20
  projectInfoExists,
24
21
  updateProjectSection
25
- } from "./chunk-7OJ6JIPL.js";
22
+ } from "./chunk-OVSYTWUU.js";
26
23
  import {
27
24
  LinearIngester
28
- } from "./chunk-LD7ZEFNY.js";
25
+ } from "./chunk-FXZAABXO.js";
29
26
  import {
30
- ExtractionPipeline,
31
27
  GitHubBranchesTool,
32
- InteractiveDashboard,
33
- StreamingManager,
34
28
  TrieCheckTool,
35
29
  TrieCloudFixTool,
36
30
  TrieExplainTool,
@@ -44,79 +38,68 @@ import {
44
38
  TriePipelineTool,
45
39
  TrieQueryContextTool,
46
40
  TrieTellTool,
41
+ TrieWatchTool,
47
42
  getPrompt,
48
43
  getSystemPrompt,
49
44
  handleCheckpointTool
50
- } from "./chunk-HYNDXZAU.js";
51
- import "./chunk-23RJT5WT.js";
52
- import "./chunk-GAL7OIYU.js";
45
+ } from "./chunk-QAM5X5HM.js";
46
+ import "./chunk-3CYMLM35.js";
47
+ import "./chunk-LJISDV3A.js";
53
48
  import {
54
- getOutputManager
55
- } from "./chunk-TIMIKBY2.js";
56
- import "./chunk-ILGMFND2.js";
57
- import "./chunk-72KSLD7A.js";
58
- import "./chunk-OTQEFXHU.js";
49
+ CodebaseIndex
50
+ } from "./chunk-YEQXKKZQ.js";
51
+ import "./chunk-KLMJKM63.js";
52
+ import "./chunk-LFNH3CSN.js";
53
+ import "./chunk-NVZZUUEU.js";
54
+ import "./chunk-T7UAH7GE.js";
59
55
  import {
60
56
  exportToJson,
61
57
  formatFriendlyError,
62
58
  importFromJson,
63
59
  isTrieInitialized
64
- } from "./chunk-53KUI7RQ.js";
60
+ } from "./chunk-EMJ7RVWB.js";
65
61
  import {
66
62
  loadConfig
67
- } from "./chunk-NKHO34UZ.js";
68
- import "./chunk-4C67GV3O.js";
63
+ } from "./chunk-FTOF3FHT.js";
64
+ import "./chunk-KYKADM7P.js";
69
65
  import "./chunk-ZV2K6M7T.js";
70
66
  import {
71
67
  findCrossProjectPatterns,
72
68
  getGlobalMemoryStats,
73
69
  listTrackedProjects,
74
70
  searchGlobalPatterns
75
- } from "./chunk-B2AHQ2IR.js";
76
- import {
77
- getStorage
78
- } from "./chunk-FG467PDD.js";
71
+ } from "./chunk-OWSGJUUR.js";
79
72
  import {
80
73
  ContextGraph
81
- } from "./chunk-FH335WL5.js";
82
- import "./chunk-ZDDE442Q.js";
83
- import {
84
- isAIAvailable,
85
- runAIAnalysis
86
- } from "./chunk-FPEMP54L.js";
87
- import "./chunk-CU5VDH6F.js";
74
+ } from "./chunk-JYWGYUKX.js";
75
+ import "./chunk-Z2E7X4WI.js";
76
+ import "./chunk-UL337UDQ.js";
77
+ import "./chunk-L4FODDDB.js";
78
+ import "./chunk-WO7CC5FH.js";
79
+ import "./chunk-2LAJKFWU.js";
80
+ import "./chunk-6NLHFIYA.js";
81
+ import "./chunk-ALSCZ7WR.js";
82
+ import "./chunk-XD2HKZVB.js";
88
83
  import {
89
84
  findSimilarIssues,
90
85
  getMemoryStats,
91
86
  getRecentIssues,
92
87
  markIssueResolved,
93
88
  purgeIssues,
94
- searchIssues,
95
- storeIssues
96
- } from "./chunk-QH77RQB3.js";
89
+ searchIssues
90
+ } from "./chunk-4ZAFQEP6.js";
97
91
  import "./chunk-EFWVF6TI.js";
98
- import "./chunk-F4NJ4CBP.js";
99
- import "./chunk-IXO4G4D3.js";
100
- import "./chunk-6NLHFIYA.js";
101
92
  import {
102
- getSkillRegistry
103
- } from "./chunk-G76DYVGX.js";
104
- import {
105
- getAutonomyConfig
106
- } from "./chunk-5KJ4UJOY.js";
107
- import {
108
- getChangedFilesSinceTimestamp,
109
- getGitChangedFiles,
110
93
  runShellCommandSync
111
- } from "./chunk-ZUEAHFSY.js";
94
+ } from "./chunk-HD5H7YSW.js";
112
95
  import "./chunk-43X6JBEM.js";
113
96
  import {
114
97
  getTrieDirectory,
115
98
  getWorkingDirectory
116
- } from "./chunk-SH7H3WRU.js";
99
+ } from "./chunk-7F2R2ITA.js";
117
100
  import {
118
101
  isInteractiveMode
119
- } from "./chunk-APMV77PU.js";
102
+ } from "./chunk-JKEEQAG2.js";
120
103
  import "./chunk-DGUM43GV.js";
121
104
 
122
105
  // src/server/mcp-server.ts
@@ -795,1436 +778,29 @@ trie_test action:"run" files:["src/utils.test.ts"]
795
778
  }
796
779
  };
797
780
 
798
- // src/tools/watch.ts
799
- import { watch, existsSync as existsSync2, readFileSync } from "fs";
800
- import { stat, readFile as readFile2 } from "fs/promises";
801
- import { join as join2, extname as extname2, basename as basename2 } from "path";
802
- import { createHash } from "crypto";
803
- var WATCH_EXTENSIONS = /* @__PURE__ */ new Set([
804
- ".ts",
805
- ".tsx",
806
- ".js",
807
- ".jsx",
808
- ".mjs",
809
- ".vue",
810
- ".svelte",
811
- ".astro",
812
- ".py",
813
- ".go",
814
- ".rs"
815
- ]);
816
- var SKIP_DIRS = /* @__PURE__ */ new Set([
817
- "node_modules",
818
- ".git",
819
- "dist",
820
- "build",
821
- ".next",
822
- ".nuxt",
823
- "coverage",
824
- ".turbo",
825
- ".cache"
826
- ]);
827
- var TrieWatchTool = class _TrieWatchTool {
828
- extractionPipeline = null;
829
- watchedDirectory = "";
830
- codebaseIndex = null;
831
- state = {
832
- isRunning: false,
833
- lastScan: /* @__PURE__ */ new Map(),
834
- pendingFiles: /* @__PURE__ */ new Set(),
835
- scanDebounceTimer: null,
836
- issueCache: /* @__PURE__ */ new Map(),
837
- totalIssuesFound: 0,
838
- filesScanned: 0,
839
- nudgedFiles: /* @__PURE__ */ new Set(),
840
- nudges: [],
841
- lastAutoScan: 0,
842
- autoScanInProgress: false,
843
- tokenBudget: {
844
- used: 0,
845
- windowStart: Date.now(),
846
- hourlyLimit: 5e4,
847
- scansSaved: 0
848
- },
849
- cleanFiles: /* @__PURE__ */ new Map()
850
- };
851
- watchers = /* @__PURE__ */ new Map();
852
- streamingManager = void 0;
853
- dashboard = void 0;
854
- lastHypothesisCheck = 0;
855
- pipelineSyncTimer = null;
856
- static HYPOTHESIS_CHECK_INTERVAL_MS = 3e5;
857
- // Check every 5 minutes
858
- static PIPELINE_SYNC_INTERVAL_MS = 30 * 60 * 1e3;
859
- // 30 minutes
860
- async execute(args) {
861
- const { action, directory, debounceMs = 1e3 } = args;
862
- switch (action) {
863
- case "start":
864
- return this.startWatching(getWorkingDirectory(directory), debounceMs);
865
- case "stop":
866
- return await this.stopWatching();
867
- case "status":
868
- return await this.getStatus();
869
- case "issues":
870
- return this.getCurrentIssues();
871
- case "nudges":
872
- return this.getNudges();
873
- default:
874
- return {
875
- content: [{
876
- type: "text",
877
- text: `Unknown action: ${action}. Use 'start', 'stop', 'status', or 'issues'.`
878
- }]
879
- };
880
- }
881
- }
882
- async startWatching(directory, debounceMs) {
883
- if (this.state.isRunning) {
884
- return {
885
- content: [{
886
- type: "text",
887
- text: "[!] Watch mode is already running. Use `trie_watch stop` to stop it first."
888
- }]
889
- };
890
- }
891
- if (!isTrieInitialized(directory)) {
892
- return {
893
- content: [{
894
- type: "text",
895
- text: "Trie is not initialized for this project. Run `trie init` first."
896
- }]
897
- };
898
- }
899
- const anthropicApiKey = process.env.ANTHROPIC_API_KEY;
900
- if (anthropicApiKey) {
901
- this.extractionPipeline = new ExtractionPipeline({
902
- workingDirectory: directory,
903
- anthropicApiKey
904
- });
905
- await this.extractionPipeline.initialize();
906
- }
907
- this.codebaseIndex = new CodebaseIndex(directory);
908
- this.state.isRunning = true;
909
- this.watchedDirectory = directory;
910
- this.state.issueCache.clear();
911
- this.state.totalIssuesFound = 0;
912
- this.state.filesScanned = 0;
913
- this.state.nudgedFiles.clear();
914
- this.state.nudges = [];
915
- try {
916
- const storage = getStorage(directory);
917
- await storage.initialize();
918
- const unresolvedNudges = await storage.queryNudges({ resolved: false });
919
- console.debug(`[Watch] Found ${unresolvedNudges.length} unresolved nudges in storage`);
920
- for (const nudge of unresolvedNudges) {
921
- let mappedSeverity = "high";
922
- if (nudge.severity === "critical") {
923
- mappedSeverity = "critical";
924
- } else if (nudge.severity === "high") {
925
- mappedSeverity = "high";
926
- }
927
- this.state.nudges.push({
928
- file: nudge.file || "unknown",
929
- // Keep full path, don't use basename
930
- message: nudge.message,
931
- severity: mappedSeverity,
932
- timestamp: new Date(nudge.timestamp).toLocaleTimeString("en-US", { hour12: false })
933
- });
934
- console.debug(`[Watch] Loaded nudge: ${nudge.message.slice(0, 60)}... (${nudge.severity} -> ${mappedSeverity})`);
935
- }
936
- if (unresolvedNudges.length > 0) {
937
- console.log(`[Watch] \u2713 Loaded ${unresolvedNudges.length} unresolved nudges from storage`);
938
- } else {
939
- console.debug(`[Watch] No unresolved nudges found in storage`);
940
- }
941
- } catch (error) {
942
- console.error("[Watch] Failed to load nudges from storage:", error);
943
- }
944
- try {
945
- const graph = new ContextGraph(directory);
946
- const allNodes = await graph.listNodes();
947
- const unresolvedIncidents = allNodes.filter(
948
- (n) => n.type === "incident" && !n.data.resolved
949
- );
950
- console.debug(`[Watch] Found ${unresolvedIncidents.length} unresolved incidents in context graph`);
951
- for (const incident of unresolvedIncidents) {
952
- const incidentData = incident.data;
953
- let mappedSeverity = "high";
954
- if (incidentData.severity === "critical") {
955
- mappedSeverity = "critical";
956
- } else if (incidentData.severity === "major") {
957
- mappedSeverity = "critical";
958
- } else if (incidentData.severity === "minor") {
959
- mappedSeverity = "high";
960
- }
961
- const edges = await graph.getEdges(incident.id);
962
- const linkedFiles = edges.filter((e) => e.type === "causedBy" || e.type === "affects").map((e) => {
963
- const node = allNodes.find((n) => n.id === e.to_id || n.id === e.from_id);
964
- if (node?.type === "file") {
965
- return node.data.path;
966
- }
967
- return null;
968
- }).filter((f) => f !== null);
969
- const file = linkedFiles[0] || "unknown";
970
- const message = `INCIDENT: ${incidentData.description}`;
971
- this.state.nudges.push({
972
- file,
973
- message,
974
- severity: mappedSeverity,
975
- timestamp: new Date(incidentData.timestamp).toLocaleTimeString("en-US", { hour12: false })
976
- });
977
- console.debug(`[Watch] Loaded incident: ${incidentData.description.slice(0, 60)}... (${incidentData.severity} -> ${mappedSeverity})`);
978
- }
979
- if (unresolvedIncidents.length > 0) {
980
- console.log(`[Watch] \u2713 Loaded ${unresolvedIncidents.length} unresolved incidents from context graph`);
981
- } else {
982
- console.debug(`[Watch] No unresolved incidents found in context graph`);
983
- }
984
- } catch (error) {
985
- console.error("[Watch] Failed to load incidents from context graph:", error);
986
- }
987
- if (!isInteractiveMode()) {
988
- 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");
989
- console.error("TRIE AGENT - NOW WATCHING");
990
- 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");
991
- console.error("Your Trie agent is now watching over your codebase.");
992
- console.error("Signal extraction: ENABLED (building governance ledger)");
993
- console.error(`Watching: ${directory}`);
994
- console.error(`Debounce: ${debounceMs}ms`);
995
- console.error("");
996
- }
997
- if (isInteractiveMode()) {
998
- this.streamingManager = new StreamingManager();
999
- this.dashboard = new InteractiveDashboard();
1000
- this.streamingManager.subscribe((update) => this.dashboard?.handleStreamUpdate(update));
1001
- const outputManager = getOutputManager();
1002
- outputManager.setMode("tui");
1003
- outputManager.setStreamingManager(this.streamingManager);
1004
- await this.dashboard.start();
1005
- this.streamingManager.reportWatchStatus({ watching: true, directories: 0, debounceMs });
1006
- } else {
1007
- getOutputManager().setMode("console");
1008
- }
1009
- await this.watchDirectory(directory, debounceMs);
1010
- await this.watchContextGraph(directory);
1011
- if (this.streamingManager) {
1012
- this.streamingManager.reportWatchStatus({
1013
- watching: true,
1014
- directories: this.watchers.size,
1015
- debounceMs
1016
- });
1017
- }
1018
- setTimeout(() => {
1019
- void this.initialGoalComplianceScan();
1020
- void this.initialHypothesisGeneration();
1021
- void this.syncPipelineIntegrations();
1022
- }, 1e3);
1023
- this.pipelineSyncTimer = setInterval(() => {
1024
- void this.syncPipelineIntegrations();
1025
- }, _TrieWatchTool.PIPELINE_SYNC_INTERVAL_MS);
1026
- const indexStatus = this.codebaseIndex?.isEmpty() ? "BUILDING (one-time, speeds up goal checks)" : "READY";
1027
- return {
1028
- content: [{
1029
- type: "text",
1030
- text: `**TRIE AGENT ACTIVATED**
1031
-
1032
- Your Trie agent is now autonomously watching and learning from your codebase.
1033
-
1034
- **Watching:** \`${directory}\`
1035
- **Debounce:** ${debounceMs}ms (waits for you to stop typing)
1036
- **Signal Extraction:** ${process.env.ANTHROPIC_API_KEY ? "ENABLED" : "LIMITED (set ANTHROPIC_API_KEY for full extraction)"}
1037
- **Codebase Index:** ${indexStatus}
1038
-
1039
- ### How the agent works:
1040
- 1. You write/edit code
1041
- 2. Agent detects the change
1042
- 3. Extracts governance, facts, blockers -> stores in ledger
1043
- 4. Predicts risks based on historical patterns
1044
- 5. Nudges you if something looks risky
1045
-
1046
- ### The agent learns:
1047
- - Every commit builds the governance ledger
1048
- - \`trie gotcha\` queries the ledger for predictions
1049
- - \`trie ok\` / \`trie bad\` teach the agent what matters
1050
-
1051
- ### Commands:
1052
- - \`trie_watch status\` - See agent status
1053
- - \`trie_watch stop\` - Stop the agent
1054
- - \`trie_index status\` - Check codebase index`
1055
- }]
1056
- };
1057
- }
1058
- shouldSkipPath(filePath) {
1059
- const parts = filePath.split("/");
1060
- return parts.some((p) => SKIP_DIRS.has(p) || p.startsWith(".") && p !== ".");
1061
- }
1062
- async watchDirectory(dir, debounceMs) {
1063
- if (!existsSync2(dir)) return;
1064
- try {
1065
- const dirStat = await stat(dir);
1066
- if (!dirStat.isDirectory()) return;
1067
- const watcher = watch(dir, { persistent: true, recursive: true }, (_eventType, filename) => {
1068
- if (!filename) return;
1069
- if (this.shouldSkipPath(filename)) return;
1070
- const ext = extname2(filename).toLowerCase();
1071
- if (!WATCH_EXTENSIONS.has(ext)) return;
1072
- const fullPath = join2(dir, filename);
1073
- if (!existsSync2(fullPath)) return;
1074
- this.state.pendingFiles.add(fullPath);
1075
- if (this.state.scanDebounceTimer) {
1076
- clearTimeout(this.state.scanDebounceTimer);
1077
- }
1078
- this.state.scanDebounceTimer = setTimeout(() => {
1079
- this.processPendingFiles();
1080
- }, debounceMs);
1081
- });
1082
- watcher.on("error", (err) => {
1083
- if (!isInteractiveMode()) {
1084
- console.error(`[!] Watcher error: ${err.message}`);
1085
- }
1086
- watcher.close();
1087
- this.watchers.delete(dir);
1088
- });
1089
- this.watchers.set(dir, watcher);
1090
- if (this.streamingManager) {
1091
- this.streamingManager.reportWatchStatus({
1092
- watching: true,
1093
- directories: 1,
1094
- debounceMs
1095
- });
1096
- }
1097
- } catch {
1098
- }
1099
- }
1100
- /**
1101
- * Watch .trie/context.json for incident changes
1102
- */
1103
- async watchContextGraph(directory) {
1104
- const contextPath = join2(getTrieDirectory(directory), "context.json");
1105
- if (!existsSync2(contextPath)) {
1106
- console.debug("[Watch] No context.json found, skipping incident watcher");
1107
- return;
1108
- }
1109
- try {
1110
- const watcher = watch(contextPath, { persistent: true }, async (_eventType, _filename) => {
1111
- console.debug("[Watch] context.json changed, reloading incidents...");
1112
- await this.reloadIncidents(directory);
1113
- });
1114
- watcher.on("error", (err) => {
1115
- console.error(`[Watch] Context watcher error: ${err.message}`);
1116
- watcher.close();
1117
- });
1118
- this.watchers.set("context.json", watcher);
1119
- console.debug("[Watch] \u2713 Watching context.json for incident changes");
1120
- } catch (error) {
1121
- console.error("[Watch] Failed to set up context.json watcher:", error);
1122
- }
1123
- }
1124
- /**
1125
- * Reload incidents from context graph
1126
- */
1127
- async reloadIncidents(directory) {
1128
- try {
1129
- const graph = new ContextGraph(directory);
1130
- const allNodes = await graph.listNodes();
1131
- const unresolvedIncidents = allNodes.filter(
1132
- (n) => n.type === "incident" && !n.data.resolved
1133
- );
1134
- this.state.nudges = this.state.nudges.filter((n) => !n.message.startsWith("INCIDENT:"));
1135
- for (const incident of unresolvedIncidents) {
1136
- const incidentData = incident.data;
1137
- let mappedSeverity = "high";
1138
- if (incidentData.severity === "critical") {
1139
- mappedSeverity = "critical";
1140
- } else if (incidentData.severity === "major") {
1141
- mappedSeverity = "critical";
1142
- } else if (incidentData.severity === "minor") {
1143
- mappedSeverity = "high";
1144
- }
1145
- const edges = await graph.getEdges(incident.id);
1146
- const linkedFiles = edges.filter((e) => e.type === "causedBy" || e.type === "affects").map((e) => {
1147
- const node = allNodes.find((n) => n.id === e.to_id || n.id === e.from_id);
1148
- if (node?.type === "file") {
1149
- return node.data.path;
1150
- }
1151
- return null;
1152
- }).filter((f) => f !== null);
1153
- const file = linkedFiles[0] || "unknown";
1154
- const message = `INCIDENT: ${incidentData.description}`;
1155
- this.state.nudges.push({
1156
- file,
1157
- message,
1158
- severity: mappedSeverity,
1159
- timestamp: new Date(incidentData.timestamp).toLocaleTimeString("en-US", { hour12: false })
1160
- });
1161
- }
1162
- console.log(`[Watch] \u2713 Reloaded ${unresolvedIncidents.length} unresolved incidents`);
1163
- } catch (error) {
1164
- console.error("[Watch] Failed to reload incidents:", error);
1165
- }
1166
- }
1167
- async processPendingFiles() {
1168
- if (this.state.pendingFiles.size === 0) return;
1169
- const files = Array.from(this.state.pendingFiles);
1170
- this.state.pendingFiles.clear();
1171
- if (!isInteractiveMode()) {
1172
- console.error(`
1173
- Detected changes in ${files.length} file(s):`);
1174
- for (const file of files) {
1175
- console.error(` - ${basename2(file)}`);
1176
- }
1177
- console.error("");
1178
- }
1179
- try {
1180
- const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
1181
- if (this.extractionPipeline) {
1182
- try {
1183
- const fileContents = await Promise.all(
1184
- files.map(async (file) => {
1185
- try {
1186
- const content = await readFile2(file, "utf-8");
1187
- return { file, content };
1188
- } catch {
1189
- return null;
1190
- }
1191
- })
1192
- );
1193
- const validFiles = fileContents.filter((f) => f !== null);
1194
- if (validFiles.length > 0) {
1195
- const combinedContent = validFiles.map(
1196
- (f) => `File: ${basename2(f.file)}
1197
- ${f.content.slice(0, 1e3)}`
1198
- // First 1KB of each file
1199
- ).join("\n\n---\n\n");
1200
- if (!isInteractiveMode()) {
1201
- console.error("[*] Extracting signals from changes...");
1202
- }
1203
- const signal = await this.extractionPipeline.process(combinedContent, {
1204
- sourceType: "file",
1205
- sourceId: `watch-${Date.now()}`
1206
- });
1207
- if (signal.governance.length > 0 || signal.facts.length > 0 || signal.blockers.length > 0) {
1208
- const govCount = signal.governance.length;
1209
- if (!isInteractiveMode()) {
1210
- console.error(` [+] Extracted: ${govCount} governance, ${signal.facts.length} facts, ${signal.blockers.length} blockers`);
1211
- }
1212
- if (this.streamingManager) {
1213
- this.streamingManager.reportSignalExtraction({
1214
- governance: govCount,
1215
- facts: signal.facts.length,
1216
- blockers: signal.blockers.length,
1217
- questions: signal.questions.length
1218
- });
1219
- }
1220
- }
1221
- }
1222
- } catch (error) {
1223
- if (!isInteractiveMode()) {
1224
- console.error(` [!] Signal extraction failed: ${error}`);
1225
- }
1226
- }
1227
- }
1228
- void this.autoScanFiles(files).catch((err) => {
1229
- getOutputManager().log("warn", `Auto scan failed: ${err}`);
1230
- });
1231
- await this.discoverPatternsFromIssues(projectPath);
1232
- const now = Date.now();
1233
- if (now - this.lastHypothesisCheck > _TrieWatchTool.HYPOTHESIS_CHECK_INTERVAL_MS) {
1234
- this.checkAndGenerateHypotheses(projectPath);
1235
- this.lastHypothesisCheck = now;
1236
- }
1237
- if (this.streamingManager) {
1238
- const now2 = Date.now();
1239
- for (const file of files) {
1240
- const lastReport = this.state.lastScan.get(file) || 0;
1241
- if (now2 - lastReport > 2e3) {
1242
- this.streamingManager.reportWatchChange(file);
1243
- }
1244
- }
1245
- }
1246
- this.state.filesScanned += files.length;
1247
- for (const file of files) {
1248
- this.state.lastScan.set(file, Date.now());
1249
- if (this.codebaseIndex) {
1250
- const relativePath = file.replace(projectPath + "/", "");
1251
- void this.codebaseIndex.indexFile(relativePath).then(() => {
1252
- void this.codebaseIndex?.save();
1253
- });
1254
- }
1255
- }
1256
- } catch (error) {
1257
- if (!isInteractiveMode()) {
1258
- console.error(`Scan error: ${error}`);
1259
- }
1260
- }
1261
- }
1262
- isQuiet() {
1263
- const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
1264
- const quietPath = join2(getTrieDirectory(projectPath), "quiet.json");
1265
- try {
1266
- const raw = readFileSync(quietPath, "utf-8");
1267
- const data = JSON.parse(raw);
1268
- const until = new Date(data.until).getTime();
1269
- return Date.now() < until;
1270
- } catch {
1271
- return false;
1272
- }
1273
- }
1274
- /**
1275
- * Check and generate hypotheses autonomously
1276
- * Claude observes patterns and creates new hypotheses to test
1277
- */
1278
- async checkAndGenerateHypotheses(projectPath) {
1279
- if (!isAIAvailable()) return;
1280
- try {
1281
- const { getHypothesisEngine } = await import("./hypothesis-O72ZLVOW.js");
1282
- const { getOutputManager: getOutputManager2 } = await import("./output-manager-DZO5LGSG.js");
1283
- const hypothesisEngine = getHypothesisEngine(projectPath);
1284
- const recentIssues = Array.from(this.state.issueCache.values()).flat();
1285
- const patterns = [];
1286
- const observations = [];
1287
- if (this.state.nudges.length > 0) {
1288
- const nudgesByFile = {};
1289
- for (const nudge of this.state.nudges) {
1290
- nudgesByFile[nudge.file] = (nudgesByFile[nudge.file] || 0) + 1;
1291
- }
1292
- const topFiles = Object.entries(nudgesByFile).sort(([, a], [, b]) => b - a).slice(0, 3);
1293
- if (topFiles[0] && topFiles[0][1] > 2) {
1294
- observations.push(`File ${topFiles[0][0]} has ${topFiles[0][1]} repeated issues this session`);
1295
- }
1296
- }
1297
- if (this.state.nudges.length > 5) {
1298
- observations.push(`High issue detection rate: ${this.state.nudges.length} violations detected in watch session`);
1299
- }
1300
- let generated = await hypothesisEngine.generateHypothesesWithAI({
1301
- recentIssues,
1302
- patterns,
1303
- observations
1304
- });
1305
- if (generated.length === 0) {
1306
- generated = await hypothesisEngine.autoGenerateHypotheses();
1307
- }
1308
- for (const hypothesis of generated) {
1309
- const message = `[New Hypothesis] "${hypothesis.statement}" (${Math.round(hypothesis.confidence * 100)}% confidence)`;
1310
- getOutputManager2().nudge(
1311
- message,
1312
- "info",
1313
- void 0,
1314
- 1e4
1315
- );
1316
- if (!isInteractiveMode()) {
1317
- console.error(`
1318
- [?] ${message}`);
1319
- console.error(` Test: ${hypothesis.testCriteria || "Collecting evidence..."}`);
1320
- }
1321
- if (this.streamingManager) {
1322
- this.streamingManager.reportSignalExtraction({
1323
- governance: 0,
1324
- facts: 0,
1325
- blockers: 0,
1326
- questions: 1
1327
- // Hypotheses are questions to answer
1328
- });
1329
- }
1330
- }
1331
- if (recentIssues.length > 10) {
1332
- await hypothesisEngine.updateConfidenceFromOutcomes();
1333
- }
1334
- } catch (error) {
1335
- if (!isInteractiveMode()) {
1336
- console.error(` [!] Hypothesis check failed: ${error}`);
1337
- }
1338
- }
1339
- }
1340
- /**
1341
- * Discover patterns from accumulated issues
1342
- * Patterns emerge naturally from your coding workflow
1343
- */
1344
- async discoverPatternsFromIssues(projectPath) {
1345
- const totalIssues = Array.from(this.state.issueCache.values()).flat().length;
1346
- if (totalIssues < 5) return;
1347
- try {
1348
- const { ContextGraph: ContextGraph2 } = await import("./graph-J4OGTYCO.js");
1349
- const { IncidentIndex } = await import("./incident-index-BWW2UEY7.js");
1350
- const { TriePatternDiscovery } = await import("./pattern-discovery-F7LU5K6E.js");
1351
- const graph = new ContextGraph2(projectPath);
1352
- const incidentIndex = await IncidentIndex.build(graph, projectPath);
1353
- const discovery = new TriePatternDiscovery(graph, incidentIndex);
1354
- const hotPatterns = discovery.discoverHotPatterns(2);
1355
- for (const hot of hotPatterns) {
1356
- const existingPatterns = await graph.listNodes();
1357
- const alreadyExists = existingPatterns.some(
1358
- (n) => n.type === "pattern" && n.data.description?.includes(hot.path)
1359
- );
1360
- if (!alreadyExists) {
1361
- await graph.addNode("pattern", {
1362
- description: `${hot.type === "directory" ? "Directory" : "File"} hot zone: ${hot.path}`,
1363
- appliesTo: [hot.path],
1364
- confidence: Math.min(0.95, hot.confidence),
1365
- occurrences: hot.incidentCount,
1366
- firstSeen: (/* @__PURE__ */ new Date()).toISOString(),
1367
- lastSeen: (/* @__PURE__ */ new Date()).toISOString(),
1368
- isAntiPattern: hot.incidentCount >= 3,
1369
- // 3+ incidents = anti-pattern
1370
- source: "local"
1371
- });
1372
- if (!isInteractiveMode()) {
1373
- console.error(` [+] Pattern discovered: ${hot.path} (${hot.incidentCount} issues)`);
1374
- }
1375
- if (this.streamingManager) {
1376
- this.streamingManager.reportSignalExtraction({
1377
- governance: 0,
1378
- facts: 1,
1379
- // Patterns are facts about the codebase
1380
- blockers: 0,
1381
- questions: 0
1382
- });
1383
- }
1384
- }
1385
- }
1386
- if (totalIssues >= 10) {
1387
- const coOccurrences = await discovery.discoverCoOccurrences(2);
1388
- for (const coOcc of coOccurrences.slice(0, 3)) {
1389
- const desc = `Files break together: ${coOcc.files[0]} + ${coOcc.files[1]}`;
1390
- const existingPatterns = await graph.listNodes();
1391
- const alreadyExists = existingPatterns.some(
1392
- (n) => n.type === "pattern" && n.data.description === desc
1393
- );
1394
- if (!alreadyExists) {
1395
- await graph.addNode("pattern", {
1396
- description: desc,
1397
- appliesTo: [...coOcc.files],
1398
- confidence: Math.min(0.95, coOcc.confidence),
1399
- occurrences: coOcc.coOccurrences,
1400
- firstSeen: (/* @__PURE__ */ new Date()).toISOString(),
1401
- lastSeen: (/* @__PURE__ */ new Date()).toISOString(),
1402
- isAntiPattern: coOcc.confidence > 0.7,
1403
- source: "local"
1404
- });
1405
- if (!isInteractiveMode()) {
1406
- console.error(` [+] Co-occurrence pattern: ${coOcc.files[0]} + ${coOcc.files[1]}`);
1407
- }
1408
- }
1409
- }
1410
- }
1411
- } catch (error) {
1412
- if (!isInteractiveMode()) {
1413
- console.error(` [!] Pattern discovery failed: ${error}`);
1414
- }
1415
- }
1416
- }
1417
- // Defaults -- overridden by config when loaded
1418
- aiWatcherCooldownMs = 3e4;
1419
- cleanFileCooldownMs = 3e5;
1420
- maxFilesPerScan = 5;
1421
- maxCharsPerFile = 4e3;
1422
- /**
1423
- * Use the trie (context graph) to score how urgently a file needs scanning.
1424
- * Higher score = more worth spending tokens on.
1425
- */
1426
- async scoreScanPriority(file, graph, projectPath) {
1427
- let score = 1;
1428
- const lastClean = this.state.cleanFiles.get(file);
1429
- if (lastClean && Date.now() - lastClean < this.cleanFileCooldownMs) {
1430
- return 0;
1431
- }
1432
- const fileNode = await graph.getNode("file", join2(projectPath, file));
1433
- if (!fileNode) return score;
1434
- const data = fileNode.data;
1435
- const riskScores = { critical: 10, high: 6, medium: 2, low: 1 };
1436
- score += riskScores[data.riskLevel] ?? 1;
1437
- score += Math.min(data.incidentCount * 3, 12);
1438
- if (data.changeCount > 10) score += 2;
1439
- return score;
1440
- }
1441
- /**
1442
- * Roll the token budget window if an hour has passed.
1443
- * Returns remaining tokens in the current window.
1444
- */
1445
- getRemainingBudget() {
1446
- const budget = this.state.tokenBudget;
1447
- const elapsed = Date.now() - budget.windowStart;
1448
- if (elapsed > 36e5) {
1449
- budget.used = 0;
1450
- budget.windowStart = Date.now();
1451
- }
1452
- return Math.max(0, budget.hourlyLimit - budget.used);
1453
- }
1454
- recordTokenUsage(tokens) {
1455
- this.state.tokenBudget.used += tokens;
1456
- }
1457
- /**
1458
- * AI-powered watcher -- the primary detection system.
1459
- *
1460
- * This is the single AI call that handles:
1461
- * 1. Code review (bugs, security, logic errors)
1462
- * 2. Goal violation detection (user-defined quality goals)
1463
- *
1464
- * When goals are active, files with goal violations bypass priority scoring
1465
- * so violations are always caught. Throttled by cooldown + token budget.
1466
- */
1467
- async autoScanFiles(files) {
1468
- if (!isAIAvailable()) return;
1469
- if (this.state.autoScanInProgress) return;
1470
- const now = Date.now();
1471
- if (now - this.state.lastAutoScan < this.aiWatcherCooldownMs) return;
1472
- this.state.autoScanInProgress = true;
1473
- this.state.lastAutoScan = now;
1474
- const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
1475
- try {
1476
- try {
1477
- const config = await getAutonomyConfig(projectPath);
1478
- const wc = config.aiWatcher;
1479
- if (!wc.enabled) return;
1480
- this.state.tokenBudget.hourlyLimit = wc.hourlyTokenLimit;
1481
- this.aiWatcherCooldownMs = wc.scanCooldownSec * 1e3;
1482
- this.cleanFileCooldownMs = wc.cleanFileCooldownSec * 1e3;
1483
- this.maxFilesPerScan = wc.maxFilesPerScan;
1484
- this.maxCharsPerFile = wc.maxCharsPerFile;
1485
- } catch {
1486
- }
1487
- const remaining = this.getRemainingBudget();
1488
- if (remaining < 500) return;
1489
- try {
1490
- const graph = new ContextGraph(projectPath);
1491
- const { getActiveGoals, recordGoalViolationCaught } = await import("./goal-validator-DV6DRSGF.js");
1492
- console.debug("[AI Watcher] Loading active goals...");
1493
- const activeGoals = await getActiveGoals(projectPath);
1494
- const hasGoals = activeGoals.length > 0;
1495
- console.debug("[AI Watcher] Goals loaded:", {
1496
- totalGoals: activeGoals.length,
1497
- hasGoals,
1498
- goals: activeGoals.map((g) => ({ id: g.id, description: g.description, status: g.status }))
1499
- });
1500
- if (this.isQuiet() && !hasGoals) return;
1501
- const scored = [];
1502
- for (const file of files) {
1503
- const relativePath = file.replace(projectPath + "/", "");
1504
- const score = await this.scoreScanPriority(relativePath, graph, projectPath);
1505
- if (hasGoals || score > 0) {
1506
- scored.push({ file, relativePath, score: Math.max(score, hasGoals ? 1 : 0) });
1507
- } else {
1508
- this.state.tokenBudget.scansSaved++;
1509
- }
1510
- }
1511
- if (scored.length === 0) return;
1512
- scored.sort((a, b) => b.score - a.score);
1513
- const budgetScale = remaining > 2e4 ? 1 : remaining > 1e4 ? 0.6 : 0.4;
1514
- const maxFiles = Math.max(1, Math.round(this.maxFilesPerScan * budgetScale));
1515
- const filesToScan = scored.slice(0, maxFiles);
1516
- const charLimit = Math.round(this.maxCharsPerFile * (remaining > 15e3 ? 1 : 0.5));
1517
- const fileContents = await Promise.all(
1518
- filesToScan.map(async ({ file, relativePath }) => {
1519
- try {
1520
- const content = await readFile2(file, "utf-8");
1521
- return { path: relativePath, content: content.slice(0, charLimit) };
1522
- } catch {
1523
- return null;
1524
- }
1525
- })
1526
- );
1527
- const valid = fileContents.filter(Boolean);
1528
- if (valid.length === 0) return;
1529
- const filesBlock = valid.map(
1530
- (f) => `### ${f.path}
1531
- \`\`\`
1532
- ${f.content}
1533
- \`\`\``
1534
- ).join("\n\n");
1535
- let goalsSection = "";
1536
- if (hasGoals) {
1537
- goalsSection = `
1538
- USER-DEFINED GOALS (IMPORTANT - check EVERY file against ALL goals):
1539
- ${activeGoals.map((g, i) => ` ${i + 1}. "${g.description}"`).join("\n")}
1540
-
1541
- Goal violations are HIGH PRIORITY. If a file violates any goal, you MUST report it.
1542
- `;
1543
- }
1544
- console.debug("[AI Watcher] Sending files to AI analysis:", {
1545
- fileCount: valid.length,
1546
- hasGoals,
1547
- goalsIncluded: hasGoals,
1548
- filePaths: valid.map((f) => f.path),
1549
- goalsSection: goalsSection.slice(0, 200) + (goalsSection.length > 200 ? "..." : "")
1550
- });
1551
- const result = await runAIAnalysis({
1552
- systemPrompt: `You are a code quality watcher. You review code for two things:
1553
-
1554
- 1. CODE ISSUES: bugs, security vulnerabilities, logic errors, risky patterns
1555
- 2. GOAL VIOLATIONS: check every file against the user's quality goals
1556
- ${goalsSection}
1557
- Reply ONLY with a JSON array. Each element must have:
1558
- - "file": relative file path
1559
- - "severity": "critical" | "major" | "minor"
1560
- - "description": 1-sentence description of what you found
1561
- - "confidence": number 0-100, how confident you are this is a real issue
1562
- - "suggestedFix": 1-sentence description of what should change to fix it
1563
- - "isGoalViolation": true if this violates a user goal, false otherwise
1564
- - "goalIndex": 0-based index of the violated goal (only if isGoalViolation is true)
1565
-
1566
- 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.
1567
-
1568
- If no issues or violations found, reply with: []
1569
- Output ONLY the JSON array, no markdown fences, no commentary.`,
1570
- userPrompt: `Review these changed files:
1571
-
1572
- ${filesBlock}`,
1573
- maxTokens: 2048,
1574
- temperature: 0.1
1575
- });
1576
- if (result.tokensUsed) {
1577
- this.recordTokenUsage(result.tokensUsed.input + result.tokensUsed.output);
1578
- }
1579
- console.debug("[AI Watcher] AI analysis result:", {
1580
- success: result.success,
1581
- contentLength: result.content ? result.content.length : 0,
1582
- tokensUsed: result.tokensUsed,
1583
- contentPreview: result.content ? result.content.slice(0, 500) : "null"
1584
- });
1585
- if (!result.success || !result.content.trim()) {
1586
- console.debug("[AI Watcher] AI analysis failed or returned empty content");
1587
- return;
1588
- }
1589
- let issues = [];
1590
- try {
1591
- const cleaned = result.content.replace(/```json?\n?|\n?```/g, "").trim();
1592
- console.debug("[AI Watcher] Parsing AI response:", { cleanedContent: cleaned.slice(0, 300) });
1593
- issues = JSON.parse(cleaned);
1594
- if (!Array.isArray(issues)) issues = [];
1595
- console.debug("[AI Watcher] Parsed issues:", {
1596
- totalIssues: issues.length,
1597
- goalViolations: issues.filter((i) => i.isGoalViolation).length,
1598
- issueTypes: issues.map((i) => ({ file: i.file, isGoalViolation: i.isGoalViolation, goalIndex: i.goalIndex }))
1599
- });
1600
- } catch (error) {
1601
- console.debug("[AI Watcher] Failed to parse AI response:", error);
1602
- return;
1603
- }
1604
- const issuedFiles = new Set(issues.map((i) => i.file));
1605
- for (const { relativePath } of filesToScan) {
1606
- if (!issuedFiles.has(relativePath)) {
1607
- this.state.cleanFiles.set(relativePath, Date.now());
1608
- }
1609
- }
1610
- if (issues.length === 0) return;
1611
- for (const issue of issues.slice(0, 10)) {
1612
- const severity = issue.severity === "critical" ? "critical" : issue.severity === "major" ? "major" : "minor";
1613
- if (issue.isGoalViolation && issue.goalIndex != null && issue.goalIndex >= 0 && issue.goalIndex < activeGoals.length) {
1614
- const goal = activeGoals[issue.goalIndex];
1615
- if (!goal) continue;
1616
- const confidence = Math.min(100, Math.max(0, issue.confidence ?? 80));
1617
- const fixId = `fix-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
1618
- console.debug("[AI Watcher] Goal violation detected:", {
1619
- goalDescription: goal.description,
1620
- file: issue.file,
1621
- violation: issue.description,
1622
- confidence,
1623
- goalIndex: issue.goalIndex,
1624
- totalActiveGoals: activeGoals.length
1625
- });
1626
- const goalViolationIssue = {
1627
- id: fixId,
1628
- file: issue.file,
1629
- agent: "goal-violation",
1630
- severity: severity === "critical" ? "critical" : severity === "major" ? "serious" : "moderate",
1631
- issue: `Goal "${goal.description}" violated: ${issue.description}`,
1632
- fix: issue.suggestedFix || "Review and fix",
1633
- category: "goal-violation",
1634
- confidence,
1635
- autoFixable: true
1636
- };
1637
- await storeIssues([goalViolationIssue], basename2(projectPath), projectPath);
1638
- await recordGoalViolationCaught(goal, issue.file, projectPath);
1639
- const confidenceStr = `${confidence}%`;
1640
- const nudgeMsg = `Goal "${goal.description}" violated in ${issue.file}: ${issue.description} [${confidenceStr} confidence]`;
1641
- console.debug("[AI Watcher] Sending nudge:", {
1642
- message: nudgeMsg,
1643
- file: issue.file,
1644
- severity: "warning"
1645
- });
1646
- getOutputManager().nudge(nudgeMsg, "warning", issue.file);
1647
- await this.persistNudge({
1648
- message: nudgeMsg,
1649
- severity: "warning",
1650
- file: issue.file,
1651
- category: "quality",
1652
- goalId: goal.id,
1653
- priority: 7,
1654
- suggestedAction: issue.suggestedFix || "Review and fix manually",
1655
- relatedIssues: [fixId]
1656
- });
1657
- if (this.streamingManager) {
1658
- this.streamingManager.reportPendingFix({
1659
- id: fixId,
1660
- file: issue.file,
1661
- description: issue.description,
1662
- goalDescription: goal.description,
1663
- confidence,
1664
- severity: issue.severity,
1665
- suggestedFix: issue.suggestedFix || "Remove the violating code"
1666
- });
1667
- }
1668
- if (!isInteractiveMode()) {
1669
- console.error(` [!] Goal violation (${confidenceStr}): ${issue.description}`);
1670
- console.error(` Fix: ${issue.suggestedFix || "Review and fix manually"}`);
1671
- }
1672
- continue;
1673
- }
1674
- const incident = await graph.addNode("incident", {
1675
- description: issue.description,
1676
- severity,
1677
- affectedUsers: null,
1678
- duration: null,
1679
- timestamp: (/* @__PURE__ */ new Date()).toISOString(),
1680
- resolved: false,
1681
- resolution: null,
1682
- fixChangeId: null,
1683
- reportedVia: "detected"
1684
- });
1685
- const filePath = join2(projectPath, issue.file);
1686
- const fileNode = await graph.getNode("file", filePath);
1687
- if (fileNode) {
1688
- await graph.addEdge(fileNode.id, incident.id, "affects");
1689
- const data = fileNode.data;
1690
- const newRisk = severity === "critical" ? "critical" : severity === "major" ? "high" : data.riskLevel === "low" ? "medium" : data.riskLevel;
1691
- await graph.updateNode("file", fileNode.id, {
1692
- incidentCount: (data.incidentCount ?? 0) + 1,
1693
- riskLevel: newRisk
1694
- });
1695
- }
1696
- this.state.totalIssuesFound++;
1697
- if (severity !== "minor") {
1698
- getOutputManager().nudge(
1699
- `${issue.description}`,
1700
- severity === "critical" ? "critical" : "warning",
1701
- issue.file,
1702
- severity === "critical" ? void 0 : 15e3
1703
- );
1704
- await this.persistNudge({
1705
- message: issue.description,
1706
- severity: severity === "critical" ? "critical" : "warning",
1707
- file: issue.file,
1708
- category: "quality",
1709
- priority: severity === "critical" ? 9 : 6,
1710
- ...issue.suggestedFix && { suggestedAction: issue.suggestedFix }
1711
- });
1712
- }
1713
- }
1714
- if (this.streamingManager && issues.length > 0) {
1715
- this.streamingManager.reportSignalExtraction({
1716
- governance: 0,
1717
- facts: 0,
1718
- blockers: issues.length,
1719
- questions: 0
1720
- });
1721
- }
1722
- } catch (error) {
1723
- getOutputManager().log("warn", `AI watcher error: ${error}`);
1724
- }
1725
- } finally {
1726
- this.state.autoScanInProgress = false;
1727
- }
1728
- }
1729
- /**
1730
- * Initial hypothesis generation when watch starts.
1731
- *
1732
- * This generates hypotheses from existing patterns and issues to give
1733
- * users immediate insights about their codebase.
1734
- */
1735
- async initialHypothesisGeneration() {
1736
- if (!isAIAvailable()) {
1737
- console.debug("[Initial Hypothesis] AI not available, skipping initial hypothesis generation");
1738
- return;
1739
- }
1740
- const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
1741
- console.debug("[Initial Hypothesis] Starting initial hypothesis generation", { projectPath });
1742
- try {
1743
- const { getHypothesisEngine } = await import("./hypothesis-O72ZLVOW.js");
1744
- const hypothesisEngine = getHypothesisEngine(projectPath);
1745
- console.debug("[Initial Hypothesis] Running AI-powered hypothesis generation...");
1746
- const generated = await hypothesisEngine.generateHypothesesWithAI({
1747
- recentIssues: [],
1748
- // No recent issues yet on startup
1749
- patterns: [],
1750
- observations: ["Initial watch session started", "Analyzing codebase for potential patterns"]
1751
- });
1752
- console.debug("[Initial Hypothesis] Generated hypotheses on startup:", {
1753
- count: generated.length,
1754
- hypotheses: generated.map((h) => ({ statement: h.statement, confidence: h.confidence }))
1755
- });
1756
- if (generated.length > 0) {
1757
- const { getOutputManager: getOutputManager2 } = await import("./output-manager-DZO5LGSG.js");
1758
- const outputManager = getOutputManager2();
1759
- for (const hypothesis of generated.slice(0, 2)) {
1760
- const message = `[Initial Hypothesis] "${hypothesis.statement}" (${Math.round(hypothesis.confidence * 100)}% confidence)`;
1761
- outputManager.nudge(message, "info", void 0, 1e4);
1762
- if (!isInteractiveMode()) {
1763
- console.error(` [?] ${message}`);
1764
- }
1765
- }
1766
- if (this.streamingManager) {
1767
- this.streamingManager.reportSignalExtraction({
1768
- governance: 0,
1769
- facts: 0,
1770
- blockers: 0,
1771
- questions: generated.length
1772
- });
1773
- }
1774
- }
1775
- } catch (error) {
1776
- console.debug("[Initial Hypothesis] Failed to generate initial hypotheses:", error);
1777
- }
1778
- }
1779
- /**
1780
- * Initial goal compliance scan when watch starts.
1781
- *
1782
- * This checks recently modified files against active goals so the user
1783
- * gets immediate feedback about goal violations without waiting for files
1784
- * to be changed.
1785
- *
1786
- * Strategy:
1787
- * 1. Check if there are any active goals - if not, skip
1788
- * 2. Find recently modified files (last 24 hours OR uncommitted changes)
1789
- * 3. Filter to watched file types
1790
- * 4. Run a quick AI scan focused only on goal violations
1791
- * 5. Nudge the user about any violations found
1792
- */
1793
- async initialGoalComplianceScan() {
1794
- if (!isAIAvailable()) {
1795
- console.debug("[Initial Scan] AI not available, skipping initial goal compliance scan");
1796
- return;
1797
- }
1798
- const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
1799
- console.debug("[Initial Scan] Starting initial goal compliance scan", { projectPath });
1800
- try {
1801
- const { getActiveGoals, recordGoalViolationCaught } = await import("./goal-validator-DV6DRSGF.js");
1802
- const activeGoals = await getActiveGoals(projectPath);
1803
- console.debug("[Initial Scan] Loaded goals for initial scan:", {
1804
- goalCount: activeGoals.length,
1805
- goals: activeGoals.map((g) => ({ id: g.id, description: g.description }))
1806
- });
1807
- if (activeGoals.length === 0) {
1808
- console.debug("[Initial Scan] No active goals found, skipping initial scan");
1809
- return;
1810
- }
1811
- if (!isInteractiveMode()) {
1812
- console.error("[*] Checking recent files against active goals...");
1813
- }
1814
- const recentFiles = /* @__PURE__ */ new Set();
1815
- const uncommittedFiles = await getGitChangedFiles(projectPath);
1816
- if (uncommittedFiles) {
1817
- uncommittedFiles.forEach((f) => recentFiles.add(join2(projectPath, f)));
1818
- }
1819
- const oneDayAgo = Date.now() - 24 * 60 * 60 * 1e3;
1820
- const recentChanges = await getChangedFilesSinceTimestamp(projectPath, oneDayAgo);
1821
- if (recentChanges) {
1822
- recentChanges.forEach((f) => recentFiles.add(f));
1823
- }
1824
- const filesToCheck = Array.from(recentFiles).filter((file) => {
1825
- const ext = extname2(file).toLowerCase();
1826
- return WATCH_EXTENSIONS.has(ext) && existsSync2(file);
1827
- });
1828
- console.debug("[Initial Scan] Files discovered for initial scan:", {
1829
- totalRecentFiles: recentFiles.size,
1830
- filteredFiles: filesToCheck.length,
1831
- filePaths: filesToCheck.slice(0, 5).map((f) => f.replace(projectPath + "/", "")),
1832
- // Show first 5
1833
- watchedExtensions: Array.from(WATCH_EXTENSIONS)
1834
- });
1835
- if (filesToCheck.length === 0) {
1836
- console.debug("[Initial Scan] No recent files found for initial scan");
1837
- return;
1838
- }
1839
- const maxInitialFiles = 10;
1840
- const filesToScan = filesToCheck.slice(0, maxInitialFiles);
1841
- if (!isInteractiveMode()) {
1842
- console.error(` Scanning ${filesToScan.length} recent file(s) against ${activeGoals.length} goal(s)...`);
1843
- }
1844
- const maxCharsPerFile = 3e3;
1845
- const fileContents = await Promise.all(
1846
- filesToScan.map(async (file) => {
1847
- try {
1848
- const content = await readFile2(file, "utf-8");
1849
- const relativePath = file.replace(projectPath + "/", "");
1850
- return { path: relativePath, content: content.slice(0, maxCharsPerFile) };
1851
- } catch {
1852
- return null;
1853
- }
1854
- })
1855
- );
1856
- const valid = fileContents.filter(Boolean);
1857
- if (valid.length === 0) return;
1858
- const filesBlock = valid.map(
1859
- (f) => `### ${f.path}
1860
- \`\`\`
1861
- ${f.content}
1862
- \`\`\``
1863
- ).join("\n\n");
1864
- const goalsSection = `
1865
- USER-DEFINED GOALS (check EVERY file against ALL goals):
1866
- ${activeGoals.map((g, i) => ` ${i + 1}. "${g.description}"`).join("\n")}
1867
-
1868
- This is an INITIAL SCAN at watch startup. Report ALL goal violations you find.
1869
- `;
1870
- const result = await runAIAnalysis({
1871
- systemPrompt: `You are checking code for GOAL VIOLATIONS ONLY.
1872
- ${goalsSection}
1873
- Reply ONLY with a JSON array. Each element must have:
1874
- - "file": relative file path
1875
- - "severity": "critical" | "major" | "minor"
1876
- - "description": 1-sentence description of the goal violation
1877
- - "confidence": number 0-100, how confident you are this is a violation
1878
- - "suggestedFix": 1-sentence description of what should change
1879
- - "isGoalViolation": true (always true for this scan)
1880
- - "goalIndex": 0-based index of the violated goal
1881
-
1882
- 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.
1883
-
1884
- If no violations found, reply with: []
1885
- Output ONLY the JSON array, no markdown fences, no commentary.`,
1886
- userPrompt: `Check these files for goal violations:
1887
-
1888
- ${filesBlock}`,
1889
- maxTokens: 2048,
1890
- temperature: 0.1
1891
- });
1892
- if (result.tokensUsed) {
1893
- this.recordTokenUsage(result.tokensUsed.input + result.tokensUsed.output);
1894
- }
1895
- if (!result.success || !result.content.trim()) return;
1896
- let issues = [];
1897
- try {
1898
- const parsed = JSON.parse(result.content.trim());
1899
- issues = Array.isArray(parsed) ? parsed : [];
1900
- } catch {
1901
- return;
1902
- }
1903
- const issuesToStore = [];
1904
- let violationsFound = 0;
1905
- for (const issue of issues) {
1906
- if (!issue.isGoalViolation || issue.confidence < 40) continue;
1907
- violationsFound++;
1908
- if (issue.goalIndex != null && issue.goalIndex >= 0 && issue.goalIndex < activeGoals.length) {
1909
- const goal = activeGoals[issue.goalIndex];
1910
- if (!goal) continue;
1911
- const fixId = `fix-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
1912
- issuesToStore.push({
1913
- id: fixId,
1914
- file: issue.file,
1915
- agent: "goal-violation",
1916
- severity: issue.severity === "critical" ? "critical" : issue.severity === "major" ? "serious" : "moderate",
1917
- issue: `Goal "${goal.description}" violated: ${issue.description}`,
1918
- fix: issue.suggestedFix || "Review and fix",
1919
- category: "goal-violation",
1920
- confidence: issue.confidence,
1921
- autoFixable: true
1922
- });
1923
- await recordGoalViolationCaught(goal, issue.file, projectPath);
1924
- const confidenceStr = issue.confidence >= 80 ? "high" : issue.confidence >= 60 ? "medium" : "low";
1925
- const nudgeMsg = `Goal "${goal.description}" violated in ${issue.file}: ${issue.description} [${confidenceStr} confidence]`;
1926
- getOutputManager().nudge(nudgeMsg, "warning", issue.file);
1927
- await this.persistNudge({
1928
- message: nudgeMsg,
1929
- severity: "warning",
1930
- file: issue.file,
1931
- category: "quality",
1932
- goalId: goal.id,
1933
- priority: issue.confidence >= 80 ? 8 : issue.confidence >= 60 ? 6 : 4,
1934
- ...issue.suggestedFix && { suggestedAction: issue.suggestedFix }
1935
- });
1936
- }
1937
- }
1938
- if (issuesToStore.length > 0) {
1939
- await storeIssues(issuesToStore, basename2(projectPath), projectPath);
1940
- }
1941
- if (!isInteractiveMode()) {
1942
- if (violationsFound > 0) {
1943
- console.error(` [!] Found ${violationsFound} goal violation(s) in recent files`);
1944
- } else {
1945
- console.error(` [\u2713] No goal violations found in recent files`);
1946
- }
1947
- }
1948
- } catch (error) {
1949
- if (!isInteractiveMode()) {
1950
- console.error(` [!] Initial goal scan error: ${error}`);
1951
- }
1952
- }
1953
- }
1954
- async syncPipelineIntegrations() {
1955
- const projectPath = this.watchedDirectory || getWorkingDirectory(void 0, true);
1956
- try {
1957
- const config = await loadConfig();
1958
- const hasLinear = !!(config.apiKeys?.linear ?? process.env.LINEAR_API_KEY);
1959
- const hasGithub = !!(config.apiKeys?.github ?? process.env.GITHUB_TOKEN);
1960
- if (!hasLinear && !hasGithub) return;
1961
- const graph = new ContextGraph(projectPath);
1962
- if (hasLinear) {
1963
- try {
1964
- const { LinearIngester: LinearIngester2 } = await import("./linear-ingester-JRDQAIAA.js");
1965
- const ingester = new LinearIngester2(projectPath, graph);
1966
- await ingester.syncTickets();
1967
- if (!isInteractiveMode()) {
1968
- console.error("[Pipeline] Linear tickets synced");
1969
- }
1970
- } catch (error) {
1971
- if (!isInteractiveMode()) {
1972
- console.error(`[Pipeline] Linear sync failed: ${error}`);
1973
- }
1974
- }
1975
- }
1976
- if (hasGithub) {
1977
- try {
1978
- const { GitHubIngester: GitHubIngester2 } = await import("./github-ingester-J2ZFYXVE.js");
1979
- const ingester = new GitHubIngester2(graph);
1980
- const token = await ingester.getApiToken();
1981
- const repoInfo = ingester.getRepoInfo(projectPath);
1982
- if (repoInfo) {
1983
- await ingester.syncPullRequests(repoInfo.owner, repoInfo.name, token);
1984
- await ingester.syncIssues(repoInfo.owner, repoInfo.name, token);
1985
- if (!isInteractiveMode()) {
1986
- console.error("[Pipeline] GitHub PRs/issues synced");
1987
- }
1988
- }
1989
- } catch (error) {
1990
- if (!isInteractiveMode()) {
1991
- console.error(`[Pipeline] GitHub sync failed: ${error}`);
1992
- }
1993
- }
1994
- }
1995
- } catch {
1996
- }
1997
- }
1998
- async stopWatching() {
1999
- if (!this.state.isRunning) {
2000
- return {
2001
- content: [{
2002
- type: "text",
2003
- text: "[!] Watch mode is not running."
2004
- }]
2005
- };
2006
- }
2007
- for (const watcher of this.watchers.values()) {
2008
- watcher.close();
2009
- }
2010
- this.watchers.clear();
2011
- if (this.extractionPipeline) {
2012
- this.extractionPipeline.close();
2013
- this.extractionPipeline = null;
2014
- }
2015
- if (this.pipelineSyncTimer) {
2016
- clearInterval(this.pipelineSyncTimer);
2017
- this.pipelineSyncTimer = null;
2018
- }
2019
- if (this.codebaseIndex) {
2020
- await this.codebaseIndex.save();
2021
- this.codebaseIndex = null;
2022
- }
2023
- if (this.state.scanDebounceTimer) {
2024
- clearTimeout(this.state.scanDebounceTimer);
2025
- }
2026
- this.state.isRunning = false;
2027
- if (!isInteractiveMode()) {
2028
- console.error("\n[*] Watch mode stopped.\n");
2029
- }
2030
- if (this.streamingManager) {
2031
- this.streamingManager.reportWatchStatus({ watching: false, directories: 0 });
2032
- }
2033
- const outputManager = getOutputManager();
2034
- outputManager.clearTUICallbacks();
2035
- outputManager.setMode("console");
2036
- if (this.dashboard) {
2037
- this.dashboard.stop();
2038
- this.dashboard = void 0;
2039
- }
2040
- const budget = this.state.tokenBudget;
2041
- const tokensK = (budget.used / 1e3).toFixed(1);
2042
- return {
2043
- content: [{
2044
- type: "text",
2045
- text: `[*] **TRIE AGENT STOPPED**
2046
-
2047
- ### Session Summary:
2048
- - Files scanned: ${this.state.filesScanned}
2049
- - Issues found: ${this.state.totalIssuesFound}
2050
- - Tokens used: ${tokensK}k / ${(budget.hourlyLimit / 1e3).toFixed(0)}k hourly limit
2051
- - Scans skipped (trie-throttled): ${budget.scansSaved}
2052
- - Governance ledger: Updated continuously
2053
-
2054
- Use \`trie_watch start\` to resume.`
2055
- }]
2056
- };
2057
- }
2058
- async getStatus() {
2059
- if (!this.state.isRunning) {
2060
- return {
2061
- content: [{
2062
- type: "text",
2063
- text: `[*] **Watch Mode Status: STOPPED**
2064
-
2065
- Use \`trie_watch start\` to begin autonomous scanning.`
2066
- }]
2067
- };
2068
- }
2069
- const recentScans = Array.from(this.state.lastScan.entries()).sort((a, b) => b[1] - a[1]).slice(0, 5).map(([file, time]) => {
2070
- const ago = Math.round((Date.now() - time) / 1e3);
2071
- return `- \`${basename2(file)}\` (${ago}s ago)`;
2072
- }).join("\n");
2073
- const recentNudges = this.state.nudges.slice(-3).map(
2074
- (n) => `- ${basename2(n.file)} [${n.severity}] @ ${n.timestamp}`
2075
- ).join("\n");
2076
- let agencyStatus = "";
2077
- try {
2078
- const { getTrieAgent } = await import("./trie-agent-ET3DAP5Y.js");
2079
- const trieAgent = getTrieAgent(this.watchedDirectory || getWorkingDirectory(void 0, true));
2080
- await trieAgent.initialize();
2081
- const status = await trieAgent.getAgencyStatus();
2082
- agencyStatus = `
2083
- ### [AI] Trie Agent:
2084
- - **Goals:** ${status.goals.active} active, ${status.goals.completed} completed${status.goals.topGoal ? ` (${status.goals.topGoal.slice(0, 40)}...)` : ""}
2085
- - **Hypotheses:** ${status.hypotheses.testing} testing, ${status.hypotheses.validated} validated
2086
- - **Risk Level:** ${status.riskLevel.toUpperCase()}
2087
- - **Effectiveness:** ${status.effectiveness}%
2088
- - **Scan Frequency:** ${Math.round(status.scanFrequency / 1e3)}s${status.isQuietHours ? " (quiet hours)" : ""}`;
2089
- } catch {
2090
- }
2091
- const budget = this.state.tokenBudget;
2092
- const remaining = this.getRemainingBudget();
2093
- const tokensK = (budget.used / 1e3).toFixed(1);
2094
- const remainingK = (remaining / 1e3).toFixed(1);
2095
- return {
2096
- content: [{
2097
- type: "text",
2098
- text: `[*] **WATCH MODE Status: RUNNING**
2099
-
2100
- ### Stats:
2101
- - Directories watched: ${this.watchers.size}
2102
- - Files scanned: ${this.state.filesScanned}
2103
- - Issues found: ${this.state.totalIssuesFound}
2104
- - Pending: ${this.state.pendingFiles.size}
2105
-
2106
- ### Token Budget:
2107
- - Used: ${tokensK}k / ${(budget.hourlyLimit / 1e3).toFixed(0)}k hourly
2108
- - Remaining: ${remainingK}k
2109
- - Scans skipped (trie-throttled): ${budget.scansSaved}
2110
- ${agencyStatus}
2111
-
2112
- ### Recently Scanned:
2113
- ${recentScans || "(none yet)"}
2114
-
2115
- ### Recent Nudges:
2116
- ${recentNudges || "(none)"}
2117
-
2118
- ### Commands:
2119
- - \`trie_watch issues\` - Get all issues found
2120
- - \`trie_watch stop\` - Stop watching`
2121
- }]
2122
- };
2123
- }
2124
- /**
2125
- * Helper to persist a nudge to both in-memory state and SQL storage
2126
- */
2127
- async persistNudge(params) {
2128
- const timestamp = (/* @__PURE__ */ new Date()).toISOString();
2129
- const nudgeId = createHash("sha256").update(`${params.message}|${params.file || ""}|${timestamp}`).digest("hex").slice(0, 16);
2130
- const nudge = {
2131
- id: nudgeId,
2132
- message: params.message,
2133
- severity: params.severity,
2134
- timestamp,
2135
- resolved: false,
2136
- dismissed: false,
2137
- priority: params.priority ?? 5,
2138
- relatedIssues: params.relatedIssues ?? [],
2139
- metadata: {},
2140
- ...params.file && { file: params.file },
2141
- ...params.category && { category: params.category },
2142
- ...params.goalId && { goalId: params.goalId },
2143
- ...params.suggestedAction && { suggestedAction: params.suggestedAction }
2144
- };
2145
- this.state.nudges.push({
2146
- file: params.file || "unknown",
2147
- // Keep full path for consistency with loaded nudges
2148
- message: params.message,
2149
- severity: params.severity === "warning" || params.severity === "info" ? "high" : params.severity,
2150
- timestamp: (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false })
2151
- });
2152
- try {
2153
- const storage = getStorage(this.watchedDirectory);
2154
- await storage.storeNudge(nudge);
2155
- console.debug(`[Watch] \u2713 Persisted nudge to storage: ${nudge.message.slice(0, 60)}...`);
2156
- } catch (error) {
2157
- console.error("[Watch] Failed to persist nudge to storage:", error);
2158
- }
2159
- }
2160
- getNudges() {
2161
- return {
2162
- content: [
2163
- {
2164
- type: "text",
2165
- text: `[#] Recent nudges (${this.state.nudges.length} this session)
2166
- ` + (this.state.nudges.length ? this.state.nudges.map(
2167
- (n) => `- ${basename2(n.file)} [${n.severity}] @ ${n.timestamp}
2168
- ${n.message}`
2169
- ).join("\n") : "(none)")
2170
- },
2171
- {
2172
- type: "json",
2173
- json: this.state.nudges
2174
- }
2175
- ]
2176
- };
2177
- }
2178
- getCurrentIssues() {
2179
- return {
2180
- content: [{
2181
- type: "text",
2182
- text: `[L] **Issues Found This Session**
2183
-
2184
- Total issues: ${this.state.totalIssuesFound}
2185
- Files scanned: ${this.state.filesScanned}
2186
-
2187
- To get a full report, run \`trie_scan\` on your codebase.`
2188
- }]
2189
- };
2190
- }
2191
- };
2192
-
2193
- // src/tools/pr-review.ts
2194
- import { readFile as readFile3 } from "fs/promises";
2195
- import { existsSync as existsSync3 } from "fs";
2196
- import { join as join3, basename as basename3, resolve as resolve2, isAbsolute as isAbsolute2 } from "path";
2197
-
2198
- // src/skills/built-in/super-reviewer.ts
2199
- var CRITICAL_REVIEW_CHECKLIST = {
2200
- stateAndLifecycle: [
2201
- "Uninitialized state accessed before setup",
2202
- "Missing cleanup on unmount/dispose",
2203
- "State mutations in wrong lifecycle phase"
2204
- ],
2205
- edgeCasesAndRaces: [
2206
- "Race conditions in async operations",
2207
- "Missing error handling for edge cases",
2208
- "Unhandled promise rejections"
2209
- ],
2210
- missingPieces: [
2211
- "Missing input validation",
2212
- "Missing error handling",
2213
- "Missing logging/monitoring"
2214
- ]
2215
- };
2216
- var SuperReviewerAgent = class {
2217
- async review(_files) {
2218
- return { issues: [] };
2219
- }
2220
- async buildReviewWorkflow(files, context) {
2221
- return { files, context };
2222
- }
2223
- };
2224
-
2225
781
  // src/tools/pr-review.ts
782
+ import { readFile as readFile2 } from "fs/promises";
783
+ import { existsSync as existsSync2 } from "fs";
784
+ import { join as join2, basename as basename2, resolve as resolve2, isAbsolute as isAbsolute2 } from "path";
2226
785
  var TriePRReviewTool = class {
2227
- agent = new SuperReviewerAgent();
786
+ // Review workflow is now ledger-driven; keep a lightweight built-in checklist.
787
+ CRITICAL_REVIEW_CHECKLIST = {
788
+ stateAndLifecycle: [
789
+ "Uninitialized state accessed before setup",
790
+ "Missing cleanup on unmount/dispose",
791
+ "State mutations in wrong lifecycle phase"
792
+ ],
793
+ edgeCasesAndRaces: [
794
+ "Race conditions in async operations",
795
+ "Missing error handling for edge cases",
796
+ "Unhandled promise rejections"
797
+ ],
798
+ missingPieces: [
799
+ "Missing input validation",
800
+ "Missing error handling",
801
+ "Missing logging/monitoring"
802
+ ]
803
+ };
2228
804
  exec(command, cwd, maxBuffer) {
2229
805
  const opts = {
2230
806
  captureOutput: false,
@@ -2272,18 +848,15 @@ Usage:
2272
848
  };
2273
849
  }
2274
850
  const designDocs = await this.findDesignDocs(changes.files, prInfo);
2275
- const workflow = await this.agent.buildReviewWorkflow(
2276
- changes.files,
2277
- {
2278
- prNumber: prInfo.number,
2279
- prTitle: prInfo.title,
2280
- prAuthor: prInfo.author,
2281
- baseBranch: prInfo.baseBranch,
2282
- headBranch: prInfo.headBranch,
2283
- mode: mode || "own",
2284
- designDocs
2285
- }
2286
- );
851
+ const workflow = this.buildReviewWorkflow(changes.files, {
852
+ ...prInfo.number ? { prNumber: prInfo.number } : {},
853
+ ...prInfo.title ? { prTitle: prInfo.title } : {},
854
+ ...prInfo.author ? { prAuthor: prInfo.author } : {},
855
+ ...prInfo.baseBranch ? { baseBranch: prInfo.baseBranch } : {},
856
+ ...prInfo.headBranch ? { headBranch: prInfo.headBranch } : {},
857
+ mode: mode || "own",
858
+ designDocs
859
+ });
2287
860
  const fileContents = await this.preloadFiles(changes.files.map((f) => f.path));
2288
861
  const reviewPrompt = this.generateReviewPrompt(workflow, changes, fileContents);
2289
862
  return {
@@ -2307,14 +880,14 @@ Usage:
2307
880
  async getPRInfo(pr, worktree) {
2308
881
  if (worktree) {
2309
882
  const worktreePath = isAbsolute2(worktree) ? worktree : resolve2(getWorkingDirectory(void 0, true), worktree);
2310
- if (!existsSync3(worktreePath)) {
883
+ if (!existsSync2(worktreePath)) {
2311
884
  return { success: false, error: `Worktree not found: ${worktreePath}` };
2312
885
  }
2313
886
  return {
2314
887
  success: true,
2315
888
  type: "worktree",
2316
889
  path: worktreePath,
2317
- title: `Local changes in ${basename3(worktreePath)}`,
890
+ title: `Local changes in ${basename2(worktreePath)}`,
2318
891
  author: this.getGitUser(),
2319
892
  baseBranch: "HEAD~1",
2320
893
  headBranch: "HEAD"
@@ -2422,6 +995,36 @@ Usage:
2422
995
  }
2423
996
  return files;
2424
997
  }
998
+ buildReviewWorkflow(files, context) {
999
+ const totalAdditions = files.reduce((sum, f) => sum + (f.additions || 0), 0);
1000
+ const totalDeletions = files.reduce((sum, f) => sum + (f.deletions || 0), 0);
1001
+ const reviewMode = context.mode === "others" ? "others" : "own";
1002
+ const reviewInstructions = {
1003
+ mode: reviewMode,
1004
+ description: reviewMode === "own" ? "Your PR \u2014 focus on footguns, missing tests, and production risks." : "Someone else's PR \u2014 focus on correctness, clarity, and maintainability."
1005
+ };
1006
+ const sorted = [...files].sort((a, b) => a.path.localeCompare(b.path));
1007
+ const fileOrder = sorted.map((f, i) => ({
1008
+ index: i + 1,
1009
+ path: f.path,
1010
+ reason: i === 0 ? "Start here to establish baseline context" : "Proceed in filename order"
1011
+ }));
1012
+ return {
1013
+ metadata: {
1014
+ ...context.prNumber ? { prNumber: context.prNumber } : {},
1015
+ prTitle: context.prTitle || "PR Review",
1016
+ prAuthor: context.prAuthor || "unknown",
1017
+ baseBranch: context.baseBranch || "unknown",
1018
+ headBranch: context.headBranch || "unknown",
1019
+ totalFiles: files.length,
1020
+ totalAdditions,
1021
+ totalDeletions,
1022
+ designDocs: context.designDocs
1023
+ },
1024
+ fileOrder,
1025
+ reviewInstructions
1026
+ };
1027
+ }
2425
1028
  /**
2426
1029
  * Find related design docs
2427
1030
  */
@@ -2440,8 +1043,8 @@ Usage:
2440
1043
  "rfcs"
2441
1044
  ];
2442
1045
  for (const docPath of designDocPaths) {
2443
- const fullPath = join3(cwd, docPath);
2444
- if (existsSync3(fullPath)) {
1046
+ const fullPath = join2(cwd, docPath);
1047
+ if (existsSync2(fullPath)) {
2445
1048
  }
2446
1049
  }
2447
1050
  return designDocs;
@@ -2454,9 +1057,9 @@ Usage:
2454
1057
  const cwd = getWorkingDirectory(void 0, true);
2455
1058
  await Promise.all(filePaths.map(async (filePath) => {
2456
1059
  try {
2457
- const fullPath = isAbsolute2(filePath) ? filePath : join3(cwd, filePath);
2458
- if (existsSync3(fullPath)) {
2459
- const content = await readFile3(fullPath, "utf-8");
1060
+ const fullPath = isAbsolute2(filePath) ? filePath : join2(cwd, filePath);
1061
+ if (existsSync2(fullPath)) {
1062
+ const content = await readFile2(fullPath, "utf-8");
2460
1063
  contents.set(filePath, content);
2461
1064
  }
2462
1065
  } catch {
@@ -2537,21 +1140,21 @@ Usage:
2537
1140
  `;
2538
1141
  prompt += `**State & Lifecycle:**
2539
1142
  `;
2540
- for (const check of CRITICAL_REVIEW_CHECKLIST.stateAndLifecycle) {
1143
+ for (const check of this.CRITICAL_REVIEW_CHECKLIST.stateAndLifecycle) {
2541
1144
  prompt += `- ${check}
2542
1145
  `;
2543
1146
  }
2544
1147
  prompt += `
2545
1148
  **Edge Cases & Races:**
2546
1149
  `;
2547
- for (const check of CRITICAL_REVIEW_CHECKLIST.edgeCasesAndRaces) {
1150
+ for (const check of this.CRITICAL_REVIEW_CHECKLIST.edgeCasesAndRaces) {
2548
1151
  prompt += `- ${check}
2549
1152
  `;
2550
1153
  }
2551
1154
  prompt += `
2552
1155
  **Missing Pieces:**
2553
1156
  `;
2554
- for (const check of CRITICAL_REVIEW_CHECKLIST.missingPieces) {
1157
+ for (const check of this.CRITICAL_REVIEW_CHECKLIST.missingPieces) {
2555
1158
  prompt += `- ${check}
2556
1159
  `;
2557
1160
  }
@@ -2899,7 +1502,7 @@ var TrieInitTool = class {
2899
1502
  "",
2900
1503
  "1. Edit `.trie/PROJECT.md` with your project description",
2901
1504
  "2. Define coding standards in `.trie/RULES.md`",
2902
- "3. Run `trie_scan` to analyze your codebase",
1505
+ "3. Run `trie watch` to analyze your codebase",
2903
1506
  '4. Run `trie_init` with action="complete" when setup is done'
2904
1507
  );
2905
1508
  return lines.join("\n");
@@ -3568,11 +2171,7 @@ var ToolRegistry = class {
3568
2171
  properties: {
3569
2172
  action: {
3570
2173
  type: "string",
3571
- description: "Optional quick action: security, legal, bugs, types, devops, architecture, ux, clean, soc2, performance, e2e, visual_qa, data_flow, agent_smith, pr_review, watch, fix, explain"
3572
- },
3573
- agent: {
3574
- type: "string",
3575
- description: "Agent key when action=agent or when using a custom skill name"
2174
+ description: "Optional quick action: pr_review, watch, fix, explain, test, visual_qa_browser"
3576
2175
  },
3577
2176
  files: {
3578
2177
  type: "array",
@@ -3623,7 +2222,7 @@ var ToolRegistry = class {
3623
2222
  issueIds: {
3624
2223
  type: "array",
3625
2224
  items: { type: "string" },
3626
- description: "Issue IDs to dispatch (from trie_scan). If omitted, dispatches all cloud-eligible pending issues. IGNORED if file+issue+fix are provided (ad-hoc mode)."
2225
+ description: "Issue IDs to dispatch (from trie_fix/watch). If omitted, dispatches all cloud-eligible pending issues. IGNORED if file+issue+fix are provided (ad-hoc mode)."
3627
2226
  },
3628
2227
  forceCloud: {
3629
2228
  type: "boolean",
@@ -3817,7 +2416,7 @@ var ToolRegistry = class {
3817
2416
  },
3818
2417
  {
3819
2418
  name: "trie_init",
3820
- description: "Initialize bootstrap files (.trie/RULES.md, .trie/TEAM.md, .trie/BOOTSTRAP.md). Detects stack and suggests skills.",
2419
+ description: "Initialize bootstrap files (.trie/RULES.md, .trie/TEAM.md, .trie/BOOTSTRAP.md). Detects stack.",
3821
2420
  inputSchema: {
3822
2421
  type: "object",
3823
2422
  properties: {
@@ -4149,17 +2748,10 @@ var ToolRegistry = class {
4149
2748
  };
4150
2749
 
4151
2750
  // src/server/resource-manager.ts
4152
- import { readdir, readFile as readFile4 } from "fs/promises";
4153
- import { existsSync as existsSync4 } from "fs";
4154
- import { join as join4, dirname as dirname2 } from "path";
2751
+ import { readdir, readFile as readFile3 } from "fs/promises";
2752
+ import { existsSync as existsSync3 } from "fs";
2753
+ import { join as join3, dirname as dirname2 } from "path";
4155
2754
  import { fileURLToPath } from "url";
4156
-
4157
- // src/skills/installer.ts
4158
- async function listInstalledSkills() {
4159
- return [];
4160
- }
4161
-
4162
- // src/server/resource-manager.ts
4163
2755
  var UI_APPS = {
4164
2756
  "ledger": {
4165
2757
  name: "Decision Ledger",
@@ -4183,7 +2775,6 @@ var UI_APPS = {
4183
2775
  }
4184
2776
  };
4185
2777
  var ResourceManager = class {
4186
- skillRegistry = getSkillRegistry();
4187
2778
  /**
4188
2779
  * Get all available resources dynamically
4189
2780
  */
@@ -4208,12 +2799,6 @@ var ResourceManager = class {
4208
2799
  description: "Detailed context state with scan history and priorities",
4209
2800
  mimeType: "application/json"
4210
2801
  },
4211
- {
4212
- uri: "trie://skills",
4213
- name: "Available Skills",
4214
- description: "List of all available Trie skills (built-in and custom)",
4215
- mimeType: "application/json"
4216
- },
4217
2802
  {
4218
2803
  uri: "trie://config",
4219
2804
  name: "Trie Configuration",
@@ -4232,12 +2817,6 @@ var ResourceManager = class {
4232
2817
  description: "Summary of loaded vulnerability detection signatures",
4233
2818
  mimeType: "application/json"
4234
2819
  },
4235
- {
4236
- uri: "trie://skills/installed",
4237
- name: "Installed Skills",
4238
- description: "External skills installed from skills.sh that Trie can apply",
4239
- mimeType: "application/json"
4240
- },
4241
2820
  {
4242
2821
  uri: "trie://bootstrap",
4243
2822
  name: "Bootstrap Status",
@@ -4270,13 +2849,12 @@ var ResourceManager = class {
4270
2849
  }
4271
2850
  );
4272
2851
  resources.push(...await this.getScanReportResources());
4273
- resources.push(...await this.getCustomSkillResources());
4274
2852
  resources.push(...this.getUIAppResources());
4275
2853
  return resources;
4276
2854
  }
4277
2855
  async getScanReportResources() {
4278
2856
  try {
4279
- const reportsDir = join4(getWorkingDirectory(void 0, true), "trie-reports");
2857
+ const reportsDir = join3(getWorkingDirectory(void 0, true), "trie-reports");
4280
2858
  const files = await readdir(reportsDir);
4281
2859
  const reportFiles = files.filter((f) => f.endsWith(".txt") || f.endsWith(".json"));
4282
2860
  return reportFiles.slice(0, 10).map((file) => ({
@@ -4289,20 +2867,6 @@ var ResourceManager = class {
4289
2867
  return [];
4290
2868
  }
4291
2869
  }
4292
- async getCustomSkillResources() {
4293
- try {
4294
- await this.skillRegistry.loadCustomSkills();
4295
- const customSkills = this.skillRegistry.getCustomSkills();
4296
- return customSkills.map((skill) => ({
4297
- uri: `trie://skills/custom/${skill.name}`,
4298
- name: `Custom Skill: ${skill.name}`,
4299
- description: skill.description,
4300
- mimeType: "application/json"
4301
- }));
4302
- } catch {
4303
- return [];
4304
- }
4305
- }
4306
2870
  /**
4307
2871
  * Read content for a specific resource
4308
2872
  */
@@ -4321,12 +2885,6 @@ var ResourceManager = class {
4321
2885
  if (parsedUri === "context/state") {
4322
2886
  return await this.getContextStateResource(uri);
4323
2887
  }
4324
- if (parsedUri === "skills") {
4325
- return await this.getBuiltInSkillsResource(uri);
4326
- }
4327
- if (parsedUri.startsWith("skills/custom/")) {
4328
- return await this.getCustomSkillResource(uri, parsedUri);
4329
- }
4330
2888
  if (parsedUri === "config") {
4331
2889
  return await this.getConfigResource(uri);
4332
2890
  }
@@ -4336,9 +2894,6 @@ var ResourceManager = class {
4336
2894
  if (parsedUri === "signatures") {
4337
2895
  return await this.getSignaturesResource(uri);
4338
2896
  }
4339
- if (parsedUri === "skills/installed") {
4340
- return await this.getInstalledSkillsResource(uri);
4341
- }
4342
2897
  if (parsedUri === "bootstrap") {
4343
2898
  return await this.getBootstrapResource(uri);
4344
2899
  }
@@ -4376,10 +2931,10 @@ var ResourceManager = class {
4376
2931
  async getUIAppResource(uri, appId) {
4377
2932
  const currentFile = fileURLToPath(import.meta.url);
4378
2933
  const distDir = dirname2(dirname2(currentFile));
4379
- const uiDir = join4(distDir, "ui");
4380
- const htmlPath = join4(uiDir, `${appId}.html`);
2934
+ const uiDir = join3(distDir, "ui");
2935
+ const htmlPath = join3(uiDir, `${appId}.html`);
4381
2936
  try {
4382
- if (!existsSync4(htmlPath)) {
2937
+ if (!existsSync3(htmlPath)) {
4383
2938
  return {
4384
2939
  contents: [{
4385
2940
  uri,
@@ -4388,7 +2943,7 @@ var ResourceManager = class {
4388
2943
  }]
4389
2944
  };
4390
2945
  }
4391
- const content = await readFile4(htmlPath, "utf-8");
2946
+ const content = await readFile3(htmlPath, "utf-8");
4392
2947
  return {
4393
2948
  contents: [{
4394
2949
  uri,
@@ -4554,24 +3109,16 @@ var ResourceManager = class {
4554
3109
  summary.push("## Available Tools", "");
4555
3110
  summary.push("| Tool | Purpose |");
4556
3111
  summary.push("|------|---------|");
4557
- summary.push("| `trie_scan` | Scan code with intelligent agent selection |");
3112
+ summary.push("| `trie_fix` | Apply high-confidence fixes |");
4558
3113
  summary.push("| `trie_fix` | Generate fix recommendations |");
4559
3114
  summary.push("| `trie_memory` | Search issue history |");
4560
3115
  summary.push("| `trie_init` | Initialize bootstrap files |");
4561
3116
  summary.push("");
4562
- try {
4563
- const skills = await listInstalledSkills();
4564
- if (skills.length > 0) {
4565
- summary.push(`**Skills:** ${skills.length} installed (${skills.slice(0, 3).map((s) => s.name).join(", ")}${skills.length > 3 ? "..." : ""})`);
4566
- summary.push("");
4567
- }
4568
- } catch {
4569
- }
4570
3117
  summary.push("---", "", "# Detailed Context", "");
4571
- const agentsMdPath = join4(getTrieDirectory(workDir), "AGENTS.md");
3118
+ const agentsMdPath = join3(getTrieDirectory(workDir), "AGENTS.md");
4572
3119
  try {
4573
- if (existsSync4(agentsMdPath)) {
4574
- const agentsContent = await readFile4(agentsMdPath, "utf-8");
3120
+ if (existsSync3(agentsMdPath)) {
3121
+ const agentsContent = await readFile3(agentsMdPath, "utf-8");
4575
3122
  summary.push(agentsContent);
4576
3123
  } else {
4577
3124
  const contextSummary = await getContextForAI();
@@ -4649,41 +3196,6 @@ This information is automatically available to Claude Code, Cursor, and other AI
4649
3196
  }]
4650
3197
  };
4651
3198
  }
4652
- async getBuiltInSkillsResource(uri) {
4653
- await this.skillRegistry.loadCustomSkills();
4654
- const skills = this.skillRegistry.getSkillDescriptions();
4655
- return {
4656
- contents: [{
4657
- uri,
4658
- mimeType: "application/json",
4659
- text: JSON.stringify({
4660
- totalSkills: skills.length,
4661
- builtinCount: skills.filter((a) => !a.isCustom).length,
4662
- customCount: skills.filter((a) => a.isCustom).length,
4663
- skills: skills.map((a) => ({
4664
- name: a.name,
4665
- description: a.description,
4666
- type: a.isCustom ? "custom" : "builtin"
4667
- }))
4668
- }, null, 2)
4669
- }]
4670
- };
4671
- }
4672
- async getCustomSkillResource(uri, parsedUri) {
4673
- const skillName = parsedUri.replace("skills/custom/", "");
4674
- await this.skillRegistry.loadCustomSkills();
4675
- const metadata = this.skillRegistry.getCustomSkillMetadata(skillName);
4676
- if (!metadata) {
4677
- throw new Error(`Custom skill not found: ${skillName}`);
4678
- }
4679
- return {
4680
- contents: [{
4681
- uri,
4682
- mimeType: "application/json",
4683
- text: JSON.stringify(metadata, null, 2)
4684
- }]
4685
- };
4686
- }
4687
3199
  async getConfigResource(uri) {
4688
3200
  const config = await loadConfig();
4689
3201
  return {
@@ -4696,8 +3208,8 @@ This information is automatically available to Claude Code, Cursor, and other AI
4696
3208
  }
4697
3209
  async getCacheStatsResource(uri) {
4698
3210
  try {
4699
- const cachePath = join4(getTrieDirectory(getWorkingDirectory(void 0, true)), ".trie-cache.json");
4700
- const cacheContent = await readFile4(cachePath, "utf-8");
3211
+ const cachePath = join3(getTrieDirectory(getWorkingDirectory(void 0, true)), ".trie-cache.json");
3212
+ const cacheContent = await readFile3(cachePath, "utf-8");
4701
3213
  const cache = JSON.parse(cacheContent);
4702
3214
  const fileCount = Object.keys(cache.files || {}).length;
4703
3215
  const totalVulns = Object.values(cache.files || {}).reduce((acc, file) => {
@@ -4724,15 +3236,15 @@ This information is automatically available to Claude Code, Cursor, and other AI
4724
3236
  mimeType: "application/json",
4725
3237
  text: JSON.stringify({
4726
3238
  error: "No cache found. Run a scan first to build the cache.",
4727
- hint: "Use trie_scan to scan your codebase"
3239
+ hint: "Run trie watch to analyze your codebase"
4728
3240
  }, null, 2)
4729
3241
  }]
4730
3242
  };
4731
3243
  }
4732
3244
  }
4733
3245
  async getSignaturesResource(uri) {
4734
- const { getVulnerabilityStats } = await import("./vulnerability-signatures-EIJQX2TS.js");
4735
- const { getVibeCodeStats } = await import("./vibe-code-signatures-ELEWJFGZ.js");
3246
+ const { getVulnerabilityStats } = await import("./vulnerability-signatures-EIKOHFPK.js");
3247
+ const { getVibeCodeStats } = await import("./vibe-code-signatures-J4GD4JOV.js");
4736
3248
  const vulnStats = getVulnerabilityStats();
4737
3249
  const vibeStats = getVibeCodeStats();
4738
3250
  return {
@@ -4747,38 +3259,11 @@ This information is automatically available to Claude Code, Cursor, and other AI
4747
3259
  }]
4748
3260
  };
4749
3261
  }
4750
- async getInstalledSkillsResource(uri) {
4751
- const skills = await listInstalledSkills();
4752
- const state = await loadContextState();
4753
- const skillsWithUsage = skills.map((skill) => {
4754
- const record = state.skills?.[skill.name];
4755
- return {
4756
- name: skill.name,
4757
- description: skill.description,
4758
- source: skill.installedFrom,
4759
- installedAt: skill.installedAt,
4760
- timesApplied: record?.timesApplied || 0,
4761
- appliedBy: record?.appliedBy || [],
4762
- lastApplied: record?.lastApplied
4763
- };
4764
- });
4765
- return {
4766
- contents: [{
4767
- uri,
4768
- mimeType: "application/json",
4769
- text: JSON.stringify({
4770
- totalSkills: skills.length,
4771
- skills: skillsWithUsage,
4772
- note: "Skills are capabilities applied by agents, not autonomous agents themselves."
4773
- }, null, 2)
4774
- }]
4775
- };
4776
- }
4777
3262
  async getScanReportResource(uri, parsedUri) {
4778
3263
  const fileName = parsedUri.replace("reports/", "");
4779
- const reportPath = join4(getWorkingDirectory(void 0, true), "trie-reports", fileName);
3264
+ const reportPath = join3(getWorkingDirectory(void 0, true), "trie-reports", fileName);
4780
3265
  try {
4781
- const content = await readFile4(reportPath, "utf-8");
3266
+ const content = await readFile3(reportPath, "utf-8");
4782
3267
  return {
4783
3268
  contents: [{
4784
3269
  uri,
@@ -5254,38 +3739,6 @@ var RequestHandlers = class {
5254
3739
  return await this.toolRegistry.getTool("register_agent").execute(args);
5255
3740
  case "watch":
5256
3741
  return await this.toolRegistry.getTool("watch").execute(args);
5257
- // Individual agent commands
5258
- case "security":
5259
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "security" });
5260
- case "legal":
5261
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "legal" });
5262
- case "accessibility":
5263
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "accessibility" });
5264
- case "design":
5265
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "design-engineer" });
5266
- case "architecture":
5267
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "software-architect" });
5268
- case "bugs":
5269
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "bug-finding" });
5270
- case "ux":
5271
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "user-testing" });
5272
- case "types":
5273
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "typecheck" });
5274
- case "devops":
5275
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "devops" });
5276
- case "clean":
5277
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "trie_clean" });
5278
- case "soc2":
5279
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "soc2" });
5280
- // New agents
5281
- case "performance":
5282
- case "perf":
5283
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "performance" });
5284
- case "e2e":
5285
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "e2e" });
5286
- case "visual_qa":
5287
- case "visual":
5288
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "visual-qa" });
5289
3742
  case "visual_qa_browser": {
5290
3743
  try {
5291
3744
  const result = await runVisualQA(args);
@@ -5328,31 +3781,6 @@ npx playwright install chromium
5328
3781
  };
5329
3782
  }
5330
3783
  }
5331
- case "data_flow":
5332
- case "dataflow":
5333
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "data-flow" });
5334
- // Special agents
5335
- case "agent_smith":
5336
- case "agentsmith":
5337
- case "smith":
5338
- if (args?.clear_memory || args?.show_stats) {
5339
- return await this.handleAgentSmith(args);
5340
- }
5341
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "agent-smith" });
5342
- case "super_reviewer":
5343
- case "superreviewer":
5344
- case "reviewer":
5345
- return await this.toolRegistry.getTool("agent").execute({ ...args, agent: "super-reviewer" });
5346
- // Custom skill tools (with backward-compatible agent aliases)
5347
- case "create_skill":
5348
- case "create_agent":
5349
- return await this.toolRegistry.getTool("create_skill").execute(args);
5350
- case "save_skill":
5351
- case "save_agent":
5352
- return await this.toolRegistry.getTool("save_skill").execute(args);
5353
- case "list_skills":
5354
- case "list_agents":
5355
- return await this.toolRegistry.getTool("list_skills").execute(args);
5356
3784
  case "pr_review":
5357
3785
  return await this.toolRegistry.getTool("pr_review").execute(args);
5358
3786
  case "project":
@@ -5454,45 +3882,16 @@ npx playwright install chromium
5454
3882
  "",
5455
3883
  "**Most common:**",
5456
3884
  "- `trie` (no args) \u2014 show this menu",
5457
- '- `trie` with `{ action: "scan", files?: [], directory?: "" }` \u2014 auto triage & scan',
5458
- '- `trie` with `{ action: "security", files?: [] }` \u2014 single-skill run (any skill name works)',
5459
- '- `trie` with `{ action: "agent_smith" }` \u2014 aggressive AI-pattern hunter',
5460
- "",
5461
- "**Other actions:**",
5462
- '- `action: "pr_review"` \u2014 interactive PR review',
5463
3885
  '- `action: "fix"` \u2014 high-confidence fixes',
5464
3886
  '- `action: "watch"` \u2014 start/stop/status autonomous watch',
3887
+ '- `action: "pr_review"` \u2014 interactive PR review',
3888
+ "",
3889
+ "**Other actions:**",
5465
3890
  '- `action: "test"` \u2014 generate/coverage/suggest/run tests (requires `files` + `action`)',
5466
3891
  '- `action: "explain"` \u2014 explain code/issues/risks',
5467
- '- `action: "list_skills"` \u2014 list all skills (external + custom)',
5468
3892
  '- `action: "visual_qa_browser"` \u2014 screenshots for visual QA',
5469
3893
  "",
5470
- "**Built-in skills:**",
5471
- "`security`, `legal`, `accessibility`, `design`, `architecture`, `bugs`, `ux`, `types`, `devops`, `clean`, `soc2`, `performance`, `e2e`, `visual_qa`, `data_flow`",
5472
- "",
5473
- "**Special skills:**",
5474
- "`agent_smith` \u2014 35 vibe code hunters with cross-file detection",
5475
- "`super_reviewer` \u2014 Interactive PR review with cross-examination",
5476
- "",
5477
- "All commands accept `trie_` prefix (e.g., `trie_scan`, `trie_security`). Short names still work for compatibility."
5478
- ].join("\n")
5479
- }]
5480
- };
5481
- }
5482
- async handleAgentSmith(_smithArgs) {
5483
- return {
5484
- content: [{
5485
- type: "text",
5486
- text: [
5487
- "\u{1F916} Agent Smith functionality has been integrated into the decision ledger.",
5488
- "",
5489
- "The autonomous agent now:",
5490
- "- Extracts patterns automatically via `trie watch`",
5491
- "- Builds decision ledger from every change",
5492
- "- Predicts problems via `trie gotcha`",
5493
- "",
5494
- "Start the agent: `trie_watch start`",
5495
- "Query the ledger: `trie_gotcha`"
3894
+ "All commands accept `trie_` prefix (e.g., `trie_fix`, `trie_watch`)."
5496
3895
  ].join("\n")
5497
3896
  }]
5498
3897
  };
@@ -5550,7 +3949,7 @@ var MCPServer = class {
5550
3949
  /**
5551
3950
  * Show startup banner
5552
3951
  */
5553
- showStartupBanner(skillCount, aiTool) {
3952
+ showStartupBanner(toolCount, aiTool) {
5554
3953
  console.error(`
5555
3954
  \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
5556
3955
  \u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D
@@ -5558,21 +3957,19 @@ var MCPServer = class {
5558
3957
  \u2588\u2588\u2551 \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u255D
5559
3958
  \u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
5560
3959
  \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D
5561
- Your central registry for Trie and its skills
3960
+ Your central registry for Trie tools
5562
3961
 
5563
3962
  by Louis Kishfy
5564
3963
 
5565
3964
  Download the Trie workspace: https://www.trie.dev
5566
3965
  Follow me on X: https://x.com/louiskishfy
5567
3966
 
5568
- ${skillCount} skills ready | ${aiTool}
3967
+ ${toolCount} tools ready | ${aiTool}
5569
3968
 
5570
3969
  Quick Start:
5571
- \u2022 "Scan this code" - Run all relevant skills
5572
- \u2022 "Run trie_security" - Security scan only
5573
- \u2022 "Run trie_soc2" - SOC 2 compliance check
5574
- \u2022 "Use trie_list_skills" - See all skills
5575
- \u2022 "Use trie_create_skill" - Make custom skill
3970
+ \u2022 "Scan this code" - Run Trie analysis
3971
+ \u2022 "Use trie" - Open the Trie menu
3972
+ \u2022 "Use trie_fix" - Apply high-confidence fixes
5576
3973
 
5577
3974
  Ready.
5578
3975
  `);
@@ -5584,9 +3981,8 @@ var MCPServer = class {
5584
3981
  try {
5585
3982
  const aiTool = detectAITool();
5586
3983
  await loadConfig();
5587
- const registry = getSkillRegistry();
5588
- const skillCount = registry.getAllSkills().length;
5589
- this.showStartupBanner(skillCount, aiTool.name);
3984
+ const toolCount = this.toolRegistry.getAllTools().length;
3985
+ this.showStartupBanner(toolCount, aiTool.name);
5590
3986
  const transport = new StdioServerTransport();
5591
3987
  await this.server.connect(transport);
5592
3988
  } catch (error) {