@triedotdev/mcp 1.0.121 → 1.0.123

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 (47) hide show
  1. package/dist/chat-store-HFOOWZYN.js +15 -0
  2. package/dist/{chunk-Y52SNUW5.js → chunk-4YJ6KLGI.js} +19 -4
  3. package/dist/{chunk-Y52SNUW5.js.map → chunk-4YJ6KLGI.js.map} +1 -1
  4. package/dist/{chunk-PPZYVTUO.js → chunk-6LD7OPJL.js} +5 -5
  5. package/dist/{chunk-5TQ7J7UI.js → chunk-B46FDUKR.js} +8 -8
  6. package/dist/{chunk-GPLRFTMB.js → chunk-CKT2A33R.js} +5 -6
  7. package/dist/chunk-CKT2A33R.js.map +1 -0
  8. package/dist/chunk-DFPVUMVE.js +347 -0
  9. package/dist/chunk-DFPVUMVE.js.map +1 -0
  10. package/dist/{chunk-FNW7Z7ZS.js → chunk-F4ZIAHTZ.js} +3 -3
  11. package/dist/{chunk-PRFHN2X6.js → chunk-K5EXATBF.js} +2 -2
  12. package/dist/{chunk-7BY2KVIN.js → chunk-QIS2VDJL.js} +680 -319
  13. package/dist/chunk-QIS2VDJL.js.map +1 -0
  14. package/dist/{chunk-IQBHPTV7.js → chunk-TRIJC5MW.js} +4 -4
  15. package/dist/{chunk-4BGAVEO6.js → chunk-UHMMANC2.js} +77 -338
  16. package/dist/chunk-UHMMANC2.js.map +1 -0
  17. package/dist/chunk-WS6OA7H6.js +266 -0
  18. package/dist/chunk-WS6OA7H6.js.map +1 -0
  19. package/dist/cli/main.js +6 -5
  20. package/dist/cli/main.js.map +1 -1
  21. package/dist/cli/yolo-daemon.js +12 -10
  22. package/dist/cli/yolo-daemon.js.map +1 -1
  23. package/dist/{goal-manager-JKTNFJQE.js → goal-manager-RREOIX6U.js} +6 -5
  24. package/dist/{goal-validator-RD6QBQJB.js → goal-validator-XYA364W3.js} +3 -2
  25. package/dist/{goal-validator-RD6QBQJB.js.map → goal-validator-XYA364W3.js.map} +1 -1
  26. package/dist/{guardian-agent-ITZIDNQD.js → guardian-agent-PTC6G37Q.js} +9 -8
  27. package/dist/{hypothesis-PEVD2IJR.js → hypothesis-WWDONGPU.js} +6 -5
  28. package/dist/hypothesis-WWDONGPU.js.map +1 -0
  29. package/dist/index.js +16 -14
  30. package/dist/index.js.map +1 -1
  31. package/dist/insight-store-F5KDBY5Y.js +22 -0
  32. package/dist/insight-store-F5KDBY5Y.js.map +1 -0
  33. package/dist/{terminal-spawn-2GU5KLPS.js → terminal-spawn-P5M5PHAV.js} +28 -6
  34. package/dist/terminal-spawn-P5M5PHAV.js.map +1 -0
  35. package/package.json +1 -1
  36. package/dist/chunk-4BGAVEO6.js.map +0 -1
  37. package/dist/chunk-7BY2KVIN.js.map +0 -1
  38. package/dist/chunk-GPLRFTMB.js.map +0 -1
  39. package/dist/terminal-spawn-2GU5KLPS.js.map +0 -1
  40. /package/dist/{goal-manager-JKTNFJQE.js.map → chat-store-HFOOWZYN.js.map} +0 -0
  41. /package/dist/{chunk-PPZYVTUO.js.map → chunk-6LD7OPJL.js.map} +0 -0
  42. /package/dist/{chunk-5TQ7J7UI.js.map → chunk-B46FDUKR.js.map} +0 -0
  43. /package/dist/{chunk-FNW7Z7ZS.js.map → chunk-F4ZIAHTZ.js.map} +0 -0
  44. /package/dist/{chunk-PRFHN2X6.js.map → chunk-K5EXATBF.js.map} +0 -0
  45. /package/dist/{chunk-IQBHPTV7.js.map → chunk-TRIJC5MW.js.map} +0 -0
  46. /package/dist/{guardian-agent-ITZIDNQD.js.map → goal-manager-RREOIX6U.js.map} +0 -0
  47. /package/dist/{hypothesis-PEVD2IJR.js.map → guardian-agent-PTC6G37Q.js.map} +0 -0
@@ -1,6 +1,9 @@
1
1
  import {
2
2
  getGuardian
3
- } from "./chunk-5TQ7J7UI.js";
3
+ } from "./chunk-B46FDUKR.js";
4
+ import {
5
+ getChatStore
6
+ } from "./chunk-DFPVUMVE.js";
4
7
  import {
5
8
  LearningEngine,
6
9
  exportToJson,
@@ -10,12 +13,12 @@ import {
10
13
  perceiveCurrentChanges,
11
14
  reasonAboutChangesHumanReadable,
12
15
  saveCheckpoint
13
- } from "./chunk-PPZYVTUO.js";
16
+ } from "./chunk-6LD7OPJL.js";
14
17
  import {
15
18
  TieredStorage,
16
19
  findCrossProjectPatterns,
17
20
  getStorage
18
- } from "./chunk-FNW7Z7ZS.js";
21
+ } from "./chunk-F4ZIAHTZ.js";
19
22
  import {
20
23
  getKeyFromKeychain,
21
24
  isAIAvailable,
@@ -24,7 +27,7 @@ import {
24
27
  } from "./chunk-WRGSH5RT.js";
25
28
  import {
26
29
  getGuardianState
27
- } from "./chunk-4BGAVEO6.js";
30
+ } from "./chunk-UHMMANC2.js";
28
31
  import {
29
32
  ContextGraph
30
33
  } from "./chunk-55CBWOEZ.js";
@@ -288,11 +291,11 @@ var StreamingManager = class {
288
291
 
289
292
  // src/cli/dashboard/index.ts
290
293
  import { render } from "ink";
291
- import React10 from "react";
294
+ import React11 from "react";
292
295
 
293
296
  // src/cli/dashboard/App.tsx
294
- import { useState as useState2, useEffect as useEffect3, useCallback as useCallback6, useRef as useRef2 } from "react";
295
- import { Box as Box13, useInput as useInput9, useApp } from "ink";
297
+ import { useState as useState2, useEffect as useEffect5, useCallback as useCallback7, useRef as useRef2 } from "react";
298
+ import { Box as Box14, useInput as useInput10, useApp } from "ink";
296
299
 
297
300
  // src/cli/dashboard/state.tsx
298
301
  import React, { createContext, useContext, useReducer } from "react";
@@ -526,7 +529,7 @@ function dashboardReducer(state, action) {
526
529
  (ni) => !existing.some((ei) => ei.message === ni.message && !ei.dismissed)
527
530
  );
528
531
  const merged = [...newOnes, ...existing].slice(0, 50);
529
- console.error("[State] ADD_INSIGHTS:", {
532
+ console.debug("[State] ADD_INSIGHTS:", {
530
533
  newCount: newOnes.length,
531
534
  existingCount: existing.length,
532
535
  mergedCount: merged.length,
@@ -661,6 +664,27 @@ function dashboardReducer(state, action) {
661
664
  }
662
665
  case "SET_CHAT_LOADING":
663
666
  return { ...state, chatState: { ...state.chatState, loading: action.loading } };
667
+ case "SET_CHAT_SESSION":
668
+ return { ...state, chatState: { ...state.chatState, currentSessionId: action.sessionId, currentSessionTitle: action.title } };
669
+ case "LOAD_CHAT_MESSAGES":
670
+ return { ...state, chatState: { ...state.chatState, messages: action.messages } };
671
+ case "CLEAR_CHAT":
672
+ return { ...state, chatState: { messages: [], inputBuffer: "", loading: false, currentSessionId: null, currentSessionTitle: null } };
673
+ case "SET_CHAT_ARCHIVE_SESSIONS":
674
+ return { ...state, chatArchivePanel: { ...state.chatArchivePanel, sessions: action.sessions } };
675
+ case "SELECT_CHAT_SESSION": {
676
+ const sessions = state.chatArchivePanel.sessions;
677
+ const newIndex = Math.max(0, Math.min(action.index, sessions.length - 1));
678
+ return { ...state, chatArchivePanel: { ...state.chatArchivePanel, selectedIndex: newIndex } };
679
+ }
680
+ case "SET_CHAT_ARCHIVE_INPUT_MODE":
681
+ return { ...state, chatArchivePanel: { ...state.chatArchivePanel, inputMode: action.mode, inputBuffer: action.mode === "rename" ? state.chatArchivePanel.sessions[state.chatArchivePanel.selectedIndex]?.title || "" : "" } };
682
+ case "SET_CHAT_ARCHIVE_INPUT_BUFFER":
683
+ return { ...state, chatArchivePanel: { ...state.chatArchivePanel, inputBuffer: action.buffer } };
684
+ case "SET_CHAT_ARCHIVE_LOADING":
685
+ return { ...state, chatArchivePanel: { ...state.chatArchivePanel, loading: action.loading } };
686
+ case "TOGGLE_ARCHIVED_CHATS":
687
+ return { ...state, chatArchivePanel: { ...state.chatArchivePanel, showArchived: !state.chatArchivePanel.showArchived } };
664
688
  case "SET_AGENT_CONFIG":
665
689
  return { ...state, agentConfig: applyAgentConfigPatch(state.agentConfig, action.config) };
666
690
  case "NAVIGATE_UP": {
@@ -789,7 +813,7 @@ function createInitialState() {
789
813
  watch: { watching: false, directories: 0, recentChanges: [], filesScannedSession: 0 },
790
814
  rawLog: [],
791
815
  rawLogPage: 0,
792
- scrollPositions: { overview: 0, rawlog: 0, agent: 0, goals: 0, hypotheses: 0, memory: 0, chat: 0 },
816
+ scrollPositions: { overview: 0, rawlog: 0, agent: 0, goals: 0, hypotheses: 0, memory: 0, chat: 0, "chat-archive": 0 },
793
817
  notification: null,
794
818
  notificationHistory: [],
795
819
  agentInsights: [],
@@ -813,7 +837,8 @@ function createInitialState() {
813
837
  hypothesesPanel: { hypotheses: [], selectedIndex: 0, selectedCompletedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0 },
814
838
  memoryTree: { loaded: false, snapshot: null, globalPatterns: [], expandedNodes: /* @__PURE__ */ new Set(["decisions"]), selectedNode: "decisions", scrollPosition: 0, lastRefresh: 0 },
815
839
  agentBrain: { loaded: false, decisions: [], patterns: [], ledgerHash: null, selectedIndex: 0, expandedIndex: null },
816
- chatState: { messages: [], inputBuffer: "", loading: false },
840
+ chatState: { messages: [], inputBuffer: "", loading: false, currentSessionId: null, currentSessionTitle: null },
841
+ chatArchivePanel: { sessions: [], selectedIndex: 0, showArchived: false, loading: false, inputMode: "browse", inputBuffer: "" },
817
842
  pendingFixes: [],
818
843
  selectedFixIndex: 0
819
844
  };
@@ -889,7 +914,8 @@ var VIEW_LABELS = {
889
914
  goals: "Goals",
890
915
  hypotheses: "Hypotheses",
891
916
  memory: "Ledger",
892
- chat: "Chat"
917
+ chat: "Chat",
918
+ "chat-archive": "History"
893
919
  };
894
920
  var VIEW_SHORT = {
895
921
  overview: "Ovr",
@@ -898,24 +924,27 @@ var VIEW_SHORT = {
898
924
  goals: "Gls",
899
925
  hypotheses: "Hyp",
900
926
  memory: "Ldg",
901
- chat: "Cht"
927
+ chat: "Cht",
928
+ "chat-archive": "Hst"
902
929
  };
903
930
  var TAB_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent", "chat"];
904
931
  var CONTEXT_HINTS = {
905
- goals: "j/k nav \xB7 a add \xB7 r run check \xB7 enter complete \xB7 d delete \xB7 x clear achieved \xB7 / help",
906
- hypotheses: "j/k nav \xB7 a add \xB7 r run check \xB7 v validate \xB7 x invalidate \xB7 / help",
907
- agent: "j/k nav \xB7 enter expand \xB7 d dismiss \xB7 / help",
908
- memory: "j/k nav \xB7 enter expand \xB7 / help",
909
- chat: "type to ask \xB7 enter send \xB7 esc clear \xB7 / help",
910
- rawlog: "n/p pages \xB7 b back \xB7 / help"
932
+ goals: "/ help",
933
+ hypotheses: "/ help",
934
+ agent: "/ help",
935
+ memory: "/ help",
936
+ chat: "/ help",
937
+ "chat-archive": "/ help",
938
+ rawlog: "/ help"
911
939
  };
912
940
  var CONTEXT_HINTS_SHORT = {
913
- goals: "j/k a r d x /",
914
- hypotheses: "j/k a r v x /",
915
- agent: "j/k enter d /",
916
- memory: "j/k enter /",
917
- chat: "enter esc /",
918
- rawlog: "n/p b /"
941
+ goals: "/",
942
+ hypotheses: "/",
943
+ agent: "/",
944
+ memory: "/",
945
+ chat: "/",
946
+ "chat-archive": "/",
947
+ rawlog: "/"
919
948
  };
920
949
  function Footer() {
921
950
  const { state } = useDashboard();
@@ -933,7 +962,7 @@ function Footer() {
933
962
  hints = narrow ? "enter esc" : "enter save \xB7 esc cancel";
934
963
  } else {
935
964
  const hintMap = narrow ? CONTEXT_HINTS_SHORT : CONTEXT_HINTS;
936
- hints = hintMap[view] || (narrow ? "s n/p /" : "n/p pages \xB7 s settings \xB7 / help");
965
+ hints = hintMap[view] || (narrow ? "/" : "/ help");
937
966
  }
938
967
  if (veryNarrow) {
939
968
  return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
@@ -947,7 +976,7 @@ function Footer() {
947
976
  " (",
948
977
  unreadNudgesCount,
949
978
  ")"
950
- ] }) : /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: labels[v] }),
979
+ ] }) : /* @__PURE__ */ jsx3(Text2, { color: "green", children: labels[v] }),
951
980
  !isLast && /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: " \xB7 " })
952
981
  ] }, v);
