@triedotdev/mcp 1.0.104 → 1.0.106

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.
@@ -1,14 +1,17 @@
1
1
  import {
2
2
  getGuardian
3
- } from "./chunk-HFKOGW7H.js";
3
+ } from "./chunk-C5NK7EGK.js";
4
4
  import {
5
+ ContextGraph,
6
+ TieredStorage,
5
7
  findCrossProjectPatterns,
6
- isAIAvailable
7
- } from "./chunk-SPQJC7RA.js";
8
+ getKeyFromKeychain,
9
+ isAIAvailable,
10
+ runAIAnalysis,
11
+ setAPIKey
12
+ } from "./chunk-S2WVHIFG.js";
8
13
  import {
9
- getGuardianState,
10
- getMemoryStats,
11
- getRecentIssues
14
+ getGuardianState
12
15
  } from "./chunk-6JPPYG7F.js";
13
16
  import {
14
17
  getTrieDirectory,
@@ -254,11 +257,11 @@ var StreamingManager = class {
254
257
 
255
258
  // src/cli/dashboard/index.ts
256
259
  import { render } from "ink";
257
- import React7 from "react";
260
+ import React10 from "react";
258
261
 
259
262
  // src/cli/dashboard/App.tsx
260
- import { useState as useState2, useEffect as useEffect2, useCallback as useCallback4, useRef } from "react";
261
- import { Box as Box11, useInput as useInput7, useApp } from "ink";
263
+ import { useState as useState3, useEffect as useEffect4, useCallback as useCallback6, useRef } from "react";
264
+ import { Box as Box12, useInput as useInput8, useApp } from "ink";
262
265
 
263
266
  // src/cli/dashboard/state.tsx
264
267
  import React, { createContext, useContext, useReducer } from "react";
@@ -273,38 +276,36 @@ function getVisibleInsights(state) {
273
276
  }
274
277
  function getMemoryTreeNodes(state) {
275
278
  const nodes = [];
276
- const { expandedNodes, issues, globalPatterns } = state.memoryTree;
277
- nodes.push({ id: "severity", level: 0 });
278
- if (expandedNodes.has("severity")) {
279
- nodes.push({ id: "severity-critical", level: 1 });
280
- if (expandedNodes.has("severity-critical")) {
281
- issues.filter((i) => i.severity === "critical").slice(0, 5).forEach((issue) => {
282
- nodes.push({ id: `severity-critical-${issue.id}`, level: 2 });
283
- });
284
- }
285
- nodes.push({ id: "severity-serious", level: 1 });
286
- nodes.push({ id: "severity-moderate", level: 1 });
287
- nodes.push({ id: "severity-low", level: 1 });
288
- }
279
+ const { expandedNodes, snapshot, globalPatterns } = state.memoryTree;
280
+ if (!snapshot) return nodes;
281
+ const fileNodes = snapshot.nodes.filter((n) => n.type === "file");
282
+ const changeNodes = snapshot.nodes.filter((n) => n.type === "change");
283
+ const patternNodes = snapshot.nodes.filter((n) => n.type === "pattern");
284
+ const incidentNodes = snapshot.nodes.filter((n) => n.type === "incident");
285
+ const decisionNodes = snapshot.nodes.filter((n) => n.type === "decision");
289
286
  nodes.push({ id: "files", level: 0 });
290
287
  if (expandedNodes.has("files")) {
291
- const byFile = /* @__PURE__ */ new Map();
292
- for (const issue of issues) {
293
- byFile.set(issue.file, (byFile.get(issue.file) || 0) + 1);
294
- }
295
- Array.from(byFile.entries()).sort((a, b) => b[1] - a[1]).slice(0, 10).forEach(([file]) => nodes.push({ id: `file-${file}`, level: 1 }));
288
+ fileNodes.slice(0, 15).forEach((n) => nodes.push({ id: `file-${n.id}`, level: 1 }));
296
289
  }
297
- nodes.push({ id: "agents", level: 0 });
298
- if (expandedNodes.has("agents")) {
299
- const byAgent = /* @__PURE__ */ new Map();
300
- for (const issue of issues) {
301
- byAgent.set(issue.agent, (byAgent.get(issue.agent) || 0) + 1);
302
- }
303
- Array.from(byAgent.entries()).sort((a, b) => b[1] - a[1]).forEach(([agent]) => nodes.push({ id: `agent-${agent}`, level: 1 }));
290
+ nodes.push({ id: "changes", level: 0 });
291
+ if (expandedNodes.has("changes")) {
292
+ changeNodes.slice(0, 10).forEach((n) => nodes.push({ id: `change-${n.id}`, level: 1 }));
304
293
  }
305
294
  nodes.push({ id: "patterns", level: 0 });
306
295
  if (expandedNodes.has("patterns")) {
307
- globalPatterns.slice(0, 5).forEach((p) => nodes.push({ id: `pattern-${p.id}`, level: 1 }));
296
+ patternNodes.slice(0, 10).forEach((n) => nodes.push({ id: `pattern-${n.id}`, level: 1 }));
297
+ }
298
+ nodes.push({ id: "incidents", level: 0 });
299
+ if (expandedNodes.has("incidents")) {
300
+ incidentNodes.slice(0, 10).forEach((n) => nodes.push({ id: `incident-${n.id}`, level: 1 }));
301
+ }
302
+ nodes.push({ id: "decisions", level: 0 });
303
+ if (expandedNodes.has("decisions")) {
304
+ decisionNodes.slice(0, 10).forEach((n) => nodes.push({ id: `decision-${n.id}`, level: 1 }));
305
+ }
306
+ nodes.push({ id: "cross-project", level: 0 });
307
+ if (expandedNodes.has("cross-project")) {
308
+ globalPatterns.slice(0, 5).forEach((p) => nodes.push({ id: `global-${p.id}`, level: 1 }));
308
309
  }
309
310
  return nodes;
310
311
  }
@@ -551,18 +552,41 @@ function dashboardReducer(state, action) {
551
552
  case "SET_MEMORY_TREE":
552
553
  return {
553
554
  ...state,
554
- memoryTree: { ...state.memoryTree, loaded: true, issues: action.issues, stats: action.stats, globalPatterns: action.patterns }
555
+ memoryTree: { ...state.memoryTree, loaded: true, snapshot: action.snapshot, globalPatterns: action.patterns }
555
556
  };
556
557
  case "SELECT_MEMORY_NODE":
557
558
  return { ...state, memoryTree: { ...state.memoryTree, selectedNode: action.nodeId } };
558
559
  case "TOGGLE_MEMORY_NODE": {
559
- const expandable = ["severity", "files", "agents", "patterns", "severity-critical", "severity-serious", "severity-moderate", "severity-low"];
560
+ const expandable = ["files", "changes", "patterns", "incidents", "decisions", "cross-project"];
560
561
  if (!expandable.includes(action.nodeId)) return state;
561
562
  const expanded = new Set(state.memoryTree.expandedNodes);
562
563
  if (expanded.has(action.nodeId)) expanded.delete(action.nodeId);
563
564
  else expanded.add(action.nodeId);
564
565
  return { ...state, memoryTree: { ...state.memoryTree, expandedNodes: expanded } };
565
566
  }
567
+ case "SET_AGENT_BRAIN":
568
+ return {
569
+ ...state,
570
+ agentBrain: {
571
+ ...state.agentBrain,
572
+ loaded: true,
573
+ decisions: action.decisions,
574
+ patterns: action.patterns,
575
+ ledgerHash: action.ledgerHash
576
+ }
577
+ };
578
+ case "SET_CHAT_INPUT":
579
+ return { ...state, chatState: { ...state.chatState, inputBuffer: action.buffer } };
580
+ case "ADD_CHAT_MESSAGE":
581
+ return {
582
+ ...state,
583
+ chatState: {
584
+ ...state.chatState,
585
+ messages: [...state.chatState.messages, { role: action.role, content: action.content, timestamp: Date.now() }].slice(-20)
586
+ }
587
+ };
588
+ case "SET_CHAT_LOADING":
589
+ return { ...state, chatState: { ...state.chatState, loading: action.loading } };
566
590
  case "SET_AGENT_CONFIG":
567
591
  return { ...state, agentConfig: applyAgentConfigPatch(state.agentConfig, action.config) };
568
592
  case "NAVIGATE_UP": {
@@ -663,7 +687,7 @@ function createInitialState() {
663
687
  watch: { watching: false, directories: 0, recentChanges: [] },
664
688
  rawLog: [],
665
689
  rawLogPage: 0,
666
- scrollPositions: { overview: 0, rawlog: 0, agent: 0, goals: 0, hypotheses: 0, memory: 0 },
690
+ scrollPositions: { overview: 0, rawlog: 0, agent: 0, goals: 0, hypotheses: 0, memory: 0, chat: 0 },
667
691
  notification: null,
668
692
  notificationHistory: [],
669
693
  agentInsights: [],
@@ -683,7 +707,9 @@ function createInitialState() {
683
707
  },
684
708
  goalsPanel: { goals: [], selectedIndex: 0, selectedAchievedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0 },
685
709
  hypothesesPanel: { hypotheses: [], selectedIndex: 0, selectedCompletedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0 },
686
- memoryTree: { loaded: false, issues: [], stats: null, globalPatterns: [], expandedNodes: /* @__PURE__ */ new Set(["severity", "files"]), selectedNode: "severity", scrollPosition: 0, lastRefresh: 0 }
710
+ memoryTree: { loaded: false, snapshot: null, globalPatterns: [], expandedNodes: /* @__PURE__ */ new Set(["files"]), selectedNode: "files", scrollPosition: 0, lastRefresh: 0 },
711
+ agentBrain: { loaded: false, decisions: [], patterns: [], ledgerHash: null, selectedIndex: 0, expandedIndex: null },
712
+ chatState: { messages: [], inputBuffer: "", loading: false }
687
713
  };
688
714
  }
689
715
  var DashboardContext = createContext(null);
@@ -1254,32 +1280,49 @@ import { readFile, writeFile, mkdir } from "fs/promises";
1254
1280
  import { join } from "path";
1255
1281
 
1256
1282
  // src/cli/dashboard/components/Header.tsx
1283
+ import { useState, useEffect } from "react";
1257
1284
  import { Box, Text } from "ink";
1258
1285
  import { jsx as jsx2, jsxs } from "react/jsx-runtime";
1286
+ var WATCH_FRAMES = ["\u25D0", "\u25D3", "\u25D1", "\u25D2"];
1259
1287
  function Header() {
1260
1288
  const { state } = useDashboard();
1261
- const time = (/* @__PURE__ */ new Date()).toLocaleTimeString("en-US", { hour12: false, hour: "2-digit", minute: "2-digit", second: "2-digit" });
1262
1289
  const { signalExtraction, watch, alerts } = state;
1263
1290
  const totalExtracted = signalExtraction.decisionsExtracted + signalExtraction.factsExtracted + signalExtraction.blockersExtracted + signalExtraction.questionsExtracted;
1291
+ const [frame, setFrame] = useState(0);
1292
+ useEffect(() => {
1293
+ if (!watch.watching) return;
1294
+ const id = setInterval(() => setFrame((f) => (f + 1) % WATCH_FRAMES.length), 150);
1295
+ return () => clearInterval(id);
1296
+ }, [watch.watching]);
1264
1297
  let statusLabel;
1265
1298
  if (watch.watching) {
1299
+ const spinner = WATCH_FRAMES[frame] || "\u25D0";
1266
1300
  statusLabel = totalExtracted > 0 ? /* @__PURE__ */ jsxs(Text, { children: [
1267
- /* @__PURE__ */ jsx2(Text, { color: "green", bold: true, children: "\u25CF LEARNING" }),
1301
+ /* @__PURE__ */ jsx2(Text, { color: "green", children: spinner }),
1302
+ " ",
1303
+ /* @__PURE__ */ jsx2(Text, { color: "green", bold: true, children: "Learning" }),
1268
1304
  " ",
1269
1305
  /* @__PURE__ */ jsxs(Text, { dimColor: true, children: [
1270
1306
  totalExtracted,
1271
1307
  " signals"
1272
1308
  ] })
1273
- ] }) : /* @__PURE__ */ jsx2(Text, { children: /* @__PURE__ */ jsx2(Text, { color: "yellow", bold: true, children: "\u25CF WATCHING" }) });
1309
+ ] }) : /* @__PURE__ */ jsxs(Text, { children: [
1310
+ /* @__PURE__ */ jsx2(Text, { color: "green", children: spinner }),
1311
+ " ",
1312
+ /* @__PURE__ */ jsx2(Text, { bold: true, children: "Watching" })
1313
+ ] });
1274
1314
  } else {
1275
- statusLabel = /* @__PURE__ */ jsx2(Text, { dimColor: true, children: "\u25CB IDLE" });
1315
+ statusLabel = /* @__PURE__ */ jsxs(Text, { children: [
1316
+ /* @__PURE__ */ jsx2(Text, { dimColor: true, children: "\u25CB" }),
1317
+ " ",
1318
+ /* @__PURE__ */ jsx2(Text, { dimColor: true, children: "Idle" })
1319
+ ] });
1276
1320
  }
1277
- return /* @__PURE__ */ jsxs(Box, { borderStyle: "round", borderColor: "gray", paddingX: 1, justifyContent: "space-between", children: [
1278
- /* @__PURE__ */ jsx2(Box, { children: /* @__PURE__ */ jsx2(Text, { color: "green", bold: true, children: "trie" }) }),
1321
+ return /* @__PURE__ */ jsxs(Box, { paddingX: 1, justifyContent: "space-between", children: [
1322
+ /* @__PURE__ */ jsx2(Text, { color: "green", bold: true, children: "trie" }),
1279
1323
  /* @__PURE__ */ jsxs(Box, { gap: 2, children: [
1280
1324
  statusLabel,
1281
- alerts.hasCritical && /* @__PURE__ */ jsx2(Text, { color: "red", bold: true, children: "\u2502 ALERT" }),
1282
- /* @__PURE__ */ jsx2(Text, { dimColor: true, children: time })
1325
+ alerts.hasCritical && /* @__PURE__ */ jsx2(Text, { color: "red", bold: true, children: "\u25CF Alert" })
1283
1326
  ] })
1284
1327
  ] });
1285
1328
  }
@@ -1293,84 +1336,39 @@ var VIEW_LABELS = {
1293
1336
  agent: "Agent",
1294
1337
  goals: "Goals",
1295
1338
  hypotheses: "Hypotheses",
1296
- memory: "Memory"
1339
+ memory: "Memory",
1340
+ chat: "Chat"
1297
1341
  };
1298
- function Hint({ k, label }) {
1299
- return /* @__PURE__ */ jsxs2(Text2, { children: [
1300
- /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: "[" }),
1301
- /* @__PURE__ */ jsx3(Text2, { bold: true, children: k }),
1302
- /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: "]" }),
1303
- /* @__PURE__ */ jsxs2(Text2, { dimColor: true, children: [
1304
- " ",
1305
- label
1306
- ] })
1307
- ] });
1308
- }
1342
+ var TAB_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent", "chat"];
1309
1343
  function Footer() {
1310
1344
  const { state } = useDashboard();
1311
1345
  const { view } = state;
1312
- const viewTabs = ["overview", "memory", "goals", "hypotheses", "agent"].map((v) => {
1313
- const isActive = v === view;
1314
- const label = VIEW_LABELS[v];
1315
- return isActive ? /* @__PURE__ */ jsx3(Text2, { color: "green", bold: true, children: ` ${label} ` }, v) : /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: ` ${label} ` }, v);
1316
- });
1317
- let hints;
1346
+ let contextHints;
1318
1347
  if (view === "goals" && state.goalsPanel.inputMode === "add") {
1319
- hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1320
- /* @__PURE__ */ jsx3(Hint, { k: "Enter", label: "Save" }),
1321
- /* @__PURE__ */ jsx3(Hint, { k: "Esc", label: "Cancel" })
1322
- ] });
1348
+ contextHints = "enter save \xB7 esc cancel";
1323
1349
  } else if (view === "hypotheses" && state.hypothesesPanel.inputMode === "add") {
1324
- hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1325
- /* @__PURE__ */ jsx3(Hint, { k: "Enter", label: "Save" }),
1326
- /* @__PURE__ */ jsx3(Hint, { k: "Esc", label: "Cancel" })
1327
- ] });
1350
+ contextHints = "enter save \xB7 esc cancel";
1328
1351
  } else if (view === "goals") {
1329
- hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1330
- /* @__PURE__ */ jsx3(Hint, { k: "j/k", label: "Nav" }),
1331
- /* @__PURE__ */ jsx3(Hint, { k: "a", label: "Add" }),
1332
- /* @__PURE__ */ jsx3(Hint, { k: "Enter", label: "Complete" }),
1333
- /* @__PURE__ */ jsx3(Hint, { k: "d", label: "Delete" })
1334
- ] });
1352
+ contextHints = "j/k nav \xB7 a add \xB7 enter complete \xB7 d delete";
1335
1353
  } else if (view === "hypotheses") {
1336
- hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1337
- /* @__PURE__ */ jsx3(Hint, { k: "j/k", label: "Nav" }),
1338
- /* @__PURE__ */ jsx3(Hint, { k: "a", label: "Add" }),
1339
- /* @__PURE__ */ jsx3(Hint, { k: "v", label: "Validate" }),
1340
- /* @__PURE__ */ jsx3(Hint, { k: "x", label: "Invalidate" })
1341
- ] });
1354
+ contextHints = "j/k nav \xB7 a add \xB7 v validate \xB7 x invalidate";
1342
1355
  } else if (view === "agent") {
1343
- hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1344
- /* @__PURE__ */ jsx3(Hint, { k: "j/k", label: "Nav" }),
1345
- /* @__PURE__ */ jsx3(Hint, { k: "Enter", label: "Expand" }),
1346
- /* @__PURE__ */ jsx3(Hint, { k: "d", label: "Dismiss" }),
1347
- /* @__PURE__ */ jsx3(Hint, { k: "i", label: "Ignore" }),
1348
- /* @__PURE__ */ jsx3(Hint, { k: "x", label: "Clear" })
1349
- ] });
1356
+ contextHints = "j/k nav \xB7 enter expand \xB7 d dismiss";
1350
1357
  } else if (view === "memory") {
1351
- hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1352
- /* @__PURE__ */ jsx3(Hint, { k: "j/k", label: "Nav" }),
1353
- /* @__PURE__ */ jsx3(Hint, { k: "Enter", label: "Expand" }),
1354
- /* @__PURE__ */ jsx3(Hint, { k: "b", label: "Back" })
1355
- ] });
1358
+ contextHints = "j/k nav \xB7 enter expand";
1359
+ } else if (view === "chat") {
1360
+ contextHints = "type to ask \xB7 enter send \xB7 esc clear";
1356
1361
  } else if (view === "rawlog") {
1357
- hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1358
- /* @__PURE__ */ jsx3(Hint, { k: "n/p", label: "Pages" }),
1359
- /* @__PURE__ */ jsx3(Hint, { k: "b", label: "Back" })
1360
- ] });
1362
+ contextHints = "n/p pages \xB7 b back";
1361
1363
  } else {
1362
- hints = /* @__PURE__ */ jsxs2(Box2, { gap: 2, children: [
1363
- /* @__PURE__ */ jsx3(Hint, { k: "Tab", label: "Views" }),
1364
- /* @__PURE__ */ jsx3(Hint, { k: "n/p", label: "Pages" }),
1365
- /* @__PURE__ */ jsx3(Hint, { k: "h", label: "Help" })
1366
- ] });
1364
+ contextHints = "n/p pages \xB7 c config";
1367
1365
  }
