@triedotdev/mcp 1.0.130 → 1.0.133

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (36) hide show
  1. package/dist/{chunk-WIMNGEY2.js → chunk-3DPVJQNM.js} +3 -3
  2. package/dist/{chunk-7TTVDHXO.js → chunk-6OUWNVLX.js} +2 -2
  3. package/dist/{chunk-K5EXATBF.js → chunk-JAKMZI5S.js} +2 -2
  4. package/dist/{chunk-WMI44VIC.js → chunk-JCU6REX7.js} +6 -2
  5. package/dist/{chunk-WMI44VIC.js.map → chunk-JCU6REX7.js.map} +1 -1
  6. package/dist/{chunk-SUPXBOJD.js → chunk-LMFREFAP.js} +294 -84
  7. package/dist/chunk-LMFREFAP.js.map +1 -0
  8. package/dist/{chunk-W2DEBKZ2.js → chunk-LRQV7SGQ.js} +3 -3
  9. package/dist/{chunk-7Q6I2CB4.js → chunk-PEJEYWVR.js} +7 -2
  10. package/dist/{chunk-7Q6I2CB4.js.map → chunk-PEJEYWVR.js.map} +1 -1
  11. package/dist/{chunk-TRIJC5MW.js → chunk-T4THB2OR.js} +2 -2
  12. package/dist/{chunk-CDU4B7AC.js → chunk-T62V4H5O.js} +7 -7
  13. package/dist/cli/main.js +5 -5
  14. package/dist/cli/yolo-daemon.js +9 -9
  15. package/dist/{client-EWP4SIG3.js → client-OVI6TBX7.js} +2 -2
  16. package/dist/{goal-manager-RREOIX6U.js → goal-manager-FAK7H4RR.js} +4 -4
  17. package/dist/{goal-validator-NLOJJ7FF.js → goal-validator-KLAK5TZN.js} +9 -3
  18. package/dist/goal-validator-KLAK5TZN.js.map +1 -0
  19. package/dist/{guardian-agent-Q34YVH4J.js → guardian-agent-3EUJUAJ2.js} +8 -8
  20. package/dist/{hypothesis-HFYZNIMZ.js → hypothesis-I276JIDW.js} +4 -4
  21. package/dist/index.js +16 -16
  22. package/dist/{ledger-JMPGJGLB.js → ledger-WKVJWHBX.js} +4 -2
  23. package/package.json +1 -1
  24. package/dist/chunk-SUPXBOJD.js.map +0 -1
  25. package/dist/goal-validator-NLOJJ7FF.js.map +0 -1
  26. /package/dist/{chunk-WIMNGEY2.js.map → chunk-3DPVJQNM.js.map} +0 -0
  27. /package/dist/{chunk-7TTVDHXO.js.map → chunk-6OUWNVLX.js.map} +0 -0
  28. /package/dist/{chunk-K5EXATBF.js.map → chunk-JAKMZI5S.js.map} +0 -0
  29. /package/dist/{chunk-W2DEBKZ2.js.map → chunk-LRQV7SGQ.js.map} +0 -0
  30. /package/dist/{chunk-TRIJC5MW.js.map → chunk-T4THB2OR.js.map} +0 -0
  31. /package/dist/{chunk-CDU4B7AC.js.map → chunk-T62V4H5O.js.map} +0 -0
  32. /package/dist/{client-EWP4SIG3.js.map → client-OVI6TBX7.js.map} +0 -0
  33. /package/dist/{goal-manager-RREOIX6U.js.map → goal-manager-FAK7H4RR.js.map} +0 -0
  34. /package/dist/{guardian-agent-Q34YVH4J.js.map → guardian-agent-3EUJUAJ2.js.map} +0 -0
  35. /package/dist/{hypothesis-HFYZNIMZ.js.map → hypothesis-I276JIDW.js.map} +0 -0
  36. /package/dist/{ledger-JMPGJGLB.js.map → ledger-WKVJWHBX.js.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  getGuardian
3
- } from "./chunk-CDU4B7AC.js";
3
+ } from "./chunk-T62V4H5O.js";
4
4
  import {
5
5
  getChatStore
6
6
  } from "./chunk-DFPVUMVE.js";
@@ -13,19 +13,19 @@ import {
13
13
  perceiveCurrentChanges,
14
14
  reasonAboutChangesHumanReadable,
15
15
  saveCheckpoint
16
- } from "./chunk-7TTVDHXO.js";
16
+ } from "./chunk-6OUWNVLX.js";
17
17
  import {
18
18
  IncidentIndex
19
19
  } from "./chunk-WHIQAGB7.js";
20
20
  import {
21
21
  findCrossProjectPatterns
22
- } from "./chunk-WIMNGEY2.js";
22
+ } from "./chunk-3DPVJQNM.js";
23
23
  import {
24
24
  getKeyFromKeychain,
25
25
  isAIAvailable,
26
26
  runAIWithTools,
27
27
  setAPIKey
28
- } from "./chunk-WMI44VIC.js";
28
+ } from "./chunk-JCU6REX7.js";
29
29
  import {
30
30
  getGuardianState
31
31
  } from "./chunk-UHMMANC2.js";
