@triedotdev/mcp 1.0.162 → 1.0.164

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.
@@ -4,12 +4,18 @@ import {
4
4
  import {
5
5
  getTrieAgent
6
6
  } from "./chunk-ERMLZJTK.js";
7
+ import {
8
+ parseGoalViolation
9
+ } from "./chunk-WCN7S3EI.js";
7
10
  import {
8
11
  CodebaseIndex
9
12
  } from "./chunk-Q5EKA5YA.js";
10
13
  import {
11
14
  getOutputManager
12
15
  } from "./chunk-VR4VWXXU.js";
16
+ import {
17
+ getInsightStore
18
+ } from "./chunk-T63OHG4Q.js";
13
19
  import {
14
20
  LearningEngine,
15
21
  exportToJson,
@@ -21,6 +27,9 @@ import {
21
27
  reasonAboutChangesHumanReadable,
22
28
  saveCheckpoint
23
29
  } from "./chunk-62JD7MIS.js";
30
+ import {
31
+ measureInitialGoalValue
32
+ } from "./chunk-ACU3IXZG.js";
24
33
  import {
25
34
  loadConfig,
26
35
  saveConfig
@@ -38,9 +47,6 @@ import {
38
47
  import {
39
48
  ContextGraph
40
49
  } from "./chunk-VUL52BQL.js";
41
- import {
42
- measureInitialGoalValue
43
- } from "./chunk-ACU3IXZG.js";
44
50
  import {
45
51
  getKeyFromKeychain,
46
52
  isAIAvailable,
@@ -693,9 +699,12 @@ function dashboardReducer(state, action) {
693
699
  const blocks = action.ledgerBlocks ?? state.memoryTree.ledgerBlocks;
694
700
  const gotchas = action.storageGotchas ?? state.memoryTree.storageGotchas;
695
701
  const facts = action.storageFacts ?? state.memoryTree.storageFacts;
702
+ const nudges = action.storageNudges ?? state.memoryTree.storageNudges;
703
+ const insights = action.storageInsights ?? state.memoryTree.storageInsights;
696
704
  const expanded = new Set(state.memoryTree.expandedNodes);
697
705
  if (blocks.length > 0) expanded.add("ledger-chain");
698
706
  if (gotchas.length > 0) expanded.add("gotchas");
707
+ if (nudges.length > 0 || insights.length > 0) expanded.add("patterns");
699
708
  return {
700
709
  ...state,
701
710
  memoryTree: {
@@ -706,6 +715,8 @@ function dashboardReducer(state, action) {
706
715
  storageGovernance: action.storageGovernance ?? state.memoryTree.storageGovernance,
707
716
  storageFacts: facts,
708
717
  storageGotchas: gotchas,
718
+ storageNudges: nudges,
719
+ storageInsights: insights,
709
720
  ledgerBlocks: blocks,
710
721
  expandedNodes: expanded
711
722
  }
@@ -970,7 +981,7 @@ function createInitialState() {
970
981
  },
971
982
  goalsPanel: { goals: [], selectedIndex: 0, selectedAchievedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0, scanningGoalId: null, scanningProgress: "" },
972
983
  hypothesesPanel: { hypotheses: [], selectedIndex: 0, selectedCompletedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0, scanningHypothesisId: null, scanningProgress: "" },
973
- memoryTree: { loaded: false, snapshot: null, globalPatterns: [], storageGovernance: [], storageFacts: [], storageGotchas: [], ledgerBlocks: [], expandedNodes: /* @__PURE__ */ new Set(["decisions"]), expandedItemId: null, selectedNode: "decisions", scrollPosition: 0, lastRefresh: 0 },
984
+ memoryTree: { loaded: false, snapshot: null, globalPatterns: [], storageGovernance: [], storageFacts: [], storageGotchas: [], storageNudges: [], storageInsights: [], ledgerBlocks: [], expandedNodes: /* @__PURE__ */ new Set(["decisions"]), expandedItemId: null, selectedNode: "decisions", scrollPosition: 0, lastRefresh: 0 },
974
985
  agentBrain: { loaded: false, governance: [], patterns: [], ledgerHash: null, selectedIndex: 0, expandedIndex: null },
975
986
  chatState: { messages: [], inputBuffer: "", loading: false, progress: null, messageQueue: [], currentSessionId: null, currentSessionTitle: null },
976
987
  chatArchivePanel: { sessions: [], selectedIndex: 0, showArchived: false, loading: false, inputMode: "browse", inputBuffer: "" },
@@ -1041,18 +1052,6 @@ function Header() {
1041
1052
  // src/cli/dashboard/components/Footer.tsx
1042
1053
  import React2 from "react";
1043
1054
  import { Box as Box2, Text as Text2, useStdout as useStdout2 } from "ink";
1044
-
1045
- // src/cli/dashboard/parse-goal-violation.ts
1046
- function parseGoalViolation(message) {
1047
- const match = message.match(/Goal "([^"]+)" violated in ([^:]+): (.+)/);
1048
- if (!match) return null;
1049
- const [, goal, file, violation] = match;
1050
- if (!goal || !file || !violation) return null;
1051
- const cleanViolation = violation.replace(/\s*\[\d+%\s*confidence\]\s*$/i, "").trim();
1052
- return { file: file.trim(), goal: goal.trim(), violation: cleanViolation };
1053
- }
1054
-
1055
- // src/cli/dashboard/components/Footer.tsx
1056
1055
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
1057
1056
  var VIEW_LABELS = {
1058
1057
  overview: "Overview",
@@ -1188,7 +1187,7 @@ function Notification() {
1188
1187
  /* @__PURE__ */ jsx4(Text3, { color, bold: true, children: "\u25CF " }),
1189
1188
  notification.message
1190
1189
  ] }),
1191
- notification.file && /* @__PURE__ */ jsxs3(Text3, { dimColor: true, children: [
1190
+ notification.file && /* @__PURE__ */ jsxs3(Text3, { wrap: "wrap", dimColor: true, children: [
1192
1191
  " \u2192 ",
1193
1192
  notification.file
1194
1193
  ] })
@@ -1983,8 +1982,8 @@ function AgentView() {
1983
1982
  if (!insight) return;
1984
1983
  try {
1985
1984
  const workDir = getWorkingDirectory(void 0, true);
1986
- const { getInsightStore } = await import("./insight-store-EC4PLSAW.js");
1987
- const store = getInsightStore(workDir);
1985
+ const { getInsightStore: getInsightStore2 } = await import("./insight-store-EC4PLSAW.js");
1986
+ const store = getInsightStore2(workDir);
1988
1987
  await store.dismissInsight(insight.id);
1989
1988
  const { getStorage: getStorage2 } = await import("./tiered-storage-FHHAJR4P.js");
1990
1989
  const storage = getStorage2(workDir);
@@ -2819,7 +2818,7 @@ function timeAgo2(iso) {
2819
2818
  function MemoryTreeView() {
2820
2819
  const { state, dispatch } = useDashboard();
2821
2820
  const { memoryTree } = state;
2822
- const { snapshot, globalPatterns, storageGovernance, storageFacts, storageGotchas, ledgerBlocks, expandedNodes, expandedItemId, selectedNode, loaded } = memoryTree;
2821
+ const { snapshot, globalPatterns, storageGovernance, storageFacts, storageGotchas, storageNudges, storageInsights, ledgerBlocks, expandedNodes, expandedItemId, selectedNode, loaded } = memoryTree;
2823
2822
  const { stdout } = useStdout8();
2824
2823
  const cols = stdout?.columns || 80;
2825
2824
  const narrow = cols < 60;
@@ -2829,15 +2828,19 @@ function MemoryTreeView() {
2829
2828
  const workDir = getWorkingDirectory(void 0, true);
2830
2829
  const graph = new ContextGraph(workDir);
2831
2830
  const storage = new TieredStorage(workDir);
2832
- const [snap, patterns, governance2, facts, gotchas, blocks] = await Promise.all([
2831
+ const insightStore = getInsightStore(workDir);
2832
+ const [snap, patterns, governance2, facts, gotchas, nudges, blocks] = await Promise.all([
2833
2833
  graph.getSnapshot(),
2834
2834
  findCrossProjectPatterns(2),
2835
2835
  storage.queryGovernance({ limit: 20 }).catch(() => []),
2836
2836
  storage.queryFacts({ limit: 20 }).catch(() => []),
2837
2837
  storage.queryGotchas({ limit: 20, resolved: false }).catch(() => []),
2838
+ storage.queryNudges({ limit: 20, resolved: false }).catch(() => []),
2838
2839
  getLedgerBlocks(workDir).catch(() => [])
2839
2840
  ]);
2840
- dispatch({ type: "SET_MEMORY_TREE", snapshot: snap, patterns, storageGovernance: governance2, storageFacts: facts, storageGotchas: gotchas, ledgerBlocks: blocks });
2841
+ await insightStore.load();
2842
+ const insights = insightStore.getActiveInsights(10);
2843
+ dispatch({ type: "SET_MEMORY_TREE", snapshot: snap, patterns, storageGovernance: governance2, storageFacts: facts, storageGotchas: gotchas, storageNudges: nudges, storageInsights: insights, ledgerBlocks: blocks });
2841
2844
  } catch (err) {
2842
2845
  dispatch({ type: "ADD_ACTIVITY", message: "Context graph load error" });
2843
2846
  }
@@ -2914,7 +2917,7 @@ function MemoryTreeView() {
2914
2917
  const order = { critical: 0, high: 1 };
2915
2918
  return (order[a.data.riskLevel] ?? 2) - (order[b.data.riskLevel] ?? 2);
2916
2919
  });
2917
- const totalEntries = productGovernance.length + learnedSignals.length + (storageFacts?.length ?? 0) + incidentNodes.length + patternNodes.length + globalPatterns.length + hotspots.length + ledgerBlocks.length;
2920
+ const totalEntries = productGovernance.length + learnedSignals.length + (storageFacts?.length ?? 0) + (storageNudges?.length ?? 0) + (storageInsights?.length ?? 0) + incidentNodes.length + patternNodes.length + globalPatterns.length + hotspots.length + ledgerBlocks.length;
2918
2921
  const expandedGovernance = expandedItemId?.startsWith("decision-") ? governance.find((g) => `decision-${g.id}` === expandedItemId) : null;
2919
2922
  const expandedIncident = expandedItemId?.startsWith("incident-") ? incidentNodes.find((n) => `incident-${n.id}` === expandedItemId) : null;
2920
2923
  const expandedGotcha = expandedItemId?.startsWith("gotcha-") ? storageGotchas.find((g) => `gotcha-${g.id}` === expandedItemId) ?? null : null;
@@ -3180,9 +3183,55 @@ function MemoryTreeView() {
3180
3183
  ] })
3181
3184
  ] }, g.id);
3182
3185
  }),
3183
- renderHeader("patterns", "Learned Signals", learnedSignals.length + (storageFacts?.length ?? 0) + patternNodes.length, learnedSignals.length === 0 && (storageFacts?.length ?? 0) === 0 && patternNodes.length === 0 ? "-- Trie learns as you work" : void 0),
3186
+ renderHeader("patterns", "Learned Signals", (storageInsights?.length ?? 0) + learnedSignals.length + (storageFacts?.length ?? 0) + (storageNudges?.length ?? 0) + patternNodes.length, (storageInsights?.length ?? 0) === 0 && learnedSignals.length === 0 && (storageFacts?.length ?? 0) === 0 && (storageNudges?.length ?? 0) === 0 && patternNodes.length === 0 ? "-- Trie learns as you work" : void 0),
3184
3187
  expandedNodes.has("patterns") && /* @__PURE__ */ jsxs10(Fragment6, { children: [
3185
- learnedSignals.length > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
3188
+ (storageInsights?.length ?? 0) > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", children: [
3189
+ /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
3190
+ " ",
3191
+ " ",
3192
+ "Learnings"
3193
+ ] }),
3194
+ storageInsights.slice(0, 5).map((insight) => {
3195
+ const descWidth = Math.max(30, contentWidth - 15);
3196
+ const desc = insight.message.length > descWidth ? insight.message.slice(0, descWidth - 3) + "..." : insight.message;
3197
+ const categoryLabel = insight.category === "security" ? "[sec]" : insight.category === "performance" ? "[perf]" : insight.category === "quality" ? "[qual]" : "[learn]";
3198
+ const confidenceColor = insight.priority >= 7 ? "green" : insight.priority >= 4 ? "yellow" : "white";
3199
+ return /* @__PURE__ */ jsxs10(Text10, { wrap: "truncate", children: [
3200
+ " ",
3201
+ /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: categoryLabel }),
3202
+ " ",
3203
+ /* @__PURE__ */ jsx11(Text10, { children: desc }),
3204
+ narrow ? null : /* @__PURE__ */ jsxs10(Text10, { color: confidenceColor, dimColor: true, children: [
3205
+ " ",
3206
+ insight.priority,
3207
+ "/10"
3208
+ ] })
3209
+ ] }, insight.id);
3210
+ })
3211
+ ] }),
3212
+ (storageNudges?.length ?? 0) > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: (storageInsights?.length ?? 0) > 0 ? 1 : 0, children: [
3213
+ /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
3214
+ " ",
3215
+ " ",
3216
+ (storageInsights?.length ?? 0) > 0 ? "Raw Detections" : "AI Detections"
3217
+ ] }),
3218
+ storageNudges.slice(0, (storageInsights?.length ?? 0) > 0 ? 3 : 5).map((n) => {
3219
+ const descWidth = Math.max(30, contentWidth - 15);
3220
+ const desc = n.message.length > descWidth ? n.message.slice(0, descWidth - 3) + "..." : n.message;
3221
+ const severityColor = n.severity === "critical" ? "red" : n.severity === "high" ? "yellow" : "cyan";
3222
+ return /* @__PURE__ */ jsxs10(Text10, { wrap: "truncate", children: [
3223
+ " ",
3224
+ /* @__PURE__ */ jsx11(Text10, { color: severityColor, children: "\u25CF" }),
3225
+ " ",
3226
+ /* @__PURE__ */ jsx11(Text10, { children: desc }),
3227
+ narrow ? null : /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
3228
+ " ",
3229
+ timeAgo2(n.timestamp)
3230
+ ] })
3231
+ ] }, n.id);
3232
+ })
3233
+ ] }),
3234
+ learnedSignals.length > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: (storageInsights?.length ?? 0) > 0 || (storageNudges?.length ?? 0) > 0 ? 1 : 0, children: [
3186
3235
  /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
3187
3236
  " ",
3188
3237
  " ",
@@ -3203,7 +3252,7 @@ function MemoryTreeView() {
3203
3252
  ] }, g.id);