1368
- return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", children: [
1369
- /* @__PURE__ */ jsx3(Box2, { borderStyle: "single", borderColor: "gray", borderTop: false, borderLeft: false, borderRight: false, children: /* @__PURE__ */ jsx3(Box2, { gap: 0, children: viewTabs }) }),
1370
- /* @__PURE__ */ jsxs2(Box2, { paddingX: 1, justifyContent: "space-between", children: [
1371
- hints,
1372
- /* @__PURE__ */ jsx3(Hint, { k: "q", label: "Quit" })
1373
- ] })
1366
+ return /* @__PURE__ */ jsxs2(Box2, { flexDirection: "column", paddingX: 1, children: [
1367
+ /* @__PURE__ */ jsxs2(Box2, { justifyContent: "space-between", children: [
1368
+ /* @__PURE__ */ jsx3(Box2, { gap: 1, children: TAB_VIEWS.map((v) => v === view ? /* @__PURE__ */ jsx3(Text2, { color: "green", bold: true, children: VIEW_LABELS[v] }, v) : /* @__PURE__ */ jsx3(Text2, { children: VIEW_LABELS[v] }, v)) }),
1369
+ /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: "q quit" })
1370
+ ] }),
1371
+ /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: contextHints })
1374
1372
  ] });
1375
1373
  }
1376
1374
 
@@ -1395,21 +1393,31 @@ function Notification() {
1395
1393
  }
1396
1394
 
1397
1395
  // src/cli/dashboard/components/ConfigDialog.tsx
1398
- import { useState } from "react";
1396
+ import { useState as useState2 } from "react";
1399
1397
  import { Box as Box4, Text as Text4, useInput } from "ink";
1400
- import { jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1398
+ import { Fragment, jsx as jsx5, jsxs as jsxs4 } from "react/jsx-runtime";
1399
+ function maskKey(key) {
1400
+ if (!key || key.length < 12) return "Not set";
1401
+ return key.slice(0, 7) + "..." + key.slice(-4);
1402
+ }
1401
1403
  function ConfigDialog({ onClose }) {
1402
1404
  const { state, dispatch } = useDashboard();
1403
- const [section, setSection] = useState("main");
1404
- const [selectedIndex, setSelectedIndex] = useState(0);
1405
- const [editing, setEditing] = useState(false);
1406
- const [editBuffer, setEditBuffer] = useState("");
1405
+ const [section, setSection] = useState2("main");
1406
+ const [selectedIndex, setSelectedIndex] = useState2(0);
1407
+ const [editing, setEditing] = useState2(false);
1408
+ const [editBuffer, setEditBuffer] = useState2("");
1409
+ const [editIsText, setEditIsText] = useState2(false);
1407
1410
  const config = state.agentConfig;
1411
+ const currentKeyDisplay = isAIAvailable() ? maskKey(getKeyFromKeychain() || process.env.ANTHROPIC_API_KEY || null) : "Not set";
1412
+ const keyActive = isAIAvailable();
1408
1413
  const mainMenu = [
1409
- { label: "Agent Smith Settings", key: "agentSmith", value: config.agentSmith.aiEnhancement ? "AI Enhanced" : "Basic", section: "main" },
1414
+ { label: "API Keys", key: "apiKeys", value: keyActive ? "Active" : "Not set", section: "main" },
1410
1415
  { label: "Performance Settings", key: "performance", value: `${config.performance.maxConcurrency} concurrent`, section: "main" },
1411
1416
  { label: "Risk Thresholds", key: "riskThresholds", value: `critical: ${config.riskThresholds.critical}%`, section: "main" }
1412
1417
  ];
1418
+ const apiKeysItems = [
1419
+ { label: "Anthropic", key: "anthropic", value: currentKeyDisplay, section: "apiKeys" }
1420
+ ];
1413
1421
  const performanceItems = [
1414
1422
  { label: "Max Concurrency", key: "maxConcurrency", value: String(config.performance.maxConcurrency), section: "performance" },
1415
1423
  { label: "Timeout (ms)", key: "timeoutMs", value: String(config.performance.timeoutMs), section: "performance" },
@@ -1422,37 +1430,50 @@ function ConfigDialog({ onClose }) {
1422
1430
  { label: "High Threshold", key: "high", value: String(config.riskThresholds.high), section: "riskThresholds" },
1423
1431
  { label: "Medium Threshold", key: "medium", value: String(config.riskThresholds.medium), section: "riskThresholds" }
1424
1432
  ];
1425
- const items = section === "main" ? mainMenu : section === "performance" ? performanceItems : section === "riskThresholds" ? riskItems : mainMenu;
1433
+ const items = section === "main" ? mainMenu : section === "apiKeys" ? apiKeysItems : section === "performance" ? performanceItems : section === "riskThresholds" ? riskItems : mainMenu;
1426
1434
  useInput((_input, key) => {
1427
1435
  if (editing) {
1428
1436
  if (key.escape) {
1429
1437
  setEditing(false);
1430
1438
  setEditBuffer("");
1439
+ setEditIsText(false);
1431
1440
  } else if (key.return) {
1432
1441
  const item = items[selectedIndex];
1433
1442
  if (item) {
1434
- const val = parseInt(editBuffer, 10);
1435
- if (!isNaN(val)) {
1436
- const patch = {};
1437
- if (section === "performance") {
1438
- if (item.key === "maxConcurrency" || item.key === "timeoutMs") {
1439
- patch.performance = { ...config.performance, [item.key]: val };
1440
- }
1441
- } else if (section === "riskThresholds") {
1442
- patch.riskThresholds = { ...config.riskThresholds, [item.key]: val };
1443
+ if (editIsText) {
1444
+ if (item.key === "anthropic" && editBuffer.length > 10) {
1445
+ setAPIKey(editBuffer);
1446
+ dispatch({ type: "ADD_ACTIVITY", message: "API key saved" });
1443
1447
  }
1444
- if (Object.keys(patch).length > 0) {
1445
- dispatch({ type: "SET_AGENT_CONFIG", config: patch });
1446
- dispatch({ type: "ADD_ACTIVITY", message: `Config: ${item.label} set to ${val}` });
1448
+ } else {
1449
+ const val = parseInt(editBuffer, 10);
1450
+ if (!isNaN(val)) {
1451
+ const patch = {};
1452
+ if (section === "performance") {
1453
+ if (item.key === "maxConcurrency" || item.key === "timeoutMs") {
1454
+ patch.performance = { ...config.performance, [item.key]: val };
1455
+ }
1456
+ } else if (section === "riskThresholds") {
1457
+ patch.riskThresholds = { ...config.riskThresholds, [item.key]: val };
1458
+ }
1459
+ if (Object.keys(patch).length > 0) {
1460
+ dispatch({ type: "SET_AGENT_CONFIG", config: patch });
1461
+ dispatch({ type: "ADD_ACTIVITY", message: `Config: ${item.label} set to ${val}` });
1462
+ }
1447
1463
  }
1448
1464
  }
1449
1465
  }
1450
1466
  setEditing(false);
1451
1467
  setEditBuffer("");
1468
+ setEditIsText(false);
1452
1469
  } else if (key.backspace || key.delete) {
1453
1470
  setEditBuffer(editBuffer.slice(0, -1));
1454
- } else if (_input && /\d/.test(_input)) {
1455
- setEditBuffer(editBuffer + _input);
1471
+ } else if (_input) {
1472
+ if (editIsText) {
1473
+ setEditBuffer(editBuffer + _input);
1474
+ } else if (/\d/.test(_input)) {
1475
+ setEditBuffer(editBuffer + _input);
1476
+ }
1456
1477
  }
1457
1478
  return;
1458
1479
  }
@@ -1473,6 +1494,10 @@ function ConfigDialog({ onClose }) {
1473
1494
  setSection(item.key);
1474
1495
  setSelectedIndex(0);
1475
1496
  }
1497
+ } else if (section === "apiKeys") {
1498
+ setEditing(true);
1499
+ setEditBuffer("");
1500
+ setEditIsText(true);
1476
1501
  } else {
1477
1502
  const item = items[selectedIndex];
1478
1503
  if (item) {
@@ -1489,32 +1514,60 @@ function ConfigDialog({ onClose }) {
1489
1514
  }
1490
1515
  }
1491
1516
  });
1492
- const sectionTitle = section === "main" ? "TRIE AGENT CONFIGURATION" : section === "performance" ? "PERFORMANCE SETTINGS" : section === "riskThresholds" ? "RISK THRESHOLDS" : section === "agentSmith" ? "AGENT SMITH SETTINGS" : "CONFIGURATION";
1517
+ const sectionTitle = section === "main" ? "TRIE CONFIGURATION" : section === "apiKeys" ? "API KEYS" : section === "performance" ? "PERFORMANCE SETTINGS" : section === "riskThresholds" ? "RISK THRESHOLDS" : "CONFIGURATION";
1493
1518
  return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", borderStyle: "round", borderColor: "gray", paddingX: 1, paddingY: 0, children: [
1494
1519
  /* @__PURE__ */ jsx5(Text4, { bold: true, children: sectionTitle }),
1495
1520
  /* @__PURE__ */ jsx5(Text4, { children: " " }),
1496
- items.map((item, idx) => {
1521
+ section === "apiKeys" && !editing && /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
1522
+ /* @__PURE__ */ jsxs4(Text4, { children: [
1523
+ " ",
1524
+ /* @__PURE__ */ jsx5(Text4, { bold: true, children: "Anthropic:" }),
1525
+ " ",
1526
+ /* @__PURE__ */ jsx5(Text4, { children: currentKeyDisplay }),
1527
+ " ",
1528
+ keyActive ? /* @__PURE__ */ jsx5(Text4, { color: "green", children: "\u25CF Active" }) : /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: "\u25CB Not set" })
1529
+ ] }),
1530
+ /* @__PURE__ */ jsx5(Text4, { children: " " }),
1531
+ /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: " enter to update esc back" })
1532
+ ] }),
1533
+ section === "apiKeys" && editing && /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
1534
+ /* @__PURE__ */ jsx5(Box4, { borderStyle: "round", borderColor: "green", paddingX: 1, children: /* @__PURE__ */ jsxs4(Text4, { children: [
1535
+ editBuffer || /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: "sk-ant-..." }),
1536
+ /* @__PURE__ */ jsx5(Text4, { bold: true, color: "green", children: "|" })
1537
+ ] }) }),
1538
+ /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
1539
+ " enter save (",
1540
+ process.platform === "darwin" ? "keychain" : "config",
1541
+ ") esc cancel"
1542
+ ] })
1543
+ ] }),
1544
+ section !== "apiKeys" && items.map((item, idx) => {
1497
1545
  const isSelected = selectedIndex === idx;
1498
1546
  return /* @__PURE__ */ jsxs4(Text4, { children: [
1499
- isSelected ? /* @__PURE__ */ jsx5(Text4, { bold: true, color: "green", children: "\u25B6 " }) : /* @__PURE__ */ jsx5(Text4, { children: " " }),
1547
+ isSelected ? /* @__PURE__ */ jsxs4(Text4, { bold: true, color: "green", children: [
1548
+ ">",
1549
+ " "
1550
+ ] }) : /* @__PURE__ */ jsx5(Text4, { children: " " }),
1500
1551
  /* @__PURE__ */ jsxs4(Text4, { bold: isSelected, children: [
1501
1552
  item.label,
1502
1553
  ": "
1503
1554
  ] }),
1504
1555
  editing && isSelected ? /* @__PURE__ */ jsxs4(Text4, { children: [
1505
1556
  editBuffer,
1506
- /* @__PURE__ */ jsx5(Text4, { bold: true, color: "green", children: "\u258C" })
1557
+ /* @__PURE__ */ jsx5(Text4, { bold: true, color: "green", children: "|" })
1507
1558
  ] }) : /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: item.value })
1508
1559
  ] }, item.key);