@@ -39,6 +39,9 @@ import {
39
39
  import {
40
40
  getOutputManager
41
41
  } from "./chunk-VRLMTOB6.js";
42
+ import {
43
+ getLedgerBlocks
44
+ } from "./chunk-PEJEYWVR.js";
42
45
  import {
43
46
  getTrieDirectory,
44
47
  getWorkingDirectory
@@ -312,19 +315,25 @@ function getVisibleInsights(state) {
312
315
  }
313
316
  function getMemoryTreeNodes(state) {
314
317
  const nodes = [];
315
- const { expandedNodes, snapshot, globalPatterns } = state.memoryTree;
316
- if (!snapshot) return nodes;
317
- const decisionNodes = snapshot.nodes.filter((n) => n.type === "decision");
318
- const incidentNodes = snapshot.nodes.filter((n) => n.type === "incident");
319
- const patternNodes = snapshot.nodes.filter((n) => n.type === "pattern");
320
- const fileNodes = snapshot.nodes.filter((n) => n.type === "file");
318
+ const { expandedNodes, snapshot, globalPatterns, storageDecisions, ledgerBlocks } = state.memoryTree;
319
+ const decisionNodes = snapshot?.nodes.filter((n) => n.type === "decision") ?? [];
320
+ const incidentNodes = snapshot?.nodes.filter((n) => n.type === "incident") ?? [];
321
+ const patternNodes = snapshot?.nodes.filter((n) => n.type === "pattern") ?? [];
322
+ const fileNodes = snapshot?.nodes.filter((n) => n.type === "file") ?? [];
321
323
  const hotspots = fileNodes.filter((n) => {
322
324
  const risk = n.data.riskLevel;
323
325
  return risk === "critical" || risk === "high";
324
326
  });
327
+ const decisions = storageDecisions.length > 0 ? storageDecisions : decisionNodes.map((n) => ({
328
+ id: n.id,
329
+ decision: n.data.decision,
330
+ context: n.data.context,
331
+ when: n.data.timestamp,
332
+ hash: void 0
333
+ }));
325
334
  nodes.push({ id: "decisions", level: 0 });
326
335
  if (expandedNodes.has("decisions")) {
327
- decisionNodes.slice(0, 10).forEach((n) => nodes.push({ id: `decision-${n.id}`, level: 1 }));
336
+ decisions.slice(0, 10).forEach((d) => nodes.push({ id: `decision-${d.id}`, level: 1 }));
328
337
  }
329
338
  nodes.push({ id: "incidents", level: 0 });
330
339
  if (expandedNodes.has("incidents")) {
@@ -344,6 +353,12 @@ function getMemoryTreeNodes(state) {
344
353
  hotspots.slice(0, 10).forEach((n) => nodes.push({ id: `file-${n.id}`, level: 1 }));
345
354
  }
346
355
  }
356
+ if (ledgerBlocks.length > 0) {
357
+ nodes.push({ id: "ledger-chain", level: 0 });
358
+ if (expandedNodes.has("ledger-chain")) {
359
+ ledgerBlocks.forEach((_, i) => nodes.push({ id: `ledger-block-${i}`, level: 1 }));
360
+ }
361
+ }
347
362
  return nodes;
348
363
  }
349
364
  function handleStreamUpdate(state, update) {
@@ -637,17 +652,30 @@ function dashboardReducer(state, action) {
637
652
  case "SET_MEMORY_TREE":
638
653
  return {
639
654
  ...state,
640
- memoryTree: { ...state.memoryTree, loaded: true, snapshot: action.snapshot, globalPatterns: action.patterns }
655
+ memoryTree: {
656
+ ...state.memoryTree,
657
+ loaded: true,
658
+ snapshot: action.snapshot,
659
+ globalPatterns: action.patterns,
660
+ storageDecisions: action.storageDecisions ?? state.memoryTree.storageDecisions,
661
+ ledgerBlocks: action.ledgerBlocks ?? state.memoryTree.ledgerBlocks
662
+ }
641
663
  };
642
664
  case "SELECT_MEMORY_NODE":
643
665
  return { ...state, memoryTree: { ...state.memoryTree, selectedNode: action.nodeId } };
666
+ case "SET_MEMORY_EXPANDED_ITEM":
667
+ return { ...state, memoryTree: { ...state.memoryTree, expandedItemId: action.itemId } };
644
668
  case "TOGGLE_MEMORY_NODE": {
645
- const expandable = ["decisions", "incidents", "patterns", "cross-project", "hotspots"];
646
- if (!expandable.includes(action.nodeId)) return state;
647
- const expanded = new Set(state.memoryTree.expandedNodes);
648
- if (expanded.has(action.nodeId)) expanded.delete(action.nodeId);
649
- else expanded.add(action.nodeId);
650
- return { ...state, memoryTree: { ...state.memoryTree, expandedNodes: expanded } };
669
+ const expandable = ["decisions", "incidents", "patterns", "cross-project", "hotspots", "ledger-chain"];
670
+ if (expandable.includes(action.nodeId)) {
671
+ const expanded = new Set(state.memoryTree.expandedNodes);
672
+ if (expanded.has(action.nodeId)) expanded.delete(action.nodeId);
673
+ else expanded.add(action.nodeId);
674
+ return { ...state, memoryTree: { ...state.memoryTree, expandedNodes: expanded } };
675
+ }
676
+ const current = state.memoryTree.expandedItemId;
677
+ const next = current === action.nodeId ? null : action.nodeId;
678
+ return { ...state, memoryTree: { ...state.memoryTree, expandedItemId: next } };
651
679
  }
652
680
  case "SET_AGENT_BRAIN":
653
681
  return {
@@ -680,13 +708,28 @@ function dashboardReducer(state, action) {
680
708
  };
681
709
  }
682
710
  case "SET_CHAT_LOADING":
683
- return { ...state, chatState: { ...state.chatState, loading: action.loading } };
711
+ return {
712
+ ...state,
713
+ chatState: {
714
+ ...state.chatState,
715
+ loading: action.loading,
716
+ ...action.loading === false ? { progress: null } : {}
717
+ }
718
+ };
719
+ case "SET_CHAT_PROGRESS":
720
+ return { ...state, chatState: { ...state.chatState, progress: action.message } };
721
+ case "QUEUE_CHAT_MESSAGE":
722
+ return { ...state, chatState: { ...state.chatState, messageQueue: [...state.chatState.messageQueue, action.message] } };
723
+ case "DEQUEUE_CHAT_MESSAGE": {
724
+ const [, ...rest] = state.chatState.messageQueue;
725
+ return { ...state, chatState: { ...state.chatState, messageQueue: rest } };
726
+ }
684
727
  case "SET_CHAT_SESSION":
685
728
  return { ...state, chatState: { ...state.chatState, currentSessionId: action.sessionId, currentSessionTitle: action.title } };
686
729
  case "LOAD_CHAT_MESSAGES":
687
730
  return { ...state, chatState: { ...state.chatState, messages: action.messages } };
688
731
  case "CLEAR_CHAT":
689
- return { ...state, chatState: { messages: [], inputBuffer: "", loading: false, currentSessionId: null, currentSessionTitle: null } };
732
+ return { ...state, chatState: { messages: [], inputBuffer: "", loading: false, progress: null, messageQueue: [], currentSessionId: null, currentSessionTitle: null } };
690
733
  case "SET_CHAT_ARCHIVE_SESSIONS":
691
734
  return { ...state, chatArchivePanel: { ...state.chatArchivePanel, sessions: action.sessions } };
692
735
  case "SELECT_CHAT_SESSION": {
@@ -852,9 +895,9 @@ function createInitialState() {
852
895
  },
853
896
  goalsPanel: { goals: [], selectedIndex: 0, selectedAchievedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0 },
854
897
  hypothesesPanel: { hypotheses: [], selectedIndex: 0, selectedCompletedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0 },
855
- memoryTree: { loaded: false, snapshot: null, globalPatterns: [], expandedNodes: /* @__PURE__ */ new Set(["decisions"]), selectedNode: "decisions", scrollPosition: 0, lastRefresh: 0 },
898
+ memoryTree: { loaded: false, snapshot: null, globalPatterns: [], storageDecisions: [], ledgerBlocks: [], expandedNodes: /* @__PURE__ */ new Set(["decisions"]), expandedItemId: null, selectedNode: "decisions", scrollPosition: 0, lastRefresh: 0 },
856
899
  agentBrain: { loaded: false, decisions: [], patterns: [], ledgerHash: null, selectedIndex: 0, expandedIndex: null },
857
- chatState: { messages: [], inputBuffer: "", loading: false, currentSessionId: null, currentSessionTitle: null },
900
+ chatState: { messages: [], inputBuffer: "", loading: false, progress: null, messageQueue: [], currentSessionId: null, currentSessionTitle: null },
858
901
  chatArchivePanel: { sessions: [], selectedIndex: 0, showArchived: false, loading: false, inputMode: "browse", inputBuffer: "" },
859
902
  pendingFixes: [],
860
903
  selectedFixIndex: 0
@@ -923,6 +966,18 @@ function Header() {
923
966
  // src/cli/dashboard/components/Footer.tsx
924
967
  import React2 from "react";
925
968
  import { Box as Box2, Text as Text2, useStdout as useStdout2 } from "ink";
969
+
970
+ // src/cli/dashboard/parse-goal-violation.ts
971
+ function parseGoalViolation(message) {
972
+ const match = message.match(/Goal "([^"]+)" violated in ([^:]+): (.+)/);
973
+ if (!match) return null;
974
+ const [, goal, file, violation] = match;
975
+ if (!goal || !file || !violation) return null;
976
+ const cleanViolation = violation.replace(/\s*\[\d+%\s*confidence\]\s*$/i, "").trim();
977
+ return { file: file.trim(), goal: goal.trim(), violation: cleanViolation };
978
+ }
979
+
980
+ // src/cli/dashboard/components/Footer.tsx
926
981
  import { jsx as jsx3, jsxs as jsxs2 } from "react/jsx-runtime";
927
982
  var VIEW_LABELS = {
928
983
  overview: "Overview",
@@ -979,6 +1034,12 @@ function Footer() {
979
1034
  hints = narrow ? "enter esc" : "enter save \xB7 esc cancel";
980
1035
  } else if (view === "chat" || view === "chat-archive") {
981
1036
  hints = "";
1037
+ } else if (view === "agent") {
1038
+ const visible = getVisibleInsights(state);
1039
+ const alerts = visible.filter((i) => i.type === "warning");
1040
+ const insight = alerts[state.selectedInsight];
1041
+ const isFixable = insight && parseGoalViolation(insight.message);
1042
+ hints = isFixable ? narrow ? "/ f" : "/ help \xB7 f fix" : (narrow ? CONTEXT_HINTS_SHORT : CONTEXT_HINTS).agent ?? (narrow ? "/" : "/ help");
982
1043
  } else {
983
1044
  const hintMap = narrow ? CONTEXT_HINTS_SHORT : CONTEXT_HINTS;
984
1045
  hints = hintMap[view] || (narrow ? "/" : "/ help");
@@ -1435,6 +1496,7 @@ var VIEW_HELP = {
1435
1496
  { key: "j / \u2193", description: "Move down" },
1436
1497
  { key: "k / \u2191", description: "Move up" },
1437
1498
  { key: "enter", description: "Expand selected nudge" },
1499
+ { key: "f", description: "Spawn Claude Code to fix selected goal violation" },
1438
1500
  { key: "d", description: "Dismiss selected nudge" },
1439
1501
  { key: "tab", description: "Navigate between views" },
1440
1502
  { key: "s", description: "Open Settings" },
@@ -1466,16 +1528,17 @@ var VIEW_HELP = {
1466
1528
  memory: [
1467
1529
  { key: "j / \u2193", description: "Move down" },
1468
1530
  { key: "k / \u2191", description: "Move up" },
1469
- { key: "enter", description: "Expand selected item" },
1531
+ { key: "enter", description: "Expand section or decision detail" },
1532
+ { key: "esc", description: "Close decision detail" },
1470
1533
  { key: "tab", description: "Navigate between views" },
1471
1534
  { key: "s", description: "Open Settings" },
1472
1535
  { key: "q / esc", description: "Quit" }
1473
1536
  ],
1474
1537
  chat: [
1475
- { key: "type", description: "Enter message" },
1538
+ { key: "type", description: "Enter message (queue while AI responds)" },
1476
1539
  { key: "enter", description: "Send message" },
1477
1540
  { key: "esc", description: "Clear input" },
1478
- { key: "h", description: "Open chat history" },
1541
+ { key: "/history", description: "Open chat history" },
1479
1542
  { key: "tab", description: "Navigate between views" },
1480
1543
  { key: "q", description: "Quit (press twice if input active)" }
1481
1544
  ],
@@ -1715,17 +1778,6 @@ function AgentView() {
1715
1778
  const visibleInsights = getVisibleInsights(state);
1716
1779
  const alerts = visibleInsights.filter((i) => i.type === "warning");
1717
1780
  const { decisions, patterns, loaded } = agentBrain;
1718
- useEffect(() => {
1719
- if (agentInsights.length > 0 || visibleInsights.length > 0) {
1720
- console.debug("[AgentView Debug]", {
1721
- totalInsights: agentInsights.length,
1722
- visibleInsights: visibleInsights.length,
1723
- alerts: alerts.length,
1724
- insightTypes: agentInsights.map((i) => i.type),
1725
- visibleTypes: visibleInsights.map((i) => i.type)
1726
- });
1727
- }
1728
- }, [agentInsights, visibleInsights, alerts]);
1729
1781
  const loadBrain = useCallback(async () => {
1730
1782
  try {
1731
1783
  const workDir = getWorkingDirectory(void 0, true);
@@ -1769,11 +1821,37 @@ function AgentView() {
1769
1821
  }
1770
1822
  dispatch({ type: "DISMISS_INSIGHT", index: selectedInsight });
1771
1823
  }, [selectedInsight, state, dispatch]);
1824
+ const spawnFixForInsight = useCallback(async () => {
1825
+ const visible = getVisibleInsights(state);
1826
+ const insight = visible[selectedInsight];
1827
+ if (!insight) return;
1828
+ const parsed = parseGoalViolation(insight.message);
1829
+ if (!parsed) {
1830
+ dispatch({ type: "ADD_ACTIVITY", message: "Selected nudge is not a goal violation (cannot fix)" });
1831
+ return;
1832
+ }
1833
+ const workDir = getWorkingDirectory(void 0, true);
1834
+ try {
1835
+ const { spawnClaudeCodeFix } = await import("./terminal-spawn-P5M5PHAV.js");
1836
+ await spawnClaudeCodeFix({
1837
+ file: parsed.file,
1838
+ goal: parsed.goal,
1839
+ violation: parsed.violation,
1840
+ suggestedFix: insight.suggestedAction || void 0,
1841
+ cwd: workDir
1842
+ });
1843
+ dispatch({ type: "ADD_ACTIVITY", message: `Spawned Claude Code to fix ${parsed.file}` });
1844
+ } catch (error) {
1845
+ const msg = error instanceof Error ? error.message : "Unknown error";
1846
+ dispatch({ type: "ADD_ACTIVITY", message: `Fix spawn failed: ${msg}` });
1847
+ }
1848
+ }, [selectedInsight, state, dispatch]);
1772
1849
  useInput3((input, key) => {
1773
1850
  if (key.upArrow || input === "k") dispatch({ type: "NAVIGATE_UP" });
1774
1851
  else if (key.downArrow || input === "j") dispatch({ type: "NAVIGATE_DOWN" });
1775
1852
  else if (key.return) dispatch({ type: "TOGGLE_INSIGHT", index: selectedInsight });
1776
1853
  else if (input === "d") void dismissInsight();
1854
+ else if (input === "f") void spawnFixForInsight();
1777
1855
  });
1778
1856
  const alertCount = alerts.length;
1779
1857
  const decCount = decisions.length;
@@ -2018,7 +2096,7 @@ function GoalsView() {
2018
2096
  if (!goal) return;
2019
2097
  dispatch({ type: "ADD_ACTIVITY", message: `Checking goal: ${goal.description.slice(0, 30)}...` });
2020
2098
  dispatch({ type: "SHOW_NOTIFICATION", message: `Scanning files...`, severity: "info", autoHideMs: 5e3 });
2021
- const { checkFilesForGoalViolations } = await import("./goal-validator-NLOJJ7FF.js");
2099
+ const { checkFilesForGoalViolations } = await import("./goal-validator-KLAK5TZN.js");
2022
2100
  const violations = await checkFilesForGoalViolations([goal], workDir);
2023
2101
  if (violations.length === 0) {
2024
2102
  dispatch({ type: "SHOW_NOTIFICATION", message: `\u2713 No violations found for: ${goal.description.slice(0, 40)}`, severity: "info", autoHideMs: 5e3 });
@@ -2220,7 +2298,7 @@ function HypothesesView() {
2220
2298
  if (!hypo) return;
2221
2299
  dispatch({ type: "ADD_ACTIVITY", message: `Testing hypothesis: ${hypo.statement.slice(0, 30)}...` });
2222
2300
  dispatch({ type: "SHOW_NOTIFICATION", message: `Gathering evidence for hypothesis...`, severity: "info", autoHideMs: 3e3 });
2223
- const { gatherEvidenceForHypothesis } = await import("./hypothesis-HFYZNIMZ.js");
2301
+ const { gatherEvidenceForHypothesis } = await import("./hypothesis-I276JIDW.js");
2224
2302
  const evidence = await gatherEvidenceForHypothesis(hypoId, workDir);
2225
2303
  if (evidence.length === 0) {
2226
2304
  dispatch({ type: "SHOW_NOTIFICATION", message: `No evidence found for: ${hypo.statement.slice(0, 40)}`, severity: "info", autoHideMs: 5e3 });
@@ -2346,16 +2424,19 @@ function timeAgo2(iso) {
2346
2424
  function MemoryTreeView() {
2347
2425
  const { state, dispatch } = useDashboard();
2348
2426
  const { memoryTree } = state;
2349
- const { snapshot, globalPatterns, expandedNodes, selectedNode, loaded } = memoryTree;
2427
+ const { snapshot, globalPatterns, storageDecisions, ledgerBlocks, expandedNodes, expandedItemId, selectedNode, loaded } = memoryTree;
2350
2428
  const loadData = useCallback4(async () => {
2351
2429
  try {
2352
2430
  const workDir = getWorkingDirectory(void 0, true);
2353
2431
  const graph = new ContextGraph(workDir);
2354
- const [snap, patterns] = await Promise.all([
2432
+ const storage = new TieredStorage(workDir);
2433
+ const [snap, patterns, decisions2, blocks] = await Promise.all([
2355
2434
  graph.getSnapshot(),
2356
- findCrossProjectPatterns(2)
2435
+ findCrossProjectPatterns(2),
2436
+ storage.queryDecisions({ limit: 20 }).catch(() => []),
2437
+ getLedgerBlocks(workDir).catch(() => [])
2357
2438
  ]);
2358
- dispatch({ type: "SET_MEMORY_TREE", snapshot: snap, patterns });
2439
+ dispatch({ type: "SET_MEMORY_TREE", snapshot: snap, patterns, storageDecisions: decisions2, ledgerBlocks: blocks });
2359
2440
  } catch {
2360
2441
  dispatch({ type: "ADD_ACTIVITY", message: "Context graph load error" });
2361
2442
  }
@@ -2369,6 +2450,7 @@ function MemoryTreeView() {
2369
2450
  if (key.upArrow || _input === "k") dispatch({ type: "NAVIGATE_UP" });
2370
2451
  else if (key.downArrow || _input === "j") dispatch({ type: "NAVIGATE_DOWN" });
2371
2452
  else if (key.return) dispatch({ type: "TOGGLE_MEMORY_NODE", nodeId: selectedNode });
2453
+ else if (key.escape && expandedItemId) dispatch({ type: "SET_MEMORY_EXPANDED_ITEM", itemId: null });
2372
2454
  });
2373
2455
  const sel = (nodeId) => selectedNode === nodeId;
2374
2456
  if (!loaded) {
@@ -2377,21 +2459,27 @@ function MemoryTreeView() {
2377
2459
  /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: " Loading..." })
2378
2460
  ] });
2379
2461
  }
2380
- if (!snapshot || snapshot.nodes.length === 0 && globalPatterns.length === 0) {
2381
- return /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", paddingX: 1, children: [
2382
- /* @__PURE__ */ jsx11(Text10, { bold: true, children: "Ledger" }),
2383
- /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: " No entries yet. Use trie tell or trie watch to build memory." })
2384
- ] });
2385
- }
2386
- const decisionNodes = snapshot.nodes.filter((n) => n.type === "decision") ?? [];
2387
- const incidentNodes = snapshot.nodes.filter((n) => n.type === "incident") ?? [];
2388
- const patternNodes = snapshot.nodes.filter((n) => n.type === "pattern") ?? [];
2389
- const fileNodes = snapshot.nodes.filter((n) => n.type === "file") ?? [];
2462
+ const decisionNodes = snapshot?.nodes.filter((n) => n.type === "decision") ?? [];
2463
+ const incidentNodes = snapshot?.nodes.filter((n) => n.type === "incident") ?? [];
2464
+ const patternNodes = snapshot?.nodes.filter((n) => n.type === "pattern") ?? [];
2465
+ const fileNodes = snapshot?.nodes.filter((n) => n.type === "file") ?? [];
2466
+ const decisions = storageDecisions.length > 0 ? storageDecisions : decisionNodes.map((n) => ({
2467
+ id: n.id,
2468
+ decision: n.data.decision,
2469
+ context: n.data.context,
2470
+ reasoning: n.data.reasoning ?? void 0,
2471
+ when: n.data.timestamp,
2472
+ files: [],
2473
+ tags: [],
2474
+ status: "active",
2475
+ outcome: n.data.outcome
2476
+ }));
2390
2477
  const hotspots = fileNodes.filter((n) => n.data.riskLevel === "critical" || n.data.riskLevel === "high").sort((a, b) => {
2391
2478
  const order = { critical: 0, high: 1 };
2392
2479
  return (order[a.data.riskLevel] ?? 2) - (order[b.data.riskLevel] ?? 2);
2393
2480
  });
2394
- const totalEntries = decisionNodes.length + incidentNodes.length + patternNodes.length + globalPatterns.length + hotspots.length;
2481
+ const totalEntries = decisions.length + incidentNodes.length + patternNodes.length + globalPatterns.length + hotspots.length + ledgerBlocks.length;
2482
+ const expandedDecision = expandedItemId?.startsWith("decision-") ? decisions.find((d) => `decision-${d.id}` === expandedItemId) : null;
2395
2483
  function renderHeader(id, label, count, emptyHint) {
2396
2484
  const expanded = expandedNodes.has(id);
2397
2485
  const isEmpty = count === 0;
@@ -2419,27 +2507,66 @@ function MemoryTreeView() {
2419
2507
  " entries"
2420
2508
  ] })
2421
2509
  ] }),
2510
+ expandedDecision && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, borderStyle: "single", borderColor: "cyan", paddingX: 1, paddingY: 1, children: [
2511
+ /* @__PURE__ */ jsx11(Text10, { bold: true, color: "cyan", children: "Decision detail (Enter or Esc to close)" }),
2512
+ /* @__PURE__ */ jsxs10(Text10, { marginTop: 1, children: [
2513
+ /* @__PURE__ */ jsx11(Text10, { bold: true, children: "Decision:" }),
2514
+ " ",
2515
+ expandedDecision.decision
2516
+ ] }),
2517
+ /* @__PURE__ */ jsxs10(Text10, { marginTop: 1, children: [
2518
+ /* @__PURE__ */ jsx11(Text10, { bold: true, children: "Context:" }),
2519
+ " ",
2520
+ expandedDecision.context
2521
+ ] }),
2522
+ expandedDecision.reasoning && /* @__PURE__ */ jsxs10(Text10, { marginTop: 1, children: [
2523
+ /* @__PURE__ */ jsx11(Text10, { bold: true, children: "Reasoning:" }),
2524
+ " ",
2525
+ expandedDecision.reasoning
2526
+ ] }),
2527
+ expandedDecision.hash && /* @__PURE__ */ jsxs10(Text10, { marginTop: 1, children: [
2528
+ /* @__PURE__ */ jsx11(Text10, { bold: true, children: "Hash:" }),
2529
+ " ",
2530
+ /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: expandedDecision.hash })
2531
+ ] }),
2532
+ expandedDecision.files?.length ? /* @__PURE__ */ jsxs10(Text10, { marginTop: 1, children: [
2533
+ /* @__PURE__ */ jsx11(Text10, { bold: true, children: "Files:" }),
2534
+ " ",
2535
+ expandedDecision.files.join(", ")
2536
+ ] }) : null,
2537
+ expandedDecision.tags?.length ? /* @__PURE__ */ jsxs10(Text10, { marginTop: 1, children: [
2538
+ /* @__PURE__ */ jsx11(Text10, { bold: true, children: "Tags:" }),
2539
+ " ",
2540
+ expandedDecision.tags.join(", ")
2541
+ ] }) : null,
2542
+ /* @__PURE__ */ jsx11(Text10, { marginTop: 1, dimColor: true, children: expandedDecision.when })
2543
+ ] }),
2422
2544
  /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, children: [
2423
- renderHeader("decisions", "Decisions", decisionNodes.length, "-- use trie tell or chat"),
2424
- expandedNodes.has("decisions") && decisionNodes.slice(0, 10).map((n) => {
2425
- const nodeId = `decision-${n.id}`;
2426
- const dec = n.data.decision.length > 55 ? n.data.decision.slice(0, 52) + "..." : n.data.decision;
2427
- const outcomeColor = n.data.outcome === "good" ? "green" : n.data.outcome === "bad" ? "red" : void 0;
2545
+ renderHeader("decisions", "Decisions", decisions.length, "-- use trie tell or chat"),
2546
+ expandedNodes.has("decisions") && decisions.slice(0, 10).map((d) => {
2547
+ const nodeId = `decision-${d.id}`;
2548
+ const dec = d.decision.length > 50 ? d.decision.slice(0, 47) + "..." : d.decision;
2549
+ const outcomeColor = d.outcome === "good" ? "green" : d.outcome === "bad" ? "red" : void 0;
2428
2550
  return /* @__PURE__ */ jsxs10(Text10, { children: [
2429
2551
  sel(nodeId) ? /* @__PURE__ */ jsx11(Text10, { bold: true, color: "green", children: "> " }) : " ",
2430
2552
  " ",
2431
2553
  outcomeColor ? /* @__PURE__ */ jsx11(Text10, { color: outcomeColor, children: "\u25CF" }) : /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "\u25CB" }),
2432
2554
  " ",
2433
2555
  sel(nodeId) ? /* @__PURE__ */ jsx11(Text10, { bold: true, color: "green", children: dec }) : /* @__PURE__ */ jsx11(Text10, { children: dec }),
2556
+ d.hash ? /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
2557
+ " [",
2558
+ d.hash.slice(0, 8),
2559
+ "]"
2560
+ ] }) : null,
2434
2561
  /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
2435
2562
  " ",
2436
- timeAgo2(n.data.timestamp)
2563
+ timeAgo2(d.when)
2437
2564
  ] }),
2438
2565
  outcomeColor ? /* @__PURE__ */ jsxs10(Text10, { color: outcomeColor, children: [
2439
2566
  " ",
2440
- n.data.outcome
2567
+ d.outcome
2441
2568
  ] }) : null
2442
- ] }, n.id);
2569
+ ] }, d.id);
2443
2570
  })