953
982
  }) }),
@@ -968,7 +997,7 @@ function Footer() {
968
997
  " (",
969
998
  unreadNudgesCount,
970
999
  ")"
971
- ] }) : /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: labels[v] }),
1000
+ ] }) : /* @__PURE__ */ jsx3(Text2, { color: "green", children: labels[v] }),
972
1001
  !isLast && /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: " \xB7 " })
973
1002
  ] }, v);
974
1003
  }) }),
@@ -1304,9 +1333,24 @@ var VIEW_HELP = {
1304
1333
  { key: "type", description: "Enter message" },
1305
1334
  { key: "enter", description: "Send message" },
1306
1335
  { key: "esc", description: "Clear input" },
1336
+ { key: "h", description: "Open chat history" },
1307
1337
  { key: "tab", description: "Navigate between views" },
1308
1338
  { key: "q", description: "Quit (press twice if input active)" }
1309
1339
  ],
1340
+ "chat-archive": [
1341
+ { key: "j / \u2193", description: "Move down" },
1342
+ { key: "k / \u2191", description: "Move up" },
1343
+ { key: "enter", description: "Load selected chat" },
1344
+ { key: "n", description: "Start new chat" },
1345
+ { key: "d", description: "Delete selected chat" },
1346
+ { key: "a", description: "Archive selected chat" },
1347
+ { key: "r", description: "Rename selected chat" },
1348
+ { key: "e", description: "Export selected chat" },
1349
+ { key: "t", description: "Toggle archived chats" },
1350
+ { key: "tab", description: "Navigate between views" },
1351
+ { key: "s", description: "Open Settings" },
1352
+ { key: "q / esc", description: "Quit" }
1353
+ ],
1310
1354
  rawlog: [
1311
1355
  { key: "n", description: "Next page" },
1312
1356
  { key: "p", description: "Previous page" },
@@ -1316,7 +1360,7 @@ var VIEW_HELP = {
1316
1360
  { key: "q / esc", description: "Quit" }
1317
1361
  ]
1318
1362
  };