1509
1560
  }),
1510
- /* @__PURE__ */ jsx5(Text4, { children: " " }),
1511
- /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: section === "main" ? "Enter to select \u2022 Esc to close" : "Enter to edit \u2022 Esc/b to go back" })
1561
+ section !== "apiKeys" && /* @__PURE__ */ jsxs4(Fragment, { children: [
1562
+ /* @__PURE__ */ jsx5(Text4, { children: " " }),
1563
+ /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: section === "main" ? "enter select \xB7 esc close" : "enter edit \xB7 esc/b back" })
1564
+ ] })
1512
1565
  ] });
1513
1566
  }
1514
1567
 
1515
1568
  // src/cli/dashboard/views/OverviewView.tsx
1516
1569
  import { Box as Box5, Text as Text5 } from "ink";
1517
- import { Fragment, jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1570
+ import { jsx as jsx6, jsxs as jsxs5 } from "react/jsx-runtime";
1518
1571
  function OverviewView() {
1519
1572
  const { state } = useDashboard();
1520
1573
  const { progress, signalExtraction, watch, issues, activityLog, activityPage } = state;
@@ -1527,92 +1580,75 @@ function OverviewView() {
1527
1580
  const pageActivities = activityLog.slice(startIdx, startIdx + activityRows);
1528
1581
  return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", paddingX: 1, children: [
1529
1582
  /* @__PURE__ */ jsxs5(Text5, { children: [
1583
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "\u25CF" }),
1584
+ " Scanned ",
1530
1585
  /* @__PURE__ */ jsx6(Text5, { bold: true, children: processedFiles }),
1586
+ " files ",
1531
1587
  /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
1532
- " files scanned in ",
1533
1588
  elapsed,
1534
1589
  "s"
1535
1590
  ] })
1536
1591
  ] }),
1537
- watch.watching && signalExtraction.enabled && /* @__PURE__ */ jsxs5(Fragment, { children: [
1538
- /* @__PURE__ */ jsx6(Text5, { children: " " }),
1539
- /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1540
- /* @__PURE__ */ jsx6(Text5, { bold: true, children: "Decision Ledger" }),
1541
- /* @__PURE__ */ jsxs5(Text5, { children: [
1542
- /* @__PURE__ */ jsx6(Text5, { bold: true, children: "Agent Learning" }),
1543
- /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " - Building institutional knowledge" })
1544
- ] }),
1545
- /* @__PURE__ */ jsx6(Text5, { children: " " }),
1546
- /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "Signals Extracted:" }),
1547
- /* @__PURE__ */ jsxs5(Text5, { children: [
1548
- " ",
1549
- /* @__PURE__ */ jsx6(Text5, { bold: true, children: signalExtraction.decisionsExtracted }),
1550
- /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " decisions" })
1551
- ] }),
1552
- /* @__PURE__ */ jsxs5(Text5, { children: [
1553
- " ",
1554
- /* @__PURE__ */ jsx6(Text5, { bold: true, children: signalExtraction.factsExtracted }),
1555
- /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " facts" })
1556
- ] }),
1557
- /* @__PURE__ */ jsxs5(Text5, { children: [
1558
- " ",
1559
- /* @__PURE__ */ jsx6(Text5, { bold: true, children: signalExtraction.blockersExtracted }),
1560
- /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " blockers" })
1561
- ] }),
1562
- /* @__PURE__ */ jsxs5(Text5, { children: [
1563
- " ",
1564
- /* @__PURE__ */ jsx6(Text5, { bold: true, children: signalExtraction.questionsExtracted }),
1565
- /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " questions" })
1566
- ] }),
1567
- /* @__PURE__ */ jsx6(Text5, { children: " " }),
1568
- /* @__PURE__ */ jsxs5(Text5, { children: [
1569
- /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "Use " }),
1570
- /* @__PURE__ */ jsx6(Text5, { bold: true, children: "trie gotcha" }),
1571
- /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " to query the ledger" })
1572
- ] })
1592
+ watch.watching && signalExtraction.enabled && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1593
+ /* @__PURE__ */ jsxs5(Text5, { children: [
1594
+ /* @__PURE__ */ jsx6(Text5, { color: "green", children: "\u25CF" }),
1595
+ " Signal extraction ",
1596
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "enabled" })
1597
+ ] }),
1598
+ (signalExtraction.decisionsExtracted > 0 || signalExtraction.factsExtracted > 0 || signalExtraction.blockersExtracted > 0) && /* @__PURE__ */ jsxs5(Text5, { children: [
1599
+ " ",
1600
+ /* @__PURE__ */ jsx6(Text5, { color: "green", children: "\u25CB" }),
1601
+ " ",
1602
+ /* @__PURE__ */ jsx6(Text5, { bold: true, children: signalExtraction.decisionsExtracted }),
1603
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " decisions" }),
1604
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " \xB7 " }),
1605
+ /* @__PURE__ */ jsx6(Text5, { bold: true, children: signalExtraction.factsExtracted }),
1606
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " facts" }),
1607
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " \xB7 " }),
1608
+ /* @__PURE__ */ jsx6(Text5, { bold: true, children: signalExtraction.blockersExtracted }),
1609
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " blockers" })
1573
1610
  ] })
1574
1611
  ] }),
1575
- criticalIssues.length > 0 && /* @__PURE__ */ jsxs5(Fragment, { children: [
1612
+ criticalIssues.length > 0 && /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1576
1613
  /* @__PURE__ */ jsx6(Text5, { children: " " }),
1577
- /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1578
- /* @__PURE__ */ jsx6(Text5, { color: "red", bold: true, children: "TOP CRITICAL ISSUES" }),
1579
- criticalIssues.map((issue, i) => {
1580
- const filename = issue.file.split("/").pop() || issue.file;
1581
- const lineNum = issue.line ? `:${issue.line}` : "";
1582
- const desc = issue.issue.slice(0, 50) + (issue.issue.length > 50 ? "..." : "");
1583
- return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1584
- /* @__PURE__ */ jsxs5(Text5, { children: [
1585
- /* @__PURE__ */ jsx6(Text5, { color: "red", children: "\u25B8" }),
1586
- " ",
1587
- /* @__PURE__ */ jsx6(Text5, { color: "red", children: desc })
1588
- ] }),
1589
- /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
1590
- " ",
1591
- filename,
1592
- lineNum
1593
- ] })
1594
- ] }, i);
1595
- })
1596
- ] })
1614
+ criticalIssues.map((issue, i) => {
1615
+ const filename = issue.file.split("/").pop() || issue.file;
1616
+ const lineNum = issue.line ? `:${issue.line}` : "";
1617
+ const desc = issue.issue.slice(0, 50) + (issue.issue.length > 50 ? "..." : "");
1618
+ return /* @__PURE__ */ jsxs5(Text5, { children: [
1619
+ /* @__PURE__ */ jsx6(Text5, { color: "red", children: "\u25CF" }),
1620
+ " ",
1621
+ /* @__PURE__ */ jsx6(Text5, { color: "red", children: desc }),
1622
+ /* @__PURE__ */ jsxs5(Text5, { dimColor: true, children: [
1623
+ " ",
1624
+ filename,
1625
+ lineNum
1626
+ ] })
1627
+ ] }, i);
1628
+ })
1597
1629
  ] }),
1598
- totalIssues === 0 && criticalIssues.length === 0 && /* @__PURE__ */ jsxs5(Fragment, { children: [
1599
- /* @__PURE__ */ jsx6(Text5, { children: " " }),
1600
- /* @__PURE__ */ jsx6(Text5, { color: "green", children: "[ok] No issues found" })
1630
+ totalIssues === 0 && criticalIssues.length === 0 && /* @__PURE__ */ jsxs5(Text5, { children: [
1631
+ /* @__PURE__ */ jsx6(Text5, { color: "green", children: "\u25CF" }),
1632
+ " No issues found"
1601
1633
  ] }),
1602
1634
  /* @__PURE__ */ jsx6(Text5, { children: " " }),
1603
1635
  /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
1604
1636
  /* @__PURE__ */ jsx6(Text5, { bold: true, children: "Activity" }),
1605
1637
  pageActivities.map((entry, i) => /* @__PURE__ */ jsxs5(Text5, { children: [
1606
- /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: entry.time }),
1607
1638
  " ",
1608
- entry.message
1639
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "\u25CF" }),
1640
+ " ",
1641
+ entry.message,
1642
+ " ",
1643
+ /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: entry.time })
1609
1644
  ] }, i)),
1610
- pageActivities.length === 0 && /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: "No activity yet." })
1645
+ pageActivities.length === 0 && /* @__PURE__ */ jsx6(Text5, { dimColor: true, children: " No activity yet." })
1611
1646
  ] })
1612
1647
  ] });
1613
1648
  }
1614
1649
 
1615
1650
  // src/cli/dashboard/views/AgentView.tsx
1651
+ import { useEffect as useEffect2, useCallback } from "react";
1616
1652
  import { Box as Box6, Text as Text6, useInput as useInput2 } from "ink";
1617
1653
 
1618
1654
  // src/cli/dashboard/theme.ts
@@ -1643,41 +1679,50 @@ function formatTimeAgo(timestamp) {
1643
1679
  const hours = Math.floor(minutes / 60);
1644
1680
  return `${hours}h ago`;
1645
1681
  }
1646
- function insightIcon(type) {
1647
- switch (type) {
1648
- case "warning":
1649
- return { icon: "[!]", color: colors.critical };
1650
- case "observation":
1651
- return { icon: "[>]", color: colors.serious };
1652
- case "suggestion":
1653
- return { icon: "[?]", color: colors.highlight };
1654
- case "celebration":
1655
- return { icon: "[+]", color: colors.success };
1656
- case "question":
1657
- return { icon: "[?]", color: colors.moderate };
1658
- default:
1659
- return { icon: "[>]", color: colors.dim };
1660
- }
1661
- }
1662
1682
  function progressBar(current, total, width = 10) {
1663
- if (total <= 0) return colors.dim("[" + "\u2591".repeat(width) + "]");
1683
+ if (total <= 0) return colors.dim("\u2591".repeat(width));
1664
1684
  const progress = Math.min(1, current / total);
1665
1685
  const filled = Math.round(width * progress);
1666
1686
  const empty = width - filled;
1667
- return colors.dim("[") + colors.success("\u2588".repeat(filled)) + colors.dim("\u2591".repeat(empty)) + colors.dim("]");
1668
- }
1669
- function stripEmojis(s) {
1670
- return s.replace(/[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}\u{FE00}-\u{FE0F}\u{200D}\u{20E3}\u{FE0F}\u{E0020}-\u{E007F}]/gu, "").trim();
1687
+ return colors.success("\u2588".repeat(filled)) + colors.dim("\u2591".repeat(empty));
1671
1688
  }
1672
1689
 
1673
1690
  // src/cli/dashboard/views/AgentView.tsx
1674
1691
  import { jsx as jsx7, jsxs as jsxs6 } from "react/jsx-runtime";
1692
+ function timeAgo(iso) {
1693
+ const ms = Date.now() - new Date(iso).getTime();
1694
+ const mins = Math.floor(ms / 6e4);
1695
+ if (mins < 60) return `${mins}m ago`;
1696
+ const hrs = Math.floor(mins / 60);
1697
+ if (hrs < 24) return `${hrs}h ago`;
1698
+ return `${Math.floor(hrs / 24)}d ago`;
1699
+ }
1675
1700
  function AgentView() {
1676
1701
  const { state, dispatch } = useDashboard();
1677
- const { agentInsights, agencyStatus, selectedInsight, expandedInsight } = state;
1678
- const totalInsights = agentInsights.length;
1702
+ const { agentInsights, agentBrain, selectedInsight, expandedInsight } = state;
1679
1703
  const visibleInsights = getVisibleInsights(state);
1680
- const activeCount = visibleInsights.length;
1704
+ const alerts = visibleInsights.filter((i) => i.type === "warning");
1705
+ const { decisions, patterns, loaded } = agentBrain;
1706
+ const loadBrain = useCallback(async () => {
1707
+ try {
1708
+ const workDir = getWorkingDirectory(void 0, true);
1709
+ const storage = new TieredStorage(workDir);
1710
+ const graph = new ContextGraph(workDir);
1711
+ const [decs, snap] = await Promise.all([
1712
+ storage.queryDecisions({ limit: 20 }),
1713
+ graph.getSnapshot()
1714
+ ]);
1715
+ const patternData = snap.nodes.filter((n) => n.type === "pattern").map((n) => n.data);
1716
+ dispatch({ type: "SET_AGENT_BRAIN", decisions: decs, patterns: patternData, ledgerHash: null });
1717
+ } catch {
1718
+ dispatch({ type: "ADD_ACTIVITY", message: "Agent brain load error" });
1719
+ }
1720
+ }, [dispatch]);
1721
+ useEffect2(() => {
1722
+ if (!loaded) {
1723
+ void loadBrain();
1724
+ }
1725
+ }, [loaded, loadBrain]);
1681
1726
  useInput2((input, key) => {
1682
1727
  if (key.upArrow || input === "k") {
1683
1728
  dispatch({ type: "NAVIGATE_UP" });
@@ -1687,186 +1732,190 @@ function AgentView() {
1687
1732
  dispatch({ type: "TOGGLE_INSIGHT", index: selectedInsight });
1688
1733
  } else if (input === "d") {
1689
1734
  dispatch({ type: "DISMISS_INSIGHT", index: selectedInsight });
1690
- } else if (input === "i") {
1691
- dispatch({ type: "IGNORE_INSIGHT", index: selectedInsight });
1692
- } else if (input === "x") {
1693
- dispatch({ type: "CLEAR_DISMISSED_INSIGHTS" });
1694
1735
  }
1695
1736
  });
1696
- const agency = agencyStatus;
1697
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
1698
- /* @__PURE__ */ jsxs6(Text6, { children: [
1699
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: "Agent Insights" }),
1700
- activeCount > 0 ? /* @__PURE__ */ jsxs6(Text6, { color: "red", bold: true, children: [
1701
- " (",
1702
- activeCount,
1703
- " active)"
1704
- ] }) : /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1705
- " (",
1706
- totalInsights,
1707
- " total)"
1708
- ] }),
1737
+ const alertCount = alerts.length;
1738
+ const decCount = decisions.length;
1739
+ const patCount = patterns.length;
1740
+ if (alertCount === 0 && decCount === 0 && patCount === 0 && !loaded) {
1741
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
1742
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: "Trie" }),
1743
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " Loading..." })
1744
+ ] });
1745
+ }
1746
+ if (alertCount === 0 && decCount === 0 && patCount === 0) {
1747
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
1748
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: "Trie" }),
1709
1749
  " ",