2444
2571
  ] }),
2445
2572
  renderHeader("incidents", "Incidents", incidentNodes.length, "-- use trie tell"),
@@ -2523,6 +2650,47 @@ function MemoryTreeView() {
2523
2650
  ] })
2524
2651
  ] }, n.id);
2525
2652
  })
2653
+ ] }),
2654
+ ledgerBlocks.length > 0 && /* @__PURE__ */ jsxs10(Fragment5, { children: [
2655
+ renderHeader("ledger-chain", "Ledger Chain (hashes)", ledgerBlocks.length),
2656
+ expandedNodes.has("ledger-chain") && ledgerBlocks.map((block, i) => {
2657
+ const nodeId = `ledger-block-${i}`;
2658
+ return /* @__PURE__ */ jsxs10(Text10, { children: [
2659
+ sel(nodeId) ? /* @__PURE__ */ jsx11(Text10, { bold: true, color: "green", children: "> " }) : " ",
2660
+ " ",
2661
+ /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: "\u25CF" }),
2662
+ " ",
2663
+ sel(nodeId) ? /* @__PURE__ */ jsxs10(Text10, { bold: true, color: "green", children: [
2664
+ "Block ",
2665
+ i + 1
2666
+ ] }) : /* @__PURE__ */ jsxs10(Text10, { children: [
2667
+ "Block ",
2668
+ i + 1
2669
+ ] }),
2670
+ /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
2671
+ " ",
2672
+ block.date
2673
+ ] }),
2674
+ " ",
2675
+ " ",
2676
+ /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
2677
+ "block: ",
2678
+ (block.blockHash || "-").slice(0, 12),
2679
+ "\u2026"
2680
+ ] }),
2681
+ " ",
2682
+ /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
2683
+ "merkle: ",
2684
+ (block.merkleRoot || "-").slice(0, 8),
2685
+ "\u2026"
2686
+ ] }),
2687
+ " ",
2688
+ /* @__PURE__ */ jsxs10(Text10, { dimColor: true, children: [
2689
+ block.entries.length,
2690
+ " entries"
2691
+ ] })
2692
+ ] }, nodeId);
2693
+ })
2526
2694
  ] })