1319
- function HelpDialog({ view, onClose }) {
1363
+ function HelpDialog({ view }) {
1320
1364
  const shortcuts = VIEW_HELP[view] || VIEW_HELP.overview;
1321
1365
  const viewName = view.charAt(0).toUpperCase() + view.slice(1);
1322
1366
  return /* @__PURE__ */ jsxs5(
@@ -1531,7 +1575,7 @@ function AgentView() {
1531
1575
  const { decisions, patterns, loaded } = agentBrain;
1532
1576
  useEffect(() => {
1533
1577
  if (agentInsights.length > 0 || visibleInsights.length > 0) {
1534
- console.error("[AgentView Debug]", {
1578
+ console.debug("[AgentView Debug]", {
1535
1579
  totalInsights: agentInsights.length,
1536
1580
  visibleInsights: visibleInsights.length,
1537
1581
  alerts: alerts.length,
@@ -1565,11 +1609,25 @@ function AgentView() {
1565
1609
  dispatch({ type: "MARK_NUDGES_READ" });
1566
1610
  }
1567
1611
  }, [dispatch, state.unreadNudgesCount]);
1612
+ const dismissInsight = useCallback(async () => {
1613
+ const visible = getVisibleInsights(state);
1614
+ const insight = visible[selectedInsight];
1615
+ if (!insight) return;
1616
+ try {
1617
+ const workDir = getWorkingDirectory(void 0, true);
1618
+ const { getInsightStore } = await import("./insight-store-F5KDBY5Y.js");
1619
+ const store = getInsightStore(workDir);
1620
+ await store.dismissInsight(insight.id);
1621
+ } catch (error) {
1622
+ console.error("Failed to persist insight dismissal:", error);
1623
+ }
1624
+ dispatch({ type: "DISMISS_INSIGHT", index: selectedInsight });
1625
+ }, [selectedInsight, state, dispatch]);
1568
1626
  useInput3((input, key) => {
1569
1627
  if (key.upArrow || input === "k") dispatch({ type: "NAVIGATE_UP" });
1570
1628
  else if (key.downArrow || input === "j") dispatch({ type: "NAVIGATE_DOWN" });
1571
1629
  else if (key.return) dispatch({ type: "TOGGLE_INSIGHT", index: selectedInsight });
1572
- else if (input === "d") dispatch({ type: "DISMISS_INSIGHT", index: selectedInsight });
1630
+ else if (input === "d") void dismissInsight();
1573
1631
  });
1574
1632
  const alertCount = alerts.length;
1575
1633
  const decCount = decisions.length;
@@ -1797,7 +1855,7 @@ function GoalsView() {
1797
1855
  return;
1798
1856
  }
1799
1857
  for (const goal of achieved) {
1800
- await agentState.deleteGoal(goal.id);
1858
+ await agentState.updateGoal(goal.id, { status: "rejected" });
1801
1859
  }
1802
1860
  dispatch({ type: "SHOW_NOTIFICATION", message: `Cleared ${achieved.length} achieved goal${achieved.length > 1 ? "s" : ""}`, severity: "info", autoHideMs: 3e3 });
1803
1861
  dispatch({ type: "ADD_ACTIVITY", message: `Cleared ${achieved.length} achieved goal${achieved.length > 1 ? "s" : ""}` });
@@ -1814,7 +1872,7 @@ function GoalsView() {
1814
1872
  if (!goal) return;
1815
1873
  dispatch({ type: "ADD_ACTIVITY", message: `Checking goal: ${goal.description.slice(0, 30)}...` });
1816
1874
  dispatch({ type: "SHOW_NOTIFICATION", message: `Scanning files for violations...`, severity: "info", autoHideMs: 3e3 });
1817
- const { checkFilesForGoalViolations } = await import("./goal-validator-RD6QBQJB.js");
1875
+ const { checkFilesForGoalViolations } = await import("./goal-validator-XYA364W3.js");
1818
1876
  const violations = await checkFilesForGoalViolations([goal], workDir);
1819
1877
  if (violations.length === 0) {
1820
1878
  dispatch({ type: "SHOW_NOTIFICATION", message: `\u2713 No violations found for: ${goal.description.slice(0, 40)}`, severity: "info", autoHideMs: 5e3 });
@@ -1826,13 +1884,11 @@ function GoalsView() {
1826
1884
  dispatch({ type: "ADD_INSIGHTS", insights: [{
1827
1885
  id: `scan-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,
1828
1886
  message: violation.message,
1829
- severity: violation.severity,
1830
1887
  timestamp: Date.now(),
1831
- category: "goal",
1888
+ category: "quality",
1832
1889
  type: "warning",
1833
1890
  dismissed: false,
1834
1891
  priority: violation.severity === "critical" ? 9 : 6,
1835
- file: violation.file,
1836
1892
  relatedIssues: []
1837
1893
  }] });
1838
1894
  }
@@ -2013,7 +2069,7 @@ function HypothesesView() {
2013
2069
  if (!hypo) return;
2014
2070
  dispatch({ type: "ADD_ACTIVITY", message: `Testing hypothesis: ${hypo.statement.slice(0, 30)}...` });
2015
2071
  dispatch({ type: "SHOW_NOTIFICATION", message: `Gathering evidence for hypothesis...`, severity: "info", autoHideMs: 3e3 });
2016
- const { gatherEvidenceForHypothesis } = await import("./hypothesis-PEVD2IJR.js");
2072
+ const { gatherEvidenceForHypothesis } = await import("./hypothesis-WWDONGPU.js");
2017
2073
  const evidence = await gatherEvidenceForHypothesis(hypoId, workDir);
2018
2074
  if (evidence.length === 0) {
2019
2075
  dispatch({ type: "SHOW_NOTIFICATION", message: `No evidence found for: ${hypo.statement.slice(0, 40)}`, severity: "info", autoHideMs: 5e3 });
@@ -2361,7 +2417,7 @@ function RawLogView() {
2361
2417
  }
2362
2418
 
2363
2419
  // src/cli/dashboard/views/ChatView.tsx
2364
- import { useCallback as useCallback5, useRef } from "react";
2420
+ import { useCallback as useCallback5, useRef, useEffect as useEffect3 } from "react";
2365
2421
  import { Box as Box12, Text as Text12, useInput as useInput8 } from "ink";
2366
2422
 
2367
2423
  // src/tools/tell.ts
@@ -2833,34 +2889,35 @@ var ExtractionPipeline = class {
2833
2889
  * Process raw content through the entire pipeline
2834
2890
  */
2835
2891
  async process(content, context) {
2836
- console.log("\u{1F50D} Extracting signals from content...");
2892
+ const outputManager = getOutputManager();
2893
+ outputManager.debug("Extracting signals from content...");
2837
2894
  let extractedSignal = await this.extractor.extract(content, context.sourceType, context.sourceId);
2838
2895
  extractedSignal = this.addIds(extractedSignal, context);
2839
- console.log(` \u2713 Extracted ${extractedSignal.decisions.length} decisions, ${extractedSignal.facts.length} facts, ${extractedSignal.blockers.length} blockers, ${extractedSignal.questions.length} questions`);
2840
- console.log("\u{1F3F7}\uFE0F Enriching with metadata...");
2896
+ outputManager.debug(`Extracted ${extractedSignal.decisions.length} decisions, ${extractedSignal.facts.length} facts, ${extractedSignal.blockers.length} blockers, ${extractedSignal.questions.length} questions`);
2897
+ outputManager.debug("Enriching with metadata...");
2841
2898
  const { metadata: enrichedMeta } = await this.enricher.enrichSignal(extractedSignal, {
2842
2899
  workingDirectory: this.workDir
2843
2900
  });
2844
2901
  if (enrichedMeta.expandedTags.length > 0) {
2845
- console.log(` \u2713 Expanded tags: ${enrichedMeta.expandedTags.slice(0, 5).join(", ")}${enrichedMeta.expandedTags.length > 5 ? "..." : ""}`);
2902
+ outputManager.debug(`Expanded tags: ${enrichedMeta.expandedTags.slice(0, 5).join(", ")}${enrichedMeta.expandedTags.length > 5 ? "..." : ""}`);
2846
2903
  }
2847
2904
  if (enrichedMeta.dependencies.length > 0) {
2848
- console.log(` \u2713 Dependencies: ${enrichedMeta.dependencies.join(", ")}`);
2905
+ outputManager.debug(`Dependencies: ${enrichedMeta.dependencies.join(", ")}`);
2849
2906
  }
2850
2907
  if (enrichedMeta.codebaseArea.length > 0) {
2851
- console.log(` \u2713 Codebase areas: ${enrichedMeta.codebaseArea.join(", ")}`);
2908
+ outputManager.debug(`Codebase areas: ${enrichedMeta.codebaseArea.join(", ")}`);
2852
2909
  }
2853
2910
  if (enrichedMeta.domain.length > 0) {
2854
- console.log(` \u2713 Domains: ${enrichedMeta.domain.join(", ")}`);
2911
+ outputManager.debug(`Domains: ${enrichedMeta.domain.join(", ")}`);
2855
2912
  }
2856
- console.log("\u{1F4BE} Storing in decision ledger...");
2913
+ outputManager.debug("Storing in decision ledger...");
2857
2914
  await this.storage.storeSignal(extractedSignal, {
2858
2915
  expandedTags: enrichedMeta.expandedTags,
2859
2916
  dependencies: enrichedMeta.dependencies,
2860
2917
  codebaseArea: enrichedMeta.codebaseArea,
2861
2918
  domain: enrichedMeta.domain
2862
2919
  });
2863
- console.log("\u2705 Successfully stored in decision ledger");
2920
+ outputManager.debug("Successfully stored in decision ledger");
2864
2921
  return extractedSignal;
2865
2922
  }
2866
2923
  /**
@@ -4892,7 +4949,7 @@ var CHAT_TOOLS = [
4892
4949
  },
4893
4950
  {
4894
4951
  name: "trie_search_files",
4895
- description: "Search source code files for text patterns, emojis, or code patterns. Use when the user asks about code content that might not be in recent nudges.",
4952
+ description: "Search source code files for text patterns using ripgrep. Note: Requires ripgrep to be installed. For emoji detection, use trie_scan_for_goal_violations instead.",
4896
4953
  input_schema: {
4897
4954
  type: "object",
4898
4955
  properties: {
@@ -4911,171 +4968,185 @@ var CHAT_TOOLS = [
4911
4968
  },
4912
4969
  required: ["pattern"]
4913
4970
  }
4971
+ },
4972
+ {
4973
+ name: "trie_scan_for_goal_violations",
4974
+ description: "Run an AI-powered scan to check for goal violations across the codebase. This is the most reliable way to detect issues like emojis, as it uses AI analysis rather than pattern matching.",
4975
+ input_schema: {
4976
+ type: "object",
4977
+ properties: {
4978
+ goalId: {
4979
+ type: "string",
4980
+ description: "Optional: Specific goal ID to check. If omitted, checks all active goals."
4981
+ }
4982
+ }
4983
+ }
4914
4984
  }
4915
4985
  ];
4916
4986
  async function executeTool(name, input) {
4917
4987
  const directory = getWorkingDirectory(void 0, true);
4918
4988
  const withDir = { ...input, directory };
4919
- switch (name) {
4920
- case "trie_tell": {
4921
- const tool = new TrieTellTool();
4922
- const result = await tool.execute(withDir);
4923
- return textFromResult(result);
4924
- }
4925
- case "trie_feedback": {
4926
- const tool = new TrieFeedbackTool();
4927
- const result = await tool.execute(withDir);
4928
- return textFromResult(result);
4929
- }
4930
- case "trie_check": {
4931
- const tool = new TrieCheckTool();
4932
- const result = await tool.execute(withDir);
4933
- return textFromResult(result);
4934
- }
4935
- case "trie_explain": {
4936
- const tool = new TrieExplainTool();
4937
- const result = await tool.execute(input);
4938
- return textFromResult(result);
4939
- }
4940
- case "trie_get_decisions": {
4941
- const tool = new TrieGetDecisionsTool();
4942
- const result = await tool.execute(withDir);
4943
- return textFromResult(result);
4944
- }
4945
- case "trie_get_blockers": {
4946
- const tool = new TrieGetBlockersTool();
4947
- const result = await tool.execute(withDir);
4948
- return textFromResult(result);
4949
- }
4950
- case "trie_query_context": {
4951
- const tool = new TrieQueryContextTool();
4952
- const result = await tool.execute(withDir);
4953
- return textFromResult(result);
4954
- }
4955
- case "trie_checkpoint": {
4956
- const result = await handleCheckpointTool(input);
4957
- return result;
4958
- }
4959
- case "trie_add_goal": {
4960
- const desc = String(input.description || "").trim();
4961
- if (!desc) return "Goal description is required.";
4962
- const category = input.category || "general";
4963
- const agentState = getGuardianState(directory);
4964
- await agentState.load();
4965
- const goal = {
4966
- id: `goal-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
4967
- description: desc,
4968
- type: "custom",
4969
- metric: "progress",
4970
- target: 100,
4971
- currentValue: 0,
4972
- startValue: 0,
4973
- status: "active",
4974
- autoGenerated: false,
4975
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4976
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
4977
- deadline: new Date(Date.now() + 14 * 864e5).toISOString(),
4978
- category
4979
- };
4980
- await agentState.addGoal(goal);
4981
- return `Goal created: "${desc}" [${category}]`;
4982
- }
4983
- case "trie_add_hypothesis": {
4984
- const stmt = String(input.statement || "").trim();
4985
- if (!stmt) return "Hypothesis statement is required.";
4986
- const category = input.category || "general";
4987
- const agentState = getGuardianState(directory);
4988
- await agentState.load();
4989
- const hypothesis = {
4990
- id: `hyp-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
4991
- statement: stmt,
4992
- confidence: 0.5,
4993
- status: "proposed",
4994
- evidence: [],
4995
- createdAt: (/* @__PURE__ */ new Date()).toISOString(),
4996
- updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
4997
- testCriteria: String(input.test_criteria || "Collect evidence from scans"),
4998
- category
4999
- };
5000
- await agentState.addHypothesis(hypothesis);
5001
- return `Hypothesis created: "${stmt}" [${category}]`;
5002
- }
5003
- case "trie_delete_incident": {
5004
- const search = String(input.search || "").trim().toLowerCase();
5005
- if (!search) return "Search text is required to find the incident.";
5006
- const graph = new ContextGraph(directory);
5007
- const nodes = await graph.listNodes();
5008
- const incidents = nodes.filter(
5009
- (n) => n.type === "incident" && n.data.description?.toLowerCase().includes(search)
5010
- );
5011
- if (incidents.length === 0) return `No incidents found matching "${search}".`;
5012
- for (const inc of incidents) {
5013
- await graph.deleteNode("incident", inc.id);
4989
+ try {
4990
+ switch (name) {
4991
+ case "trie_tell": {
4992
+ const tool = new TrieTellTool();
4993
+ const result = await tool.execute(withDir);
4994
+ return textFromResult(result);
5014
4995
  }
5015
- await exportToJson(graph);
5016
- const descs = incidents.map((i) => `"${i.data.description.slice(0, 60)}"`);
5017
- return `Deleted ${incidents.length} incident(s): ${descs.join(", ")}`;
5018
- }
5019
- case "trie_add_decision": {
5020
- const dec = String(input.decision || "").trim();
5021
- const ctx = String(input.context || "").trim();
5022
- if (!dec) return "Decision text is required.";
5023
- if (!ctx) return "Decision context is required.";
5024
- const now = (/* @__PURE__ */ new Date()).toISOString();
5025
- const id = `dec-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
5026
- const hash = createHash("sha256").update(`${dec}|${ctx}|${now}`).digest("hex").slice(0, 16);
5027
- const files = Array.isArray(input.files) ? input.files.map(String) : [];
5028
- const tags = Array.isArray(input.tags) ? input.tags.map(String) : [];
5029
- const reasoningStr = input.reasoning ? String(input.reasoning) : null;
5030
- const decisionObj = {
5031
- id,
5032
- decision: dec,
5033
- context: ctx,
5034
- when: now,
5035
- who: "user",
5036
- files,
5037
- tags,
5038
- status: "active",
5039
- hash,
5040
- ...reasoningStr ? { reasoning: reasoningStr } : {}
5041
- };
5042
- const storage = new TieredStorage(directory);
5043
- await storage.storeSignal({
5044
- decisions: [decisionObj],
5045
- facts: [],
5046
- blockers: [],
5047
- questions: [],
5048
- metadata: {
5049
- extractedAt: now,
5050
- sourceType: "conversation"
4996
+ case "trie_feedback": {
4997
+ const tool = new TrieFeedbackTool();
4998
+ const result = await tool.execute(withDir);
4999
+ return textFromResult(result);
5000
+ }
5001
+ case "trie_check": {
5002
+ const tool = new TrieCheckTool();
5003
+ const result = await tool.execute(withDir);
5004
+ return textFromResult(result);
5005
+ }
5006
+ case "trie_explain": {
5007
+ const tool = new TrieExplainTool();
5008
+ const result = await tool.execute(withDir);
5009
+ return textFromResult(result);
5010
+ }
5011
+ case "trie_get_decisions": {
5012
+ const tool = new TrieGetDecisionsTool();
5013
+ const result = await tool.execute(withDir);
5014
+ return textFromResult(result);
5015
+ }
5016
+ case "trie_get_blockers": {
5017
+ const tool = new TrieGetBlockersTool();
5018
+ const result = await tool.execute(withDir);
5019
+ return textFromResult(result);
5020
+ }
5021
+ case "trie_query_context": {
5022
+ const tool = new TrieQueryContextTool();
5023
+ const result = await tool.execute(withDir);
5024
+ return textFromResult(result);
5025
+ }
5026
+ case "trie_checkpoint": {
5027
+ const result = await handleCheckpointTool(input);
5028
+ return result;
5029
+ }
5030
+ case "trie_add_goal": {
5031
+ const desc = String(input.description || "").trim();
5032
+ if (!desc) return "Goal description is required.";
5033
+ const category = input.category || "general";
5034
+ const agentState = getGuardianState(directory);
5035
+ await agentState.load();
5036
+ const goal = {
5037
+ id: `goal-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
5038
+ description: desc,
5039
+ type: "custom",
5040
+ metric: "progress",
5041
+ target: 100,
5042
+ currentValue: 0,
5043
+ startValue: 0,
5044
+ status: "active",
5045
+ autoGenerated: false,
5046
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
5047
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
5048
+ deadline: new Date(Date.now() + 14 * 864e5).toISOString(),
5049
+ category
5050
+ };
5051
+ await agentState.addGoal(goal);
5052
+ return `Goal created: "${desc}" [${category}]`;
5053
+ }
5054
+ case "trie_add_hypothesis": {
5055
+ const stmt = String(input.statement || "").trim();
5056
+ if (!stmt) return "Hypothesis statement is required.";
5057
+ const category = input.category || "general";
5058
+ const agentState = getGuardianState(directory);
5059
+ await agentState.load();
5060
+ const hypothesis = {
5061
+ id: `hyp-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
5062
+ statement: stmt,
5063
+ confidence: 0.5,
5064
+ status: "proposed",
5065
+ evidence: [],
5066
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
5067
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
5068
+ testCriteria: String(input.test_criteria || "Collect evidence from scans"),
5069
+ category
5070
+ };
5071
+ await agentState.addHypothesis(hypothesis);
5072
+ return `Hypothesis created: "${stmt}" [${category}]`;
5073
+ }
5074
+ case "trie_delete_incident": {
5075
+ const search = String(input.search || "").trim().toLowerCase();
5076
+ if (!search) return "Search text is required to find the incident.";
5077
+ const graph = new ContextGraph(directory);
5078
+ const nodes = await graph.listNodes();
5079
+ const incidents = nodes.filter(
5080
+ (n) => n.type === "incident" && n.data.description?.toLowerCase().includes(search)
5081
+ );
5082
+ if (incidents.length === 0) return `No incidents found matching "${search}".`;
5083
+ for (const inc of incidents) {
5084
+ await graph.deleteNode("incident", inc.id);
5051
5085
  }
5052
- });
5053
- const graph = new ContextGraph(directory);
5054
- await graph.addNode("decision", {
5055
- context: ctx,
5056
- decision: dec,
5057
- reasoning: reasoningStr,
5058
- outcome: "unknown",
5059
- timestamp: now
5060
- });
5061
- return `Decision recorded [${hash}]: "${dec}"`;
5062
- }
5063
- case "trie_propose_fix": {
5064
- const file = String(input.file || "").trim();
5065
- const goal = String(input.goal || "").trim();
5066
- const violation = String(input.violation || "").trim();
5067
- const suggestedFix = input.suggestedFix ? String(input.suggestedFix) : void 0;
5068
- if (!file) return "File path is required.";
5069
- if (!goal) return "Goal description is required.";
5070
- if (!violation) return "Violation description is required.";
5071
- const fixProposal = {
5072
- file,
5073
- goal,
5074
- violation,
5075
- suggestedFix,
5076
- directory
5077
- };
5078
- return `I found a violation to fix:
5086
+ await exportToJson(graph);
5087
+ const descs = incidents.map((i) => `"${i.data.description.slice(0, 60)}"`);
5088
+ return `Deleted ${incidents.length} incident(s): ${descs.join(", ")}`;
5089
+ }
5090
+ case "trie_add_decision": {
5091
+ const dec = String(input.decision || "").trim();
5092
+ const ctx = String(input.context || "").trim();
5093
+ if (!dec) return "Decision text is required.";
5094
+ if (!ctx) return "Decision context is required.";
5095
+ const now = (/* @__PURE__ */ new Date()).toISOString();
5096
+ const id = `dec-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
5097
+ const hash = createHash("sha256").update(`${dec}|${ctx}|${now}`).digest("hex").slice(0, 16);
5098
+ const files = Array.isArray(input.files) ? input.files.map(String) : [];
5099
+ const tags = Array.isArray(input.tags) ? input.tags.map(String) : [];
5100
+ const reasoningStr = input.reasoning ? String(input.reasoning) : null;
5101
+ const decisionObj = {
5102
+ id,
5103
+ decision: dec,
5104
+ context: ctx,
5105
+ when: now,
5106
+ who: "user",
5107
+ files,
5108
+ tags,
5109
+ status: "active",
5110
+ hash,
5111
+ ...reasoningStr ? { reasoning: reasoningStr } : {}
5112
+ };
5113
+ const storage = new TieredStorage(directory);
5114
+ await storage.storeSignal({
5115
+ decisions: [decisionObj],
5116
+ facts: [],
5117
+ blockers: [],
5118
+ questions: [],
5119
+ metadata: {
5120
+ extractedAt: now,
5121
+ sourceType: "conversation"
5122
+ }
5123
+ });
5124
+ const graph = new ContextGraph(directory);
5125
+ await graph.addNode("decision", {
5126
+ context: ctx,
5127
+ decision: dec,
5128
+ reasoning: reasoningStr,
5129
+ outcome: "unknown",
5130
+ timestamp: now
5131
+ });
5132
+ return `Decision recorded [${hash}]: "${dec}"`;
5133
+ }
5134
+ case "trie_propose_fix": {
5135
+ const file = String(input.file || "").trim();
5136
+ const goal = String(input.goal || "").trim();
5137
+ const violation = String(input.violation || "").trim();
5138
+ const suggestedFix = input.suggestedFix ? String(input.suggestedFix) : void 0;
5139
+ if (!file) return "File path is required.";
5140
+ if (!goal) return "Goal description is required.";
5141
+ if (!violation) return "Violation description is required.";
5142
+ const fixProposal = {
5143
+ file,
5144
+ goal,
5145
+ violation,
5146
+ suggestedFix,
5147
+ directory
5148
+ };
5149
+ return `I found a violation to fix:
5079
5150
 
5080
5151
  \u{1F4C1} File: ${file}
5081
5152
  \u{1F3AF} Goal: ${goal}
@@ -5087,76 +5158,111 @@ Would you like me to spawn Claude Code to fix this?
5087
5158
  Type "yes" to proceed, or "no" to cancel.
5088
5159
 
5089
5160
  [PENDING_FIX:${JSON.stringify(fixProposal)}]`;
5090
- }
5091
- case "trie_search_files": {
5092
- const pattern = String(input.pattern || "").trim();
5093
- const filePattern = input.filePattern ? String(input.filePattern).trim() : void 0;
5094
- const contextLines = typeof input.contextLines === "number" ? input.contextLines : 2;
5095
- if (!pattern) return "Search pattern is required.";
5096
- const { spawnSync } = await import("child_process");
5097
- try {
5098
- const rgArgs = [
5099
- "--context",
5100
- String(contextLines),
5101
- "--heading",
5102
- "--line-number",
5103
- "--color=never",
5104
- "--max-count",
5105
- "50"
5106
- // Limit matches per file
5107
- ];
5108
- if (filePattern) {
5109
- rgArgs.push("--glob", filePattern);
5110
- }
5111
- rgArgs.push(
5112
- "--glob",
5113
- "!node_modules/**",
5114
- "--glob",
5115
- "!.git/**",
5116
- "--glob",
5117
- "!dist/**",
5118
- "--glob",
5119
- "!build/**",
5120
- "--glob",
5121
- "!coverage/**"
5122
- );
5123
- rgArgs.push(pattern, directory);
5124
- const result = spawnSync("rg", rgArgs, {
5125
- encoding: "utf-8",
5126
- maxBuffer: 10 * 1024 * 1024,
5127
- // 10MB
5128
- cwd: directory
5129
- });
5130
- if (result.error) {
5131
- if (result.error.code === "ENOENT") {
5132
- return `Error: ripgrep (rg) not found. Please install it:
5161
+ }
5162
+ case "trie_search_files": {
5163
+ const pattern = String(input.pattern || "").trim();
5164
+ const filePattern = input.filePattern ? String(input.filePattern).trim() : void 0;
5165
+ const contextLines = typeof input.contextLines === "number" ? input.contextLines : 2;
5166
+ if (!pattern) return "Search pattern is required.";
5167
+ const { spawnSync } = await import("child_process");
5168
+ try {
5169
+ const rgArgs = [
5170
+ "--context",
5171
+ String(contextLines),
5172
+ "--heading",
5173
+ "--line-number",
5174
+ "--color=never",
5175
+ "--max-count",
5176
+ "50"
5177
+ // Limit matches per file
5178
+ ];
5179
+ if (filePattern) {
5180
+ rgArgs.push("--glob", filePattern);
5181
+ }
5182
+ rgArgs.push(
5183
+ "--glob",
5184
+ "!node_modules/**",
5185
+ "--glob",
5186
+ "!.git/**",
5187
+ "--glob",
5188
+ "!dist/**",
5189
+ "--glob",
5190
+ "!build/**",
5191
+ "--glob",
5192
+ "!coverage/**"
5193
+ );
5194
+ rgArgs.push(pattern, directory);
5195
+ const result = spawnSync("rg", rgArgs, {
5196
+ encoding: "utf-8",
5197
+ maxBuffer: 10 * 1024 * 1024,
5198
+ // 10MB
5199
+ cwd: directory
5200
+ });
5201
+ if (result.error) {
5202
+ if (result.error.code === "ENOENT") {
5203
+ return `Error: ripgrep (rg) not found. Please install it:
5133
5204
  brew install ripgrep (macOS)
5134
5205
  apt install ripgrep (Ubuntu)
5135
- Or search files using the AI-powered goal scan instead.`;
5206
+ Or use trie_scan_for_goal_violations for AI-powered analysis instead.`;
5207
+ }
5208
+ return `Search failed: ${result.error.message}`;
5136
5209
  }
5137
- return `Search failed: ${result.error.message}`;
5138
- }
5139
- if (result.status === 1 || !result.stdout || !result.stdout.trim()) {
5140
- return `No matches found for pattern: ${pattern}`;
5141
- }
5142
- if (result.status === 2) {
5143
- return `Search error: ${result.stderr || "Unknown error"}`;
5144
- }
5145
- const maxLength = 5e3;
5146
- const output = result.stdout;
5147
- const truncated = output.length > maxLength ? output.slice(0, maxLength) + `
5210
+ if (result.status === 1 || !result.stdout || !result.stdout.trim()) {
5211
+ return `No matches found for pattern: ${pattern}`;
5212
+ }
5213
+ if (result.status === 2) {
5214
+ return `Search error: ${result.stderr || "Unknown error"}`;
5215
+ }
5216
+ const maxLength = 5e3;
5217
+ const output = result.stdout;
5218
+ const truncated = output.length > maxLength ? output.slice(0, maxLength) + `
5148
5219
 
5149
5220
  ... (truncated, ${output.length - maxLength} more characters)` : output;
5150
- const matchCount = (output.match(/^\d+:/gm) || []).length;
5151
- return `Found ${matchCount} match(es) for "${pattern}":
5221
+ const matchCount = (output.match(/^\d+:/gm) || []).length;
5222
+ return `Found ${matchCount} match(es) for "${pattern}":
5152
5223
 
5153
5224
  ${truncated}`;
5154
- } catch (error) {
5155
- return `Search failed: ${error.message}`;
5225
+ } catch (error) {
5226
+ return `Search failed: ${error.message}`;
5227
+ }
5156
5228
  }
5229
+ case "trie_scan_for_goal_violations": {
5230
+ const goalId = input.goalId ? String(input.goalId).trim() : void 0;
5231
+ try {
5232
+ const { checkFilesForGoalViolations, getActiveGoals } = await import("./goal-validator-XYA364W3.js");
5233
+ const agentState = getGuardianState(directory);
5234
+ await agentState.load();
5235
+ const allGoals = await getActiveGoals(directory);
5236
+ const goalsToCheck = goalId ? allGoals.filter((g) => g.id === goalId) : allGoals;
5237
+ if (goalsToCheck.length === 0) {
5238
+ return goalId ? `No active goal found with ID: ${goalId}` : "No active goals to check. Add goals in the Goals view first.";
5239
+ }
5240
+ const violations = await checkFilesForGoalViolations(goalsToCheck, directory);
5241
+ if (violations.length === 0) {
5242
+ return `\u2713 Scan complete! No violations found for ${goalsToCheck.length} goal(s).`;
5243
+ }
5244
+ let result = `Found ${violations.length} violation(s):
5245
+
5246
+ `;
5247
+ for (const v of violations) {
5248
+ result += `\u26A0\uFE0F ${v.file}
5249
+ `;
5250
+ result += ` ${v.message}
5251
+
5252
+ `;
5253
+ }
5254
+ result += "These violations have been recorded and will appear in the Goals view.";
5255
+ return result;
5256
+ } catch (error) {
5257
+ return `Scan failed: ${error.message}`;
5258
+ }
5259
+ }
5260
+ default:
5261
+ return `Unknown tool: ${name}`;
5157
5262
  }
5158
- default:
5159
- return `Unknown tool: ${name}`;
5263
+ } catch (error) {
5264
+ const errorMsg = error instanceof Error ? error.message : "Unknown error";
5265
+ return `Tool execution failed: ${errorMsg}`;
5160
5266
  }
5161
5267
  }
5162
5268
 
@@ -5190,7 +5296,8 @@ async function buildContext(workDir, dashboardState) {
5190
5296
  return `- "${g.description}" [${g.category || "general"}]${caughtCount > 0 ? ` - ${caughtCount} violation(s)${lastCaught}` : ""}`;
5191
5297
  }).join("\n"));
5192
5298
  }
5193
- } catch {
5299
+ } catch (error) {
5300
+ console.error("Failed to load guardian state:", error);
5194
5301
  }
5195
5302
  try {
5196
5303
  const storage = new TieredStorage(workDir);
@@ -5201,7 +5308,8 @@ async function buildContext(workDir, dashboardState) {
5201
5308
  (d) => `- ${d.decision} (${d.when}${d.hash ? `, hash: ${d.hash.slice(0, 8)}` : ""})`
5202
5309
  ).join("\n"));
5203
5310
  }
5204
- } catch {
5311
+ } catch (error) {
5312
+ console.error("Failed to query decisions:", error);
5205
5313
  }
5206
5314
  try {
5207
5315
  const blockers = await storage.queryBlockers({ limit: 5 });
@@ -5210,9 +5318,11 @@ async function buildContext(workDir, dashboardState) {
5210
5318
  (b) => `- ${b.blocker} [${b.impact}]`
5211
5319
  ).join("\n"));
5212
5320
  }
5213
- } catch {
5321
+ } catch (error) {
5322
+ console.error("Failed to query blockers:", error);
5214
5323
  }
5215
- } catch {
5324
+ } catch (error) {
5325
+ console.error("Storage unavailable:", error);
5216
5326
  }
5217
5327
  try {
5218
5328
  const graph = new ContextGraph(workDir);
@@ -5244,7 +5354,8 @@ async function buildContext(workDir, dashboardState) {
5244
5354
  return `- ${d.description} (${Math.round(d.confidence * 100)}%${d.isAntiPattern ? ", anti-pattern" : ""})`;
5245
5355
  }).join("\n"));
5246
5356
  }
5247
- } catch {
5357
+ } catch (error) {
5358
+ console.error("Context graph unavailable:", error);
5248
5359
  }
5249
5360
  return parts.length > 0 ? parts.join("\n\n") : "No context data available yet.";
5250
5361
  }