1710
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Your autonomous code companion" })
1711
- ] }),
1712
- agency && /* @__PURE__ */ jsxs6(Box6, { gap: 2, children: [
1750
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Proactive code guardian" }),
1751
+ /* @__PURE__ */ jsx7(Text6, { children: " " }),
1713
1752
  /* @__PURE__ */ jsxs6(Text6, { children: [
1714
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Goals:" }),
1715
- " ",
1716
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: agency.goals.active }),
1717
- "/",
1718
- agency.goals.completed + agency.goals.active
1753
+ " ",
1754
+ /* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
1755
+ " Alerts you about gotchas before you push"
1719
1756
  ] }),
1720
1757
  /* @__PURE__ */ jsxs6(Text6, { children: [
1721
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Hypo:" }),
1722
- " ",
1723
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: agency.hypotheses.testing }),
1724
- " testing"
1758
+ " ",
1759
+ /* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
1760
+ " Records decisions with traceable hashes"
1725
1761
  ] }),
1726
1762
  /* @__PURE__ */ jsxs6(Text6, { children: [
1727
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Risk:" }),
1728
- " ",
1729
- /* @__PURE__ */ jsx7(Text6, { color: agency.riskLevel === "critical" ? "red" : agency.riskLevel === "high" ? "yellow" : agency.riskLevel === "medium" ? "yellow" : "green", children: agency.riskLevel.toUpperCase() })
1763
+ " ",
1764
+ /* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
1765
+ " Learns patterns from your feedback (trie ok / trie bad)"
1730
1766
  ] }),
1731
1767
  /* @__PURE__ */ jsxs6(Text6, { children: [
1732
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Effect:" }),
1733
- " ",
1734
- /* @__PURE__ */ jsxs6(Text6, { color: agency.effectiveness >= 80 ? "green" : agency.effectiveness >= 50 ? "yellow" : "yellow", children: [
1735
- agency.effectiveness,
1736
- "%"
1737
- ] })
1768
+ " ",
1769
+ /* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
1770
+ " Gets smarter over time"
1738
1771
  ] }),
1739
- agency.isQuietHours && /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "[quiet]" })
1740
- ] }),
1741
- /* @__PURE__ */ jsx7(Text6, { children: " " }),
1742
- visibleInsights.length === 0 && state.notificationHistory.length === 0 ? /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1743
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: "The Trie Agent is watching over your code." }),
1744
- /* @__PURE__ */ jsx7(Text6, { children: " " }),
1745
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Unlike a log viewer, the Trie Agent:" }),
1746
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " \u2022 Synthesizes insights from all skills" }),
1747
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " \u2022 Speaks conversationally about what matters" }),
1748
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " \u2022 Suggests specific actions to take" }),
1749
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " \u2022 Celebrates when you fix issues" }),
1750
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " \u2022 Tracks patterns over time" }),
1751
1772
  /* @__PURE__ */ jsx7(Text6, { children: " " }),
1752
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "When the Trie Agent has something to say, it'll appear here." }),
1773
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " Start watching to get proactive alerts," }),
1774
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " or run trie tell / trie ok / trie bad to teach it." }),
1753
1775
  /* @__PURE__ */ jsx7(Text6, { children: " " }),
1754
1776
  isAIAvailable() ? /* @__PURE__ */ jsxs6(Text6, { children: [
1755
- /* @__PURE__ */ jsx7(Text6, { color: "green", children: "[+]" }),
1756
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " AI-enhanced insights enabled" })
1777
+ /* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
1778
+ " ",
1779
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "AI-enhanced analysis enabled" })
1757
1780
  ] }) : /* @__PURE__ */ jsxs6(Text6, { children: [
1758
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "Want smarter insights? Set " }),
1781
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u25CB" }),
1782
+ " Set ",
1759
1783
  /* @__PURE__ */ jsx7(Text6, { bold: true, children: "ANTHROPIC_API_KEY" }),
1760
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " for AI enhancement" })
1784
+ " ",
1785
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "for AI insights" })
1761
1786
  ] })
1762
- ] }) : /* @__PURE__ */ jsx7(Box6, { flexDirection: "column", children: visibleInsights.map((insight, idx) => {
1763
- const isSelected = idx === selectedInsight;
1764
- const isExpanded = idx === expandedInsight;
1765
- const ago = formatTimeAgo(insight.timestamp);
1766
- const { icon, color } = insightIcon(insight.type);
1767
- const cleanMessage = stripEmojis(insight.message);
1768
- const msgMaxLen = 70;
1769
- const msg = cleanMessage.length > msgMaxLen ? cleanMessage.slice(0, msgMaxLen - 3) + "..." : cleanMessage;
1770
- const status = isExpanded ? "v" : ">";
1771
- return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginBottom: 1, children: [
1772
- /* @__PURE__ */ jsxs6(Text6, { children: [
1773
- isSelected ? /* @__PURE__ */ jsx7(Text6, { bold: true, color: "green", children: "\u25B6 " }) : /* @__PURE__ */ jsx7(Text6, { children: " " }),
1774
- /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1775
- status,
1776
- " "
1777
- ] }),
1778
- isSelected ? /* @__PURE__ */ jsx7(Text6, { inverse: true, children: ` ${icon} ${msg} ` }) : /* @__PURE__ */ jsxs6(Text6, { children: [
1779
- icon,
1787
+ ] });
1788
+ }
1789
+ const confidentPatterns = patterns.filter((p) => p.confidence > 0.7).length;
1790
+ const learningPatterns = patterns.filter((p) => p.confidence <= 0.7).length;
1791
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
1792
+ /* @__PURE__ */ jsxs6(Text6, { children: [
1793
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: "Trie" }),
1794
+ " ",
1795
+ /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1796
+ alertCount,
1797
+ " alert",
1798
+ alertCount !== 1 ? "s" : "",
1799
+ " ",
1800
+ decCount,
1801
+ " decision",
1802
+ decCount !== 1 ? "s" : "",
1803
+ " ",
1804
+ patCount,
1805
+ " pattern",
1806
+ patCount !== 1 ? "s" : ""
1807
+ ] })
1808
+ ] }),
1809
+ /* @__PURE__ */ jsx7(Text6, { children: " " }),
1810
+ alertCount > 0 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1811
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: " Alerts" }),
1812
+ alerts.map((insight, idx) => {
1813
+ const isSelected = idx === selectedInsight;
1814
+ const isExpanded = idx === expandedInsight;
1815
+ const ago = formatTimeAgo(insight.timestamp);
1816
+ const msg = insight.message.slice(0, 60) + (insight.message.length > 60 ? "..." : "");
1817
+ const riskColor2 = insight.priority >= 8 ? "red" : insight.priority >= 5 ? "yellow" : void 0;
1818
+ return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1819
+ /* @__PURE__ */ jsxs6(Text6, { children: [
1820
+ isSelected ? /* @__PURE__ */ jsxs6(Text6, { bold: true, color: "green", children: [
1821
+ ">",
1822
+ " "
1823
+ ] }) : /* @__PURE__ */ jsx7(Text6, { children: " " }),
1824
+ riskColor2 ? /* @__PURE__ */ jsx7(Text6, { color: riskColor2, children: "\u25CF" }) : /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u25CB" }),
1780
1825
  " ",
1781
- color(msg)
1782
- ] })
1783
- ] }),
1784
- /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1785
- " ",
1786
- ago,
1787
- " \u2022 ",
1788
- insight.category,
1789
- isSelected && !isExpanded ? " \u2022 Press Enter to expand" : ""
1790
- ] }),
1791
- isExpanded && insight.details && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginLeft: 7, children: [
1792
- insight.details.issueBreakdown && Object.keys(insight.details.issueBreakdown).length > 0 && /* @__PURE__ */ jsxs6(Text6, { children: [
1793
- insight.details.issueBreakdown["critical"] ? /* @__PURE__ */ jsxs6(Text6, { color: "red", children: [
1794
- insight.details.issueBreakdown["critical"],
1795
- " critical"
1796
- ] }) : null,
1797
- insight.details.issueBreakdown["serious"] ? /* @__PURE__ */ jsxs6(Text6, { color: "yellow", children: [
1798
- " \u2022 ",
1799
- insight.details.issueBreakdown["serious"],
1800
- " serious"
1801
- ] }) : null,
1802
- insight.details.issueBreakdown["moderate"] ? /* @__PURE__ */ jsxs6(Text6, { color: "blue", children: [
1803
- " \u2022 ",
1804
- insight.details.issueBreakdown["moderate"],
1805
- " moderate"
1806
- ] }) : null
1807
- ] }),
1808
- insight.details.affectedFiles && insight.details.affectedFiles.length > 0 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1809
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: "Files:" }),
1810
- insight.details.affectedFiles.slice(0, 8).map((f, fi) => /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1811
- " \u2022 ",
1812
- f
1813
- ] }, fi)),
1814
- insight.details.affectedFiles.length > 8 && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1815
- " ... +",
1816
- insight.details.affectedFiles.length - 8,
1817
- " more"
1826
+ isSelected ? /* @__PURE__ */ jsx7(Text6, { bold: true, children: msg }) : /* @__PURE__ */ jsx7(Text6, { children: msg }),
1827
+ " ",
1828
+ /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1829
+ insight.category,
1830
+ " \xB7 ",
1831
+ ago
1818
1832
  ] })
1819
1833
  ] }),
1820
- insight.details.examples && insight.details.examples.length > 0 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1821
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: "Examples:" }),
1822
- insight.details.examples.slice(0, 5).map((ex, ei) => /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1823
- " \u2022 ",
1824
- ex.slice(0, 60),
1825
- ex.length > 60 ? "..." : ""
1826
- ] }, ei))
1827
- ] }),
1828
- insight.details.comparison && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1829
- insight.details.trend === "improving" ? "\u2193" : insight.details.trend === "worsening" ? "\u2191" : "\u2192",
1834
+ (isExpanded || isSelected) && insight.suggestedAction && /* @__PURE__ */ jsxs6(Text6, { children: [
1835
+ " ",
1836
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u2192" }),
1830
1837
  " ",
1831
- insight.details.comparison
1838
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: insight.suggestedAction })
1832
1839
  ] })
1833
- ] }),
1834
- insight.suggestedAction && (isExpanded || isSelected) && /* @__PURE__ */ jsxs6(Text6, { children: [
1835
- " ",
1836
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u2192 " }),
1837
- /* @__PURE__ */ jsx7(Text6, { bold: true, children: insight.suggestedAction })
1838
- ] }),
1839
- insight.actionCommand && isExpanded && /* @__PURE__ */ jsxs6(Text6, { children: [
1840
- " ",
1841
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "$ " }),
1842
- /* @__PURE__ */ jsx7(Text6, { color: "green", children: insight.actionCommand }),
1843
- isSelected && /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " " }),
1844
- isSelected && /* @__PURE__ */ jsx7(Text6, { bold: true, children: "[Enter to run]" })
1845
- ] })
1846
- ] }, insight.id);
1847
- }) }),
1840
+ ] }, insight.id);
1841
+ }),
1842
+ /* @__PURE__ */ jsx7(Text6, { children: " " })
1843
+ ] }),
1844
+ decCount > 0 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1845
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: " Decisions" }),
1846
+ decisions.slice(0, 10).map((dec) => {
1847
+ const ago = timeAgo(dec.when);
1848
+ const hash = dec.hash ? dec.hash.slice(0, 6) : "";
1849
+ const active = dec.status === "active";
1850
+ return /* @__PURE__ */ jsxs6(Text6, { children: [
1851
+ " ",
1852
+ active ? /* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }) : /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u25CB" }),
1853
+ " ",
1854
+ /* @__PURE__ */ jsxs6(Text6, { children: [
1855
+ dec.decision.slice(0, 45),
1856
+ dec.decision.length > 45 ? "..." : ""
1857
+ ] }),
1858
+ " ",
1859
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: ago }),
1860
+ hash && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1861
+ " ",
1862
+ hash
1863
+ ] })
1864
+ ] }, dec.id);
1865
+ }),
1866
+ /* @__PURE__ */ jsx7(Text6, { children: " " })
1867
+ ] }),
1868
+ patCount > 0 && /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", children: [
1869
+ /* @__PURE__ */ jsx7(Text6, { bold: true, children: " Patterns" }),
1870
+ confidentPatterns > 0 && /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1871
+ " ",
1872
+ confidentPatterns,
1873
+ " confident ",
1874
+ learningPatterns,
1875
+ " learning"
1876
+ ] }),
1877
+ patterns.slice(0, 8).map((pat, idx) => {
1878
+ const conf = Math.round(pat.confidence * 100);
1879
+ const confColor = conf > 70 ? "green" : conf > 40 ? "yellow" : void 0;
1880
+ const desc = pat.description.slice(0, 45) + (pat.description.length > 45 ? "..." : "");
1881
+ return /* @__PURE__ */ jsxs6(Text6, { children: [
1882
+ " ",
1883
+ pat.isAntiPattern ? /* @__PURE__ */ jsx7(Text6, { color: "red", children: "\u25CF" }) : /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u25CB" }),
1884
+ " ",
1885
+ /* @__PURE__ */ jsx7(Text6, { children: desc }),
1886
+ " ",
1887
+ confColor ? /* @__PURE__ */ jsxs6(Text6, { color: confColor, children: [
1888
+ conf,
1889
+ "%"
1890
+ ] }) : /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1891
+ conf,
1892
+ "%"
1893
+ ] }),
1894
+ pat.isAntiPattern && /* @__PURE__ */ jsx7(Text6, { color: "red", children: " anti-pattern" })
1895
+ ] }, idx);
1896
+ })
1897
+ ] }),
1848
1898
  /* @__PURE__ */ jsx7(Text6, { children: " " }),