3204
3253
  })
3205
3254
  ] }),
3206
- (storageFacts?.length ?? 0) > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: learnedSignals.length > 0 ? 1 : 0, children: [
3255
+ (storageFacts?.length ?? 0) > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: (storageInsights?.length ?? 0) > 0 || (storageNudges?.length ?? 0) > 0 || learnedSignals.length > 0 ? 1 : 0, children: [
3207
3256
  /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
3208
3257
  " ",
3209
3258
  " ",
@@ -3224,8 +3273,8 @@ function MemoryTreeView() {
3224
3273
  ] }, f.id);
3225
3274
  })
3226
3275
  ] }),
3227
- patternNodes.length > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: learnedSignals.length > 0 || (storageFacts?.length ?? 0) > 0 ? 1 : 0, children: [
3228
- (learnedSignals.length > 0 || (storageFacts?.length ?? 0) > 0) && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
3276
+ patternNodes.length > 0 && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: (storageInsights?.length ?? 0) > 0 || (storageNudges?.length ?? 0) > 0 || learnedSignals.length > 0 || (storageFacts?.length ?? 0) > 0 ? 1 : 0, children: [
3277
+ ((storageInsights?.length ?? 0) > 0 || (storageNudges?.length ?? 0) > 0 || learnedSignals.length > 0 || (storageFacts?.length ?? 0) > 0) && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
3229
3278
  " ",
3230
3279
  " ",
3231
3280
  "Patterns"
@@ -3236,7 +3285,7 @@ function MemoryTreeView() {
3236
3285
  const confColor = conf > 70 ? "green" : conf > 40 ? "yellow" : void 0;
3237
3286
  const descWidth = Math.max(30, contentWidth - 15);
3238
3287
  const desc = n.data.description.length > descWidth ? n.data.description.slice(0, descWidth - 3) + "..." : n.data.description;
3239
- const hasPreceding = learnedSignals.length > 0 || (storageFacts?.length ?? 0) > 0;
3288
+ const hasPreceding = (storageInsights?.length ?? 0) > 0 || (storageNudges?.length ?? 0) > 0 || learnedSignals.length > 0 || (storageFacts?.length ?? 0) > 0;
3240
3289
  return /* @__PURE__ */ jsxs10(Text10, { wrap: "truncate", children: [
3241
3290
  sel(nodeId) ? /* @__PURE__ */ jsx11(Text10, { bold: true, color: "green", children: "> " }) : hasPreceding ? " " : " ",
3242
3291
  !hasPreceding && " ",
@@ -3256,7 +3305,7 @@ function MemoryTreeView() {
3256
3305
  ] }, n.id);
3257
3306
  })
3258
3307
  ] }),