@@ -5262,20 +5373,20 @@ var SYSTEM_PROMPT = `You are Trie, a code guardian assistant embedded in a termi
5262
5373
  - Query stored decisions, blockers, facts, and questions from the decision ledger
5263
5374
  - Create and manage goals and hypotheses
5264
5375
  - Propose fixes for goal violations (requires user confirmation before spawning Claude Code)
5376
+ - Run AI-powered scans to detect goal violations across the entire codebase
5265
5377
  - Save work checkpoints
5266
5378
 
5267
- **IMPORTANT - File Searching:**
5268
- - You have a trie_search_files tool but it requires ripgrep to be installed
5269
- - For searching code patterns (like emojis, TODO comments, etc.), use the provided project context first
5270
- - If the user asks about emojis or goal violations, check the "Recent goal violations (nudges)" section
5271
- - DO NOT use regex Unicode ranges in search patterns - they don't work reliably
5272
- - Instead, suggest the user press 'r' in Goals view to run an AI-powered scan
5379
+ **IMPORTANT - Finding Code Issues:**
5380
+ - You have a trie_scan_for_goal_violations tool - use this to scan the codebase for goal violations
5381
+ - This is the BEST way to find emojis, TODOs, or other patterns that violate goals
5382
+ - It uses AI analysis and is much more reliable than regex pattern matching
5383
+ - You also have trie_search_files but it requires ripgrep (often not installed)
5273
5384
 
5274
- **When user asks about code content:**
5385
+ **When user asks about code content (emojis, TODOs, etc.):**
5275
5386
  1. First check the "Recent goal violations (nudges)" section in project context
5276
5387
  2. If found, report what you see
5277
- 3. If not found, suggest: "Press 'r' in Goals view to run an AI-powered scan"
5278
- 4. Do NOT attempt manual file searches for emoji detection
5388
+ 3. If not found or user wants a full scan: Call trie_scan_for_goal_violations
5389
+ 4. The scan will find all violations and update the Goals view automatically
5279
5390
 
5280
5391
  **When user asks to fix violations:**
5281
5392
  1. Look in "Recent goal violations (nudges)" section of project context
@@ -5284,16 +5395,39 @@ var SYSTEM_PROMPT = `You are Trie, a code guardian assistant embedded in a termi
5284
5395
  4. Do NOT assume the user wants to proceed - always get confirmation first