1849
1899
  /* @__PURE__ */ jsxs6(Box6, { gap: 2, children: [
1850
- agentInsights.filter((i) => i.type === "warning").length > 0 && /* @__PURE__ */ jsxs6(Text6, { color: "red", children: [
1851
- agentInsights.filter((i) => i.type === "warning").length,
1852
- " warnings"
1853
- ] }),
1854
- agentInsights.filter((i) => i.type === "suggestion").length > 0 && /* @__PURE__ */ jsxs6(Text6, { bold: true, children: [
1855
- agentInsights.filter((i) => i.type === "suggestion").length,
1856
- " suggestions"
1857
- ] }),
1858
- agentInsights.filter((i) => i.type === "celebration").length > 0 && /* @__PURE__ */ jsxs6(Text6, { color: "green", children: [
1859
- agentInsights.filter((i) => i.type === "celebration").length,
1860
- " wins"
1861
- ] }),
1862
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u2502" }),
1863
- isAIAvailable() ? /* @__PURE__ */ jsx7(Text6, { color: "green", children: "AI \u2713" }) : /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "AI off" })
1900
+ isAIAvailable() ? /* @__PURE__ */ jsxs6(Text6, { children: [
1901
+ /* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
1902
+ " ",
1903
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "AI" })
1904
+ ] }) : /* @__PURE__ */ jsx7(Text6, { children: /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: "\u25CB AI off" }) }),
1905
+ agentInsights.filter((i) => i.type === "celebration").length > 0 && /* @__PURE__ */ jsxs6(Text6, { children: [
1906
+ /* @__PURE__ */ jsx7(Text6, { color: "green", children: "\u25CF" }),
1907
+ " ",
1908
+ /* @__PURE__ */ jsxs6(Text6, { dimColor: true, children: [
1909
+ agentInsights.filter((i) => i.type === "celebration").length,
1910
+ " wins"
1911
+ ] })
1912
+ ] })
1864
1913
  ] })
1865
1914
  ] });
1866
1915
  }
1867
1916
 
1868
1917
  // src/cli/dashboard/views/GoalsView.tsx
1869
- import { useCallback } from "react";
1918
+ import { useCallback as useCallback2 } from "react";
1870
1919
  import { Box as Box7, Text as Text7, useInput as useInput3 } from "ink";
1871
1920
  import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
1872
1921
  function calculateGoalProgress(goal) {
@@ -1885,7 +1934,7 @@ function GoalsView() {
1885
1934
  const activeGoals = goalsPanel.goals.filter((g) => g.status === "active");
1886
1935
  const achievedGoals = goalsPanel.goals.filter((g) => g.status === "achieved");
1887
1936
  const otherGoals = goalsPanel.goals.filter((g) => g.status !== "active" && g.status !== "achieved");
1888
- const refreshGoals = useCallback(async () => {
1937
+ const refreshGoals = useCallback2(async () => {
1889
1938
  try {
1890
1939
  const workDir = getWorkingDirectory(void 0, true);
1891
1940
  const agentState = getGuardianState(workDir);
@@ -1901,7 +1950,7 @@ function GoalsView() {
1901
1950
  } catch {
1902
1951
  }
1903
1952
  }, [dispatch]);
1904
- const addGoal = useCallback(async (description) => {
1953
+ const addGoal = useCallback2(async (description) => {
1905
1954
  if (!description.trim()) return;
1906
1955
  try {
1907
1956
  const workDir = getWorkingDirectory(void 0, true);
@@ -1927,7 +1976,7 @@ function GoalsView() {
1927
1976
  } catch {
1928
1977
  }
1929
1978
  }, [dispatch, refreshGoals]);
1930
- const completeGoal = useCallback(async (goalId) => {
1979
+ const completeGoal = useCallback2(async (goalId) => {
1931
1980
  try {
1932
1981
  const workDir = getWorkingDirectory(void 0, true);
1933
1982
  const agentState = getGuardianState(workDir);
@@ -1942,7 +1991,7 @@ function GoalsView() {
1942
1991
  } catch {
1943
1992
  }
1944
1993
  }, [dispatch, refreshGoals]);
1945
- const deleteGoal = useCallback(async (goalId) => {
1994
+ const deleteGoal = useCallback2(async (goalId) => {
1946
1995
  try {
1947
1996
  const workDir = getWorkingDirectory(void 0, true);
1948
1997
  const agentState = getGuardianState(workDir);
@@ -1953,7 +2002,7 @@ function GoalsView() {
1953
2002
  } catch {
1954
2003
  }
1955
2004
  }, [dispatch, refreshGoals]);
1956
- const reactivateGoal = useCallback(async (goalId) => {
2005
+ const reactivateGoal = useCallback2(async (goalId) => {
1957
2006
  try {
1958
2007
  const workDir = getWorkingDirectory(void 0, true);
1959
2008
  const agentState = getGuardianState(workDir);
@@ -2003,75 +2052,76 @@ function GoalsView() {
2003
2052
  ] }),
2004
2053
  /* @__PURE__ */ jsx8(Text7, { children: " " }),
2005
2054
  goalsPanel.inputMode === "add" ? /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2006
- /* @__PURE__ */ jsxs7(Text7, { children: [
2007
- /* @__PURE__ */ jsx8(Text7, { bold: true, children: "New goal:" }),
2008
- " ",
2055
+ /* @__PURE__ */ jsx8(Box7, { borderStyle: "round", borderColor: "green", paddingX: 1, children: /* @__PURE__ */ jsxs7(Text7, { children: [
2009
2056
  goalsPanel.inputBuffer,
2010
- /* @__PURE__ */ jsx8(Text7, { bold: true, color: "green", children: "\u258C" })
2011
- ] }),
2012
- /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: 'Examples: "Reduce auth bugs by 50%", "Eliminate critical issues"' }),
2013
- /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "Press Enter to add, Escape to cancel" })
2057
+ /* @__PURE__ */ jsx8(Text7, { bold: true, color: "green", children: "|" })
2058
+ ] }) }),
2059
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " enter save \xB7 esc cancel" })
2014
2060
  ] }) : /* @__PURE__ */ jsx8(Fragment2, { children: goalsPanel.goals.length === 0 ? /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2015
- /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "No goals yet." }),
2016
- /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "Press [a] to add your first goal, or wait for auto-generated goals." })
2061
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " No goals yet." }),
2062
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " Press a to add your first goal." })
2017
2063
  ] }) : /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2018
2064
  activeGoals.length > 0 && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2019
- /* @__PURE__ */ jsx8(Text7, { bold: true, children: "Active:" }),
2020
2065
  activeGoals.map((goal, idx) => {
2021
2066
  const isSelected = goalsPanel.selectedIndex === idx;
2022
2067
  const progress = calculateGoalProgress(goal);
2023
- const bar = progressBar(progress, 100, 10);
2024
- const source = goal.autoGenerated ? /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "[auto]" }) : /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "[manual]" });
2068
+ const bar = progressBar(progress, 100, 8);
2069
+ const source = goal.autoGenerated ? "auto" : "manual";
2025
2070
  return /* @__PURE__ */ jsxs7(Text7, { children: [
2026
- isSelected ? /* @__PURE__ */ jsx8(Text7, { bold: true, color: "green", children: "\u25B6 " }) : /* @__PURE__ */ jsx8(Text7, { children: " " }),
2027
- bar,
2028
- " ",
2029
- goal.description.slice(0, 50),
2071
+ isSelected ? /* @__PURE__ */ jsxs7(Text7, { bold: true, color: "green", children: [
2072
+ ">",
2073
+ " "
2074
+ ] }) : /* @__PURE__ */ jsx8(Text7, { children: " " }),
2075
+ /* @__PURE__ */ jsx8(Text7, { color: "green", children: "\u25CB" }),
2030
2076
  " ",
2031
- source
2077
+ goal.description.slice(0, 45),
2078
+ /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
2079
+ " ",
2080
+ source,
2081
+ " ",
2082
+ bar,
2083
+ " ",
2084
+ progress,
2085
+ "%"
2086
+ ] })
2032
2087
  ] }, goal.id);
2033
2088
  }),
2034
2089
  /* @__PURE__ */ jsx8(Text7, { children: " " })
2035
2090
  ] }),
2036
2091
  achievedGoals.length > 0 && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2037
- /* @__PURE__ */ jsxs7(Text7, { children: [
2038
- /* @__PURE__ */ jsx8(Text7, { color: "green", children: "Achieved:" }),
2039
- /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " [x to remove]" })
2040
- ] }),
2041
- achievedGoals.slice(0, 5).map((g) => /* @__PURE__ */ jsxs7(Text7, { color: "green", children: [
2042
- " [+] ",
2092
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " Achieved" }),
2093
+ achievedGoals.slice(0, 5).map((g) => /* @__PURE__ */ jsxs7(Text7, { children: [
2094
+ " ",
2095
+ /* @__PURE__ */ jsx8(Text7, { color: "green", children: "\u25CF" }),
2096
+ " ",
2043
2097
  g.description.slice(0, 50)
2044
2098
  ] }, g.id)),
2045
2099
  achievedGoals.length > 5 && /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
2046
- " +",
2100
+ " +",
2047
2101
  achievedGoals.length - 5,
2048
2102
  " more"
2049
2103
  ] }),
2050
2104
  /* @__PURE__ */ jsx8(Text7, { children: " " })
2051
2105
  ] }),
2052
2106
  otherGoals.length > 0 && /* @__PURE__ */ jsxs7(Box7, { flexDirection: "column", children: [
2053
- /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "Other:" }),
2054
- otherGoals.slice(0, 2).map((g) => {
2055
- const icon = g.status === "failed" ? "[X]" : g.status === "paused" ? "[P]" : "\u2022";
2056
- return /* @__PURE__ */ jsxs7(Text7, { children: [
2107
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: " Other" }),
2108
+ otherGoals.slice(0, 2).map((g) => /* @__PURE__ */ jsxs7(Text7, { children: [
2109
+ " ",
2110
+ /* @__PURE__ */ jsx8(Text7, { dimColor: true, children: "\u25CB" }),
2111
+ " ",
2112
+ g.description.slice(0, 50),
2113
+ /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
2057
2114
  " ",
2058
- icon,
2059
- " ",
2060
- g.description.slice(0, 50),
2061
- /* @__PURE__ */ jsxs7(Text7, { dimColor: true, children: [
2062
- " (",
2063
- g.status,
2064
- ")"
2065
- ] })
2066
- ] }, g.id);
2067
- })
2115
+ g.status
2116
+ ] })
2117
+ ] }, g.id))
2068
2118
  ] })
2069
2119
  ] }) })
2070
2120
  ] });
2071
2121
  }
2072
2122
 
2073
2123
  // src/cli/dashboard/views/HypothesesView.tsx
2074
- import { useCallback as useCallback2 } from "react";
2124
+ import { useCallback as useCallback3 } from "react";
2075
2125
  import { Box as Box8, Text as Text8, useInput as useInput4 } from "ink";
2076
2126
  import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2077
2127
  function HypothesesView() {
@@ -2080,7 +2130,7 @@ function HypothesesView() {
2080
2130
  const testing = hypothesesPanel.hypotheses.filter((h) => h.status === "testing");
2081
2131
  const validated = hypothesesPanel.hypotheses.filter((h) => h.status === "validated");
2082
2132
  const invalidated = hypothesesPanel.hypotheses.filter((h) => h.status === "invalidated");
2083
- const refreshHypotheses = useCallback2(async () => {
2133
+ const refreshHypotheses = useCallback3(async () => {
2084
2134
  try {
2085
2135
  const workDir = getWorkingDirectory(void 0, true);
2086
2136
  const agentState = getGuardianState(workDir);
@@ -2096,7 +2146,7 @@ function HypothesesView() {
2096
2146
  } catch {
2097
2147
  }
2098
2148
  }, [dispatch]);
2099
- const addHypothesis = useCallback2(async (statement) => {
2149
+ const addHypothesis = useCallback3(async (statement) => {
2100
2150
  if (!statement.trim()) return;
2101
2151
  try {
2102
2152
  const workDir = getWorkingDirectory(void 0, true);
@@ -2118,7 +2168,7 @@ function HypothesesView() {
2118
2168
  } catch {
2119
2169
  }
2120
2170
  }, [dispatch, refreshHypotheses]);
2121
- const updateHypothesis = useCallback2(async (hypoId, action) => {
2171
+ const updateHypothesis = useCallback3(async (hypoId, action) => {
2122
2172
  try {
2123
2173
  const workDir = getWorkingDirectory(void 0, true);
2124
2174
  const agentState = getGuardianState(workDir);
@@ -2131,7 +2181,7 @@ function HypothesesView() {
2131
2181
  } catch {
2132
2182
  }
2133
2183
  }, [dispatch, refreshHypotheses]);
2134
- const reactivateHypothesis = useCallback2(async (hypoId) => {
2184
+ const reactivateHypothesis = useCallback3(async (hypoId) => {
2135
2185
  try {
2136
2186
  const workDir = getWorkingDirectory(void 0, true);
2137
2187
  const agentState = getGuardianState(workDir);
@@ -2184,74 +2234,63 @@ function HypothesesView() {
2184
2234
  ] }),
2185
2235
  /* @__PURE__ */ jsx9(Text8, { children: " " }),
2186
2236
  hypothesesPanel.inputMode === "add" ? /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2187
- /* @__PURE__ */ jsxs8(Text8, { children: [
2188
- /* @__PURE__ */ jsx9(Text8, { bold: true, children: "New hypothesis:" }),
2189
- " ",
2237
+ /* @__PURE__ */ jsx9(Box8, { borderStyle: "round", borderColor: "green", paddingX: 1, children: /* @__PURE__ */ jsxs8(Text8, { children: [
2190
2238
  hypothesesPanel.inputBuffer,
2191
- /* @__PURE__ */ jsx9(Text8, { bold: true, color: "green", children: "\u258C" })
2192
- ] }),
2193
- /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: 'Examples: "Mondays have more bugs", "Code reviews reduce issues"' }),
2194
- /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Press Enter to add, Escape to cancel" })
2239
+ /* @__PURE__ */ jsx9(Text8, { bold: true, color: "green", children: "|" })
2240
+ ] }) }),
2241
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " enter save \xB7 esc cancel" })
2195
2242
  ] }) : /* @__PURE__ */ jsx9(Fragment3, { children: hypothesesPanel.hypotheses.length === 0 ? /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2196
- /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "No hypotheses yet." }),
2197
- /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Press [a] to add your first hypothesis." }),
2198
- /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "The agent will collect evidence and update confidence over time." })
2243
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " No hypotheses yet." }),
2244
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " Press a to add your first hypothesis." })
2199
2245
  ] }) : /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2200
2246
  testing.length > 0 && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2201
- /* @__PURE__ */ jsx9(Text8, { bold: true, children: "Testing:" }),
2202
2247
  testing.map((hypo, idx) => {
2203
2248
  const isSelected = hypothesesPanel.selectedIndex === idx;
2204
2249
  const conf = Math.round(hypo.confidence * 100);
2205
- return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2206
- /* @__PURE__ */ jsxs8(Text8, { children: [
2207
- isSelected ? /* @__PURE__ */ jsx9(Text8, { bold: true, color: "green", children: "\u25B6 " }) : /* @__PURE__ */ jsx9(Text8, { children: " " }),
2208
- '[?] "',
2209
- hypo.statement.slice(0, 50),
2210
- '" ',
2211
- /* @__PURE__ */ jsxs8(Text8, { color: conf >= 70 ? "green" : conf >= 40 ? "yellow" : "yellow", children: [
2212
- "(",
2213
- conf,
2214
- "%)"
2215
- ] })
2216
- ] }),
2250
+ return /* @__PURE__ */ jsx9(Box8, { flexDirection: "column", children: /* @__PURE__ */ jsxs8(Text8, { children: [
2251
+ isSelected ? /* @__PURE__ */ jsxs8(Text8, { bold: true, color: "green", children: [
2252
+ ">",
2253
+ " "
2254
+ ] }) : /* @__PURE__ */ jsx9(Text8, { children: " " }),
2255
+ /* @__PURE__ */ jsx9(Text8, { color: "yellow", children: "\u25CB" }),
2256
+ " ",
2257
+ hypo.statement.slice(0, 50),
2217
2258
  /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
2218
- " Evidence: ",
2259
+ " ",
2260
+ conf,
2261
+ "% \xB7 ",
2219
2262
  hypo.evidenceCount,
2220
- " points"
2263
+ " evidence"
2221
2264
  ] })
2222
- ] }, hypo.id);
2265
+ ] }) }, hypo.id);
2223
2266
  }),