3259
- patternNodes.length === 0 && learnedSignals.length === 0 && (storageFacts?.length ?? 0) === 0 && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
3308
+ patternNodes.length === 0 && learnedSignals.length === 0 && (storageFacts?.length ?? 0) === 0 && (storageNudges?.length ?? 0) === 0 && (storageInsights?.length ?? 0) === 0 && /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
3260
3309
  " ",
3261
3310
  " ",
3262
3311
  "No signals learned yet. Trie will extract insights as you work."
@@ -6889,7 +6938,7 @@ var TrieGetBlockersTool = class {
6889
6938
  const emoji = blocker.impact === "critical" ? "\u{1F534}" : blocker.impact === "high" ? "\u{1F7E0}" : blocker.impact === "medium" ? "\u{1F7E1}" : "\u{1F7E2}";
6890
6939
  output += `${emoji} [${impact}] ${blocker.blocker}
6891
6940
  `;
6892
- if (blocker.affectedAreas.length > 0) {
6941
+ if ((blocker.affectedAreas?.length ?? 0) > 0) {
6893
6942
  output += ` Affects: ${blocker.affectedAreas.join(", ")}
6894
6943
  `;
6895
6944
  }
@@ -6976,6 +7025,48 @@ function formatNudges(nudges) {
6976
7025
  }
6977
7026
  return out;
6978
7027
  }
7028
+ var TrieGetNudgesTool = class {
7029
+ async execute(input) {
7030
+ const workDir = input.directory || getWorkingDirectory(void 0, true);
7031
+ const storage = getStorage(workDir);
7032
+ await storage.initialize();
7033
+ const limit = input.limit ?? 20;
7034
+ const nudges = await storage.queryNudges({
7035
+ resolved: false,
7036
+ severity: input.severity,
7037
+ file: input.file,
7038
+ limit
7039
+ });
7040
+ if (nudges.length === 0) {
7041
+ return {
7042
+ content: [{
7043
+ type: "text",
7044
+ text: "No unresolved nudges (goal violations) found. Run trie scan to detect new issues."
7045
+ }]
7046
+ };
7047
+ }
7048
+ const { parseGoalViolation: parseGoalViolation2 } = await import("./parse-goal-violation-SACGFG3C.js");
7049
+ let out = `Found ${nudges.length} nudge(s) / goal violation(s):
7050
+
7051
+ `;
7052
+ for (const n of nudges) {
7053
+ const parsed = parseGoalViolation2(n.message);
7054
+ out += `\u26A0\uFE0F [${n.severity}] ${n.message}
7055
+ `;
7056
+ out += ` File: ${n.file || parsed?.file || "unknown"}
7057
+ `;
7058
+ if (parsed) {
7059
+ out += ` \u2192 trie_propose_fix: file="${parsed.file}" goal="${parsed.goal}" violation="${parsed.violation.slice(0, 80)}${parsed.violation.length > 80 ? "..." : ""}"
7060
+ `;
7061
+ }
7062
+ if (n.suggestedAction) out += ` Suggested: ${n.suggestedAction}
7063
+ `;
7064
+ out += "\n";
7065
+ }
7066
+ out += "To fix: call trie_propose_fix or trie_propose_fixes_batch with file, goal, violation from above.\n";
7067
+ return { content: [{ type: "text", text: out }] };
7068
+ }
7069
+ };
6979
7070
  function formatIncidents(incidents) {
6980
7071
  if (incidents.length === 0) return "No incidents found.";
6981
7072
  let out = `Found ${incidents.length} incident(s):
@@ -7932,6 +8023,18 @@ var CHAT_TOOLS = [
7932
8023
  }
7933
8024
  }
7934
8025
  },
8026
+ {
8027
+ name: "trie_get_nudges",
8028
+ description: "Get unresolved nudges (goal violations). Use when automating fixes: call trie_get_nudges, then trie_propose_fix or trie_propose_fixes_batch with file/goal/violation from results.",
8029
+ input_schema: {
8030
+ type: "object",
8031
+ properties: {
8032
+ limit: { type: "number", description: "Max results (default 20)" },
8033
+ severity: { type: "string", enum: ["critical", "high", "warning", "info"], description: "Filter by severity" },
8034
+ file: { type: "string", description: "Filter by file path" }
8035
+ }
8036
+ }
8037
+ },
7935
8038
  {
7936
8039
  name: "trie_query_ledger_blocks",
7937
8040
  description: 'Query the ledger chain blocks \u2014 the tamper-evident chain of recorded issues. Use when user asks about "blocks", "ledger chain", "what issues in my blocks", "most frequent issues in blocks", etc. Returns block summary and aggregation of issues by file, severity, and agent.',
@@ -8212,6 +8315,11 @@ async function executeTool(name, input, onProgress) {
8212
8315
  const result = await tool.execute(withDir);
8213
8316
  return textFromResult(result);
8214
8317
  }
8318
+ case "trie_get_nudges": {
8319
+ const tool = new TrieGetNudgesTool();
8320
+ const result = await tool.execute(withDir);
8321
+ return textFromResult(result);
8322
+ }
8215
8323
  case "trie_query_ledger_blocks": {
8216
8324
  const tool = new TrieQueryLedgerBlocksTool();
8217
8325
  const result = await tool.execute(withDir);
@@ -8791,9 +8899,9 @@ var SYSTEM_PROMPT = `You are Trie, a code assistant embedded in a terminal TUI.
8791
8899
  3. NEVER use numeric IDs like 1, 2, 3 - always use the full ID like "hyp-1771957097120-bogco0"
8792
8900
  4. If hypothesis IDs aren't in the context, first call trie_query_context with type="hypotheses" to fetch them
8793
8901
 
8794
- **When user asks to fix violations:**
8795
- 1. Look in "Recent goal violations (nudges)" section of project context
8796
- 2. Extract: file path, goal description, and violation details for ALL files
8902
+ **When user asks to fix violations (or automate fixes):**
8903
+ 1. Call trie_get_nudges for full list of unresolved nudges (or check "Recent goal violations" in trie://context)
8904
+ 2. Extract: file path, goal description, and violation details for ALL nudges
8797
8905
  3. If multiple violations: Call trie_propose_fixes_batch ONCE with all fixes
8798
8906
  4. If single violation: Call trie_propose_fix once
8799
8907
  5. AFTER the tool call completes, the system will ask for user confirmation - do NOT add your own confirmation message
@@ -9907,7 +10015,248 @@ var InteractiveDashboard = class {
9907
10015
  import { watch, existsSync as existsSync6, readFileSync as readFileSync2 } from "fs";
9908
10016
  import { stat, readFile as readFile5 } from "fs/promises";
9909
10017
  import { join as join4, extname as extname3, basename } from "path";
10018
+ import { createHash as createHash3 } from "crypto";
10019
+
10020
+ // src/agent/signal-summarizer.ts
10021
+ import Anthropic2 from "@anthropic-ai/sdk";
9910
10022
  import { createHash as createHash2 } from "crypto";
10023
+ var SIGNAL_THRESHOLD = 5;
10024
+ var SUMMARIZE_PROMPT = `You are an AI that learns patterns about a codebase from repeated issues.
10025
+
10026
+ Given a batch of similar code quality issues, extract a LEARNING about the codebase's tendencies. Don't summarize or count issues - identify what this pattern reveals about the codebase or team habits.
10027
+
10028
+ Good learnings (what we want):
10029
+ - "Type safety tends to be weak in this codebase"
10030
+ - "Error handling is often skipped in async code"
10031
+ - "The dashboard module has inconsistent patterns"
10032
+ - "State management doesn't follow a clear convention"
10033
+
10034
+ Bad learnings (avoid these):
10035
+ - "5 type safety issues detected" (just counting)
10036
+ - "Consider adding null checks" (action without insight)
10037
+ - "Issues found in src/dashboard" (no actual learning)
10038
+
10039
+ Respond with JSON:
10040
+ {
10041
+ "learning": "One sentence stating what Trie learned about this codebase (a tendency, habit, or pattern)",
10042
+ "evidence": "Brief explanation of what patterns led to this conclusion",
10043
+ "suggestedAction": "What could improve this tendency",
10044
+ "category": "quality" | "security" | "performance" | "pattern",
10045
+ "confidence": 1-10 (how confident is this learning based on evidence)
10046
+ }`;
10047
+ var SignalSummarizer = class {
10048
+ client = null;
10049
+ projectPath;
10050
+ processedBatches = /* @__PURE__ */ new Set();
10051
+ constructor(projectPath) {
10052
+ this.projectPath = projectPath;
10053
+ const apiKey = process.env.ANTHROPIC_API_KEY;
10054
+ if (apiKey) {
10055
+ this.client = new Anthropic2({ apiKey });
10056
+ }
10057
+ }
10058
+ /**
10059
+ * Check if we have enough nudges to generate a signal
10060
+ */
10061
+ async checkAndSummarize() {
10062
+ const storage = getStorage(this.projectPath);
10063
+ await storage.initialize();
10064
+ const nudges = await storage.queryNudges({ resolved: false, limit: 100 });
10065
+ if (nudges.length < SIGNAL_THRESHOLD) {
10066
+ return null;
10067
+ }
10068
+ const batches = this.groupNudges(nudges);
10069
+ for (const batch of batches) {
10070
+ if (batch.nudges.length >= SIGNAL_THRESHOLD && !this.processedBatches.has(batch.key)) {
10071
+ const insight = await this.summarizeBatch(batch);
10072
+ if (insight) {
10073
+ this.processedBatches.add(batch.key);
10074
+ return insight;
10075
+ }
10076
+ }
10077
+ }
10078
+ return null;
10079
+ }
10080
+ /**
10081
+ * Group nudges by similarity (same goal, same category, similar files)
10082
+ */
10083
+ groupNudges(nudges) {
10084
+ const groups = /* @__PURE__ */ new Map();
10085
+ for (const nudge of nudges) {
10086
+ const goalMatch = nudge.message.match(/Goal "([^"]+)" violated/);
10087
+ const goalPattern = goalMatch?.[1];
10088
+ const key = goalPattern ? `goal:${goalPattern}` : `category:${nudge.category || "general"}`;
10089
+ if (!groups.has(key)) {
10090
+ groups.set(key, {
10091
+ key,
10092
+ nudges: [],
10093
+ category: nudge.category || "quality",
10094
+ goalPattern,
10095
+ files: []
10096
+ });
10097
+ }
10098
+ const batch = groups.get(key);
10099
+ batch.nudges.push(nudge);
10100
+ if (nudge.file && !batch.files.includes(nudge.file)) {
10101
+ batch.files.push(nudge.file);
10102
+ }
10103
+ }
10104
+ return Array.from(groups.values());
10105
+ }
10106
+ /**
10107
+ * Use AI to summarize a batch of nudges into an insight
10108
+ */
10109
+ async summarizeBatch(batch) {
10110
+ if (!this.client) {
10111
+ return this.createFallbackInsight(batch);
10112
+ }
10113
+ try {
10114
+ const nudgeDescriptions = batch.nudges.slice(0, 10).map((n) => `- ${n.message}${n.file ? ` (${n.file})` : ""}`).join("\n");
10115
+ const response = await this.client.messages.create({
10116
+ model: "claude-3-haiku-20240307",
10117
+ max_tokens: 512,
10118
+ temperature: 0.3,
10119
+ messages: [{
10120
+ role: "user",
10121
+ content: `${SUMMARIZE_PROMPT}
10122
+
10123
+ Batch of ${batch.nudges.length} similar issues:
10124
+ ${nudgeDescriptions}
10125
+
10126
+ Files affected: ${batch.files.slice(0, 5).join(", ")}${batch.files.length > 5 ? ` (+${batch.files.length - 5} more)` : ""}`
10127
+ }]
10128
+ });
10129
+ const text = response.content[0]?.type === "text" ? response.content[0].text : "";
10130
+ const parsed = this.parseResponse(text);
10131
+ if (!parsed) {
10132
+ return this.createFallbackInsight(batch);
10133
+ }
10134
+ const insight = {
10135
+ id: `signal-${createHash2("sha256").update(batch.key + Date.now()).digest("hex").slice(0, 12)}`,
10136
+ type: "observation",
10137
+ message: parsed.learning,
10138
+ context: parsed.evidence,
10139
+ suggestedAction: parsed.suggestedAction,
10140
+ relatedIssues: batch.nudges.map((n) => n.id),
10141
+ priority: parsed.confidence,
10142
+ timestamp: Date.now(),
10143
+ dismissed: false,
10144
+ category: parsed.category,
10145
+ details: {
10146
+ affectedFiles: batch.files,
10147
+ issueBreakdown: { [batch.category]: batch.nudges.length },
10148
+ summary: parsed.learning
10149
+ }
10150
+ };
10151
+ const insightStore = getInsightStore(this.projectPath);
10152
+ await insightStore.load();
10153
+ await insightStore.addInsight(insight);
10154
+ const storage = getStorage(this.projectPath);
10155
+ for (const nudge of batch.nudges) {
10156
+ await storage.resolveNudge(nudge.id, "auto-fixed");
10157
+ }
10158
+ return insight;
10159
+ } catch (error) {
10160
+ console.error("[SignalSummarizer] AI summarization failed:", error);
10161
+ return this.createFallbackInsight(batch);
10162
+ }
10163
+ }
10164
+ /**
10165
+ * Parse AI response
10166
+ */
10167
+ parseResponse(text) {
10168
+ try {
10169
+ const jsonMatch = text.match(/\{[\s\S]*\}/);
10170
+ if (!jsonMatch) return null;
10171
+ const parsed = JSON.parse(jsonMatch[0]);
10172
+ return {
10173
+ learning: parsed.learning || "Pattern detected",
10174
+ evidence: parsed.evidence,
10175
+ suggestedAction: parsed.suggestedAction || "Review affected files",
10176
+ category: parsed.category || "quality",
10177
+ confidence: Math.min(10, Math.max(1, parsed.confidence || 5))
10178
+ };
10179
+ } catch {
10180
+ return null;
10181
+ }
10182
+ }
10183
+ /**
10184
+ * Create a fallback insight without AI
10185
+ */
10186
+ createFallbackInsight(batch) {
10187
+ let message;
10188
+ let suggestedAction;
10189
+ if (batch.goalPattern) {
10190
+ const pattern = batch.goalPattern.toLowerCase();
10191
+ if (pattern.includes("type") || pattern.includes("safety")) {
10192
+ message = `Type safety tends to be weak in this codebase`;
10193
+ } else if (pattern.includes("error") || pattern.includes("handling")) {
10194
+ message = `Error handling is often incomplete`;
10195
+ } else if (pattern.includes("test")) {
10196
+ message = `Test coverage appears insufficient`;
10197
+ } else if (pattern.includes("security") || pattern.includes("auth")) {
10198
+ message = `Security practices need attention`;
10199
+ } else {
10200
+ message = `"${batch.goalPattern}" compliance tends to be inconsistent`;
10201
+ }
10202
+ suggestedAction = `Establish stricter conventions for ${pattern}`;
10203
+ } else {
10204
+ if (batch.category === "security") {
10205
+ message = `Security practices need strengthening`;
10206
+ } else if (batch.category === "performance") {
10207
+ message = `Performance optimizations are often overlooked`;
10208
+ } else {
10209
+ message = `Code quality patterns are inconsistent`;
10210
+ }
10211
+ suggestedAction = `Review ${batch.category} conventions across the codebase`;
10212
+ }
10213
+ return {
10214
+ id: `signal-${createHash2("sha256").update(batch.key + Date.now()).digest("hex").slice(0, 12)}`,
10215
+ type: "observation",
10216
+ message,
10217
+ suggestedAction,
10218
+ relatedIssues: batch.nudges.map((n) => n.id),
10219
+ priority: 5,
10220
+ timestamp: Date.now(),
10221
+ dismissed: false,
10222
+ category: batch.category || "quality",
10223
+ details: {
10224
+ affectedFiles: batch.files,
10225
+ issueBreakdown: { [batch.category]: batch.nudges.length }
10226
+ }
10227
+ };
10228
+ }
10229
+ /**
10230
+ * Force summarization of all current nudge batches
10231
+ */
10232
+ async summarizeAll() {
10233
+ const storage = getStorage(this.projectPath);
10234
+ await storage.initialize();
10235
+ const nudges = await storage.queryNudges({ resolved: false, limit: 100 });
10236
+ const batches = this.groupNudges(nudges);
10237
+ const insights = [];
10238
+ for (const batch of batches) {
10239
+ if (batch.nudges.length >= SIGNAL_THRESHOLD) {
10240
+ const insight = await this.summarizeBatch(batch);
10241
+ if (insight) {
10242
+ insights.push(insight);
10243
+ }
10244
+ }
10245
+ }
10246
+ return insights;
10247
+ }
10248
+ };
10249
+ var summarizers = /* @__PURE__ */ new Map();
10250
+ function getSignalSummarizer(projectPath) {
10251
+ let summarizer = summarizers.get(projectPath);
10252
+ if (!summarizer) {
10253
+ summarizer = new SignalSummarizer(projectPath);
10254
+ summarizers.set(projectPath, summarizer);
10255
+ }
10256
+ return summarizer;
10257
+ }
10258
+
10259
+ // src/tools/watch.ts
9911
10260
  var WATCH_EXTENSIONS = /* @__PURE__ */ new Set([
9912
10261
  ".ts",
9913
10262
  ".tsx",
@@ -11277,7 +11626,7 @@ ${recentNudges || "(none)"}
11277
11626
  */
11278
11627
  async persistNudge(params) {
11279
11628
  const timestamp = (/* @__PURE__ */ new Date()).toISOString();
11280
- const nudgeId = createHash2("sha256").update(`${params.message}|${params.file || ""}|${timestamp}`).digest("hex").slice(0, 16);
11629
+ const nudgeId = createHash3("sha256").update(`${params.message}|${params.file || ""}|${timestamp}`).digest("hex").slice(0, 16);
11281
11630
  const nudge = {
11282
11631
  id: nudgeId,
11283
11632
  message: params.message,
@@ -11304,10 +11653,46 @@ ${recentNudges || "(none)"}
11304
11653
  const storage = getStorage(this.watchedDirectory);
11305
11654
  await storage.storeNudge(nudge);
11306
11655
  console.debug(`[Watch] \u2713 Persisted nudge to storage: ${nudge.message.slice(0, 60)}...`);
11656
+ void this.checkSignalThreshold();
11307
11657
  } catch (error) {
11308
11658
  console.error("[Watch] Failed to persist nudge to storage:", error);
11309
11659
  }
11310
11660
  }
11661
+ /**
11662
+ * Check if we have enough nudges (5+) to generate an AI-summarized signal.
11663
+ * Runs periodically after nudge persistence to batch similar issues into insights.
11664
+ */
11665
+ async checkSignalThreshold() {
11666
+ try {
11667
+ const summarizer = getSignalSummarizer(this.watchedDirectory);
11668
+ const insight = await summarizer.checkAndSummarize();
11669
+ if (insight) {
11670
+ getOutputManager().nudge(
11671
+ `Trie learned: ${insight.message}`,
11672
+ "info",
11673
+ void 0,
11674
+ 15e3
11675
+ );
11676
+ if (!isInteractiveMode()) {
11677
+ console.error(` [+] Learning: ${insight.message}`);
11678
+ if (insight.suggestedAction) {
11679
+ console.error(` Suggestion: ${insight.suggestedAction}`);
11680
+ }
11681
+ }
11682
+ if (this.streamingManager) {
11683
+ this.streamingManager.reportSignalExtraction({
11684
+ governance: 1,
11685
+ // Insights are a form of governance
11686
+ facts: 0,
11687
+ blockers: 0,
11688
+ questions: 0
11689
+ });
11690
+ }
11691
+ }
11692
+ } catch (error) {
11693
+ console.debug("[Watch] Signal threshold check failed:", error);
11694
+ }
11695
+ }
11311
11696
  getNudges() {
11312
11697
  return {
11313
11698
  content: [
@@ -11356,6 +11741,7 @@ export {
11356
11741
  TrieGetBlockersTool,
11357
11742
  TrieGetRelatedGovernanceTool,
11358
11743
  TrieGetRelatedDecisionsTool,
11744
+ TrieGetNudgesTool,
11359
11745
  TrieQueryContextTool,
11360
11746
  TrieQueryLedgerBlocksTool,
11361
11747
  handleCheckpointTool,
@@ -11364,4 +11750,4 @@ export {
11364
11750
  InteractiveDashboard,
11365
11751
  TrieWatchTool
11366
11752
  };
11367
- //# sourceMappingURL=chunk-Q4K7CFCK.js.map
11753
+ //# sourceMappingURL=chunk-D6E4Q4I6.js.map