5285
5396
 
5286
5397
  Examples:
5287
- - User: "do we have emojis?" \u2192 Check nudges first. If none: "I don't see emoji violations in recent nudges. Press 'r' in Goals view to run a scan."
5398
+ - User: "do we have emojis?" \u2192 Check nudges first. If none or unclear: Call trie_scan_for_goal_violations to scan the codebase.
5399
+ - User: "run a full scan for emojis" \u2192 Call trie_scan_for_goal_violations directly.
5288
5400
  - User: "fix the emoji violation" \u2192 Find emoji violation in nudges, call trie_propose_fix (will ask user to confirm)
5289
- - User: "search for TODO comments" \u2192 "The file search tool requires ripgrep. I recommend checking recent nudges or running a goal scan."
5401
+ - User: "search for TODO comments" \u2192 If there's a goal about TODOs, use trie_scan_for_goal_violations. Otherwise explain no such goal exists.
5290
5402
 
5291
5403
  Answer concisely. Reference specific files, decisions, and patterns when relevant.`;
5292
5404
  function ChatView() {
5293
5405
  const { state, dispatch } = useDashboard();
5294
5406
  const { chatState } = state;
5295
- const { messages, inputBuffer, loading } = chatState;
5407
+ const { messages, inputBuffer, loading, currentSessionId, currentSessionTitle } = chatState;
5296
5408
  const loadingRef = useRef(false);
5409
+ useEffect3(() => {
5410
+ if (messages.length === 0) return;
5411
+ const saveChat = async () => {
5412
+ try {
5413
+ const workDir = getWorkingDirectory(void 0, true);
5414
+ const { getChatStore: getChatStore2 } = await import("./chat-store-HFOOWZYN.js");
5415
+ const store = getChatStore2(workDir);
5416
+ const sessionId = await store.saveSession(
5417
+ messages,
5418
+ currentSessionId || void 0,
5419
+ currentSessionTitle || void 0
5420
+ );
5421
+ if (!currentSessionId) {
5422
+ dispatch({ type: "SET_CHAT_SESSION", sessionId, title: null });
5423
+ }
5424
+ } catch (error) {
5425
+ console.error("Failed to auto-save chat:", error);
5426
+ }
5427
+ };
5428
+ const timeout = setTimeout(() => void saveChat(), 2e3);
5429
+ return () => clearTimeout(timeout);
5430
+ }, [messages, currentSessionId, currentSessionTitle, dispatch]);
5297
5431
  const sendMessage = useCallback5(async (question) => {
5298
5432
  if (loadingRef.current) return;
5299
5433
  loadingRef.current = true;
@@ -5306,9 +5440,12 @@ function ChatView() {
5306
5440
  if (lastAssistantMessage?.pendingFix) {
5307
5441
  const response = question.trim().toLowerCase();
5308
5442
  if (response === "yes" || response === "y") {
5309
- const { spawnClaudeCodeFix } = await import("./terminal-spawn-2GU5KLPS.js");
5443
+ const { spawnClaudeCodeFix } = await import("./terminal-spawn-P5M5PHAV.js");
5310
5444
  try {
5311
- await spawnClaudeCodeFix(lastAssistantMessage.pendingFix);
5445
+ await spawnClaudeCodeFix({
5446
+ ...lastAssistantMessage.pendingFix,
5447
+ cwd: lastAssistantMessage.pendingFix.directory
5448
+ });
5312
5449
  dispatch({
5313
5450
  type: "ADD_CHAT_MESSAGE",
5314
5451
  role: "assistant",
@@ -5405,7 +5542,8 @@ ${contextBlock}`;
5405
5542
  })