2224
2267
  /* @__PURE__ */ jsx9(Text8, { children: " " })
2225
2268
  ] }),
2226
2269
  validated.length > 0 && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2227
- /* @__PURE__ */ jsxs8(Text8, { children: [
2228
- /* @__PURE__ */ jsx9(Text8, { color: "green", children: "Validated:" }),
2229
- /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " [r to remove]" })
2230
- ] }),
2231
- validated.slice(0, 3).map((h) => /* @__PURE__ */ jsxs8(Text8, { color: "green", children: [
2232
- ' [+] "',
2233
- h.statement.slice(0, 50),
2234
- '"'
2270
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " Validated" }),
2271
+ validated.slice(0, 3).map((h) => /* @__PURE__ */ jsxs8(Text8, { children: [
2272
+ " ",
2273
+ /* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u25CF" }),
2274
+ " ",
2275
+ h.statement.slice(0, 50)
2235
2276
  ] }, h.id)),
2236
2277
  validated.length > 3 && /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
2237
- " +",
2278
+ " +",
2238
2279
  validated.length - 3,
2239
2280
  " more"
2240
2281
  ] }),
2241
2282
  /* @__PURE__ */ jsx9(Text8, { children: " " })
2242
2283
  ] }),
2243
2284
  invalidated.length > 0 && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2244
- /* @__PURE__ */ jsxs8(Text8, { children: [
2245
- /* @__PURE__ */ jsx9(Text8, { color: "yellow", children: "Invalidated:" }),
2246
- /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " [r to remove]" })
2247
- ] }),
2248
- invalidated.slice(0, 2).map((h) => /* @__PURE__ */ jsx9(Text8, { children: /* @__PURE__ */ jsxs8(Text8, { color: "yellow", children: [
2249
- ' [X] "',
2250
- h.statement.slice(0, 50),
2251
- '"'
2252
- ] }) }, h.id)),
2285
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " Invalidated" }),
2286
+ invalidated.slice(0, 2).map((h) => /* @__PURE__ */ jsxs8(Text8, { children: [
2287
+ " ",
2288
+ /* @__PURE__ */ jsx9(Text8, { color: "red", children: "\u25CF" }),
2289
+ " ",
2290
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: h.statement.slice(0, 50) })
2291
+ ] }, h.id)),
2253
2292
  invalidated.length > 2 && /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
2254
- " +",
2293
+ " +",
2255
2294
  invalidated.length - 2,
2256
2295
  " more"
2257
2296
  ] })
@@ -2261,31 +2300,48 @@ function HypothesesView() {
2261
2300
  }
2262
2301
 
2263
2302
  // src/cli/dashboard/views/MemoryTreeView.tsx
2264
- import { useEffect, useCallback as useCallback3 } from "react";
2303
+ import { useEffect as useEffect3, useCallback as useCallback4 } from "react";
2265
2304
  import { Box as Box9, Text as Text9, useInput as useInput5 } from "ink";
2266
2305
  import { jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2267
- function severityBar(count, max, width = 16) {
2268
- const filled = max > 0 ? Math.round(count / max * width) : 0;
2269
- return "\u2588".repeat(filled) + "\u2591".repeat(width - filled);
2306
+ var RISK_ORDER = { critical: 0, high: 1, medium: 2, low: 3, unknown: 4 };
2307
+ function riskColor(risk) {
2308
+ switch (risk) {
2309
+ case "critical":
2310
+ return "red";
2311
+ case "high":
2312
+ return "yellow";
2313
+ case "medium":
2314
+ return "blue";
2315
+ default:
2316
+ return void 0;
2317
+ }
2318
+ }
2319
+ function timeAgo2(iso) {
2320
+ const ms = Date.now() - new Date(iso).getTime();
2321
+ const mins = Math.floor(ms / 6e4);
2322
+ if (mins < 60) return `${mins}m`;
2323
+ const hrs = Math.floor(mins / 60);
2324
+ if (hrs < 24) return `${hrs}h`;
2325
+ return `${Math.floor(hrs / 24)}d`;
2270
2326
  }
2271
2327
  function MemoryTreeView() {
2272
2328
  const { state, dispatch } = useDashboard();
2273
2329
  const { memoryTree } = state;
2274
- const { issues, stats, globalPatterns, expandedNodes, selectedNode, loaded } = memoryTree;
2275
- const loadData = useCallback3(async () => {
2330
+ const { snapshot, globalPatterns, expandedNodes, selectedNode, loaded } = memoryTree;
2331
+ const loadData = useCallback4(async () => {
2276
2332
  try {
2277
2333
  const workDir = getWorkingDirectory(void 0, true);
2278
- const [issueList, memStats, patterns] = await Promise.all([
2279
- getRecentIssues({ workDir, limit: 200, daysBack: 30 }),
2280
- getMemoryStats(workDir),
2334
+ const graph = new ContextGraph(workDir);
2335
+ const [snap, patterns] = await Promise.all([
2336
+ graph.getSnapshot(),
2281
2337
  findCrossProjectPatterns(2)
2282
2338
  ]);
2283
- dispatch({ type: "SET_MEMORY_TREE", issues: issueList, stats: memStats, patterns });
2339
+ dispatch({ type: "SET_MEMORY_TREE", snapshot: snap, patterns });
2284
2340
  } catch {
2285
- dispatch({ type: "ADD_ACTIVITY", message: "Memory load error" });
2341
+ dispatch({ type: "ADD_ACTIVITY", message: "Context graph load error" });
2286
2342
  }
2287
2343
  }, [dispatch]);
2288
- useEffect(() => {
2344
+ useEffect3(() => {
2289
2345
  if (!loaded) {
2290
2346
  void loadData();
2291
2347
  }
@@ -2295,167 +2351,196 @@ function MemoryTreeView() {
2295
2351
  else if (key.downArrow || _input === "j") dispatch({ type: "NAVIGATE_DOWN" });
2296
2352
  else if (key.return) dispatch({ type: "TOGGLE_MEMORY_NODE", nodeId: selectedNode });
2297
2353
  });
2298
- const bySeverity = { critical: [], serious: [], moderate: [], low: [] };
2299
- for (const issue of issues) {
2300
- const arr = bySeverity[issue.severity];
2301
- if (arr) arr.push(issue);
2302
- }
2303
- const byFile = /* @__PURE__ */ new Map();
2304
- for (const issue of issues) {
2305
- if (!byFile.has(issue.file)) byFile.set(issue.file, []);
2306
- byFile.get(issue.file).push(issue);
2307
- }
2308
- const sortedFiles = Array.from(byFile.entries()).sort((a, b) => b[1].length - a[1].length).slice(0, 10);
2309
- const byAgent = /* @__PURE__ */ new Map();
2310
- for (const issue of issues) {
2311
- if (!byAgent.has(issue.agent)) byAgent.set(issue.agent, []);
2312
- byAgent.get(issue.agent).push(issue);
2313
- }
2314
- const sortedAgents = Array.from(byAgent.entries()).sort((a, b) => b[1].length - a[1].length);
2315
- const maxCount = Math.max(bySeverity["critical"]?.length || 0, bySeverity["serious"]?.length || 0, bySeverity["moderate"]?.length || 0, bySeverity["low"]?.length || 0, 1);
2316
- const totalIssues = stats?.totalIssues || issues.length;
2317
2354
  const sel = (nodeId) => selectedNode === nodeId;
2355
+ if (!loaded) {
2356
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 1, children: [
2357
+ /* @__PURE__ */ jsx10(Text9, { bold: true, children: "Context" }),
2358
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: " Loading context graph..." })
2359
+ ] });
2360
+ }
2361
+ const nodeCount = snapshot?.nodes.length ?? 0;
2362
+ const edgeCount = snapshot?.edges.length ?? 0;
2363
+ if (nodeCount === 0 && globalPatterns.length === 0) {
2364
+ return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 1, children: [
2365
+ /* @__PURE__ */ jsx10(Text9, { bold: true, children: "Context" }),
2366
+ /* @__PURE__ */ jsx10(Text9, { children: " " }),
2367
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: " No context data yet." }),
2368
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: " Run trie watch or trie tell to populate the graph." })
2369
+ ] });
2370
+ }
2371
+ const fileNodes = snapshot?.nodes.filter((n) => n.type === "file") ?? [];
2372
+ const changeNodes = snapshot?.nodes.filter((n) => n.type === "change") ?? [];
2373
+ const patternNodes = snapshot?.nodes.filter((n) => n.type === "pattern") ?? [];
2374
+ const incidentNodes = snapshot?.nodes.filter((n) => n.type === "incident") ?? [];
2375
+ const decisionNodes = snapshot?.nodes.filter((n) => n.type === "decision") ?? [];
2376
+ const sortedFiles = [...fileNodes].sort(
2377
+ (a, b) => (RISK_ORDER[a.data.riskLevel] ?? 4) - (RISK_ORDER[b.data.riskLevel] ?? 4)
2378
+ );
2379
+ const sortedChanges = [...changeNodes].sort(
2380
+ (a, b) => new Date(b.data.timestamp).getTime() - new Date(a.data.timestamp).getTime()
2381
+ );
2382
+ function renderSectionHeader(id, label, count) {
2383
+ const expanded = expandedNodes.has(id);
2384
+ return /* @__PURE__ */ jsxs9(Text9, { children: [
2385
+ sel(id) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2386
+ ">",
2387
+ " "
2388
+ ] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2389
+ expanded ? /* @__PURE__ */ jsx10(Text9, { color: "green", children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2390
+ " ",
2391
+ sel(id) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2392
+ label,
2393
+ " (",
2394
+ count,
2395
+ ")"
2396
+ ] }) : /* @__PURE__ */ jsxs9(Text9, { bold: true, children: [
2397
+ label,
2398
+ " (",
2399
+ count,
2400
+ ")"
2401
+ ] })
2402
+ ] });
2403
+ }
2318
2404
  return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", paddingX: 1, children: [
2319
2405
  /* @__PURE__ */ jsxs9(Text9, { children: [
2320
- /* @__PURE__ */ jsx10(Text9, { bold: true, children: "Memory" }),
2406
+ /* @__PURE__ */ jsx10(Text9, { bold: true, children: "Context" }),
2321
2407
  " ",
2322
2408
  /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2323
- "[",
2324
- totalIssues,
2325
- " issues]"
2409
+ nodeCount,
2410
+ " nodes ",
2411
+ edgeCount,
2412
+ " edges"
2326
2413
  ] })
2327
2414
  ] }),
2328
2415
  /* @__PURE__ */ jsx10(Text9, { children: " " }),