2527
2695
  ] });
2528
2696
  }
@@ -5158,7 +5326,7 @@ var CHAT_TOOLS = [
5158
5326
  }
5159
5327
  }
5160
5328
  ];
5161
- async function executeTool(name, input) {
5329
+ async function executeTool(name, input, onProgress) {
5162
5330
  const directory = getWorkingDirectory(void 0, true);
5163
5331
  const withDir = { ...input, directory };
5164
5332
  try {
@@ -5436,7 +5604,8 @@ ${truncated}`;
5436
5604
  case "trie_scan_for_goal_violations": {
5437
5605
  const goalId = input.goalId ? String(input.goalId).trim() : void 0;
5438
5606
  try {
5439
- const { checkFilesForGoalViolations, getActiveGoals } = await import("./goal-validator-NLOJJ7FF.js");
5607
+ onProgress?.("Loading goals...");
5608
+ const { checkFilesForGoalViolations, getActiveGoals } = await import("./goal-validator-KLAK5TZN.js");
5440
5609
  const agentState = getGuardianState(directory);
5441
5610
  await agentState.load();
5442
5611
  const allGoals = await getActiveGoals(directory);
@@ -5444,7 +5613,8 @@ ${truncated}`;
5444
5613
  if (goalsToCheck.length === 0) {
5445
5614
  return goalId ? `No active goal found with ID: ${goalId}` : "No active goals to check. Add goals in the Goals view first.";
5446
5615
  }
5447
- const violations = await checkFilesForGoalViolations(goalsToCheck, directory);
5616
+ onProgress?.("Scanning codebase for violations...");
5617
+ const violations = await checkFilesForGoalViolations(goalsToCheck, directory, void 0, onProgress);
5448
5618
  if (violations.length === 0) {
5449
5619
  return `\u2713 Scan complete! No violations found for ${goalsToCheck.length} goal(s).`;
5450
5620
  }
@@ -5615,7 +5785,7 @@ Answer concisely. Reference specific files, decisions, and patterns when relevan
5615
5785
  function ChatView() {
5616
5786
  const { state, dispatch } = useDashboard();
5617
5787
  const { chatState } = state;
5618
- const { messages, inputBuffer, loading, currentSessionId, currentSessionTitle } = chatState;
5788
+ const { messages, inputBuffer, loading, progress, messageQueue, currentSessionId, currentSessionTitle } = chatState;
5619
5789
  const loadingRef = useRef(false);
5620
5790
  const [cursorVisible, setCursorVisible] = useState2(true);
5621
5791
  const [scrollOffset, setScrollOffset] = useState2(0);
@@ -5632,6 +5802,13 @@ function ChatView() {
5632
5802
  useEffect3(() => {
5633
5803
  setScrollOffset(0);
5634
5804
  }, [messages.length]);
5805
+ useEffect3(() => {
5806
+ if (!loading && messageQueue.length > 0) {
5807
+ const msg = messageQueue[0];
5808
+ dispatch({ type: "DEQUEUE_CHAT_MESSAGE" });
5809
+ void sendMessage(msg);
5810
+ }
5811
+ }, [loading, messageQueue.length, sendMessage, dispatch]);
5635
5812
  useEffect3(() => {
5636
5813
  if (messages.length === 0) return;
5637
5814
  const saveChat = async () => {
@@ -5660,6 +5837,7 @@ function ChatView() {
5660
5837
  dispatch({ type: "ADD_CHAT_MESSAGE", role: "user", content: question });
5661
5838
  dispatch({ type: "SET_CHAT_INPUT", buffer: "" });
5662
5839
  dispatch({ type: "SET_CHAT_LOADING", loading: true });
5840
+ dispatch({ type: "SET_CHAT_PROGRESS", message: "Thinking..." });
5663
5841
  try {
5664
5842
  const workDir = getWorkingDirectory(void 0, true);
5665
5843
  const response = question.trim().toLowerCase();
@@ -5753,14 +5931,22 @@ ${contextBlock}`;
5753
5931
  ...messages,
5754
5932
  { role: "user", content: question, timestamp: Date.now() }
5755
5933
  ]);
5756
- const result = await runAIWithTools({
5757
- systemPrompt: fullSystem,
5758
- messages: history,
5759
- tools: CHAT_TOOLS,
5760
- executeTool,
5761
- maxTokens: 4096,
5762
- maxToolRounds: 8
5934
+ const CHAT_TIMEOUT_MS = 18e4;
5935
+ const timeoutPromise = new Promise((_, reject) => {
5936
+ setTimeout(() => reject(new Error("Request timed out. Large scans (e.g. emoji removal) can take a few minutes. Try again or run the scan from the Goals view.")), CHAT_TIMEOUT_MS);
5763
5937
  });
5938
+ const result = await Promise.race([
5939
+ runAIWithTools({
5940
+ systemPrompt: fullSystem,
5941
+ messages: history,
5942
+ tools: CHAT_TOOLS,
5943
+ executeTool,
5944
+ maxTokens: 4096,
5945
+ maxToolRounds: 8,
5946
+ onProgress: (msg) => dispatch({ type: "SET_CHAT_PROGRESS", message: msg })
5947
+ }),
5948
+ timeoutPromise
5949
+ ]);
5764
5950
  if (result.success) {
5765
5951
  const action = {
5766
5952
  type: "ADD_CHAT_MESSAGE",
@@ -5837,11 +6023,18 @@ ${contextBlock}`;
5837
6023
  });
5838
6024
  } finally {
5839
6025
  dispatch({ type: "SET_CHAT_LOADING", loading: false });
6026
+ dispatch({ type: "SET_CHAT_PROGRESS", message: null });
5840
6027
  loadingRef.current = false;
5841
6028
  }
5842
6029
  }, [dispatch, messages, state]);
5843
6030
  useInput8((input, key) => {
5844
- if (loading) return;
6031
+ if (loading && key.escape) {
6032
+ loadingRef.current = false;
6033
+ dispatch({ type: "SET_CHAT_LOADING", loading: false });
6034
+ dispatch({ type: "SET_CHAT_PROGRESS", message: null });
6035
+ dispatch({ type: "ADD_CHAT_MESSAGE", role: "assistant", content: "Request cancelled." });
6036
+ return;
6037
+ }
5845
6038
  if (key.upArrow) {
5846
6039
  const maxScroll = Math.max(0, messages.length - VISIBLE_MESSAGES);
5847
6040
  setScrollOffset((prev) => Math.min(prev + 1, maxScroll));
@@ -5850,8 +6043,18 @@ ${contextBlock}`;
5850
6043
  setScrollOffset((prev) => Math.max(prev - 1, 0));
5851
6044
  return;
5852
6045
  }
6046
+ if (key.return && inputBuffer.trim() === "/history") {
6047
+ dispatch({ type: "SET_CHAT_INPUT", buffer: "" });
6048
+ dispatch({ type: "SET_VIEW", view: "chat-archive" });
6049
+ return;
6050
+ }
5853
6051
  if (key.return && inputBuffer.trim().length > 0) {
5854
- void sendMessage(inputBuffer.trim());
6052
+ if (loading) {
6053
+ dispatch({ type: "QUEUE_CHAT_MESSAGE", message: inputBuffer.trim() });
6054
+ dispatch({ type: "SET_CHAT_INPUT", buffer: "" });
6055
+ } else {
6056
+ void sendMessage(inputBuffer.trim());
6057
+ }
5855
6058
  } else if (key.escape) {
5856
6059
  dispatch({ type: "SET_CHAT_INPUT", buffer: "" });
5857
6060
  } else if (key.backspace || key.delete) {
@@ -5882,7 +6085,12 @@ ${contextBlock}`;
5882
6085
  " ",
5883
6086
  currentSessionTitle
5884
6087
  ] }),
5885
- /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " (h for history)" }),
6088
+ /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " (/history)" }),
6089
+ messageQueue.length > 0 && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
6090
+ " [",
6091
+ messageQueue.length,
6092
+ " queued]"
6093
+ ] }),
5886
6094
  messages.length > VISIBLE_MESSAGES && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