5406
5543
  });
5407
5544
  }
5408
- } catch {
5545
+ } catch (error) {
5546
+ console.error("Failed to update state after tool calls:", error);
5409
5547
  }
5410
5548
  }
5411
5549
  }
@@ -5447,7 +5585,14 @@ ${contextBlock}`;
5447
5585
  ] });
5448
5586
  }
5449
5587
  return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
5450
- /* @__PURE__ */ jsx13(Text12, { bold: true, children: "Chat" }),
5588
+ /* @__PURE__ */ jsxs12(Text12, { children: [
5589
+ /* @__PURE__ */ jsx13(Text12, { bold: true, children: "Chat" }),
5590
+ currentSessionTitle && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
5591
+ " ",
5592
+ currentSessionTitle
5593
+ ] }),
5594
+ /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " (h for history)" })
5595
+ ] }),
5451
5596
  /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", flexGrow: 1, overflow: "hidden", marginTop: 1, children: [
5452
5597
  messages.length === 0 && !loading && /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " Ask about your codebase, decisions, patterns, or risks." }),
5453
5598
  messages.map((msg, idx) => /* @__PURE__ */ jsx13(Box12, { flexDirection: "column", marginTop: idx === 0 ? 0 : 1, marginBottom: 1, children: msg.role === "user" ? /* @__PURE__ */ jsxs12(Text12, { children: [
@@ -5489,8 +5634,219 @@ function formatToolInput(input) {
5489
5634
  return parts.length > 0 ? parts.join(", ") : "";
5490
5635
  }
5491
5636
 
5492
- // src/cli/dashboard/App.tsx
5637
+ // src/cli/dashboard/views/ChatArchiveView.tsx
5638
+ import { useEffect as useEffect4, useCallback as useCallback6 } from "react";
5639
+ import { Box as Box13, Text as Text13, useInput as useInput9 } from "ink";
5493
5640
  import { jsx as jsx14, jsxs as jsxs13 } from "react/jsx-runtime";
5641
+ function formatTimeAgo2(timestamp) {
5642
+ const seconds = Math.floor((Date.now() - timestamp) / 1e3);
5643
+ if (seconds < 60) return `${seconds}s ago`;
5644
+ const minutes = Math.floor(seconds / 60);
5645
+ if (minutes < 60) return `${minutes}m ago`;
5646
+ const hours = Math.floor(minutes / 60);
5647
+ if (hours < 24) return `${hours}h ago`;
5648
+ const days = Math.floor(hours / 24);
5649
+ if (days < 30) return `${days}d ago`;
5650
+ const months = Math.floor(days / 30);
5651
+ if (months < 12) return `${months}mo ago`;
5652
+ return `${Math.floor(months / 12)}y ago`;
5653
+ }
5654
+ function ChatArchiveView() {
5655
+ const { state, dispatch } = useDashboard();
5656
+ const { chatArchivePanel } = state;
5657
+ const { sessions, selectedIndex, showArchived, loading, inputMode, inputBuffer } = chatArchivePanel;
5658
+ const loadSessions = useCallback6(async () => {
5659
+ dispatch({ type: "SET_CHAT_ARCHIVE_LOADING", loading: true });
5660
+ try {
5661
+ const workDir = getWorkingDirectory(void 0, true);
5662
+ const store = getChatStore(workDir);
5663
+ const sessionsList = await store.listSessions(showArchived);
5664
+ dispatch({ type: "SET_CHAT_ARCHIVE_SESSIONS", sessions: sessionsList });
5665
+ } catch (error) {
5666
+ dispatch({ type: "ADD_ACTIVITY", message: `Failed to load chat sessions: ${error instanceof Error ? error.message : "unknown"}` });
5667
+ }
5668
+ dispatch({ type: "SET_CHAT_ARCHIVE_LOADING", loading: false });
5669
+ }, [showArchived, dispatch]);
5670
+ useEffect4(() => {
5671
+ void loadSessions();
5672
+ }, [loadSessions]);
5673
+ const loadChatSession = useCallback6(async (sessionId) => {
5674
+ try {
5675
+ const workDir = getWorkingDirectory(void 0, true);
5676
+ const store = getChatStore(workDir);
5677
+ const session = await store.loadSession(sessionId);
5678
+ if (session) {
5679
+ dispatch({ type: "LOAD_CHAT_MESSAGES", messages: session.messages });
5680
+ dispatch({ type: "SET_CHAT_SESSION", sessionId: session.id, title: session.title });
5681
+ dispatch({ type: "SET_VIEW", view: "chat" });
5682
+ dispatch({ type: "ADD_ACTIVITY", message: `Loaded chat: ${session.title}` });
5683
+ } else {
5684
+ dispatch({ type: "SHOW_NOTIFICATION", message: "Chat session not found", severity: "warning", autoHideMs: 3e3 });
5685
+ }
5686
+ } catch (error) {
5687
+ dispatch({ type: "SHOW_NOTIFICATION", message: `Failed to load chat: ${error instanceof Error ? error.message : "unknown"}`, severity: "warning", autoHideMs: 3e3 });
5688
+ }
5689
+ }, [dispatch]);
5690
+ const deleteSession = useCallback6(async () => {
5691
+ if (sessions.length === 0) return;
5692
+ const session = sessions[selectedIndex];
5693
+ if (!session) return;
5694
+ try {
5695
+ const workDir = getWorkingDirectory(void 0, true);
5696
+ const store = getChatStore(workDir);
5697
+ await store.deleteSession(session.id);
5698
+ dispatch({ type: "ADD_ACTIVITY", message: `Deleted chat: ${session.title}` });
5699
+ dispatch({ type: "SHOW_NOTIFICATION", message: "Chat deleted", severity: "info", autoHideMs: 2e3 });
5700
+ await loadSessions();
5701
+ } catch (error) {
5702
+ dispatch({ type: "SHOW_NOTIFICATION", message: `Failed to delete: ${error instanceof Error ? error.message : "unknown"}`, severity: "warning", autoHideMs: 3e3 });
5703
+ }
5704
+ }, [sessions, selectedIndex, dispatch, loadSessions]);
5705
+ const archiveSession = useCallback6(async () => {
5706
+ if (sessions.length === 0) return;
5707
+ const session = sessions[selectedIndex];
5708
+ if (!session) return;
5709
+ try {
5710
+ const workDir = getWorkingDirectory(void 0, true);
5711
+ const store = getChatStore(workDir);
5712
+ await store.archiveSession(session.id);
5713
+ dispatch({ type: "ADD_ACTIVITY", message: `Archived chat: ${session.title}` });
5714
+ dispatch({ type: "SHOW_NOTIFICATION", message: "Chat archived", severity: "info", autoHideMs: 2e3 });
5715
+ await loadSessions();
5716
+ } catch (error) {
5717
+ dispatch({ type: "SHOW_NOTIFICATION", message: `Failed to archive: ${error instanceof Error ? error.message : "unknown"}`, severity: "warning", autoHideMs: 3e3 });
5718
+ }
5719
+ }, [sessions, selectedIndex, dispatch, loadSessions]);
5720
+ const renameSession = useCallback6(async (newTitle) => {
5721
+ if (sessions.length === 0 || !newTitle.trim()) return;
5722
+ const session = sessions[selectedIndex];
5723
+ if (!session) return;
5724
+ try {
5725
+ const workDir = getWorkingDirectory(void 0, true);
5726
+ const store = getChatStore(workDir);
5727
+ await store.renameSession(session.id, newTitle.trim());
5728
+ dispatch({ type: "ADD_ACTIVITY", message: `Renamed chat to: ${newTitle}` });
5729
+ dispatch({ type: "SHOW_NOTIFICATION", message: "Chat renamed", severity: "info", autoHideMs: 2e3 });
5730
+ dispatch({ type: "SET_CHAT_ARCHIVE_INPUT_MODE", mode: "browse" });
5731
+ await loadSessions();
5732
+ } catch (error) {
5733
+ dispatch({ type: "SHOW_NOTIFICATION", message: `Failed to rename: ${error instanceof Error ? error.message : "unknown"}`, severity: "warning", autoHideMs: 3e3 });
5734
+ }
5735
+ }, [sessions, selectedIndex, dispatch, loadSessions]);
5736
+ const exportSession = useCallback6(async () => {
5737
+ if (sessions.length === 0) return;
5738
+ const session = sessions[selectedIndex];
5739
+ if (!session) return;
5740
+ try {
5741
+ const workDir = getWorkingDirectory(void 0, true);
5742
+ const store = getChatStore(workDir);
5743
+ const exported = await store.exportSession(session.id);
5744
+ if (exported) {
5745
+ dispatch({ type: "SHOW_NOTIFICATION", message: "Chat exported (check logs for JSON)", severity: "info", autoHideMs: 3e3 });
5746
+ console.log("=== EXPORTED CHAT ===");
5747
+ console.log(exported);
5748
+ console.log("=== END EXPORT ===");
5749
+ }
5750
+ } catch (error) {
5751
+ dispatch({ type: "SHOW_NOTIFICATION", message: `Failed to export: ${error instanceof Error ? error.message : "unknown"}`, severity: "warning", autoHideMs: 3e3 });
5752
+ }
5753
+ }, [sessions, selectedIndex, dispatch]);
5754
+ useInput9((input, key) => {
5755
+ if (inputMode === "rename") {
5756
+ if (key.return) {
5757
+ void renameSession(inputBuffer);
5758
+ } else if (key.escape) {
5759
+ dispatch({ type: "SET_CHAT_ARCHIVE_INPUT_MODE", mode: "browse" });
5760
+ } else if (key.backspace || key.delete) {
5761
+ dispatch({ type: "SET_CHAT_ARCHIVE_INPUT_BUFFER", buffer: inputBuffer.slice(0, -1) });
5762
+ } else if (input && !key.ctrl && !key.meta) {
5763
+ dispatch({ type: "SET_CHAT_ARCHIVE_INPUT_BUFFER", buffer: inputBuffer + input });
5764
+ }
5765
+ return;
5766
+ }
5767
+ if (key.upArrow || input === "k") {
5768
+ const newIndex = Math.max(0, selectedIndex - 1);
5769
+ dispatch({ type: "SELECT_CHAT_SESSION", index: newIndex });
5770
+ } else if (key.downArrow || input === "j") {
5771
+ const newIndex = Math.min(sessions.length - 1, selectedIndex + 1);
5772
+ dispatch({ type: "SELECT_CHAT_SESSION", index: newIndex });
5773
+ } else if (key.return) {
5774
+ if (sessions[selectedIndex]) {
5775
+ void loadChatSession(sessions[selectedIndex].id);
5776
+ }
5777
+ } else if (input === "d") {
5778
+ void deleteSession();
5779
+ } else if (input === "a") {
5780
+ void archiveSession();
5781
+ } else if (input === "r") {
5782
+ dispatch({ type: "SET_CHAT_ARCHIVE_INPUT_MODE", mode: "rename" });
5783
+ } else if (input === "e") {
5784
+ void exportSession();
5785
+ } else if (input === "t") {
5786
+ dispatch({ type: "TOGGLE_ARCHIVED_CHATS" });
5787
+ } else if (input === "n") {
5788
+ dispatch({ type: "CLEAR_CHAT" });
5789
+ dispatch({ type: "SET_VIEW", view: "chat" });
5790
+ }
5791
+ });
5792
+ if (loading) {
5793
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingX: 1, children: [
5794
+ /* @__PURE__ */ jsx14(Text13, { bold: true, children: "Chat Archive" }),
5795
+ /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: " Loading..." })
5796
+ ] });
5797
+ }
5798
+ if (sessions.length === 0) {
5799
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingX: 1, children: [
5800
+ /* @__PURE__ */ jsx14(Text13, { bold: true, children: "Chat Archive" }),
5801
+ /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
5802
+ " ",
5803
+ showArchived ? "No archived chats" : "No chat history yet"
5804
+ ] }),
5805
+ /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: " Press n to start a new chat" })
5806
+ ] });
5807
+ }
5808
+ if (inputMode === "rename") {
5809
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingX: 1, children: [
5810
+ /* @__PURE__ */ jsx14(Text13, { bold: true, children: "Rename Chat" }),
5811
+ /* @__PURE__ */ jsxs13(Box13, { marginTop: 1, children: [
5812
+ /* @__PURE__ */ jsx14(Text13, { children: "Title: " }),
5813
+ /* @__PURE__ */ jsx14(Text13, { children: inputBuffer }),
5814
+ /* @__PURE__ */ jsx14(Text13, { children: "\u2502" })
5815
+ ] }),
5816
+ /* @__PURE__ */ jsx14(Box13, { marginTop: 1, children: /* @__PURE__ */ jsx14(Text13, { dimColor: true, children: "enter save \xB7 esc cancel" }) })
5817
+ ] });
5818
+ }
5819
+ return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", paddingX: 1, children: [
5820
+ /* @__PURE__ */ jsxs13(Text13, { children: [
5821
+ /* @__PURE__ */ jsx14(Text13, { bold: true, children: "Chat Archive" }),
5822
+ /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
5823
+ " ",
5824
+ sessions.length,
5825
+ " chat",
5826
+ sessions.length !== 1 ? "s" : ""
5827
+ ] }),
5828
+ showArchived && /* @__PURE__ */ jsx14(Text13, { color: "yellow", children: " (showing archived)" })
5829
+ ] }),
5830
+ /* @__PURE__ */ jsx14(Box13, { flexDirection: "column", marginTop: 1, children: sessions.map((session, idx) => {
5831
+ const isSelected = idx === selectedIndex;
5832
+ const ago = formatTimeAgo2(session.updatedAt);
5833
+ const titleDisplay = session.title.length > 60 ? session.title.slice(0, 60) + "..." : session.title;
5834
+ return /* @__PURE__ */ jsx14(Box13, { flexDirection: "column", children: /* @__PURE__ */ jsxs13(Text13, { children: [
5835
+ isSelected ? /* @__PURE__ */ jsx14(Text13, { bold: true, color: "green", children: "> " }) : " ",
5836
+ isSelected ? /* @__PURE__ */ jsx14(Text13, { bold: true, children: titleDisplay }) : /* @__PURE__ */ jsx14(Text13, { children: titleDisplay }),
5837
+ /* @__PURE__ */ jsxs13(Text13, { dimColor: true, children: [
5838
+ " ",
5839
+ session.messageCount,
5840
+ " msgs \xB7 ",
5841
+ ago
5842
+ ] })
5843
+ ] }) }, session.id);
5844
+ }) })
5845
+ ] });
5846
+ }
5847
+
5848
+ // src/cli/dashboard/App.tsx
5849
+ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
5494
5850
  var MAIN_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent", "chat"];
5495
5851
  async function applyGoalFix(fix, dispatch) {
5496
5852
  try {
@@ -5529,7 +5885,7 @@ ${content}
5529
5885
  fixedContent = fixedContent.replace(/^```\w*\n?/, "").replace(/\n?```$/, "");
5530
5886
  }
5531
5887
  await writeFile(fullPath, fixedContent, "utf-8");
5532
- const { recordGoalViolationFixed, getActiveGoals } = await import("./goal-validator-RD6QBQJB.js");
5888
+ const { recordGoalViolationFixed, getActiveGoals } = await import("./goal-validator-XYA364W3.js");
5533
5889
  const goals = await getActiveGoals(projectPath);
5534
5890
  const matchedGoal = goals.find((g) => g.description === fix.goalDescription);
5535
5891
  if (matchedGoal) {
@@ -5552,7 +5908,7 @@ function DashboardApp({ onReady }) {
5552
5908
  const stateRef = useRef2(state);
5553
5909
  stateRef.current = state;
5554
5910
  const configPath = join2(getTrieDirectory(getWorkingDirectory(void 0, true)), "agent.json");
5555
- const loadConfig = useCallback6(async () => {
5911
+ const loadConfig = useCallback7(async () => {
5556
5912
  if (!existsSync3(configPath)) return;
5557
5913
  try {
5558
5914
  const raw = await readFile2(configPath, "utf-8");
@@ -5561,7 +5917,7 @@ function DashboardApp({ onReady }) {
5561
5917
  } catch {
5562
5918
  }
5563
5919
  }, [configPath]);
5564
- const persistConfig = useCallback6(async () => {
5920
+ const persistConfig = useCallback7(async () => {
5565
5921
  try {
5566
5922
  const workDir = getWorkingDirectory(void 0, true);
5567
5923
  await mkdir(getTrieDirectory(workDir), { recursive: true });
@@ -5573,7 +5929,7 @@ function DashboardApp({ onReady }) {
5573
5929
  } catch {
5574
5930
  }
5575
5931
  }, [configPath]);
5576
- const processInsights = useCallback6(async (issues) => {
5932
+ const processInsights = useCallback7(async (issues) => {
5577
5933
  try {
5578
5934
  const workDir = getWorkingDirectory(void 0, true);
5579
5935
  const trieAgent = getGuardian(workDir);
@@ -5599,7 +5955,7 @@ function DashboardApp({ onReady }) {
5599
5955
  dispatchRef.current({ type: "ADD_ACTIVITY", message: `Trie Agent error: ${error instanceof Error ? error.message : "unknown"}` });
5600
5956
  }
5601
5957
  }, []);
5602
- const refreshGoals = useCallback6(async () => {
5958
+ const refreshGoals = useCallback7(async () => {
5603
5959
  try {
5604
5960
  const workDir = getWorkingDirectory(void 0, true);
5605
5961
  const agentState = getGuardianState(workDir);
@@ -5615,7 +5971,7 @@ function DashboardApp({ onReady }) {
5615
5971
  } catch {
5616
5972
  }
5617
5973
  }, []);
5618
- const refreshHypotheses = useCallback6(async () => {
5974
+ const refreshHypotheses = useCallback7(async () => {
5619
5975
  try {
5620
5976
  const workDir = getWorkingDirectory(void 0, true);
5621
5977
  const agentState = getGuardianState(workDir);
@@ -5631,7 +5987,7 @@ function DashboardApp({ onReady }) {
5631
5987
  } catch {
5632
5988
  }
5633
5989
  }, []);
5634
- useEffect3(() => {
5990
+ useEffect5(() => {
5635
5991
  void loadConfig();
5636
5992
  void refreshGoals();
5637
5993
  void refreshHypotheses();
@@ -5646,7 +6002,6 @@ function DashboardApp({ onReady }) {
5646
6002
  dispatchRef.current({ type: "STREAM_UPDATE", update: { type: "raw_log", data: { time, level, message }, timestamp: Date.now() } });
5647
6003
  },
5648
6004
  onNudge: (nudge) => {
5649
- console.error("[Dashboard] onNudge called:", { message: nudge.message, severity: nudge.severity, file: nudge.file });
5650
6005
  const action = { type: "SHOW_NOTIFICATION", message: nudge.message, severity: nudge.severity };
5651
6006
  if (nudge.file !== void 0) action.file = nudge.file;
5652
6007
  if (nudge.autoHideMs !== void 0) action.autoHideMs = nudge.autoHideMs;
@@ -5663,7 +6018,6 @@ function DashboardApp({ onReady }) {
5663
6018
  relatedIssues: [],
5664
6019
  dismissed: false
5665
6020
  };
5666
- console.error("[Dashboard] Adding insight:", { id: insight.id, type: insight.type, category: insight.category, priority: insight.priority });
5667
6021
  dispatchRef.current({ type: "ADD_INSIGHTS", insights: [insight] });
5668
6022
  }
5669
6023
  }
@@ -5688,21 +6042,21 @@ function DashboardApp({ onReady }) {
5688
6042
  outputManager.setMode("console");
5689
6043
  };
5690
6044
  }, [loadConfig, onReady, processInsights, refreshGoals, refreshHypotheses]);
5691
- useEffect3(() => {
6045
+ useEffect5(() => {
5692
6046
  const interval = setInterval(() => {
5693
6047
  dispatchRef.current({ type: "AUTO_DISMISS_NOTIFICATIONS" });
5694
6048
  }, 5e3);
5695
6049
  return () => clearInterval(interval);
5696
6050
  }, []);
5697
6051
  const applyingFixIds = useRef2(/* @__PURE__ */ new Set());
5698
- useEffect3(() => {
6052
+ useEffect5(() => {
5699
6053
  const toApply = state.pendingFixes.filter((f) => f.status === "applying" && !applyingFixIds.current.has(f.id));
5700
6054
  for (const fix of toApply) {
5701
6055
  applyingFixIds.current.add(fix.id);
5702
6056
  void applyGoalFix(fix, dispatchRef.current);
5703
6057
  }
5704
6058
  }, [state.pendingFixes]);
5705
- useInput9((input, key) => {
6059
+ useInput10((input, key) => {
5706
6060
  if (showConfig) return;
5707
6061
  if (state.view === "goals" && state.goalsPanel.inputMode === "add") return;
5708
6062
  if (state.view === "hypotheses" && state.hypothesesPanel.inputMode === "add") return;
@@ -5724,7 +6078,7 @@ function DashboardApp({ onReady }) {
5724
6078
  }
5725
6079
  if (input === "q" || key.escape) {
5726
6080
  exit();
5727
- process.exit(0);
6081
+ return;
5728
6082
  }
5729
6083
  if (key.tab) {
5730
6084
  const currentIndex = MAIN_VIEWS.indexOf(state.view);
@@ -5732,7 +6086,7 @@ function DashboardApp({ onReady }) {
5732
6086
  dispatch({ type: "SET_VIEW", view: MAIN_VIEWS[nextIndex] || "overview" });
5733
6087
  return;
5734
6088
  }
5735
- if (state.view === "goals" || state.view === "hypotheses") {
6089
+ if (state.view === "goals" || state.view === "hypotheses" || state.view === "chat-archive") {
5736
6090
  return;
5737
6091
  }
5738
6092
  if (input === "s") {
@@ -5765,6 +6119,10 @@ function DashboardApp({ onReady }) {
5765
6119
  dispatch({ type: "SET_VIEW", view: "chat" });
5766
6120
  return;
5767
6121
  }
6122
+ if (input === "h") {
6123
+ dispatch({ type: "SET_VIEW", view: "chat-archive" });
6124
+ return;
6125
+ }
5768
6126
  if (state.view === "agent" || state.view === "memory") return;
5769
6127
  if (input === "b") dispatch({ type: "GO_BACK" });
5770
6128
  if (input === "n") dispatch({ type: "NEXT_PAGE" });
@@ -5773,41 +6131,44 @@ function DashboardApp({ onReady }) {
5773
6131
  let viewComponent;
5774
6132
  switch (state.view) {
5775
6133
  case "overview":
5776
- viewComponent = /* @__PURE__ */ jsx14(OverviewView, {});
6134
+ viewComponent = /* @__PURE__ */ jsx15(OverviewView, {});
5777
6135
  break;
5778
6136
  case "agent":
5779
- viewComponent = /* @__PURE__ */ jsx14(AgentView, {});
6137
+ viewComponent = /* @__PURE__ */ jsx15(AgentView, {});
5780
6138
  break;
5781
6139
  case "goals":
5782
- viewComponent = /* @__PURE__ */ jsx14(GoalsView, {});
6140
+ viewComponent = /* @__PURE__ */ jsx15(GoalsView, {});
5783
6141
  break;
5784
6142
  case "hypotheses":
5785
- viewComponent = /* @__PURE__ */ jsx14(HypothesesView, {});
6143
+ viewComponent = /* @__PURE__ */ jsx15(HypothesesView, {});
5786
6144
  break;
5787
6145
  case "memory":
5788
- viewComponent = /* @__PURE__ */ jsx14(MemoryTreeView, {});
6146
+ viewComponent = /* @__PURE__ */ jsx15(MemoryTreeView, {});
5789
6147
  break;
5790
6148
  case "rawlog":
5791
- viewComponent = /* @__PURE__ */ jsx14(RawLogView, {});
6149
+ viewComponent = /* @__PURE__ */ jsx15(RawLogView, {});
5792
6150
  break;
5793
6151
  case "chat":
5794
- viewComponent = /* @__PURE__ */ jsx14(ChatView, {});
6152
+ viewComponent = /* @__PURE__ */ jsx15(ChatView, {});
6153
+ break;
6154
+ case "chat-archive":
6155
+ viewComponent = /* @__PURE__ */ jsx15(ChatArchiveView, {});
5795
6156
  break;
5796
6157
  default:
5797
- viewComponent = /* @__PURE__ */ jsx14(OverviewView, {});
6158
+ viewComponent = /* @__PURE__ */ jsx15(OverviewView, {});
5798
6159
  }
5799
- return /* @__PURE__ */ jsxs13(Box13, { flexDirection: "column", height: process.stdout.rows || 40, children: [
5800
- /* @__PURE__ */ jsx14(Header, {}),
5801
- !showConfig && !showHelp && /* @__PURE__ */ jsx14(Notification, {}),
5802
- /* @__PURE__ */ jsx14(Box13, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: showConfig ? /* @__PURE__ */ jsx14(ConfigDialog, { onClose: () => {
6160
+ return /* @__PURE__ */ jsxs14(Box14, { flexDirection: "column", height: process.stdout.rows || 40, children: [
6161
+ /* @__PURE__ */ jsx15(Header, {}),
6162
+ !showConfig && !showHelp && /* @__PURE__ */ jsx15(Notification, {}),
6163
+ /* @__PURE__ */ jsx15(Box14, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: showConfig ? /* @__PURE__ */ jsx15(ConfigDialog, { onClose: () => {
5803
6164
  setShowConfig(false);
5804
6165
  void persistConfig();
5805
- } }) : showHelp ? /* @__PURE__ */ jsx14(HelpDialog, { view: state.view, onClose: () => setShowHelp(false) }) : viewComponent }),
5806
- /* @__PURE__ */ jsx14(Footer, {})
6166
+ } }) : showHelp ? /* @__PURE__ */ jsx15(HelpDialog, { view: state.view, onClose: () => setShowHelp(false) }) : viewComponent }),
6167
+ /* @__PURE__ */ jsx15(Footer, {})
5807
6168
  ] });
5808
6169
  }
5809
6170
  function App({ onReady }) {
5810
- return /* @__PURE__ */ jsx14(DashboardProvider, { children: /* @__PURE__ */ jsx14(DashboardApp, { onReady }) });
6171
+ return /* @__PURE__ */ jsx15(DashboardProvider, { children: /* @__PURE__ */ jsx15(DashboardApp, { onReady }) });
5811
6172
  }
5812
6173
 
5813
6174
  // src/cli/dashboard/index.ts
@@ -5817,7 +6178,7 @@ var InteractiveDashboard = class {
5817
6178
  getConfigFn = null;
5818
6179
  async start() {
5819
6180
  this.app = render(
5820
- React10.createElement(App, {
6181
+ React11.createElement(App, {
5821
6182
  onReady: (handler, getConfig) => {
5822
6183
  this.updateHandler = handler;
5823
6184
  this.getConfigFn = getConfig;
@@ -5862,4 +6223,4 @@ export {
5862
6223
  handleCheckpointTool,
5863
6224
  InteractiveDashboard
5864
6225
  };
5865
- //# sourceMappingURL=chunk-7BY2KVIN.js.map
6226
+ //# sourceMappingURL=chunk-QIS2VDJL.js.map