2329
- !loaded ? /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "Loading memory data..." }) : issues.length === 0 && globalPatterns.length === 0 ? /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2330
- /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "No issues in memory yet." }),
2331
- /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "Run a scan to populate the memory tree." })
2332
- ] }) : /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2333
- /* @__PURE__ */ jsxs9(Text9, { children: [
2334
- sel("severity") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "\u25B6 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2335
- expandedNodes.has("severity") ? "\u25BC" : "\u25B6",
2336
- " ",
2337
- sel("severity") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "By Severity" }) : /* @__PURE__ */ jsx10(Text9, { bold: true, children: "By Severity" })
2338
- ] }),
2339
- expandedNodes.has("severity") && ["critical", "serious", "moderate", "low"].map((sev) => {
2340
- const count = bySeverity[sev]?.length || 0;
2341
- const nodeId = `severity-${sev}`;
2342
- const barStr = severityBar(count, maxCount);
2343
- const isLow = sev === "low";
2344
- const sevColorMap = { critical: "red", serious: "yellow", moderate: "blue" };
2345
- const sevColor = isLow ? void 0 : sevColorMap[sev];
2346
- const SevText = ({ children }) => isLow ? /* @__PURE__ */ jsx10(Text9, { dimColor: true, children }) : sevColor ? /* @__PURE__ */ jsx10(Text9, { color: sevColor, children }) : /* @__PURE__ */ jsx10(Text9, { children });
2347
- return /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2348
- /* @__PURE__ */ jsxs9(Text9, { children: [
2349
- sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2350
- " \u2502 ",
2351
- sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: sev }) : /* @__PURE__ */ jsx10(SevText, { children: sev }),
2352
- ` (${count}) `,
2353
- /* @__PURE__ */ jsx10(SevText, { children: barStr })
2354
- ] }),
2355
- expandedNodes.has(nodeId) && (bySeverity[sev] || []).slice(0, 5).map((issue, i) => {
2356
- const issueId = `severity-${sev}-${issue.id}`;
2357
- const filename = issue.file.split("/").pop() || issue.file;
2358
- const line = issue.line ? `:${issue.line}` : "";
2359
- const desc = issue.issue.slice(0, 35) + (issue.issue.length > 35 ? "..." : "");
2360
- return /* @__PURE__ */ jsxs9(Text9, { children: [
2361
- sel(issueId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2362
- " \u2502 ",
2363
- i === Math.min(5, bySeverity[sev]?.length || 0) - 1 ? "\u2514\u2500 " : "\u251C\u2500 ",
2364
- /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2365
- filename,
2366
- line
2367
- ] }),
2368
- " - ",
2369
- /* @__PURE__ */ jsx10(SevText, { children: desc })
2370
- ] }, i);
2371
- })
2372
- ] }, sev);
2373
- }),
2374
- /* @__PURE__ */ jsxs9(Text9, { children: [
2375
- sel("files") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2376
- expandedNodes.has("files") ? "\u25BC" : "\u25B6",
2416
+ renderSectionHeader("files", "Files", fileNodes.length),
2417
+ expandedNodes.has("files") && sortedFiles.slice(0, 15).map((n) => {
2418
+ const nodeId = `file-${n.id}`;
2419
+ const path = n.data.path.split("/").slice(-2).join("/");
2420
+ const risk = n.data.riskLevel;
2421
+ const color = riskColor(risk);
2422
+ return /* @__PURE__ */ jsxs9(Text9, { children: [
2423
+ sel(nodeId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2424
+ ">",
2425
+ " "
2426
+ ] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2427
+ " ",
2428
+ color ? /* @__PURE__ */ jsx10(Text9, { color, children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2377
2429
  " ",
2378
- sel("files") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "By File (Hot Spots)" }) : /* @__PURE__ */ jsx10(Text9, { bold: true, children: "By File (Hot Spots)" })
2379
- ] }),
2380
- expandedNodes.has("files") && sortedFiles.map(([file, fileIssues], idx) => {
2381
- const fileId = `file-${file}`;
2382
- const filename = file.split("/").pop() || file;
2383
- const count = fileIssues.length;
2384
- const isLast = idx === sortedFiles.length - 1;
2385
- return /* @__PURE__ */ jsxs9(Text9, { children: [
2386
- sel(fileId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2387
- " ",
2388
- isLast ? "\u2514\u2500 " : "\u251C\u2500 ",
2389
- sel(fileId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: filename }) : /* @__PURE__ */ jsx10(Text9, { children: filename }),
2390
- ` (${count})`
2391
- ] }, file);
2392
- }),
2393
- /* @__PURE__ */ jsxs9(Text9, { children: [
2394
- sel("agents") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2395
- expandedNodes.has("agents") ? "\u25BC" : "\u25B6",
2430
+ sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: path }) : /* @__PURE__ */ jsx10(Text9, { children: path }),
2431
+ " ",
2432
+ color ? /* @__PURE__ */ jsx10(Text9, { color, children: risk }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: risk }),
2433
+ " ",
2434
+ /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2435
+ n.data.changeCount,
2436
+ " changes"
2437
+ ] }),
2438
+ n.data.incidentCount > 0 && /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2439
+ " ",
2440
+ n.data.incidentCount,
2441
+ " incidents"
2442
+ ] })
2443
+ ] }, n.id);
2444
+ }),
2445
+ renderSectionHeader("changes", "Changes", changeNodes.length),
2446
+ expandedNodes.has("changes") && sortedChanges.slice(0, 10).map((n) => {
2447
+ const nodeId = `change-${n.id}`;
2448
+ const msg = n.data.message.slice(0, 45) + (n.data.message.length > 45 ? "..." : "");
2449
+ const outcome = n.data.outcome;
2450
+ const outcomeColor = outcome === "incident" ? "red" : outcome === "success" ? "green" : void 0;
2451
+ return /* @__PURE__ */ jsxs9(Text9, { children: [
2452
+ sel(nodeId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2453
+ ">",
2454
+ " "
2455
+ ] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2456
+ " ",
2457
+ outcomeColor ? /* @__PURE__ */ jsx10(Text9, { color: outcomeColor, children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2396
2458
  " ",
2397
- sel("agents") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "By Agent" }) : /* @__PURE__ */ jsx10(Text9, { bold: true, children: "By Agent" })
2398
- ] }),
2399
- expandedNodes.has("agents") && sortedAgents.map(([agent, agentIssues], idx) => {
2400
- const agentId = `agent-${agent}`;
2401
- const isLast = idx === sortedAgents.length - 1;
2402
- return /* @__PURE__ */ jsxs9(Text9, { children: [
2403
- sel(agentId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2404
- " ",
2405
- isLast ? "\u2514\u2500 " : "\u251C\u2500 ",
2406
- sel(agentId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: agent }) : /* @__PURE__ */ jsx10(Text9, { children: agent }),
2407
- ` (${agentIssues.length})`
2408
- ] }, agent);
2409
- }),
2410
- /* @__PURE__ */ jsxs9(Text9, { children: [
2411
- sel("patterns") ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2412
- expandedNodes.has("patterns") ? "\u25BC" : "\u25B6",
2459
+ sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: msg }) : /* @__PURE__ */ jsx10(Text9, { children: msg }),
2460
+ " ",
2461
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: timeAgo2(n.data.timestamp) })
2462
+ ] }, n.id);
2463
+ }),
2464
+ renderSectionHeader("patterns", "Patterns", patternNodes.length),
2465
+ expandedNodes.has("patterns") && patternNodes.slice(0, 10).map((n) => {
2466
+ const nodeId = `pattern-${n.id}`;
2467
+ const conf = Math.round(n.data.confidence * 100);
2468
+ const confColor = conf > 70 ? "green" : conf > 40 ? "yellow" : void 0;
2469
+ const desc = n.data.description.slice(0, 45) + (n.data.description.length > 45 ? "..." : "");
2470
+ return /* @__PURE__ */ jsxs9(Text9, { children: [
2471
+ sel(nodeId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2472
+ ">",
2473
+ " "
2474
+ ] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2475
+ " ",
2476
+ n.data.isAntiPattern ? /* @__PURE__ */ jsx10(Text9, { color: "red", children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2413
2477
  " ",
2414
- sel("patterns") ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2415
- "Patterns (",
2416
- globalPatterns.length,
2417
- " recurring)"
2418
- ] }) : /* @__PURE__ */ jsxs9(Text9, { bold: true, children: [
2419
- "Patterns (",
2420
- globalPatterns.length,
2421
- " recurring)"
2422
- ] })
2423
- ] }),
2424
- expandedNodes.has("patterns") && globalPatterns.slice(0, 5).map((pattern, idx) => {
2425
- const patternId = `pattern-${pattern.id}`;
2426
- const isLast = idx === Math.min(4, globalPatterns.length - 1);
2427
- const desc = pattern.pattern.slice(0, 40) + (pattern.pattern.length > 40 ? "..." : "");
2428
- return /* @__PURE__ */ jsxs9(Text9, { children: [
2429
- sel(patternId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "\u2192 " }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2430
- " ",
2431
- isLast ? "\u2514\u2500 " : "\u251C\u2500 ",
2432
- /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2433
- '"',
2434
- desc,
2435
- '" - seen in ',
2436
- pattern.projects.length,
2437
- " projects"
2438
- ] })
2439
- ] }, pattern.id);
2440
- }),
2441
- /* @__PURE__ */ jsx10(Text9, { children: " " }),
2442
- /* @__PURE__ */ jsxs9(Box9, { gap: 2, children: [
2443
- /* @__PURE__ */ jsxs9(Text9, { children: [
2444
- /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "Trend: " }),
2445
- stats?.improvementTrend === "improving" ? /* @__PURE__ */ jsx10(Text9, { color: "green", children: "\u2191 Improving" }) : stats?.improvementTrend === "declining" ? /* @__PURE__ */ jsx10(Text9, { color: "red", children: "\u2193 Declining" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u2192 Stable" })
2446
- ] }),
2447
- /* @__PURE__ */ jsxs9(Text9, { children: [
2448
- /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "Resolved:" }),
2449
- " ",
2450
- /* @__PURE__ */ jsx10(Text9, { color: "green", children: stats?.resolvedCount || 0 })
2478
+ sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: desc }) : /* @__PURE__ */ jsx10(Text9, { children: desc }),
2479
+ " ",
2480
+ confColor ? /* @__PURE__ */ jsxs9(Text9, { color: confColor, children: [
2481
+ conf,
2482
+ "%"
2483
+ ] }) : /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2484
+ conf,
2485
+ "%"
2451
2486
  ] }),
2452
- /* @__PURE__ */ jsxs9(Text9, { children: [
2453
- /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "Historical:" }),
2454
- " ",
2455
- /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: stats?.historicalIssues || 0 })
2487
+ n.data.isAntiPattern && /* @__PURE__ */ jsx10(Text9, { color: "red", children: " anti-pattern" })
2488
+ ] }, n.id);
2489
+ }),
2490
+ renderSectionHeader("incidents", "Incidents", incidentNodes.length),
2491
+ expandedNodes.has("incidents") && incidentNodes.slice(0, 10).map((n) => {
2492
+ const nodeId = `incident-${n.id}`;
2493
+ const sevColor = n.data.severity === "critical" ? "red" : n.data.severity === "major" ? "yellow" : void 0;
2494
+ const desc = n.data.description.slice(0, 45) + (n.data.description.length > 45 ? "..." : "");
2495
+ return /* @__PURE__ */ jsxs9(Text9, { children: [
2496
+ sel(nodeId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2497
+ ">",
2498
+ " "
2499
+ ] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2500
+ " ",
2501
+ sevColor ? /* @__PURE__ */ jsx10(Text9, { color: sevColor, children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2502
+ " ",
2503
+ sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: desc }) : /* @__PURE__ */ jsx10(Text9, { children: desc }),
2504
+ " ",
2505
+ n.data.resolved ? /* @__PURE__ */ jsx10(Text9, { color: "green", children: "resolved" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "open" })
2506
+ ] }, n.id);
2507
+ }),
2508
+ renderSectionHeader("decisions", "Decisions", decisionNodes.length),
2509
+ expandedNodes.has("decisions") && decisionNodes.slice(0, 10).map((n) => {
2510
+ const nodeId = `decision-${n.id}`;
2511
+ const dec = n.data.decision.slice(0, 45) + (n.data.decision.length > 45 ? "..." : "");
2512
+ const outcomeColor = n.data.outcome === "good" ? "green" : n.data.outcome === "bad" ? "red" : void 0;
2513
+ return /* @__PURE__ */ jsxs9(Text9, { children: [
2514
+ sel(nodeId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2515
+ ">",
2516
+ " "
2517
+ ] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2518
+ " ",
2519
+ outcomeColor ? /* @__PURE__ */ jsx10(Text9, { color: outcomeColor, children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: "\u25CB" }),
2520
+ " ",
2521
+ sel(nodeId) ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: dec }) : /* @__PURE__ */ jsx10(Text9, { children: dec }),
2522
+ " ",
2523
+ outcomeColor ? /* @__PURE__ */ jsx10(Text9, { color: outcomeColor, children: n.data.outcome }) : /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: n.data.outcome })
2524
+ ] }, n.id);
2525
+ }),
2526
+ renderSectionHeader("cross-project", "Cross-Project", globalPatterns.length),
2527
+ expandedNodes.has("cross-project") && globalPatterns.slice(0, 5).map((pattern) => {
2528
+ const patternId = `global-${pattern.id}`;
2529
+ const desc = pattern.pattern.slice(0, 40) + (pattern.pattern.length > 40 ? "..." : "");
2530
+ return /* @__PURE__ */ jsxs9(Text9, { children: [
2531
+ sel(patternId) ? /* @__PURE__ */ jsxs9(Text9, { bold: true, color: "green", children: [
2532
+ ">",
2533
+ " "
2534
+ ] }) : /* @__PURE__ */ jsx10(Text9, { children: " " }),
2535
+ " ",
2536
+ /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2537
+ desc,
2538
+ " \xB7 ",
2539
+ pattern.projects.length,
2540
+ " projects"
2456
2541
  ] })
2457
- ] })
2458
- ] })
2542
+ ] }, pattern.id);
2543
+ })
2459
2544
  ] });
2460
2545
  }
2461
2546
 
@@ -2491,33 +2576,167 @@ function RawLogView() {
2491
2576
  /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: " entries" })
2492
2577
  ] }),
2493
2578
  /* @__PURE__ */ jsx11(Text10, { children: " " }),
2494
- rawLog.length === 0 ? /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "No log entries yet." }) : /* @__PURE__ */ jsx11(Box10, { flexDirection: "column", children: logs.map((entry, i) => {
2495
- const levelTag = `[${entry.level.toUpperCase().padEnd(5)}]`;
2496
- const levelEl = entry.level === "error" ? /* @__PURE__ */ jsx11(Text10, { color: "red", children: levelTag }) : entry.level === "warn" ? /* @__PURE__ */ jsx11(Text10, { color: "yellow", children: levelTag }) : entry.level === "info" ? /* @__PURE__ */ jsx11(Text10, { color: "green", children: levelTag }) : /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: levelTag });
2579
+ rawLog.length === 0 ? /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: " No log entries yet." }) : /* @__PURE__ */ jsx11(Box10, { flexDirection: "column", children: logs.map((entry, i) => {
2580
+ const dot = entry.level === "error" ? /* @__PURE__ */ jsx11(Text10, { color: "red", children: "\u25CF" }) : entry.level === "warn" ? /* @__PURE__ */ jsx11(Text10, { color: "yellow", children: "\u25CF" }) : entry.level === "info" ? /* @__PURE__ */ jsx11(Text10, { color: "green", children: "\u25CF" }) : /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "\u25CB" });
2497
2581
  return /* @__PURE__ */ jsxs10(Text10, { children: [
2498
- /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: entry.time }),
2499
- " ",
2500
- levelEl,
2582
+ " ",
2583
+ dot,
2501
2584
  " ",
2502
- entry.message.slice(0, 80)
2585
+ entry.message.slice(0, 70),
2586
+ " ",
2587
+ /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: entry.time })
2503
2588
  ] }, i);
2504
2589
  }) })
2505
2590
  ] });
2506
2591
  }
2507
2592
 
2508
- // src/cli/dashboard/App.tsx
2593
+ // src/cli/dashboard/views/ChatView.tsx
2594
+ import { useCallback as useCallback5 } from "react";
2595
+ import { Box as Box11, Text as Text11, useInput as useInput7 } from "ink";
2509
2596
  import { jsx as jsx12, jsxs as jsxs11 } from "react/jsx-runtime";