5887
6095
  " [",
5888
6096
  canScrollUp ? "\u2191" : " ",
@@ -5915,7 +6123,11 @@ ${contextBlock}`;
5915
6123
  ] }, li))
5916
6124
  ] }) }, idx)),
5917
6125
  canScrollDown && /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " \u2193 more messages below" }),
5918
- loading && /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " Thinking..." })
6126
+ loading && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
6127
+ " ",
6128
+ progress || "Thinking...",
6129
+ /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " (Esc to cancel)" })
6130
+ ] })
5919
6131
  ] }),
5920
6132
  /* @__PURE__ */ jsx13(Box12, { borderStyle: "single", borderColor: "green", paddingX: 1, flexShrink: 0, flexGrow: 0, children: /* @__PURE__ */ jsx13(Text12, { children: inputBuffer ? /* @__PURE__ */ jsxs12(Fragment6, { children: [
5921
6133
  inputBuffer,
@@ -5931,11 +6143,13 @@ function formatToolInput(input) {
5931
6143
  for (const [k, v] of Object.entries(input)) {
5932
6144
  if (k === "directory") continue;
5933
6145
  if (Array.isArray(v)) {
5934
- if (v.length > 0 && typeof v[0] === "object") {
6146
+ if (v.length > 0 && typeof v[0] === "object" && v[0] !== null) {
5935
6147
  parts.push(`${k}: [${v.length} item${v.length !== 1 ? "s" : ""}]`);
5936
6148
  } else {
5937
6149
  parts.push(`${k}: [${v.join(", ")}]`);
5938
6150
  }
6151
+ } else if (typeof v === "object" && v !== null) {
6152
+ parts.push(`${k}: {object}`);
5939
6153
  } else {
5940
6154
  parts.push(`${k}: ${String(v)}`);
5941
6155
  }
@@ -6159,7 +6373,7 @@ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
6159
6373
  var MAIN_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent", "chat"];
6160
6374
  async function applyGoalFix(fix, dispatch) {
6161
6375
  try {
6162
- const { runAIAnalysis, isAIAvailable: isAIAvailable2 } = await import("./client-EWP4SIG3.js");
6376
+ const { runAIAnalysis, isAIAvailable: isAIAvailable2 } = await import("./client-OVI6TBX7.js");
6163
6377
  if (!isAIAvailable2()) {
6164
6378
  dispatch({ type: "DISMISS_FIX", id: fix.id });
6165
6379
  getOutputManager().nudge("AI not available for fix", "warning");
@@ -6194,7 +6408,7 @@ ${content}
6194
6408
  fixedContent = fixedContent.replace(/^```\w*\n?/, "").replace(/\n?```$/, "");
6195
6409
  }
6196
6410
  await writeFile(fullPath, fixedContent, "utf-8");
6197
- const { recordGoalViolationFixed, getActiveGoals } = await import("./goal-validator-NLOJJ7FF.js");
6411
+ const { recordGoalViolationFixed, getActiveGoals } = await import("./goal-validator-KLAK5TZN.js");
6198
6412
  const goals = await getActiveGoals(projectPath);
6199
6413
  const matchedGoal = goals.find((g) => g.description === fix.goalDescription);
6200
6414
  if (matchedGoal) {
@@ -6452,10 +6666,6 @@ function DashboardApp({ onReady }) {
6452
6666
  dispatch({ type: "SET_VIEW", view: "chat" });
6453
6667
  return;
6454
6668
  }
6455
- if (input === "h") {
6456
- dispatch({ type: "SET_VIEW", view: "chat-archive" });
6457
- return;
6458
- }
6459
6669
  if (state.view === "agent" || state.view === "memory") return;
6460
6670
  if (input === "b") dispatch({ type: "GO_BACK" });
6461
6671
  if (input === "n") dispatch({ type: "NEXT_PAGE" });
@@ -6556,4 +6766,4 @@ export {
6556
6766
  handleCheckpointTool,
6557
6767
  InteractiveDashboard
6558
6768
  };
6559
- //# sourceMappingURL=chunk-SUPXBOJD.js.map
6769
+ //# sourceMappingURL=chunk-LMFREFAP.js.map