2510
- var MAIN_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent"];
2597
+ function ChatView() {
2598
+ const { state, dispatch } = useDashboard();
2599
+ const { chatState } = state;
2600
+ const { messages, inputBuffer, loading } = chatState;
2601
+ const sendMessage = useCallback5(async (question) => {
2602
+ dispatch({ type: "ADD_CHAT_MESSAGE", role: "user", content: question });
2603
+ dispatch({ type: "SET_CHAT_INPUT", buffer: "" });
2604
+ dispatch({ type: "SET_CHAT_LOADING", loading: true });
2605
+ try {
2606
+ const workDir = getWorkingDirectory(void 0, true);
2607
+ const storage = new TieredStorage(workDir);
2608
+ const graph = new ContextGraph(workDir);
2609
+ const [decisions, blockers, snap] = await Promise.all([
2610
+ storage.queryDecisions({ limit: 10 }),
2611
+ storage.queryBlockers({ limit: 5 }),
2612
+ graph.getSnapshot()
2613
+ ]);
2614
+ const contextParts = [];
2615
+ if (decisions.length > 0) {
2616
+ contextParts.push("Recent decisions:\n" + decisions.map(
2617
+ (d) => `- ${d.decision} (${d.when}${d.hash ? `, hash: ${d.hash.slice(0, 8)}` : ""})`
2618
+ ).join("\n"));
2619
+ }
2620
+ if (blockers.length > 0) {
2621
+ contextParts.push("Active blockers:\n" + blockers.map(
2622
+ (b) => `- ${b.blocker} [${b.impact}]`
2623
+ ).join("\n"));
2624
+ }
2625
+ const fileNodes = snap.nodes.filter((n) => n.type === "file");
2626
+ const riskFiles = fileNodes.filter((n) => n.data && "riskLevel" in n.data && (n.data.riskLevel === "critical" || n.data.riskLevel === "high")).slice(0, 10);
2627
+ if (riskFiles.length > 0) {
2628
+ contextParts.push("High-risk files:\n" + riskFiles.map(
2629
+ (n) => `- ${n.data.path} (${n.data.riskLevel})`
2630
+ ).join("\n"));
2631
+ }
2632
+ const patternNodes = snap.nodes.filter((n) => n.type === "pattern").slice(0, 5);
2633
+ if (patternNodes.length > 0) {
2634
+ contextParts.push("Learned patterns:\n" + patternNodes.map(
2635
+ (n) => `- ${n.data.description} (${Math.round(n.data.confidence * 100)}% confidence)`
2636
+ ).join("\n"));
2637
+ }
2638
+ const contextBlock = contextParts.length > 0 ? contextParts.join("\n\n") : "No context data available yet.";
2639
+ const result = await runAIAnalysis({
2640
+ systemPrompt: `You are Trie, a code guardian assistant embedded in a TUI. Answer concisely based on the project context below. Reference specific decisions, patterns, and files when relevant.
2641
+
2642
+ Project context:
2643
+ ${contextBlock}`,
2644
+ userPrompt: question,
2645
+ maxTokens: 1024,
2646
+ temperature: 0.4
2647
+ });
2648
+ if (result.success) {
2649
+ dispatch({ type: "ADD_CHAT_MESSAGE", role: "assistant", content: result.content });
2650
+ } else {
2651
+ dispatch({ type: "ADD_CHAT_MESSAGE", role: "assistant", content: result.error || "Failed to get a response." });
2652
+ }
2653
+ } catch (err) {
2654
+ dispatch({ type: "ADD_CHAT_MESSAGE", role: "assistant", content: `Error: ${err instanceof Error ? err.message : "unknown"}` });
2655
+ } finally {
2656
+ dispatch({ type: "SET_CHAT_LOADING", loading: false });
2657
+ }
2658
+ }, [dispatch]);
2659
+ useInput7((input, key) => {
2660
+ if (loading) return;
2661
+ if (key.return && inputBuffer.trim().length > 0) {
2662
+ void sendMessage(inputBuffer.trim());
2663
+ } else if (key.escape) {
2664
+ dispatch({ type: "SET_CHAT_INPUT", buffer: "" });
2665
+ } else if (key.backspace || key.delete) {
2666
+ dispatch({ type: "SET_CHAT_INPUT", buffer: inputBuffer.slice(0, -1) });
2667
+ } else if (input && !key.ctrl && !key.meta) {
2668
+ dispatch({ type: "SET_CHAT_INPUT", buffer: inputBuffer + input });
2669
+ }
2670
+ });
2671
+ if (!isAIAvailable()) {
2672
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, children: [
2673
+ /* @__PURE__ */ jsx12(Text11, { bold: true, children: "Chat" }),
2674
+ " ",
2675
+ /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "Ask Trie anything" }),
2676
+ /* @__PURE__ */ jsx12(Text11, { children: " " }),
2677
+ /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: " AI is not available." }),
2678
+ /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
2679
+ " Press ",
2680
+ /* @__PURE__ */ jsx12(Text11, { bold: true, children: "c" }),
2681
+ " to open settings and add your Anthropic API key,"
2682
+ ] }),
2683
+ /* @__PURE__ */ jsxs11(Text11, { dimColor: true, children: [
2684
+ " or set ",
2685
+ /* @__PURE__ */ jsx12(Text11, { bold: true, children: "ANTHROPIC_API_KEY" }),
2686
+ " in your environment."
2687
+ ] })
2688
+ ] });
2689
+ }
2690
+ return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", paddingX: 1, children: [
2691
+ /* @__PURE__ */ jsxs11(Text11, { children: [
2692
+ /* @__PURE__ */ jsx12(Text11, { bold: true, children: "Chat" }),
2693
+ " ",
2694
+ /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "Ask Trie anything" })
2695
+ ] }),
2696
+ /* @__PURE__ */ jsx12(Text11, { children: " " }),
2697
+ messages.length === 0 && !loading && /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", children: [
2698
+ /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: " Ask about your codebase, decisions, patterns, or risks." }),
2699
+ /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: " Trie uses your context graph and decision ledger to answer." }),
2700
+ /* @__PURE__ */ jsx12(Text11, { children: " " })
2701
+ ] }),
2702
+ messages.map((msg, idx) => /* @__PURE__ */ jsx12(Box11, { flexDirection: "column", marginBottom: 1, children: msg.role === "user" ? /* @__PURE__ */ jsxs11(Text11, { children: [
2703
+ " ",
2704
+ /* @__PURE__ */ jsx12(Text11, { bold: true, color: "green", children: "You:" }),
2705
+ " ",
2706
+ msg.content
2707
+ ] }) : /* @__PURE__ */ jsx12(Box11, { flexDirection: "column", children: /* @__PURE__ */ jsxs11(Text11, { children: [
2708
+ " ",
2709
+ /* @__PURE__ */ jsx12(Text11, { bold: true, children: "Trie:" }),
2710
+ " ",
2711
+ msg.content.slice(0, 500),
2712
+ msg.content.length > 500 ? "..." : ""
2713
+ ] }) }) }, idx)),
2714
+ loading && /* @__PURE__ */ jsxs11(Text11, { children: [
2715
+ " ",
2716
+ /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "Thinking..." })
2717
+ ] }),
2718
+ /* @__PURE__ */ jsx12(Box11, { flexGrow: 1 }),
2719
+ /* @__PURE__ */ jsx12(Box11, { borderStyle: "round", borderColor: "green", paddingX: 1, children: /* @__PURE__ */ jsxs11(Text11, { children: [
2720
+ inputBuffer || /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: "Ask a question..." }),
2721
+ /* @__PURE__ */ jsx12(Text11, { bold: true, color: "green", children: "|" })
2722
+ ] }) }),
2723
+ /* @__PURE__ */ jsx12(Text11, { dimColor: true, children: " enter send esc clear" })
2724
+ ] });
2725
+ }
2726
+
2727
+ // src/cli/dashboard/App.tsx
2728
+ import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
2729
+ var MAIN_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent", "chat"];
2511
2730
  function DashboardApp({ onReady }) {
2512
2731
  const { state, dispatch } = useDashboard();
2513
2732
  const { exit } = useApp();
2514
- const [showConfig, setShowConfig] = useState2(false);
2733
+ const [showConfig, setShowConfig] = useState3(false);
2515
2734
  const dispatchRef = useRef(dispatch);
2516
2735
  dispatchRef.current = dispatch;
2517
2736
  const stateRef = useRef(state);
2518
2737
  stateRef.current = state;
2519
2738
  const configPath = join(getTrieDirectory(getWorkingDirectory(void 0, true)), "agent.json");
2520
- const loadConfig = useCallback4(async () => {
2739
+ const loadConfig = useCallback6(async () => {
2521
2740
  if (!existsSync(configPath)) return;
2522
2741
  try {
2523
2742
  const raw = await readFile(configPath, "utf-8");
@@ -2526,14 +2745,14 @@ function DashboardApp({ onReady }) {
2526
2745
  } catch {
2527
2746
  }
2528
2747
  }, [configPath]);
2529
- const persistConfig = useCallback4(async () => {
2748
+ const persistConfig = useCallback6(async () => {
2530
2749
  try {
2531
2750
  await mkdir(getTrieDirectory(getWorkingDirectory(void 0, true)), { recursive: true });
2532
2751
  await writeFile(configPath, JSON.stringify(stateRef.current.agentConfig, null, 2), "utf-8");
2533
2752
  } catch {
2534
2753
  }
2535
2754
  }, [configPath]);
2536
- const processInsights = useCallback4(async (issues) => {
2755
+ const processInsights = useCallback6(async (issues) => {
2537
2756
  try {
2538
2757
  const workDir = getWorkingDirectory(void 0, true);
2539
2758
  const trieAgent = getGuardian(workDir);
@@ -2559,7 +2778,7 @@ function DashboardApp({ onReady }) {
2559
2778
  dispatchRef.current({ type: "ADD_ACTIVITY", message: `Trie Agent error: ${error instanceof Error ? error.message : "unknown"}` });
2560
2779
  }
2561
2780
  }, []);
2562
- const refreshGoals = useCallback4(async () => {
2781
+ const refreshGoals = useCallback6(async () => {
2563
2782
  try {
2564
2783
  const workDir = getWorkingDirectory(void 0, true);
2565
2784
  const agentState = getGuardianState(workDir);
@@ -2575,7 +2794,7 @@ function DashboardApp({ onReady }) {
2575
2794
  } catch {
2576
2795
  }
2577
2796
  }, []);
2578
- const refreshHypotheses = useCallback4(async () => {
2797
+ const refreshHypotheses = useCallback6(async () => {
2579
2798
  try {
2580
2799
  const workDir = getWorkingDirectory(void 0, true);
2581
2800
  const agentState = getGuardianState(workDir);
@@ -2591,7 +2810,7 @@ function DashboardApp({ onReady }) {
2591
2810
  } catch {
2592
2811
  }
2593
2812
  }, []);
2594
- useEffect2(() => {
2813
+ useEffect4(() => {
2595
2814
  void loadConfig();
2596
2815
  void refreshGoals();
2597
2816
  void refreshHypotheses();
@@ -2632,16 +2851,24 @@ function DashboardApp({ onReady }) {
2632
2851
  outputManager.setMode("console");
2633
2852
  };
2634
2853
  }, [loadConfig, onReady, processInsights, refreshGoals, refreshHypotheses]);
2635
- useEffect2(() => {
2854
+ useEffect4(() => {
2636
2855
  const interval = setInterval(() => {
2637
2856
  dispatchRef.current({ type: "AUTO_DISMISS_NOTIFICATIONS" });
2638
2857
  }, 5e3);
2639
2858
  return () => clearInterval(interval);
2640
2859
  }, []);
2641
- useInput7((input, key) => {
2860
+ useInput8((input, key) => {
2642
2861
  if (showConfig) return;
2643
2862
  if (state.view === "goals" && state.goalsPanel.inputMode === "add") return;
2644
2863
  if (state.view === "hypotheses" && state.hypothesesPanel.inputMode === "add") return;
2864
+ if (state.view === "chat") {
2865
+ if (key.tab) {
2866
+ const currentIndex = MAIN_VIEWS.indexOf(state.view);
2867
+ const nextIndex = (currentIndex + 1) % MAIN_VIEWS.length;
2868
+ dispatch({ type: "SET_VIEW", view: MAIN_VIEWS[nextIndex] || "overview" });
2869
+ }
2870
+ return;
2871
+ }
2645
2872
  if (input === "q" || key.escape) {
2646
2873
  exit();
2647
2874
  process.exit(0);
@@ -2652,7 +2879,7 @@ function DashboardApp({ onReady }) {
2652
2879
  dispatch({ type: "SET_VIEW", view: MAIN_VIEWS[nextIndex] || "overview" });
2653
2880
  return;
2654
2881
  }
2655
- if (input === "c") {
2882
+ if (input === "s") {
2656
2883
  setShowConfig(true);
2657
2884
  return;
2658
2885
  }
@@ -2678,6 +2905,10 @@ function DashboardApp({ onReady }) {
2678
2905
  dispatch({ type: "SET_VIEW", view: "memory" });
2679
2906
  return;
2680
2907
  }
2908
+ if (input === "c") {
2909
+ dispatch({ type: "SET_VIEW", view: "chat" });
2910
+ return;
2911
+ }
2681
2912
  if (state.view === "agent" || state.view === "memory") return;
2682
2913
  if (input === "b") dispatch({ type: "GO_BACK" });
2683
2914
  if (input === "n") dispatch({ type: "NEXT_PAGE" });
@@ -2686,38 +2917,41 @@ function DashboardApp({ onReady }) {
2686
2917
  let viewComponent;
2687
2918
  switch (state.view) {
2688
2919
  case "overview":
2689
- viewComponent = /* @__PURE__ */ jsx12(OverviewView, {});
2920
+ viewComponent = /* @__PURE__ */ jsx13(OverviewView, {});
2690
2921
  break;
2691
2922
  case "agent":
2692
- viewComponent = /* @__PURE__ */ jsx12(AgentView, {});
2923
+ viewComponent = /* @__PURE__ */ jsx13(AgentView, {});
2693
2924
  break;
2694
2925
  case "goals":
2695
- viewComponent = /* @__PURE__ */ jsx12(GoalsView, {});
2926
+ viewComponent = /* @__PURE__ */ jsx13(GoalsView, {});
2696
2927
  break;
2697
2928
  case "hypotheses":
2698
- viewComponent = /* @__PURE__ */ jsx12(HypothesesView, {});
2929
+ viewComponent = /* @__PURE__ */ jsx13(HypothesesView, {});
2699
2930
  break;
2700
2931
  case "memory":
2701
- viewComponent = /* @__PURE__ */ jsx12(MemoryTreeView, {});
2932
+ viewComponent = /* @__PURE__ */ jsx13(MemoryTreeView, {});
2702
2933
  break;
2703
2934
  case "rawlog":
2704
- viewComponent = /* @__PURE__ */ jsx12(RawLogView, {});
2935
+ viewComponent = /* @__PURE__ */ jsx13(RawLogView, {});
2936
+ break;
2937
+ case "chat":
2938
+ viewComponent = /* @__PURE__ */ jsx13(ChatView, {});
2705
2939
  break;
2706
2940
  default:
2707
- viewComponent = /* @__PURE__ */ jsx12(OverviewView, {});
2941
+ viewComponent = /* @__PURE__ */ jsx13(OverviewView, {});
2708
2942
  }
2709
- return /* @__PURE__ */ jsxs11(Box11, { flexDirection: "column", height: process.stdout.rows || 40, children: [
2710
- /* @__PURE__ */ jsx12(Header, {}),
2711
- /* @__PURE__ */ jsx12(Notification, {}),
2712
- /* @__PURE__ */ jsx12(Box11, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: showConfig ? /* @__PURE__ */ jsx12(ConfigDialog, { onClose: () => {
2943
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", height: process.stdout.rows || 40, children: [
2944
+ /* @__PURE__ */ jsx13(Header, {}),
2945
+ /* @__PURE__ */ jsx13(Notification, {}),
2946
+ /* @__PURE__ */ jsx13(Box12, { flexGrow: 1, flexDirection: "column", overflow: "hidden", children: showConfig ? /* @__PURE__ */ jsx13(ConfigDialog, { onClose: () => {
2713
2947
  setShowConfig(false);
2714
2948
  void persistConfig();
2715
2949
  } }) : viewComponent }),
2716
- /* @__PURE__ */ jsx12(Footer, {})
2950
+ /* @__PURE__ */ jsx13(Footer, {})
2717
2951
  ] });
2718
2952
  }
2719
2953
  function App({ onReady }) {
2720
- return /* @__PURE__ */ jsx12(DashboardProvider, { children: /* @__PURE__ */ jsx12(DashboardApp, { onReady }) });
2954
+ return /* @__PURE__ */ jsx13(DashboardProvider, { children: /* @__PURE__ */ jsx13(DashboardApp, { onReady }) });
2721
2955
  }
2722
2956
 
2723
2957
  // src/cli/dashboard/index.ts
@@ -2727,7 +2961,7 @@ var InteractiveDashboard = class {
2727
2961
  getConfigFn = null;
2728
2962
  async start() {
2729
2963
  this.app = render(
2730
- React7.createElement(App, {
2964
+ React10.createElement(App, {
2731
2965
  onReady: (handler, getConfig) => {
2732
2966
  this.updateHandler = handler;
2733
2967
  this.getConfigFn = getConfig;
@@ -2761,4 +2995,4 @@ export {
2761
2995
  getOutputManager,
2762
2996
  InteractiveDashboard
2763
2997
  };
2764
- //# sourceMappingURL=chunk-M3WF7ZXI.js.map
2998
+ //# sourceMappingURL=chunk-3YDNSKKP.js.map