@triedotdev/mcp 1.0.138 → 1.0.140

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 (74) hide show
  1. package/README.md +184 -38
  2. package/dist/{autonomy-config-TZ6HF4FA.js → autonomy-config-ZCOSTMPD.js} +2 -2
  3. package/dist/{chunk-X3F5QDER.js → chunk-4O2KRHK4.js} +934 -132
  4. package/dist/chunk-4O2KRHK4.js.map +1 -0
  5. package/dist/{chunk-J5EMP4XW.js → chunk-5KJ4UJOY.js} +9 -4
  6. package/dist/chunk-5KJ4UJOY.js.map +1 -0
  7. package/dist/chunk-62POBLFC.js +1925 -0
  8. package/dist/chunk-62POBLFC.js.map +1 -0
  9. package/dist/{chunk-GFFUDJMK.js → chunk-75ADWWUF.js} +13 -13
  10. package/dist/chunk-75ADWWUF.js.map +1 -0
  11. package/dist/{chunk-D3AS5LY7.js → chunk-7OJ6JIPL.js} +39 -604
  12. package/dist/chunk-7OJ6JIPL.js.map +1 -0
  13. package/dist/{chunk-3RRXWX3V.js → chunk-AF2APASP.js} +38 -4
  14. package/dist/{chunk-3RRXWX3V.js.map → chunk-AF2APASP.js.map} +1 -1
  15. package/dist/{chunk-QSWUPSLK.js → chunk-FH335WL5.js} +9 -1
  16. package/dist/chunk-FH335WL5.js.map +1 -0
  17. package/dist/{chunk-Y32FM3MR.js → chunk-FPEMP54L.js} +21 -15
  18. package/dist/chunk-FPEMP54L.js.map +1 -0
  19. package/dist/{chunk-EDDT4ZIH.js → chunk-GXF6JOCN.js} +21 -323
  20. package/dist/chunk-GXF6JOCN.js.map +1 -0
  21. package/dist/chunk-LD7ZEFNY.js +132 -0
  22. package/dist/chunk-LD7ZEFNY.js.map +1 -0
  23. package/dist/chunk-NKHO34UZ.js +467 -0
  24. package/dist/chunk-NKHO34UZ.js.map +1 -0
  25. package/dist/{chunk-YOKQ25IW.js → chunk-OQ4A3RDY.js} +14 -14
  26. package/dist/{chunk-6LLH3TBZ.js → chunk-UOSTOLU7.js} +12 -12
  27. package/dist/{chunk-67GSG2ST.js → chunk-XTTZAQWJ.js} +18 -15
  28. package/dist/chunk-XTTZAQWJ.js.map +1 -0
  29. package/dist/{chunk-FOCXXIXY.js → chunk-YEIJW6X6.js} +2 -2
  30. package/dist/chunk-YOJGSRZK.js +216 -0
  31. package/dist/chunk-YOJGSRZK.js.map +1 -0
  32. package/dist/cli/main.js +573 -59
  33. package/dist/cli/main.js.map +1 -1
  34. package/dist/cli/yolo-daemon.js +15 -13
  35. package/dist/cli/yolo-daemon.js.map +1 -1
  36. package/dist/{client-JTU5TRLB.js → client-INNE2GGZ.js} +2 -2
  37. package/dist/{codebase-index-FNJ4GCBE.js → codebase-index-5SEOESWM.js} +3 -3
  38. package/dist/fast-analyzer-AYLZB5TW.js +216 -0
  39. package/dist/fast-analyzer-AYLZB5TW.js.map +1 -0
  40. package/dist/github-ingester-J2ZFYXVE.js +11 -0
  41. package/dist/{goal-manager-6BJQ36AH.js → goal-manager-ZBWKWEML.js} +3 -3
  42. package/dist/{goal-validator-GISXYANK.js → goal-validator-HNXXUCPW.js} +3 -3
  43. package/dist/{graph-X2FMRQLG.js → graph-J4OGTYCO.js} +2 -2
  44. package/dist/{hypothesis-K3KQJOXJ.js → hypothesis-JCUMZKTG.js} +3 -3
  45. package/dist/index.js +1090 -108
  46. package/dist/index.js.map +1 -1
  47. package/dist/{issue-store-BO5OWLJW.js → issue-store-LZWZIGM7.js} +2 -2
  48. package/dist/linear-ingester-JRDQAIAA.js +11 -0
  49. package/dist/linear-ingester-JRDQAIAA.js.map +1 -0
  50. package/dist/{trie-agent-XMSGMD7E.js → trie-agent-M6PHM6UD.js} +10 -10
  51. package/dist/trie-agent-M6PHM6UD.js.map +1 -0
  52. package/package.json +15 -8
  53. package/dist/chunk-67GSG2ST.js.map +0 -1
  54. package/dist/chunk-D3AS5LY7.js.map +0 -1
  55. package/dist/chunk-EDDT4ZIH.js.map +0 -1
  56. package/dist/chunk-GFFUDJMK.js.map +0 -1
  57. package/dist/chunk-J5EMP4XW.js.map +0 -1
  58. package/dist/chunk-QSWUPSLK.js.map +0 -1
  59. package/dist/chunk-X3F5QDER.js.map +0 -1
  60. package/dist/chunk-Y32FM3MR.js.map +0 -1
  61. package/dist/chunk-Z2P4WST6.js +0 -883
  62. package/dist/chunk-Z2P4WST6.js.map +0 -1
  63. /package/dist/{autonomy-config-TZ6HF4FA.js.map → autonomy-config-ZCOSTMPD.js.map} +0 -0
  64. /package/dist/{chunk-YOKQ25IW.js.map → chunk-OQ4A3RDY.js.map} +0 -0
  65. /package/dist/{chunk-6LLH3TBZ.js.map → chunk-UOSTOLU7.js.map} +0 -0
  66. /package/dist/{chunk-FOCXXIXY.js.map → chunk-YEIJW6X6.js.map} +0 -0
  67. /package/dist/{client-JTU5TRLB.js.map → client-INNE2GGZ.js.map} +0 -0
  68. /package/dist/{codebase-index-FNJ4GCBE.js.map → codebase-index-5SEOESWM.js.map} +0 -0
  69. /package/dist/{goal-manager-6BJQ36AH.js.map → github-ingester-J2ZFYXVE.js.map} +0 -0
  70. /package/dist/{goal-validator-GISXYANK.js.map → goal-manager-ZBWKWEML.js.map} +0 -0
  71. /package/dist/{graph-X2FMRQLG.js.map → goal-validator-HNXXUCPW.js.map} +0 -0
  72. /package/dist/{hypothesis-K3KQJOXJ.js.map → graph-J4OGTYCO.js.map} +0 -0
  73. /package/dist/{issue-store-BO5OWLJW.js.map → hypothesis-JCUMZKTG.js.map} +0 -0
  74. /package/dist/{trie-agent-XMSGMD7E.js.map → issue-store-LZWZIGM7.js.map} +0 -0
@@ -1,9 +1,9 @@
1
- import {
2
- getTrieAgent
3
- } from "./chunk-YOKQ25IW.js";
4
1
  import {
5
2
  getChatStore
6
3
  } from "./chunk-23RJT5WT.js";
4
+ import {
5
+ getTrieAgent
6
+ } from "./chunk-OQ4A3RDY.js";
7
7
  import {
8
8
  LearningEngine,
9
9
  exportToJson,
@@ -13,42 +13,51 @@ import {
13
13
  perceiveCurrentChanges,
14
14
  reasonAboutChangesHumanReadable,
15
15
  saveCheckpoint
16
- } from "./chunk-EDDT4ZIH.js";
16
+ } from "./chunk-GXF6JOCN.js";
17
+ import {
18
+ loadConfig,
19
+ saveConfig
20
+ } from "./chunk-NKHO34UZ.js";
17
21
  import {
18
22
  IncidentIndex
19
23
  } from "./chunk-4C67GV3O.js";
20
24
  import {
21
25
  findCrossProjectPatterns
22
- } from "./chunk-6LLH3TBZ.js";
26
+ } from "./chunk-UOSTOLU7.js";
27
+ import {
28
+ ContextGraph
29
+ } from "./chunk-FH335WL5.js";
23
30
  import {
24
31
  measureInitialGoalValue
25
- } from "./chunk-GFFUDJMK.js";
32
+ } from "./chunk-75ADWWUF.js";
26
33
  import {
27
34
  getKeyFromKeychain,
28
35
  isAIAvailable,
29
36
  runAIWithTools,
30
37
  setAPIKey
31
- } from "./chunk-Y32FM3MR.js";
38
+ } from "./chunk-FPEMP54L.js";
32
39
  import {
33
40
  getProjectState
34
41
  } from "./chunk-LT6VUZG2.js";
42
+ import {
43
+ deleteBlocks,
44
+ getLedgerBlocks
45
+ } from "./chunk-62POBLFC.js";
35
46
  import {
36
47
  TieredStorage,
37
48
  getStorage
38
49
  } from "./chunk-FG467PDD.js";
39
50
  import {
40
- ContextGraph
41
- } from "./chunk-QSWUPSLK.js";
42
- import {
43
- getOutputManager
44
- } from "./chunk-TIMIKBY2.js";
45
- import {
46
- getLedgerBlocks
47
- } from "./chunk-Z2P4WST6.js";
51
+ loadAutonomyConfig,
52
+ saveAutonomyConfig
53
+ } from "./chunk-5KJ4UJOY.js";
48
54
  import {
49
55
  getTrieDirectory,
50
56
  getWorkingDirectory
51
57
  } from "./chunk-SH7H3WRU.js";
58
+ import {
59
+ getOutputManager
60
+ } from "./chunk-TIMIKBY2.js";
52
61
  import {
53
62
  isInteractiveMode
54
63
  } from "./chunk-APMV77PU.js";
@@ -302,7 +311,7 @@ import { render } from "ink";
302
311
  import React11 from "react";
303
312
 
304
313
  // src/cli/dashboard/App.tsx
305
- import { useState as useState3, useEffect as useEffect5, useCallback as useCallback7, useRef as useRef2 } from "react";
314
+ import { useState as useState3, useEffect as useEffect5, useCallback as useCallback7, useRef as useRef4 } from "react";
306
315
  import { Box as Box14, useInput as useInput10, useApp, useStdout as useStdout11 } from "ink";
307
316
 
308
317
  // src/cli/dashboard/state.tsx
@@ -439,8 +448,7 @@ function handleStreamUpdate(state, update) {
439
448
  lastChange: entry.time,
440
449
  filesScannedSession: s.watch.filesScannedSession + 1
441
450
  };
442
- const shortFile = update.data.file.split("/").slice(-2).join("/");
443
- s = addActivity(s, `Change: ${shortFile}`);
451
+ s = addActivity(s, `Change: ${update.data.file}`);
444
452
  break;
445
453
  }
446
454
  case "signal_extracted": {
@@ -506,8 +514,13 @@ function dashboardReducer(state, action) {
506
514
  switch (action.type) {
507
515
  case "STREAM_UPDATE":
508
516
  return handleStreamUpdate(state, action.update);
509
- case "SET_VIEW":
510
- return { ...state, previousView: state.view, view: action.view };
517
+ case "SET_VIEW": {
518
+ const next = { ...state, previousView: state.view, view: action.view };
519
+ if (action.view !== "memory" && state.memoryTree.pendingLedgerDelete) {
520
+ next.memoryTree = { ...state.memoryTree, pendingLedgerDelete: null };
521
+ }
522
+ return next;
523
+ }
511
524
  case "GO_BACK":
512
525
  return { ...state, view: state.previousView || "overview", previousView: null };
513
526
  case "ADD_ACTIVITY":
@@ -660,6 +673,8 @@ function dashboardReducer(state, action) {
660
673
  return { ...state, hypothesesPanel: { ...state.hypothesesPanel, inputBuffer: action.buffer } };
661
674
  case "SELECT_HYPOTHESIS":
662
675
  return { ...state, hypothesesPanel: { ...state.hypothesesPanel, selectedIndex: action.index } };
676
+ case "SET_HYPOTHESIS_SCANNING":
677
+ return { ...state, hypothesesPanel: { ...state.hypothesesPanel, scanningHypothesisId: action.hypothesisId, scanningProgress: action.progress } };
663
678
  case "SET_MEMORY_TREE": {
664
679
  const blocks = action.ledgerBlocks ?? state.memoryTree.ledgerBlocks;
665
680
  const gotchas = action.storageGotchas ?? state.memoryTree.storageGotchas;
@@ -686,6 +701,8 @@ function dashboardReducer(state, action) {
686
701
  return { ...state, memoryTree: { ...state.memoryTree, selectedNode: action.nodeId } };
687
702
  case "SET_MEMORY_EXPANDED_ITEM":
688
703
  return { ...state, memoryTree: { ...state.memoryTree, expandedItemId: action.itemId } };
704
+ case "SET_PENDING_LEDGER_DELETE":
705
+ return { ...state, memoryTree: { ...state.memoryTree, pendingLedgerDelete: action.date } };
689
706
  case "TOGGLE_MEMORY_NODE": {
690
707
  const expandable = ["decisions", "incidents", "patterns", "cross-project", "hotspots", "ledger-chain"];
691
708
  if (expandable.includes(action.nodeId)) {
@@ -938,8 +955,8 @@ function createInitialState() {
938
955
  aiWatcher: { enabled: true, hourlyTokenLimit: 5e4, scanCooldownSec: 30, cleanFileCooldownSec: 300, maxFilesPerScan: 5, maxCharsPerFile: 4e3 }
939
956
  },
940
957
  goalsPanel: { goals: [], selectedIndex: 0, selectedAchievedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0, scanningGoalId: null, scanningProgress: "" },
941
- hypothesesPanel: { hypotheses: [], selectedIndex: 0, selectedCompletedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0 },
942
- memoryTree: { loaded: false, snapshot: null, globalPatterns: [], storageGovernance: [], storageGotchas: [], ledgerBlocks: [], expandedNodes: /* @__PURE__ */ new Set(["decisions"]), expandedItemId: null, selectedNode: "decisions", scrollPosition: 0, lastRefresh: 0 },
958
+ hypothesesPanel: { hypotheses: [], selectedIndex: 0, selectedCompletedIndex: 0, inputMode: "browse", inputBuffer: "", lastRefresh: 0, scanningHypothesisId: null, scanningProgress: "" },
959
+ memoryTree: { loaded: false, snapshot: null, globalPatterns: [], storageGovernance: [], storageGotchas: [], ledgerBlocks: [], expandedNodes: /* @__PURE__ */ new Set(["decisions"]), expandedItemId: null, selectedNode: "decisions", scrollPosition: 0, lastRefresh: 0, pendingLedgerDelete: null },
943
960
  agentBrain: { loaded: false, governance: [], patterns: [], ledgerHash: null, selectedIndex: 0, expandedIndex: null },
944
961
  chatState: { messages: [], inputBuffer: "", loading: false, progress: null, messageQueue: [], currentSessionId: null, currentSessionTitle: null },
945
962
  chatArchivePanel: { sessions: [], selectedIndex: 0, showArchived: false, loading: false, inputMode: "browse", inputBuffer: "" },
@@ -1171,13 +1188,39 @@ function ConfigDialog({ onClose }) {
1171
1188
  const [clearingMemory, setClearingMemory] = useState(false);
1172
1189
  const [indexStats, setIndexStats] = useState(null);
1173
1190
  const [indexing, setIndexing] = useState(false);
1191
+ const [cursorKeyDisplay, setCursorKeyDisplay] = useState("Not set");
1192
+ const [linearKeyDisplay, setLinearKeyDisplay] = useState("Not set");
1193
+ const [githubKeyDisplay, setGithubKeyDisplay] = useState("Not set");
1174
1194
  const config = state.agentConfig;
1195
+ React3.useEffect(() => {
1196
+ const loadApiKeys = async () => {
1197
+ try {
1198
+ const workDir = getWorkingDirectory(void 0, true);
1199
+ const cfg = await loadAutonomyConfig(workDir);
1200
+ const cursorKey = cfg.cursorApiKey || process.env.CURSOR_API_KEY || null;
1201
+ setCursorKeyDisplay(maskKey(cursorKey));
1202
+ } catch {
1203
+ setCursorKeyDisplay("Not set");
1204
+ }
1205
+ try {
1206
+ const trieConfig = await loadConfig();
1207
+ const linearKey = trieConfig.apiKeys?.linear ?? process.env.LINEAR_API_KEY ?? null;
1208
+ setLinearKeyDisplay(maskKey(linearKey));
1209
+ const githubKey = trieConfig.apiKeys?.github ?? process.env.GITHUB_TOKEN ?? null;
1210
+ setGithubKeyDisplay(maskKey(githubKey));
1211
+ } catch {
1212
+ setLinearKeyDisplay("Not set");
1213
+ setGithubKeyDisplay("Not set");
1214
+ }
1215
+ };
1216
+ void loadApiKeys();
1217
+ }, []);
1175
1218
  React3.useEffect(() => {
1176
1219
  if (section === "codebaseIndex") {
1177
1220
  const loadStats = async () => {
1178
1221
  try {
1179
1222
  const workDir = getWorkingDirectory(void 0, true);
1180
- const { CodebaseIndex } = await import("./codebase-index-FNJ4GCBE.js");
1223
+ const { CodebaseIndex } = await import("./codebase-index-5SEOESWM.js");
1181
1224
  const index = new CodebaseIndex(workDir);
1182
1225
  const stats = index.getStats();
1183
1226
  let lastUpdatedDisplay = "Never";
@@ -1216,7 +1259,10 @@ function ConfigDialog({ onClose }) {
1216
1259
  { label: "Memory", key: "memory", value: "Clear & Reset", section: "main" }
1217
1260
  ];
1218
1261
  const apiKeysItems = [
1219
- { label: "Anthropic", key: "anthropic", value: currentKeyDisplay, section: "apiKeys" }
1262
+ { label: "Anthropic", key: "anthropic", value: currentKeyDisplay, section: "apiKeys" },
1263
+ { label: "Linear", key: "linear", value: linearKeyDisplay, section: "apiKeys" },
1264
+ { label: "GitHub", key: "github", value: githubKeyDisplay, section: "apiKeys" },
1265
+ { label: "Cursor", key: "cursor", value: cursorKeyDisplay, section: "apiKeys" }
1220
1266
  ];
1221
1267
  const performanceItems = [
1222
1268
  { label: "Max Concurrency", key: "maxConcurrency", value: String(config.performance.maxConcurrency), section: "performance" },
@@ -1277,6 +1323,25 @@ function ConfigDialog({ onClose }) {
1277
1323
  if (item.key === "anthropic" && editBuffer.length > 10) {
1278
1324
  setAPIKey(editBuffer);
1279
1325
  dispatch({ type: "ADD_ACTIVITY", message: "API key saved" });
1326
+ } else if (item.key === "linear" && editBuffer.length > 5) {
1327
+ void (async () => {
1328
+ const cfg = await loadConfig();
1329
+ await saveConfig({ ...cfg, apiKeys: { ...cfg.apiKeys, linear: editBuffer } });
1330
+ })();
1331
+ setLinearKeyDisplay(maskKey(editBuffer));
1332
+ dispatch({ type: "ADD_ACTIVITY", message: "Linear API key saved" });
1333
+ } else if (item.key === "github" && editBuffer.length > 5) {
1334
+ void (async () => {
1335
+ const cfg = await loadConfig();
1336
+ await saveConfig({ ...cfg, apiKeys: { ...cfg.apiKeys, github: editBuffer } });
1337
+ })();
1338
+ setGithubKeyDisplay(maskKey(editBuffer));
1339
+ dispatch({ type: "ADD_ACTIVITY", message: "GitHub token saved" });
1340
+ } else if (item.key === "cursor" && editBuffer.length > 10) {
1341
+ const workDir = getWorkingDirectory(void 0, true);
1342
+ void saveAutonomyConfig(workDir, { cloudAgentEnabled: true, cursorApiKey: editBuffer });
1343
+ setCursorKeyDisplay(maskKey(editBuffer));
1344
+ dispatch({ type: "ADD_ACTIVITY", message: "Cursor API key saved" });
1280
1345
  }
1281
1346
  } else {
1282
1347
  const val = parseInt(editBuffer, 10);
@@ -1348,7 +1413,7 @@ function ConfigDialog({ onClose }) {
1348
1413
  const loadStats = async () => {
1349
1414
  try {
1350
1415
  const workDir = getWorkingDirectory(void 0, true);
1351
- const { CodebaseIndex } = await import("./codebase-index-FNJ4GCBE.js");
1416
+ const { CodebaseIndex } = await import("./codebase-index-5SEOESWM.js");
1352
1417
  const index = new CodebaseIndex(workDir);
1353
1418
  const stats = index.getStats();
1354
1419
  setIndexStats({
@@ -1423,7 +1488,7 @@ function ConfigDialog({ onClose }) {
1423
1488
  }
1424
1489
  async function reindexCodebase() {
1425
1490
  const workDir = getWorkingDirectory(void 0, true);
1426
- const { CodebaseIndex } = await import("./codebase-index-FNJ4GCBE.js");
1491
+ const { CodebaseIndex } = await import("./codebase-index-5SEOESWM.js");
1427
1492
  const { glob } = await import("glob");
1428
1493
  const index = new CodebaseIndex(workDir);
1429
1494
  const indexPattern = `${workDir}/**/*.{ts,tsx,js,jsx,mjs,vue,svelte,astro,py,go,rs,java,c,cpp,h,hpp,cs,rb,php,css,scss,html}`;
@@ -1496,18 +1561,30 @@ function ConfigDialog({ onClose }) {
1496
1561
  indexing ? /* @__PURE__ */ jsx5(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: " Re-indexing codebase..." }) }) : /* @__PURE__ */ jsx5(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: " enter to execute \xB7 esc back" }) })
1497
1562
  ] }),
1498
1563
  !showConfirmClear && section === "apiKeys" && !editing && /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
1499
- /* @__PURE__ */ jsxs4(Text4, { children: [
1500
- " ",
1501
- "Anthropic: ",
1502
- currentKeyDisplay,
1503
- " ",
1504
- keyActive ? /* @__PURE__ */ jsx5(Text4, { color: "green", children: "\u25CF Active" }) : /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: "\u25CB Not set" })
1505
- ] }),
1564
+ apiKeysItems.map((item, idx) => {
1565
+ const isSelected = selectedIndex === idx;
1566
+ const isActive = item.value !== "Not set";
1567
+ return /* @__PURE__ */ jsxs4(Text4, { children: [
1568
+ isSelected ? /* @__PURE__ */ jsx5(Text4, { bold: true, color: "green", children: "> " }) : " ",
1569
+ /* @__PURE__ */ jsxs4(Text4, { bold: isSelected, children: [
1570
+ item.label,
1571
+ ":"
1572
+ ] }),
1573
+ " ",
1574
+ item.value,
1575
+ " ",
1576
+ isActive ? /* @__PURE__ */ jsx5(Text4, { color: "green", children: "\u25CF Active" }) : /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: "\u25CB Not set" })
1577
+ ] }, item.key);
1578
+ }),
1506
1579
  /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: " enter to update \xB7 esc back" })
1507
1580
  ] }),
1508
1581
  !showConfirmClear && section === "apiKeys" && editing && /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", marginTop: 1, children: [
1582
+ /* @__PURE__ */ jsxs4(Text4, { dimColor: true, children: [
1583
+ " Editing: ",
1584
+ apiKeysItems[selectedIndex]?.label ?? "Key"
1585
+ ] }),
1509
1586
  /* @__PURE__ */ jsx5(Box4, { borderStyle: "single", borderColor: "green", paddingX: 1, children: /* @__PURE__ */ jsxs4(Text4, { children: [
1510
- editBuffer || /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: "sk-ant-..." }),
1587
+ editBuffer || /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: "key-..." }),
1511
1588
  /* @__PURE__ */ jsx5(Text4, { bold: true, color: "green", children: "|" })
1512
1589
  ] }) }),
1513
1590
  /* @__PURE__ */ jsx5(Text4, { dimColor: true, children: " enter save \xB7 esc cancel" })
@@ -1768,12 +1845,15 @@ function OverviewView() {
1768
1845
  ] }),
1769
1846
  /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, children: [
1770
1847
  /* @__PURE__ */ jsx7(Text6, { bold: true, children: "Activity" }),
1771
- pageActivities.map((entry, i) => /* @__PURE__ */ jsxs6(Text6, { wrap: "wrap", children: [
1772
- " ",
1773
- /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: entry.time }),
1774
- " ",
1775
- entry.message
1776
- ] }, i)),
1848
+ pageActivities.map((entry, i) => {
1849
+ const msgMax = Math.max(20, contentWidth - 12);
1850
+ return /* @__PURE__ */ jsxs6(Text6, { wrap: "truncate", children: [
1851
+ " ",
1852
+ /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: entry.time }),
1853
+ " ",
1854
+ truncate(entry.message, msgMax)
1855
+ ] }, i);
1856
+ }),
1777
1857
  pageActivities.length === 0 && /* @__PURE__ */ jsx7(Text6, { dimColor: true, children: " No activity yet" })
1778
1858
  ] })
1779
1859
  ] });
@@ -2048,7 +2128,7 @@ function AgentView() {
2048
2128
  }
2049
2129
 
2050
2130
  // src/cli/dashboard/views/GoalsView.tsx
2051
- import { useCallback as useCallback2 } from "react";
2131
+ import { useCallback as useCallback2, useRef } from "react";
2052
2132
  import { Box as Box8, Text as Text8, useInput as useInput4, useStdout as useStdout6 } from "ink";
2053
2133
  import { Fragment as Fragment4, jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
2054
2134
  function calculateGoalProgress(goal) {
@@ -2067,9 +2147,14 @@ function calculateGoalProgress(goal) {
2067
2147
  }
2068
2148
  return Math.round(goal.currentValue / goal.target * 100);
2069
2149
  }
2150
+ function isBinaryGoal(goal) {
2151
+ const start = goal.startValue ?? 0;
2152
+ return goal.target === 0 && start === 0;
2153
+ }
2070
2154
  function GoalsView() {
2071
2155
  const { state, dispatch } = useDashboard();
2072
2156
  const { goalsPanel } = state;
2157
+ const scanAbortRef = useRef(null);
2073
2158
  const { stdout } = useStdout6();
2074
2159
  const cols = stdout?.columns || 80;
2075
2160
  const narrow = cols < 60;
@@ -2086,12 +2171,11 @@ function GoalsView() {
2086
2171
  dispatch({
2087
2172
  type: "SET_GOALS",
2088
2173
  goals: goals.map((g) => {
2089
- const base = { id: g.id, description: g.description, type: g.type, target: g.target, currentValue: g.currentValue, status: g.status, autoGenerated: g.autoGenerated, updatedAt: g.updatedAt, ...g.achievedAt != null ? { achievedAt: g.achievedAt } : {}, ...g.achievedBy != null ? { achievedBy: g.achievedBy } : {}, ...g.category != null ? { category: g.category } : {} };
2174
+ const base = { id: g.id, description: g.description, type: g.type, target: g.target, currentValue: g.currentValue, startValue: g.startValue, status: g.status, autoGenerated: g.autoGenerated, updatedAt: g.updatedAt, ...g.achievedAt != null ? { achievedAt: g.achievedAt } : {}, ...g.achievedBy != null ? { achievedBy: g.achievedBy } : {}, ...g.category != null ? { category: g.category } : {} };
2090
2175
  return base;
2091
2176
  })
2092
2177
  });
2093
2178
  } catch (err) {
2094
- console.debug("[GoalsView] refreshGoals failed:", err);
2095
2179
  }
2096
2180
  }, [dispatch]);
2097
2181
  const addGoal = useCallback2(async (description) => {
@@ -2119,7 +2203,6 @@ function GoalsView() {
2119
2203
  dispatch({ type: "ADD_ACTIVITY", message: `Goal added: ${description}` });
2120
2204
  await refreshGoals();
2121
2205
  } catch (err) {
2122
- console.debug("[GoalsView] addGoal failed:", err);
2123
2206
  }
2124
2207
  }, [dispatch, refreshGoals]);
2125
2208
  const completeGoal = useCallback2(async (goalId) => {
@@ -2139,7 +2222,6 @@ function GoalsView() {
2139
2222
  await refreshGoals();
2140
2223
  }
2141
2224
  } catch (err) {
2142
- console.debug("[GoalsView] completeGoal failed:", err);
2143
2225
  }
2144
2226
  }, [dispatch, refreshGoals, goalsPanel.selectedIndex, activeGoals.length]);
2145
2227
  const deleteGoal = useCallback2(async (goalId) => {
@@ -2155,7 +2237,6 @@ function GoalsView() {
2155
2237
  dispatch({ type: "ADD_ACTIVITY", message: "Goal removed" });
2156
2238
  await refreshGoals();
2157
2239
  } catch (err) {
2158
- console.debug("[GoalsView] deleteGoal failed:", err);
2159
2240
  }
2160
2241
  }, [dispatch, refreshGoals, goalsPanel.selectedIndex, activeGoals.length]);
2161
2242
  const reactivateGoal = useCallback2(async (goalId) => {
@@ -2167,7 +2248,6 @@ function GoalsView() {
2167
2248
  dispatch({ type: "ADD_ACTIVITY", message: "Goal reactivated" });
2168
2249
  await refreshGoals();
2169
2250
  } catch (err) {
2170
- console.debug("[GoalsView] reactivateGoal failed:", err);
2171
2251
  }
2172
2252
  }, [dispatch, refreshGoals]);
2173
2253
  const reactivateAllAchievedGoals = useCallback2(async () => {
@@ -2187,7 +2267,6 @@ function GoalsView() {
2187
2267
  dispatch({ type: "ADD_ACTIVITY", message: `Reactivated ${achieved.length} goal${achieved.length > 1 ? "s" : ""}` });
2188
2268
  await refreshGoals();
2189
2269
  } catch (err) {
2190
- console.debug("[GoalsView] reactivateAllAchievedGoals failed:", err);
2191
2270
  dispatch({ type: "SHOW_NOTIFICATION", message: "Failed to reactivate goals", severity: "warning", autoHideMs: 5e3 });
2192
2271
  }
2193
2272
  }, [dispatch, refreshGoals, goalsPanel.goals]);
@@ -2218,10 +2297,13 @@ function GoalsView() {
2218
2297
  const workDir = getWorkingDirectory(void 0, true);
2219
2298
  const goalSummary = goalsPanel.goals.find((g) => g.id === goalId);
2220
2299
  if (!goalSummary) return;
2300
+ scanAbortRef.current?.abort();
2301
+ scanAbortRef.current = new AbortController();
2302
+ const signal = scanAbortRef.current.signal;
2221
2303
  dispatch({ type: "SET_GOAL_SCANNING", goalId, progress: "Starting scan..." });
2222
2304
  dispatch({ type: "ADD_ACTIVITY", message: `Scanning goal: ${goalSummary.description}...` });
2223
2305
  dispatch({ type: "SET_GOAL_SCANNING", goalId, progress: "Loading goal configuration..." });
2224
- const { checkFilesForGoalViolations } = await import("./goal-validator-GISXYANK.js");
2306
+ const { checkFilesForGoalViolations } = await import("./goal-validator-HNXXUCPW.js");
2225
2307
  const agentState = getProjectState(workDir);
2226
2308
  await agentState.load();
2227
2309
  const fullGoal = agentState.getAllGoals().find((g) => g.id === goalId);
@@ -2233,7 +2315,8 @@ function GoalsView() {
2233
2315
  dispatch({ type: "SET_GOAL_SCANNING", goalId, progress: "Analyzing codebase..." });
2234
2316
  const violations = await checkFilesForGoalViolations([fullGoal], workDir, void 0, (progressMsg) => {
2235
2317
  dispatch({ type: "SET_GOAL_SCANNING", goalId, progress: progressMsg });
2236
- });
2318
+ }, signal);
2319
+ scanAbortRef.current = null;
2237
2320
  dispatch({ type: "SET_GOAL_SCANNING", goalId: null, progress: "" });
2238
2321
  if (violations.length === 0) {
2239
2322
  dispatch({ type: "SHOW_NOTIFICATION", message: `\u2713 No violations found for: ${goalSummary.description}`, severity: "info", autoHideMs: 5e3 });
@@ -2255,13 +2338,24 @@ function GoalsView() {
2255
2338
  }
2256
2339
  }
2257
2340
  } catch (error) {
2341
+ scanAbortRef.current = null;
2258
2342
  dispatch({ type: "SET_GOAL_SCANNING", goalId: null, progress: "" });
2259
- const errorMsg = error instanceof Error ? error.message : "unknown error";
2260
- dispatch({ type: "SHOW_NOTIFICATION", message: `Scan failed: ${errorMsg}`, severity: "warning", autoHideMs: 5e3 });
2261
- dispatch({ type: "ADD_ACTIVITY", message: `\u2717 Scan failed: ${errorMsg}` });
2343
+ const isAborted = error instanceof DOMException && error.name === "AbortError";
2344
+ if (isAborted) {
2345
+ dispatch({ type: "SHOW_NOTIFICATION", message: "Scan cancelled", severity: "info", autoHideMs: 3e3 });
2346
+ dispatch({ type: "ADD_ACTIVITY", message: "Scan cancelled" });
2347
+ } else {
2348
+ const errorMsg = error instanceof Error ? error.message : "unknown error";
2349
+ dispatch({ type: "SHOW_NOTIFICATION", message: `Scan failed: ${errorMsg}`, severity: "warning", autoHideMs: 5e3 });
2350
+ dispatch({ type: "ADD_ACTIVITY", message: `\u2717 Scan failed: ${errorMsg}` });
2351
+ }
2262
2352
  }
2263
2353
  }, [dispatch, goalsPanel.goals]);
2264
2354
  useInput4((_input, key) => {
2355
+ if (goalsPanel.scanningGoalId && key.escape) {
2356
+ scanAbortRef.current?.abort();
2357
+ return;
2358
+ }
2265
2359
  if (goalsPanel.inputMode === "add") {
2266
2360
  if (key.escape) {
2267
2361
  dispatch({ type: "SET_GOALS_INPUT_MODE", mode: "browse" });
@@ -2313,21 +2407,23 @@ function GoalsView() {
2313
2407
  activeGoals.map((goal, idx) => {
2314
2408
  const isSelected = goalsPanel.selectedIndex === idx;
2315
2409
  const isScanning = goalsPanel.scanningGoalId === goal.id;
2410
+ const binary = isBinaryGoal(goal);
2316
2411
  const progress = calculateGoalProgress(goal);
2317
2412
  const barWidth = narrow ? 6 : Math.min(12, Math.floor(contentWidth / 8));
2318
2413
  const bar = progressBar(progress, 100, barWidth);
2319
2414
  const sourceLabel = goal.autoGenerated ? "AI" : "you";
2320
2415
  if (isScanning) {
2321
2416
  return /* @__PURE__ */ jsx9(Box8, { borderStyle: "round", borderColor: "cyan", paddingX: 1, children: /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2322
- /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", children: [
2417
+ /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", overflow: "visible", children: [
2323
2418
  /* @__PURE__ */ jsx9(Text8, { bold: true, color: "cyan", children: "\u27F3 " }),
2324
2419
  /* @__PURE__ */ jsx9(Text8, { color: "cyan", bold: true, children: goal.description })
2325
2420
  ] }),
2326
- /* @__PURE__ */ jsx9(Text8, { color: "cyan", dimColor: true, children: goalsPanel.scanningProgress || "Scanning..." })
2421
+ /* @__PURE__ */ jsx9(Text8, { color: "cyan", dimColor: true, children: goalsPanel.scanningProgress || "Scanning..." }),
2422
+ /* @__PURE__ */ jsx9(Text8, { color: "cyan", dimColor: true, children: " Esc to cancel" })
2327
2423
  ] }) }, goal.id);
2328
2424
  }
2329
2425
  return /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
2330
- /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", children: [
2426
+ /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", overflow: "visible", children: [
2331
2427
  isSelected ? /* @__PURE__ */ jsx9(Text8, { bold: true, color: "green", children: "> " }) : " ",
2332
2428
  goal.autoGenerated ? /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: "\u25C7" }) : /* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u25CB" }),
2333
2429
  " ",
@@ -2338,7 +2434,15 @@ function GoalsView() {
2338
2434
  "]"
2339
2435
  ] })
2340
2436
  ] }),
2341
- /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
2437
+ binary ? /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
2438
+ " ",
2439
+ goal.currentValue === 0 ? /* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u2713 Compliant" }) : /* @__PURE__ */ jsxs8(Text8, { color: "yellow", children: [
2440
+ "\u26A0 ",
2441
+ goal.currentValue,
2442
+ " violation",
2443
+ goal.currentValue !== 1 ? "s" : ""
2444
+ ] })
2445
+ ] }) : /* @__PURE__ */ jsxs8(Text8, { dimColor: true, children: [
2342
2446
  " ",
2343
2447
  bar,
2344
2448
  " ",
@@ -2351,7 +2455,7 @@ function GoalsView() {
2351
2455
  /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " Achieved" }),
2352
2456
  achievedGoals.slice(0, 5).map((g) => {
2353
2457
  const byLabel = g.achievedBy === "agent" ? "AI" : "you";
2354
- return /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", children: [
2458
+ return /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", overflow: "visible", children: [
2355
2459
  " ",
2356
2460
  g.achievedBy === "agent" ? /* @__PURE__ */ jsx9(Text8, { color: "cyan", children: "\u25CF" }) : /* @__PURE__ */ jsx9(Text8, { color: "green", children: "\u25CF" }),
2357
2461
  " ",
@@ -2372,7 +2476,7 @@ function GoalsView() {
2372
2476
  otherGoals.length > 0 && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginTop: 1, children: [
2373
2477
  /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " Other" }),
2374
2478
  otherGoals.slice(0, 2).map((g) => {
2375
- return /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", children: [
2479
+ return /* @__PURE__ */ jsxs8(Text8, { wrap: "wrap", overflow: "visible", children: [
2376
2480
  " ",
2377
2481
  /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "\u25CB" }),
2378
2482
  " ",
@@ -2387,12 +2491,13 @@ function GoalsView() {
2387
2491
  }
2388
2492
 
2389
2493
  // src/cli/dashboard/views/HypothesesView.tsx
2390
- import { useCallback as useCallback3 } from "react";
2494
+ import { useCallback as useCallback3, useRef as useRef2 } from "react";
2391
2495
  import { Box as Box9, Text as Text9, useInput as useInput5, useStdout as useStdout7 } from "ink";
2392
2496
  import { Fragment as Fragment5, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
2393
2497
  function HypothesesView() {
2394
2498
  const { state, dispatch } = useDashboard();
2395
2499
  const { hypothesesPanel } = state;
2500
+ const scanAbortRef = useRef2(null);
2396
2501
  const { stdout } = useStdout7();
2397
2502
  const cols = stdout?.columns || 80;
2398
2503
  const narrow = cols < 60;
@@ -2414,7 +2519,6 @@ function HypothesesView() {
2414
2519
  })
2415
2520
  });
2416
2521
  } catch (err) {
2417
- console.debug("[HypothesesView] refreshHypotheses failed:", err);
2418
2522
  }
2419
2523
  }, [dispatch]);
2420
2524
  const addHypothesis = useCallback3(async (statement) => {
@@ -2438,7 +2542,6 @@ function HypothesesView() {
2438
2542
  dispatch({ type: "ADD_ACTIVITY", message: `Hypothesis added: ${statement}` });
2439
2543
  await refreshHypotheses();
2440
2544
  } catch (err) {
2441
- console.debug("[HypothesesView] addHypothesis failed:", err);
2442
2545
  }
2443
2546
  }, [dispatch, refreshHypotheses]);
2444
2547
  const updateHypothesis = useCallback3(async (hypoId, action) => {
@@ -2452,7 +2555,6 @@ function HypothesesView() {
2452
2555
  dispatch({ type: "ADD_ACTIVITY", message: `Hypothesis ${action === "validate" ? "validated" : action === "invalidate" ? "invalidated" : "removed"}` });
2453
2556
  await refreshHypotheses();
2454
2557
  } catch (err) {
2455
- console.debug("[HypothesesView] updateHypothesis failed:", err);
2456
2558
  }
2457
2559
  }, [dispatch, refreshHypotheses]);
2458
2560
  const reactivateHypothesis = useCallback3(async (hypoId) => {
@@ -2464,7 +2566,6 @@ function HypothesesView() {
2464
2566
  dispatch({ type: "ADD_ACTIVITY", message: "Hypothesis reactivated" });
2465
2567
  await refreshHypotheses();
2466
2568
  } catch (err) {
2467
- console.debug("[HypothesesView] reactivateHypothesis failed:", err);
2468
2569
  }
2469
2570
  }, [dispatch, refreshHypotheses]);
2470
2571
  const checkHypothesisNow = useCallback3(async (hypoId) => {
@@ -2472,10 +2573,16 @@ function HypothesesView() {
2472
2573
  const workDir = getWorkingDirectory(void 0, true);
2473
2574
  const hypo = hypothesesPanel.hypotheses.find((h) => h.id === hypoId);
2474
2575
  if (!hypo) return;
2576
+ scanAbortRef.current?.abort();
2577
+ scanAbortRef.current = new AbortController();
2578
+ const signal = scanAbortRef.current.signal;
2579
+ dispatch({ type: "SET_HYPOTHESIS_SCANNING", hypothesisId: hypoId, progress: "Gathering evidence..." });
2475
2580
  dispatch({ type: "ADD_ACTIVITY", message: `Testing hypothesis: ${hypo.statement}` });
2476
2581
  dispatch({ type: "SHOW_NOTIFICATION", message: `Gathering evidence for hypothesis...`, severity: "info", autoHideMs: 3e3 });
2477
- const { gatherEvidenceForHypothesis } = await import("./hypothesis-K3KQJOXJ.js");
2478
- const evidence = await gatherEvidenceForHypothesis(hypoId, workDir);
2582
+ const { gatherEvidenceForHypothesis } = await import("./hypothesis-JCUMZKTG.js");
2583
+ const evidence = await gatherEvidenceForHypothesis(hypoId, workDir, signal);
2584
+ scanAbortRef.current = null;
2585
+ dispatch({ type: "SET_HYPOTHESIS_SCANNING", hypothesisId: null, progress: "" });
2479
2586
  if (evidence.length === 0) {
2480
2587
  dispatch({ type: "SHOW_NOTIFICATION", message: `No evidence found for: ${hypo.statement}`, severity: "info", autoHideMs: 5e3 });
2481
2588
  dispatch({ type: "ADD_ACTIVITY", message: `No evidence found` });
@@ -2487,10 +2594,22 @@ function HypothesesView() {
2487
2594
  await refreshHypotheses();
2488
2595
  }
2489
2596
  } catch (error) {
2490
- dispatch({ type: "ADD_ACTIVITY", message: `Check failed: ${error instanceof Error ? error.message : "unknown"}` });
2597
+ scanAbortRef.current = null;
2598
+ dispatch({ type: "SET_HYPOTHESIS_SCANNING", hypothesisId: null, progress: "" });
2599
+ const isAborted = error instanceof DOMException && error.name === "AbortError";
2600
+ if (isAborted) {
2601
+ dispatch({ type: "SHOW_NOTIFICATION", message: "Test cancelled", severity: "info", autoHideMs: 3e3 });
2602
+ dispatch({ type: "ADD_ACTIVITY", message: "Test cancelled" });
2603
+ } else {
2604
+ dispatch({ type: "ADD_ACTIVITY", message: `Check failed: ${error instanceof Error ? error.message : "unknown"}` });
2605
+ }
2491
2606
  }
2492
2607
  }, [dispatch, hypothesesPanel.hypotheses, refreshHypotheses]);
2493
2608
  useInput5((_input, key) => {
2609
+ if (hypothesesPanel.scanningHypothesisId && key.escape) {
2610
+ scanAbortRef.current?.abort();
2611
+ return;
2612
+ }
2494
2613
  if (hypothesesPanel.inputMode === "add") {
2495
2614
  if (key.escape) {
2496
2615
  dispatch({ type: "SET_HYPOTHESES_INPUT_MODE", mode: "browse" });
@@ -2543,15 +2662,25 @@ function HypothesesView() {
2543
2662
  ] }),
2544
2663
  testing.map((hypo, idx) => {
2545
2664
  const isSelected = hypothesesPanel.selectedIndex === idx;
2665
+ const isScanning = hypothesesPanel.scanningHypothesisId === hypo.id;
2546
2666
  const hasEvidence = hypo.evidenceCount > 0;
2547
2667
  const confLabel = hasEvidence ? `${Math.round(hypo.confidence * 100)}%` : "untested";
2548
- const statementWidth = Math.max(25, contentWidth - 25);
2549
2668
  const sourceLabel = hypo.autoGenerated ? "AI" : "you";
2550
- return /* @__PURE__ */ jsxs9(Text9, { wrap: "truncate", children: [
2669
+ if (isScanning) {
2670
+ return /* @__PURE__ */ jsx10(Box9, { borderStyle: "round", borderColor: "cyan", paddingX: 1, children: /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", children: [
2671
+ /* @__PURE__ */ jsxs9(Text9, { wrap: "wrap", children: [
2672
+ /* @__PURE__ */ jsx10(Text9, { bold: true, color: "cyan", children: "\u27F3 " }),
2673
+ /* @__PURE__ */ jsx10(Text9, { color: "cyan", bold: true, children: hypo.statement })
2674
+ ] }),
2675
+ /* @__PURE__ */ jsx10(Text9, { color: "cyan", dimColor: true, children: hypothesesPanel.scanningProgress || "Testing..." }),
2676
+ /* @__PURE__ */ jsx10(Text9, { color: "cyan", dimColor: true, children: " Esc to cancel" })
2677
+ ] }) }, hypo.id);
2678
+ }
2679
+ return /* @__PURE__ */ jsxs9(Text9, { wrap: "wrap", children: [
2551
2680
  isSelected ? /* @__PURE__ */ jsx10(Text9, { bold: true, color: "green", children: "> " }) : " ",
2552
2681
  hypo.autoGenerated ? /* @__PURE__ */ jsx10(Text9, { color: "cyan", children: "\u25C7" }) : /* @__PURE__ */ jsx10(Text9, { color: "green", children: "\u25CB" }),
2553
2682
  " ",
2554
- hypo.statement.slice(0, statementWidth),
2683
+ hypo.statement,
2555
2684
  /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2556
2685
  " [",
2557
2686
  sourceLabel,
@@ -2564,15 +2693,14 @@ function HypothesesView() {
2564
2693
  validated.length > 0 && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginTop: 1, children: [
2565
2694
  /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: " Validated" }),
2566
2695
  validated.slice(0, 3).map((h) => {
2567
- const statementWidth = Math.max(30, contentWidth - 12);
2568
2696
  const sourceLabel = h.autoGenerated ? "AI" : "you";
2569
2697
  const validatedByLabel = h.validatedBy === "agent" ? "AI" : "you";
2570
2698
  const suffix = sourceLabel !== validatedByLabel ? ` [${sourceLabel}\u2192${validatedByLabel}]` : ` [${sourceLabel}]`;
2571
- return /* @__PURE__ */ jsxs9(Text9, { wrap: "truncate", children: [
2699
+ return /* @__PURE__ */ jsxs9(Text9, { wrap: "wrap", children: [
2572
2700
  " ",
2573
2701
  h.autoGenerated ? /* @__PURE__ */ jsx10(Text9, { color: "cyan", children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { color: "green", children: "\u25CF" }),
2574
2702
  " ",
2575
- h.statement.slice(0, statementWidth),
2703
+ h.statement,
2576
2704
  /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: suffix })
2577
2705
  ] }, h.id);
2578
2706
  }),
@@ -2585,13 +2713,12 @@ function HypothesesView() {
2585
2713
  invalidated.length > 0 && /* @__PURE__ */ jsxs9(Box9, { flexDirection: "column", marginTop: 1, children: [
2586
2714
  /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: " Invalidated" }),
2587
2715
  invalidated.slice(0, 2).map((h) => {
2588
- const statementWidth = Math.max(30, contentWidth - 12);
2589
2716
  const sourceLabel = h.autoGenerated ? "AI" : "you";
2590
- return /* @__PURE__ */ jsxs9(Text9, { wrap: "truncate", children: [
2717
+ return /* @__PURE__ */ jsxs9(Text9, { wrap: "wrap", children: [
2591
2718
  " ",
2592
2719
  h.autoGenerated ? /* @__PURE__ */ jsx10(Text9, { color: "cyan", children: "\u25CF" }) : /* @__PURE__ */ jsx10(Text9, { color: "red", children: "\u25CF" }),
2593
2720
  " ",
2594
- /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: h.statement.slice(0, statementWidth) }),
2721
+ /* @__PURE__ */ jsx10(Text9, { dimColor: true, children: h.statement }),
2595
2722
  /* @__PURE__ */ jsxs9(Text9, { dimColor: true, children: [
2596
2723
  " [",
2597
2724
  sourceLabel,
@@ -2624,7 +2751,7 @@ function timeAgo2(iso) {
2624
2751
  function MemoryTreeView() {
2625
2752
  const { state, dispatch } = useDashboard();
2626
2753
  const { memoryTree } = state;
2627
- const { snapshot, globalPatterns, storageGovernance, storageGotchas, ledgerBlocks, expandedNodes, expandedItemId, selectedNode, loaded } = memoryTree;
2754
+ const { snapshot, globalPatterns, storageGovernance, storageGotchas, ledgerBlocks, expandedNodes, expandedItemId, selectedNode, loaded, pendingLedgerDelete } = memoryTree;
2628
2755
  const { stdout } = useStdout8();
2629
2756
  const cols = stdout?.columns || 80;
2630
2757
  const narrow = cols < 60;
@@ -2643,7 +2770,6 @@ function MemoryTreeView() {
2643
2770
  ]);
2644
2771
  dispatch({ type: "SET_MEMORY_TREE", snapshot: snap, patterns, storageGovernance: governance2, storageGotchas: gotchas, ledgerBlocks: blocks });
2645
2772
  } catch (err) {
2646
- console.debug("[MemoryTreeView] loadData failed:", err);
2647
2773
  dispatch({ type: "ADD_ACTIVITY", message: "Context graph load error" });
2648
2774
  }
2649
2775
  }, [dispatch]);
@@ -2668,21 +2794,65 @@ function MemoryTreeView() {
2668
2794
  dispatch({ type: "SET_MEMORY_EXPANDED_ITEM", itemId: null });
2669
2795
  void loadData();
2670
2796
  } catch (err) {
2671
- console.debug("[MemoryTreeView] incident action failed:", err);
2672
2797
  dispatch({ type: "ADD_ACTIVITY", message: "Failed to update incident" });
2673
2798
  }
2674
2799
  }, [selectedNode, expandedItemId, loadData, dispatch]);
2800
+ const handleLedgerBlockDelete = useCallback4(async () => {
2801
+ const dateToDelete = pendingLedgerDelete;
2802
+ if (!dateToDelete) return;
2803
+ try {
2804
+ dispatch({ type: "ADD_ACTIVITY", message: `Attempting to delete ledger block ${dateToDelete}...` });
2805
+ const workDir = getWorkingDirectory(void 0, true);
2806
+ const result = await deleteBlocks([dateToDelete], workDir, true);
2807
+ if (result.success) {
2808
+ dispatch({ type: "ADD_ACTIVITY", message: `Ledger block ${dateToDelete} deleted permanently` });
2809
+ dispatch({ type: "SET_MEMORY_EXPANDED_ITEM", itemId: null });
2810
+ dispatch({ type: "SET_PENDING_LEDGER_DELETE", date: null });
2811
+ void loadData();
2812
+ } else {
2813
+ dispatch({ type: "ADD_ACTIVITY", message: `Failed to delete block: ${result.error}` });
2814
+ dispatch({ type: "SHOW_NOTIFICATION", message: result.error ?? "Delete failed", severity: "warning" });
2815
+ dispatch({ type: "SET_PENDING_LEDGER_DELETE", date: null });
2816
+ }
2817
+ } catch (err) {
2818
+ const msg = err instanceof Error ? err.message : "unknown error";
2819
+ dispatch({ type: "ADD_ACTIVITY", message: `Failed to delete ledger block: ${msg}` });
2820
+ dispatch({ type: "SHOW_NOTIFICATION", message: `Delete failed: ${msg}`, severity: "warning" });
2821
+ dispatch({ type: "SET_PENDING_LEDGER_DELETE", date: null });
2822
+ }
2823
+ }, [pendingLedgerDelete, loadData, dispatch]);
2675
2824
  useInput6((_input, key) => {
2676
2825
  const incidentSelected = selectedNode?.startsWith("incident-") || expandedItemId?.startsWith("incident-");
2826
+ const ledgerBlockSelected = selectedNode?.startsWith("ledger-block-") || expandedItemId?.startsWith("ledger-block-");
2827
+ if (pendingLedgerDelete) {
2828
+ if (_input === "y" || _input === "Y" || key.return) {
2829
+ void handleLedgerBlockDelete();
2830
+ return;
2831
+ }
2832
+ if (_input === "n" || _input === "N" || key.escape) {
2833
+ dispatch({ type: "SET_PENDING_LEDGER_DELETE", date: null });
2834
+ return;
2835
+ }
2836
+ return;
2837
+ }
2677
2838
  if (incidentSelected && (_input === "d" || _input === "D")) {
2678
2839
  void handleIncidentAction("delete");
2679
2840
  return;
2680
2841
  }
2842
+ if (ledgerBlockSelected && (_input === "d" || _input === "D")) {
2843
+ const blockNodeId = selectedNode?.startsWith("ledger-block-") ? selectedNode : expandedItemId?.startsWith("ledger-block-") ? expandedItemId : null;
2844
+ const blockIndex = blockNodeId ? parseInt(blockNodeId.replace("ledger-block-", ""), 10) : -1;
2845
+ const block = blockIndex >= 0 ? ledgerBlocks[blockIndex] : null;
2846
+ if (block) {
2847
+ dispatch({ type: "SET_PENDING_LEDGER_DELETE", date: block.date });
2848
+ }
2849
+ return;
2850
+ }
2681
2851
  if (incidentSelected && (_input === "r" || _input === "c")) {
2682
2852
  void handleIncidentAction("resolve");
2683
2853
  return;
2684
2854
  }
2685
- if (_input === "R" || !incidentSelected && _input === "r") {
2855
+ if (_input === "R" || !incidentSelected && !ledgerBlockSelected && _input === "r") {
2686
2856
  dispatch({ type: "INVALIDATE_MEMORY_TREE" });
2687
2857
  return;
2688
2858
  }
@@ -2838,7 +3008,7 @@ function MemoryTreeView() {
2838
3008
  ] }) })
2839
3009
  ] }),
2840
3010
  expandedLedgerBlock && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, borderStyle: "single", borderColor: "magenta", paddingX: 1, paddingY: 1, children: [
2841
- /* @__PURE__ */ jsx11(Text10, { bold: true, color: "magenta", children: "Ledger Block Details \xB7 Esc close" }),
3011
+ /* @__PURE__ */ jsx11(Text10, { bold: true, color: "magenta", children: "Ledger Block Details \xB7 d delete \xB7 Esc close" }),
2842
3012
  (() => {
2843
3013
  const aiAgents = /* @__PURE__ */ new Set(["goal-violation", "claude", "agent", "ai"]);
2844
3014
  const hasAIAgents = expandedLedgerBlock.entries.some((e) => aiAgents.has(e.agent));
@@ -2910,6 +3080,23 @@ function MemoryTreeView() {
2910
3080
  expandedLedgerBlock.createdAt
2911
3081
  ] }) })
2912
3082
  ] }),
3083
+ pendingLedgerDelete && /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, borderStyle: "single", borderColor: "red", paddingX: 1, paddingY: 1, children: [
3084
+ /* @__PURE__ */ jsx11(Text10, { bold: true, color: "red", children: "\u26A0\uFE0F DANGER: PERMANENT DELETION" }),
3085
+ /* @__PURE__ */ jsx11(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text10, { children: "You are about to permanently delete ledger block:" }) }),
3086
+ /* @__PURE__ */ jsx11(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text10, { bold: true, color: "cyan", children: pendingLedgerDelete }) }),
3087
+ /* @__PURE__ */ jsx11(Box10, { marginTop: 1, children: /* @__PURE__ */ jsx11(Text10, { color: "red", children: "This operation cannot be undone and will permanently" }) }),
3088
+ /* @__PURE__ */ jsx11(Box10, { marginTop: 0, children: /* @__PURE__ */ jsx11(Text10, { color: "red", children: "remove all issues and data from this block." }) }),
3089
+ /* @__PURE__ */ jsx11(Box10, { marginTop: 1, children: /* @__PURE__ */ jsxs10(Text10, { children: [
3090
+ /* @__PURE__ */ jsx11(Text10, { bold: true, color: "green", children: "y" }),
3091
+ " or ",
3092
+ /* @__PURE__ */ jsx11(Text10, { bold: true, color: "green", children: "Enter" }),
3093
+ " to confirm \xB7 ",
3094
+ /* @__PURE__ */ jsx11(Text10, { bold: true, children: "n" }),
3095
+ " or ",
3096
+ /* @__PURE__ */ jsx11(Text10, { bold: true, children: "Esc" }),
3097
+ " to cancel"
3098
+ ] }) })
3099
+ ] }),
2913
3100
  /* @__PURE__ */ jsxs10(Box10, { flexDirection: "column", marginTop: 1, children: [
2914
3101
  renderHeader("decisions", "Product Governance", governance.length, "-- use trie tell or chat"),
2915
3102
  expandedNodes.has("decisions") && governance.slice(0, 10).map((g) => {
@@ -3135,7 +3322,7 @@ function MemoryTreeView() {
3135
3322
  topAgent
3136
3323
  ] })
3137
3324
  ] }) : null,
3138
- sel(nodeId) ? /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: " [Enter: details]" }) : null
3325
+ sel(nodeId) ? /* @__PURE__ */ jsx11(Text10, { dimColor: true, children: " [Enter: details, d: delete]" }) : null
3139
3326
  ] }, nodeId);
3140
3327
  })
3141
3328
  ] })
@@ -3183,7 +3370,7 @@ function RawLogView() {
3183
3370
  }
3184
3371
 
3185
3372
  // src/cli/dashboard/views/ChatView.tsx
3186
- import { useCallback as useCallback5, useRef, useEffect as useEffect3, useState as useState2 } from "react";
3373
+ import { useCallback as useCallback5, useRef as useRef3, useEffect as useEffect3, useState as useState2 } from "react";
3187
3374
  import { Box as Box12, Text as Text12, useInput as useInput8, useStdout as useStdout9 } from "ink";
3188
3375
 
3189
3376
  // src/tools/tell.ts
@@ -5709,6 +5896,555 @@ ${checkpoint.files.length > 0 ? `**Files:** ${checkpoint.files.join(", ")}` : ""
5709
5896
  }
5710
5897
  }
5711
5898
 
5899
+ // src/tools/pipeline.ts
5900
+ var TriePipelineTool = class {
5901
+ async execute(input) {
5902
+ try {
5903
+ const workDir = input.directory || getWorkingDirectory(void 0, true);
5904
+ const graph = new ContextGraph(workDir);
5905
+ const action = input.action ?? "status";
5906
+ switch (action) {
5907
+ case "status":
5908
+ return this.statusView(graph, input.focus);
5909
+ case "coverage":
5910
+ return this.coverageView(graph);
5911
+ case "create_tickets":
5912
+ return this.createTickets(graph, workDir, input.issueIds ?? []);
5913
+ default:
5914
+ return { isError: true, content: [{ type: "text", text: `Unknown action: ${action}` }] };
5915
+ }
5916
+ } catch (error) {
5917
+ return {
5918
+ isError: true,
5919
+ content: [{ type: "text", text: `Pipeline failed: ${error.message}` }]
5920
+ };
5921
+ }
5922
+ }
5923
+ async statusView(graph, focus) {
5924
+ const nodes = await graph.listNodes();
5925
+ const tickets = nodes.filter((n) => n.type === "linear-ticket");
5926
+ const prs = nodes.filter((n) => n.type === "pull-request");
5927
+ const ghIssues = nodes.filter((n) => n.type === "github-issue");
5928
+ const trieIssues = nodes.filter((n) => n.type === "issue");
5929
+ const LINE = "\u2500".repeat(68);
5930
+ const lines = [];
5931
+ lines.push("PIPELINE STATUS");
5932
+ lines.push(LINE);
5933
+ if (focus) {
5934
+ return this.focusedView(graph, nodes, focus, tickets, prs, ghIssues, trieIssues);
5935
+ }
5936
+ const activeTickets = tickets.filter(
5937
+ (t) => ["started", "In Progress", "in progress"].some(
5938
+ (s) => t.data.status.toLowerCase().includes(s.toLowerCase())
5939
+ )
5940
+ );
5941
+ if (activeTickets.length > 0) {
5942
+ lines.push(`ACTIVE LINEAR TICKETS (${activeTickets.length} in progress)`);
5943
+ for (const t of activeTickets) {
5944
+ const linkedPR = prs.find(
5945
+ (pr) => pr.data.linkedTicketIds.includes(t.data.ticketId)
5946
+ );
5947
+ const prInfo = linkedPR ? `PR #${linkedPR.data.prNumber} (CI: ${linkedPR.data.ciStatus})` : "No PR yet";
5948
+ lines.push(
5949
+ ` ${padEnd(t.data.ticketId, 10)}${padEnd(truncate2(t.data.title, 35), 37)}${padEnd(t.data.priority, 9)}${prInfo}`
5950
+ );
5951
+ }
5952
+ lines.push("");
5953
+ } else if (tickets.length > 0) {
5954
+ lines.push(`LINEAR TICKETS (${tickets.length} synced, none actively in progress)`);
5955
+ lines.push("");
5956
+ } else {
5957
+ lines.push("LINEAR TICKETS: not synced yet \u2014 run trie_linear_sync");
5958
+ lines.push("");
5959
+ }
5960
+ if (prs.length > 0) {
5961
+ lines.push(`OPEN PULL REQUESTS (${prs.length})`);
5962
+ for (const pr of prs) {
5963
+ const stateTag = pr.data.isDraft ? "draft" : pr.data.state;
5964
+ const ticketRef = pr.data.linkedTicketIds.length > 0 ? ` (${pr.data.linkedTicketIds.join(", ")})` : "";
5965
+ lines.push(
5966
+ ` #${padEnd(String(pr.data.prNumber), 5)}${padEnd(truncate2(pr.data.title, 30) + ticketRef, 42)}${padEnd(stateTag, 10)}CI: ${padEnd(pr.data.ciStatus, 10)}Review: ${pr.data.reviewStatus}`
5967
+ );
5968
+ }
5969
+ lines.push("");
5970
+ } else {
5971
+ lines.push("PULL REQUESTS: not synced yet \u2014 run trie_github_sync");
5972
+ lines.push("");
5973
+ }
5974
+ if (ghIssues.length > 0) {
5975
+ lines.push(`OPEN GITHUB ISSUES (${ghIssues.length})`);
5976
+ for (const issue of ghIssues.slice(0, 10)) {
5977
+ const labels = issue.data.labels.length > 0 ? `[${issue.data.labels.join(", ")}]` : "";
5978
+ const linked = issue.data.linkedTicketIds.length > 0 ? `linked: ${issue.data.linkedTicketIds.join(", ")}` : "no ticket";
5979
+ lines.push(
5980
+ ` #${padEnd(String(issue.data.issueNumber), 5)}${padEnd(truncate2(issue.data.title, 35), 37)}${padEnd(labels, 18)}${linked}`
5981
+ );
5982
+ }
5983
+ if (ghIssues.length > 10) {
5984
+ lines.push(` ... and ${ghIssues.length - 10} more`);
5985
+ }
5986
+ lines.push("");
5987
+ }
5988
+ const openTrieIssues = trieIssues.filter((i) => i.data.status === "open");
5989
+ const uncoveredIssues = await this.findUncoveredIssues(graph, openTrieIssues, prs, tickets);
5990
+ if (uncoveredIssues.length > 0) {
5991
+ lines.push(`COVERAGE GAPS (${uncoveredIssues.length} Trie issue${uncoveredIssues.length !== 1 ? "s" : ""} with no ticket or PR)`);
5992
+ for (const issue of uncoveredIssues.slice(0, 10)) {
5993
+ const loc = `${shortPath(issue.data.file)}:${issue.data.line ?? "?"}`;
5994
+ lines.push(` ${padEnd(loc, 32)}${padEnd(issue.data.severity, 10)}${truncate2(issue.data.issueText, 40)}`);
5995
+ }
5996
+ if (uncoveredIssues.length > 10) {
5997
+ lines.push(` ... and ${uncoveredIssues.length - 10} more`);
5998
+ }
5999
+ lines.push("");
6000
+ const ids = uncoveredIssues.slice(0, 5).map((i) => `"${i.id}"`).join(",");
6001
+ lines.push(` Create tickets: trie_pipeline action:create_tickets issueIds:[${ids}]`);
6002
+ }
6003
+ lines.push(LINE);
6004
+ return { content: [{ type: "text", text: lines.join("\n") }] };
6005
+ }
6006
+ async focusedView(_graph, _allNodes, focus, tickets, prs, ghIssues, trieIssues) {
6007
+ const LINE = "\u2500".repeat(68);
6008
+ const lines = [];
6009
+ lines.push(`PIPELINE FOCUS: ${focus}`);
6010
+ lines.push(LINE);
6011
+ const matchedTicket = tickets.find((t) => t.data.ticketId === focus);
6012
+ if (matchedTicket) {
6013
+ lines.push(`LINEAR TICKET: ${matchedTicket.data.ticketId}`);
6014
+ lines.push(` Title: ${matchedTicket.data.title}`);
6015
+ lines.push(` Status: ${matchedTicket.data.status}`);
6016
+ lines.push(` Priority: ${matchedTicket.data.priority}`);
6017
+ if (matchedTicket.data.assignee) lines.push(` Assignee: ${matchedTicket.data.assignee}`);
6018
+ if (matchedTicket.data.url) lines.push(` URL: ${matchedTicket.data.url}`);
6019
+ lines.push("");
6020
+ const linkedPRs = prs.filter(
6021
+ (pr) => pr.data.linkedTicketIds.includes(matchedTicket.data.ticketId)
6022
+ );
6023
+ if (linkedPRs.length > 0) {
6024
+ lines.push(` LINKED PRs (${linkedPRs.length}):`);
6025
+ for (const pr of linkedPRs) {
6026
+ lines.push(` #${pr.data.prNumber} ${pr.data.title} CI: ${pr.data.ciStatus} Review: ${pr.data.reviewStatus}`);
6027
+ }
6028
+ } else {
6029
+ lines.push(" No PR linked to this ticket.");
6030
+ }
6031
+ lines.push(LINE);
6032
+ return { content: [{ type: "text", text: lines.join("\n") }] };
6033
+ }
6034
+ const prNum = parseInt(focus.replace("#", ""), 10);
6035
+ if (!isNaN(prNum)) {
6036
+ const matchedPR = prs.find((pr) => pr.data.prNumber === prNum);
6037
+ if (matchedPR) {
6038
+ lines.push(`PR #${matchedPR.data.prNumber}: ${matchedPR.data.title}`);
6039
+ lines.push(` State: ${matchedPR.data.state}${matchedPR.data.isDraft ? " (draft)" : ""}`);
6040
+ lines.push(` Author: ${matchedPR.data.author}`);
6041
+ lines.push(` Branch: ${matchedPR.data.branch} \u2192 ${matchedPR.data.baseBranch}`);
6042
+ lines.push(` CI: ${matchedPR.data.ciStatus}`);
6043
+ lines.push(` Review: ${matchedPR.data.reviewStatus}`);
6044
+ lines.push(` URL: ${matchedPR.data.url}`);
6045
+ if (matchedPR.data.linkedTicketIds.length > 0) {
6046
+ lines.push(` Tickets: ${matchedPR.data.linkedTicketIds.join(", ")}`);
6047
+ }
6048
+ if (matchedPR.data.filesChanged.length > 0) {
6049
+ lines.push(` Files (${matchedPR.data.filesChanged.length}):`);
6050
+ for (const f of matchedPR.data.filesChanged.slice(0, 15)) {
6051
+ lines.push(` ${f}`);
6052
+ }
6053
+ if (matchedPR.data.filesChanged.length > 15) {
6054
+ lines.push(` ... and ${matchedPR.data.filesChanged.length - 15} more`);
6055
+ }
6056
+ }
6057
+ lines.push(LINE);
6058
+ return { content: [{ type: "text", text: lines.join("\n") }] };
6059
+ }
6060
+ }
6061
+ const relatedPRs = prs.filter(
6062
+ (pr) => pr.data.filesChanged.some((f) => f.includes(focus) || focus.includes(f))
6063
+ );
6064
+ const relatedIssues = trieIssues.filter((i) => i.data.file.includes(focus));
6065
+ const relatedGhIssues = ghIssues.filter(
6066
+ (i) => (i.data.body ?? "").includes(focus)
6067
+ );
6068
+ if (relatedPRs.length > 0) {
6069
+ lines.push(`PRs touching this file (${relatedPRs.length}):`);
6070
+ for (const pr of relatedPRs) {
6071
+ lines.push(` #${pr.data.prNumber} ${pr.data.title} \u2014 ${pr.data.state}`);
6072
+ }
6073
+ lines.push("");
6074
+ }
6075
+ if (relatedIssues.length > 0) {
6076
+ lines.push(`Trie issues in this file (${relatedIssues.length}):`);
6077
+ for (const issue of relatedIssues.slice(0, 5)) {
6078
+ lines.push(` ${issue.data.severity}: ${truncate2(issue.data.issueText, 50)} (line ${issue.data.line ?? "?"})`);
6079
+ }
6080
+ lines.push("");
6081
+ }
6082
+ if (relatedGhIssues.length > 0) {
6083
+ lines.push(`GitHub issues mentioning this file (${relatedGhIssues.length}):`);
6084
+ for (const issue of relatedGhIssues.slice(0, 5)) {
6085
+ lines.push(` #${issue.data.issueNumber} ${issue.data.title}`);
6086
+ }
6087
+ }
6088
+ if (relatedPRs.length === 0 && relatedIssues.length === 0 && relatedGhIssues.length === 0) {
6089
+ lines.push("No pipeline context found for this focus.");
6090
+ }
6091
+ lines.push(LINE);
6092
+ return { content: [{ type: "text", text: lines.join("\n") }] };
6093
+ }
6094
+ async coverageView(graph) {
6095
+ const nodes = await graph.listNodes();
6096
+ const tickets = nodes.filter((n) => n.type === "linear-ticket");
6097
+ const prs = nodes.filter((n) => n.type === "pull-request");
6098
+ const trieIssues = nodes.filter((n) => n.type === "issue" && n.data.status === "open");
6099
+ const uncovered = await this.findUncoveredIssues(graph, trieIssues, prs, tickets);
6100
+ const LINE = "\u2500".repeat(68);
6101
+ const lines = [];
6102
+ lines.push("COVERAGE GAPS");
6103
+ lines.push(LINE);
6104
+ lines.push(`${uncovered.length} Trie issue${uncovered.length !== 1 ? "s" : ""} not tracked in any Linear ticket or GitHub PR`);
6105
+ lines.push("");
6106
+ if (uncovered.length === 0) {
6107
+ lines.push("All issues are covered. Nice.");
6108
+ } else {
6109
+ const critical = uncovered.filter((i) => i.data.severity === "critical");
6110
+ const serious = uncovered.filter((i) => i.data.severity === "serious");
6111
+ const rest = uncovered.filter((i) => !["critical", "serious"].includes(i.data.severity));
6112
+ for (const group of [
6113
+ { label: "CRITICAL", items: critical },
6114
+ { label: "SERIOUS", items: serious },
6115
+ { label: "OTHER", items: rest }
6116
+ ]) {
6117
+ if (group.items.length === 0) continue;
6118
+ lines.push(`${group.label} (${group.items.length}):`);
6119
+ for (const issue of group.items.slice(0, 10)) {
6120
+ const loc = `${shortPath(issue.data.file)}:${issue.data.line ?? "?"}`;
6121
+ lines.push(` ${padEnd(loc, 32)}${truncate2(issue.data.issueText, 45)}`);
6122
+ }
6123
+ if (group.items.length > 10) {
6124
+ lines.push(` ... and ${group.items.length - 10} more`);
6125
+ }
6126
+ lines.push("");
6127
+ }
6128
+ if (critical.length > 0 || serious.length > 0) {
6129
+ const ids = [...critical, ...serious].slice(0, 5).map((i) => `"${i.id}"`).join(",");
6130
+ lines.push(`Create tickets: trie_pipeline action:create_tickets issueIds:[${ids}]`);
6131
+ }
6132
+ }
6133
+ lines.push(LINE);
6134
+ return { content: [{ type: "text", text: lines.join("\n") }] };
6135
+ }
6136
+ async createTickets(graph, _workDir, issueIds) {
6137
+ if (issueIds.length === 0) {
6138
+ return {
6139
+ isError: true,
6140
+ content: [{ type: "text", text: "No issue IDs provided. Use trie_pipeline action:coverage to find uncovered issues." }]
6141
+ };
6142
+ }
6143
+ const config = await loadConfig();
6144
+ const linearKey = config.apiKeys?.linear ?? process.env.LINEAR_API_KEY;
6145
+ if (!linearKey) {
6146
+ return {
6147
+ isError: true,
6148
+ content: [{ type: "text", text: "Linear API key not configured. Set it via Config \u2192 API Keys \u2192 Linear or LINEAR_API_KEY env var." }]
6149
+ };
6150
+ }
6151
+ const nodes = await graph.listNodes();
6152
+ const created = [];
6153
+ const failed = [];
6154
+ for (const issueId of issueIds) {
6155
+ const issueNode = nodes.find((n) => n.id === issueId && n.type === "issue");
6156
+ if (!issueNode) {
6157
+ failed.push(`${issueId}: not found`);
6158
+ continue;
6159
+ }
6160
+ try {
6161
+ const title = `[Trie ${issueNode.data.severity}] ${truncate2(issueNode.data.issueText, 80)}`;
6162
+ const description = [
6163
+ `**File:** \`${issueNode.data.file}\`${issueNode.data.line ? `:${issueNode.data.line}` : ""}`,
6164
+ `**Severity:** ${issueNode.data.severity}`,
6165
+ `**Found by:** ${issueNode.data.foundBy}`,
6166
+ `**Issue:** ${issueNode.data.issueText}`,
6167
+ issueNode.data.fix ? `**Suggested fix:** ${issueNode.data.fix}` : ""
6168
+ ].filter(Boolean).join("\n");
6169
+ const priority = issueNode.data.severity === "critical" ? 1 : issueNode.data.severity === "serious" ? 2 : issueNode.data.severity === "moderate" ? 3 : 4;
6170
+ const mutation = `
6171
+ mutation CreateIssue($input: IssueCreateInput!) {
6172
+ issueCreate(input: $input) {
6173
+ success
6174
+ issue { id identifier url }
6175
+ }
6176
+ }
6177
+ `;
6178
+ const response = await fetch("https://api.linear.app/graphql", {
6179
+ method: "POST",
6180
+ headers: {
6181
+ "Content-Type": "application/json",
6182
+ "Authorization": linearKey
6183
+ },
6184
+ body: JSON.stringify({
6185
+ query: mutation,
6186
+ variables: {
6187
+ input: { title, description, priority }
6188
+ }
6189
+ })
6190
+ });
6191
+ if (!response.ok) {
6192
+ failed.push(`${issueId}: Linear API error ${response.status}`);
6193
+ continue;
6194
+ }
6195
+ const data = await response.json();
6196
+ if (data.data?.issueCreate?.success) {
6197
+ const ticket = data.data.issueCreate.issue;
6198
+ created.push(`${ticket.identifier} \u2192 ${issueId}`);
6199
+ await graph.addEdge(issueNode.id, `linear:${ticket.identifier}`, "relatedTo");
6200
+ } else {
6201
+ failed.push(`${issueId}: Linear create failed`);
6202
+ }
6203
+ } catch (error) {
6204
+ failed.push(`${issueId}: ${error.message}`);
6205
+ }
6206
+ }
6207
+ const LINE = "\u2500".repeat(45);
6208
+ const lines = ["TICKET CREATION", LINE];
6209
+ if (created.length > 0) {
6210
+ lines.push(`Created ${created.length} ticket(s):`);
6211
+ for (const c of created) lines.push(` ${c}`);
6212
+ }
6213
+ if (failed.length > 0) {
6214
+ lines.push(`Failed ${failed.length}:`);
6215
+ for (const f of failed) lines.push(` ${f}`);
6216
+ }
6217
+ lines.push(LINE);
6218
+ return { content: [{ type: "text", text: lines.join("\n") }] };
6219
+ }
6220
+ async findUncoveredIssues(graph, trieIssues, prs, tickets) {
6221
+ const coveredFiles = /* @__PURE__ */ new Set();
6222
+ for (const pr of prs) {
6223
+ for (const f of pr.data.filesChanged) {
6224
+ coveredFiles.add(f);
6225
+ }
6226
+ }
6227
+ for (const ticket of tickets) {
6228
+ for (const f of ticket.data.linkedFiles) {
6229
+ coveredFiles.add(f);
6230
+ }
6231
+ }
6232
+ const coveredIssueIds = /* @__PURE__ */ new Set();
6233
+ for (const issue of trieIssues) {
6234
+ const edges = await graph.getEdges(issue.id, "both");
6235
+ for (const edge of edges) {
6236
+ const otherNodeId = edge.from_id === issue.id ? edge.to_id : edge.from_id;
6237
+ if (otherNodeId.startsWith("pr:") || otherNodeId.startsWith("linear:")) {
6238
+ coveredIssueIds.add(issue.id);
6239
+ break;
6240
+ }
6241
+ }
6242
+ }
6243
+ return trieIssues.filter((issue) => {
6244
+ if (coveredIssueIds.has(issue.id)) return false;
6245
+ const normalizedFile = issue.data.file.replace(/^\.\//, "");
6246
+ for (const covered of coveredFiles) {
6247
+ if (normalizedFile.endsWith(covered) || covered.endsWith(normalizedFile)) {
6248
+ return false;
6249
+ }
6250
+ }
6251
+ return true;
6252
+ });
6253
+ }
6254
+ /**
6255
+ * Generate a brief summary for system prompt injection.
6256
+ * Only called when data is fresh (< 1 hour).
6257
+ */
6258
+ async getPipelineSummary(graph) {
6259
+ const nodes = await graph.listNodes();
6260
+ const tickets = nodes.filter((n) => n.type === "linear-ticket");
6261
+ const prs = nodes.filter((n) => n.type === "pull-request");
6262
+ const ghIssues = nodes.filter((n) => n.type === "github-issue");
6263
+ const trieIssues = nodes.filter((n) => n.type === "issue" && n.data.status === "open");
6264
+ if (tickets.length === 0 && prs.length === 0) return null;
6265
+ const activeTickets = tickets.filter(
6266
+ (t) => ["started", "In Progress", "in progress"].some(
6267
+ (s) => t.data.status.toLowerCase().includes(s.toLowerCase())
6268
+ )
6269
+ );
6270
+ const ciFailingPRs = prs.filter((pr) => pr.data.ciStatus === "failing");
6271
+ const approvedPRs = prs.filter((pr) => pr.data.reviewStatus === "approved");
6272
+ const uncovered = await this.findUncoveredIssues(graph, trieIssues, prs, tickets);
6273
+ const criticalUncovered = uncovered.filter((i) => i.data.severity === "critical" || i.data.severity === "serious");
6274
+ const parts = [];
6275
+ parts.push(`PIPELINE CONTEXT (as of ${(/* @__PURE__ */ new Date()).toISOString().slice(0, 16)}):`);
6276
+ if (activeTickets.length > 0) {
6277
+ const ticketIds = activeTickets.slice(0, 5).map((t) => t.data.ticketId).join(", ");
6278
+ parts.push(`- Linear: ${activeTickets.length} ticket${activeTickets.length !== 1 ? "s" : ""} in progress (${ticketIds})`);
6279
+ }
6280
+ if (prs.length > 0) {
6281
+ const details = [];
6282
+ if (ciFailingPRs.length > 0) details.push(`${ciFailingPRs.length} CI failing`);
6283
+ if (approvedPRs.length > 0) details.push(`${approvedPRs.length} approved`);
6284
+ parts.push(`- GitHub: ${prs.length} open PR${prs.length !== 1 ? "s" : ""}${details.length > 0 ? ` (${details.join(", ")})` : ""}, ${ghIssues.length} open issue${ghIssues.length !== 1 ? "s" : ""}`);
6285
+ }
6286
+ if (criticalUncovered.length > 0) {
6287
+ parts.push(`- Coverage: ${criticalUncovered.length} critical/serious Trie issue${criticalUncovered.length !== 1 ? "s" : ""} have no ticket or PR`);
6288
+ }
6289
+ parts.push("");
6290
+ parts.push('Ask "pipeline status" for full view, or mention a ticket/PR number for details.');
6291
+ return parts.join("\n");
6292
+ }
6293
+ };
6294
+ function shortPath(file) {
6295
+ const parts = file.split("/");
6296
+ return parts.length > 2 ? parts.slice(-2).join("/") : file;
6297
+ }
6298
+ function padEnd(str, len) {
6299
+ if (str.length >= len) return str.slice(0, len);
6300
+ return str + " ".repeat(len - str.length);
6301
+ }
6302
+ function truncate2(str, maxLen) {
6303
+ if (str.length <= maxLen) return str;
6304
+ return str.slice(0, maxLen - 1) + "\u2026";
6305
+ }
6306
+
6307
+ // src/tools/github-branches.ts
6308
+ import { execSync } from "child_process";
6309
+ var GitHubBranchesTool = class {
6310
+ async execute(input) {
6311
+ const workDir = input.directory || getWorkingDirectory(void 0, true);
6312
+ const limit = Math.min(Math.max(1, input.limit ?? 15), 30);
6313
+ const config = await loadConfig();
6314
+ const token = config.apiKeys?.github ?? process.env.GITHUB_TOKEN ?? null;
6315
+ if (!token) {
6316
+ return {
6317
+ content: [{
6318
+ type: "text",
6319
+ text: 'GitHub token not configured.\n\nSet one of:\n \u2022 Environment variable: GITHUB_TOKEN=ghp_...\n \u2022 Config dialog (C key) \u2192 API Keys \u2192 GitHub\n \u2022 .trie/config.json: { "apiKeys": { "github": "ghp_..." } }\n\nToken needs `repo` scope for private repos, `public_repo` for public.'
6320
+ }]
6321
+ };
6322
+ }
6323
+ const repoInfo = this.getRepoInfo(workDir);
6324
+ if (!repoInfo) {
6325
+ return {
6326
+ content: [{
6327
+ type: "text",
6328
+ text: "Could not detect GitHub repository.\n\nMake sure this directory is a git repo with a GitHub remote:\n git remote get-url origin"
6329
+ }]
6330
+ };
6331
+ }
6332
+ try {
6333
+ const branches = await this.fetchBranches(repoInfo.owner, repoInfo.name, token);
6334
+ const withDates = await this.enrichWithLatestCommit(
6335
+ repoInfo.owner,
6336
+ repoInfo.name,
6337
+ branches,
6338
+ token,
6339
+ limit
6340
+ );
6341
+ const lines = [
6342
+ `# GitHub Branches \u2014 ${repoInfo.owner}/${repoInfo.name}`,
6343
+ "",
6344
+ "**Branches by latest commit (most recent first):**",
6345
+ "",
6346
+ ...withDates.map((b) => {
6347
+ const dateStr = b.lastCommitDate ? new Date(b.lastCommitDate).toLocaleString("en-US", {
6348
+ month: "short",
6349
+ day: "numeric",
6350
+ hour: "numeric",
6351
+ minute: "2-digit"
6352
+ }) : "\u2014";
6353
+ const msg = b.lastCommitMessage ? b.lastCommitMessage.split("\n")[0]?.slice(0, 50) : "";
6354
+ return `- **${b.name}** \u2014 ${dateStr}${msg ? ` \u2014 ${msg}${msg.length >= 50 ? "\u2026" : ""}` : ""}`;
6355
+ }),
6356
+ "",
6357
+ "---",
6358
+ "",
6359
+ "Use `git fetch origin` to refresh local refs before comparing."
6360
+ ];
6361
+ return {
6362
+ content: [{ type: "text", text: lines.join("\n") }]
6363
+ };
6364
+ } catch (err) {
6365
+ const msg = err instanceof Error ? err.message : String(err);
6366
+ return {
6367
+ content: [{
6368
+ type: "text",
6369
+ text: `GitHub API error: ${msg}
6370
+
6371
+ Check token validity and repo access. Token needs \`repo\` or \`public_repo\` scope.`
6372
+ }]
6373
+ };
6374
+ }
6375
+ }
6376
+ getRepoInfo(projectPath) {
6377
+ try {
6378
+ const url = execSync("git remote get-url origin", {
6379
+ cwd: projectPath,
6380
+ encoding: "utf-8",
6381
+ stdio: ["pipe", "pipe", "pipe"]
6382
+ }).trim();
6383
+ const sshMatch = url.match(/github\.com[:/]([^/]+)\/([^/.]+)/);
6384
+ if (sshMatch) return { owner: sshMatch[1], name: sshMatch[2].replace(/\.git$/, "") };
6385
+ const httpsMatch = url.match(/github\.com\/([^/]+)\/([^/.]+)/);
6386
+ if (httpsMatch) return { owner: httpsMatch[1], name: httpsMatch[2].replace(/\.git$/, "") };
6387
+ return null;
6388
+ } catch {
6389
+ return null;
6390
+ }
6391
+ }
6392
+ async fetchBranches(owner, repo, token) {
6393
+ const url = `https://api.github.com/repos/${owner}/${repo}/branches?per_page=100`;
6394
+ const branches = await this.fetchJson(url, token);
6395
+ return branches;
6396
+ }
6397
+ async enrichWithLatestCommit(owner, repo, branches, token, limit) {
6398
+ const results = [];
6399
+ for (let i = 0; i < Math.min(branches.length, limit); i++) {
6400
+ const branch = branches[i];
6401
+ try {
6402
+ const url = `https://api.github.com/repos/${owner}/${repo}/commits?sha=${encodeURIComponent(branch.name)}&per_page=1`;
6403
+ const commits = await this.fetchJson(url, token);
6404
+ const commit = commits[0];
6405
+ results.push({
6406
+ name: branch.name,
6407
+ lastCommitDate: commit?.commit?.author?.date ?? null,
6408
+ lastCommitMessage: commit?.commit?.message ?? null
6409
+ });
6410
+ } catch {
6411
+ results.push({ name: branch.name, lastCommitDate: null, lastCommitMessage: null });
6412
+ }
6413
+ }
6414
+ results.sort((a, b) => {
6415
+ if (!a.lastCommitDate) return 1;
6416
+ if (!b.lastCommitDate) return -1;
6417
+ return new Date(b.lastCommitDate).getTime() - new Date(a.lastCommitDate).getTime();
6418
+ });
6419
+ return results;
6420
+ }
6421
+ async fetchJson(url, token) {
6422
+ const response = await fetch(url, {
6423
+ headers: {
6424
+ Accept: "application/vnd.github.v3+json",
6425
+ Authorization: `Bearer ${token}`,
6426
+ "User-Agent": "trie-agents",
6427
+ "X-GitHub-Api-Version": "2022-11-28"
6428
+ }
6429
+ });
6430
+ if (response.status === 401) {
6431
+ throw new Error("GitHub token is invalid or expired.");
6432
+ }
6433
+ if (response.status === 403) {
6434
+ const resetHeader = response.headers.get("X-RateLimit-Reset");
6435
+ const resetTime = resetHeader ? new Date(parseInt(resetHeader, 10) * 1e3).toLocaleTimeString() : "unknown";
6436
+ throw new Error(`GitHub API rate limit exceeded. Resets at ${resetTime}.`);
6437
+ }
6438
+ if (response.status === 404) {
6439
+ throw new Error("Repository not found or token lacks access.");
6440
+ }
6441
+ if (!response.ok) {
6442
+ throw new Error(`GitHub API error ${response.status}: ${response.statusText}`);
6443
+ }
6444
+ return await response.json();
6445
+ }
6446
+ };
6447
+
5712
6448
  // src/cli/dashboard/chat-tools.ts
5713
6449
  import { createHash } from "crypto";
5714
6450
  function textFromResult(result) {
@@ -5807,6 +6543,31 @@ var CHAT_TOOLS = [
5807
6543
  required: ["query"]
5808
6544
  }
5809
6545
  },
6546
+ {
6547
+ name: "trie_github_branches",
6548
+ description: "Fetch GitHub branches with latest commit info. Use when the user asks which branch has the latest updates, what branches exist, or when branches were last updated. Requires GitHub API key.",
6549
+ input_schema: {
6550
+ type: "object",
6551
+ properties: {
6552
+ limit: { type: "number", description: "Max branches to return (default 15, max 30)" }
6553
+ }
6554
+ }
6555
+ },
6556
+ {
6557
+ name: "trie_get_pipeline",
6558
+ description: "Get current pipeline status: open PRs, active Linear tickets, open GitHub issues, and Trie scan issues not yet tracked in any ticket or PR. Use when the user asks about the status of work, what PRs are open, or what tickets are in progress.",
6559
+ input_schema: {
6560
+ type: "object",
6561
+ properties: {
6562
+ focus: { type: "string", description: "Optional file path or ticket ID to narrow the view" },
6563
+ include: {
6564
+ type: "array",
6565
+ items: { type: "string", enum: ["prs", "tickets", "issues", "coverage"] },
6566
+ description: "What to include (default: all)"
6567
+ }
6568
+ }
6569
+ }
6570
+ },
5810
6571
  {
5811
6572
  name: "trie_checkpoint",
5812
6573
  description: "Save a work checkpoint, list recent checkpoints, or get the last one.",
@@ -6005,6 +6766,20 @@ async function executeTool(name, input, onProgress) {
6005
6766
  const result = await tool.execute(withDir);
6006
6767
  return textFromResult(result);
6007
6768
  }
6769
+ case "trie_github_branches": {
6770
+ const branchesTool = new GitHubBranchesTool();
6771
+ const branchesArgs = { directory };
6772
+ if (typeof input.limit === "number") branchesArgs.limit = input.limit;
6773
+ const result = await branchesTool.execute(branchesArgs);
6774
+ return textFromResult(result);
6775
+ }
6776
+ case "trie_get_pipeline": {
6777
+ const pipelineTool = new TriePipelineTool();
6778
+ const pipelineArgs = { action: "status", directory };
6779
+ if (input.focus) pipelineArgs.focus = String(input.focus);
6780
+ const result = await pipelineTool.execute(pipelineArgs);
6781
+ return textFromResult(result);
6782
+ }
6008
6783
  case "trie_checkpoint": {
6009
6784
  const result = await handleCheckpointTool(input);
6010
6785
  return result;
@@ -6247,7 +7022,7 @@ ${truncated}`;
6247
7022
  const goalId = input.goalId ? String(input.goalId).trim() : void 0;
6248
7023
  try {
6249
7024
  onProgress?.("Loading goals...");
6250
- const { checkFilesForGoalViolations, getActiveGoals } = await import("./goal-validator-GISXYANK.js");
7025
+ const { getActiveGoals } = await import("./goal-validator-HNXXUCPW.js");
6251
7026
  const agentState = getProjectState(directory);
6252
7027
  await agentState.load();
6253
7028
  const allGoals = await getActiveGoals(directory);
@@ -6256,11 +7031,21 @@ ${truncated}`;
6256
7031
  return goalId ? `No active goal found with ID: ${goalId}` : "No active goals to check. Add goals in the Goals view first.";
6257
7032
  }
6258
7033
  onProgress?.("Scanning codebase for violations...");
6259
- const violations = await checkFilesForGoalViolations(goalsToCheck, directory, void 0, onProgress);
7034
+ const { analyzeFilesRapidly } = await import("./fast-analyzer-AYLZB5TW.js");
7035
+ const analysisOptions = {
7036
+ maxFiles: 50,
7037
+ enableSmartBatching: true
7038
+ };
7039
+ if (onProgress) {
7040
+ analysisOptions.onProgress = onProgress;
7041
+ }
7042
+ const analysisResult = await analyzeFilesRapidly(goalsToCheck, directory, analysisOptions);
7043
+ const violations = analysisResult.violations;
6260
7044
  if (violations.length === 0) {
6261
- return `\u2713 Scan complete! No violations found for ${goalsToCheck.length} goal(s).`;
7045
+ const cacheInfo2 = analysisResult.cacheHitRatio > 0 ? ` (${Math.round(analysisResult.cacheHitRatio * 100)}% cache hit, ${analysisResult.timeMs}ms)` : ` (${analysisResult.timeMs}ms)`;
7046
+ return `\u2713 Scan complete! No violations found for ${goalsToCheck.length} goal(s).${cacheInfo2}`;
6262
7047
  }
6263
- const { storeIssues } = await import("./issue-store-BO5OWLJW.js");
7048
+ const { storeIssues } = await import("./issue-store-LZWZIGM7.js");
6264
7049
  const { basename } = await import("path");
6265
7050
  const issuesToStore = violations.map((v, i) => ({
6266
7051
  id: `goal-violation-${Date.now()}-${i}`,
@@ -6274,18 +7059,19 @@ ${truncated}`;
6274
7059
  autoFixable: false
6275
7060
  }));
6276
7061
  await storeIssues(issuesToStore, basename(directory), directory);
6277
- let result = `Found ${violations.length} violation(s):
7062
+ let violationsReport = `Found ${violations.length} violation(s):
6278
7063
 
6279
7064
  `;
6280
7065
  for (const v of violations) {
6281
- result += `\u26A0\uFE0F ${v.file}
7066
+ violationsReport += `\u26A0\uFE0F ${v.file}
6282
7067
  `;
6283
- result += ` ${v.message}
7068
+ violationsReport += ` ${v.message}
6284
7069
 
6285
7070
  `;
6286
7071
  }
6287
- result += "Violations recorded to ledger (AI source). Check Ledger view.";
6288
- return result;
7072
+ const cacheInfo = analysisResult.cacheHitRatio > 0 ? ` Cache hit: ${Math.round(analysisResult.cacheHitRatio * 100)}% \u2022 Time: ${analysisResult.timeMs}ms` : ` Analysis time: ${analysisResult.timeMs}ms`;
7073
+ violationsReport += `Violations recorded to ledger (AI source).${cacheInfo}`;
7074
+ return violationsReport;
6289
7075
  } catch (error) {
6290
7076
  return `Scan failed: ${error.message}`;
6291
7077
  }
@@ -6320,7 +7106,7 @@ ${truncated}`;
6320
7106
  }
6321
7107
  try {
6322
7108
  onProgress?.("Gathering evidence for hypothesis...");
6323
- const { gatherEvidenceForHypothesis } = await import("./hypothesis-K3KQJOXJ.js");
7109
+ const { gatherEvidenceForHypothesis } = await import("./hypothesis-JCUMZKTG.js");
6324
7110
  const evidence = await gatherEvidenceForHypothesis(hypothesisId, directory);
6325
7111
  if (evidence.length === 0) {
6326
7112
  return `No evidence found for this hypothesis yet. The codebase may not have enough data to validate it \u2014 try running trie_scan_for_goal_violations first to populate issues, or add more context.`;
@@ -6539,11 +7325,13 @@ function ChatView() {
6539
7325
  const { state, dispatch } = useDashboard();
6540
7326
  const { chatState } = state;
6541
7327
  const { messages, inputBuffer, loading, progress, messageQueue, currentSessionId, currentSessionTitle } = chatState;
6542
- const loadingRef = useRef(false);
7328
+ const loadingRef = useRef3(false);
6543
7329
  const { stdout } = useStdout9();
6544
7330
  const [cursorVisible, setCursorVisible] = useState2(true);
6545
7331
  const [scrollOffset, setScrollOffset] = useState2(0);
6546
7332
  const terminalHeight = stdout?.rows || 24;
7333
+ const terminalWidth = stdout?.columns || 80;
7334
+ const contentWidth = Math.max(40, terminalWidth - 4);
6547
7335
  const availableLines = Math.max(8, terminalHeight - 7);
6548
7336
  const VISIBLE_MESSAGES = Math.min(availableLines, 20);
6549
7337
  useEffect3(() => {
@@ -6765,7 +7553,7 @@ ${contextBlock}`;
6765
7553
  dispatch({
6766
7554
  type: "SET_GOALS",
6767
7555
  goals: goals.map((g) => {
6768
- const base = { id: g.id, description: g.description, type: g.type, target: g.target, currentValue: g.currentValue, status: g.status, autoGenerated: g.autoGenerated, updatedAt: g.updatedAt, ...g.category != null ? { category: g.category } : {} };
7556
+ const base = { id: g.id, description: g.description, type: g.type, target: g.target, currentValue: g.currentValue, startValue: g.startValue, status: g.status, autoGenerated: g.autoGenerated, updatedAt: g.updatedAt, ...g.category != null ? { category: g.category } : {} };
6769
7557
  return base;
6770
7558
  })
6771
7559
  });
@@ -6885,16 +7673,16 @@ ${contextBlock}`;
6885
7673
  "]"
6886
7674
  ] })
6887
7675
  ] }) }),
6888
- /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", flexGrow: 1, flexShrink: 1, height: "100%", minHeight: 0, marginTop: 1, marginBottom: 1, children: [
7676
+ /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", flexGrow: 1, flexShrink: 1, height: "100%", minHeight: 0, marginTop: 1, marginBottom: 1, width: terminalWidth, children: [
6889
7677
  messages.length === 0 && !loading && /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " Ask about your codebase, decisions, patterns, or risks." }),
6890
7678
  canScrollUp && /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " \u2191 more messages above" }),
6891
- visibleMessages.map((msg, idx) => /* @__PURE__ */ jsx13(Box12, { flexDirection: "column", marginTop: idx === 0 ? 0 : 1, children: msg.role === "user" ? /* @__PURE__ */ jsxs12(Text12, { wrap: "wrap", children: [
7679
+ visibleMessages.map((msg, idx) => /* @__PURE__ */ jsx13(Box12, { flexDirection: "column", marginTop: idx === 0 ? 0 : 1, width: contentWidth, children: msg.role === "user" ? /* @__PURE__ */ jsxs12(Text12, { wrap: "wrap", children: [
6892
7680
  " ",
6893
7681
  /* @__PURE__ */ jsx13(Text12, { bold: true, color: "green", children: "You:" }),
6894
7682
  " ",
6895
- msg.content
7683
+ wrapLine(msg.content, contentWidth - 8)
6896
7684
  ] }) : /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", children: [
6897
- msg.toolCalls && msg.toolCalls.length > 0 && msg.toolCalls.map((tc, ti) => /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
7685
+ msg.toolCalls && msg.toolCalls.length > 0 && msg.toolCalls.map((tc, ti) => /* @__PURE__ */ jsxs12(Text12, { wrap: "wrap", dimColor: true, children: [
6898
7686
  " ",
6899
7687
  /* @__PURE__ */ jsxs12(Text12, { color: "yellow", children: [
6900
7688
  "[",
@@ -6902,9 +7690,9 @@ ${contextBlock}`;
6902
7690
  "]"
6903
7691
  ] }),
6904
7692
  " ",
6905
- formatToolInput(tc.input)
7693
+ wrapLine(formatToolInput(tc.input), contentWidth - 12)
6906
7694
  ] }, ti)),
6907
- msg.content.split("\n").map((line, li) => /* @__PURE__ */ jsxs12(Text12, { wrap: "wrap", children: [
7695
+ wrapContent(msg.content, contentWidth - 8).map((line, li) => /* @__PURE__ */ jsxs12(Text12, { wrap: "wrap", children: [
6908
7696
  li === 0 ? " Trie: " : " ",
6909
7697
  line
6910
7698
  ] }, li))
@@ -6925,6 +7713,31 @@ ${contextBlock}`;
6925
7713
  ] }) }) })
6926
7714
  ] });
6927
7715
  }
7716
+ function wrapLine(text, width) {
7717
+ if (width <= 0 || text.length <= width) return text;
7718
+ const lines = [];
7719
+ const words = text.split(/\s+/);
7720
+ let current = "";
7721
+ for (const w of words) {
7722
+ const wouldBe = current ? current + " " + w : w;
7723
+ if (wouldBe.length <= width) {
7724
+ current = wouldBe;
7725
+ } else {
7726
+ if (current) lines.push(current);
7727
+ current = w.length > width ? w.match(new RegExp(`.{1,${width}}`, "g"))?.join("\n") ?? w : w;
7728
+ }
7729
+ }
7730
+ if (current) lines.push(current);
7731
+ return lines.join("\n");
7732
+ }
7733
+ function wrapContent(content, width) {
7734
+ const result = [];
7735
+ for (const para of content.split("\n")) {
7736
+ const wrapped = wrapLine(para.trim(), width);
7737
+ result.push(...wrapped.split("\n"));
7738
+ }
7739
+ return result;
7740
+ }
6928
7741
  function formatToolInput(input) {
6929
7742
  const parts = [];
6930
7743
  for (const [k, v] of Object.entries(input)) {
@@ -7166,7 +7979,7 @@ import { jsx as jsx15, jsxs as jsxs14 } from "react/jsx-runtime";
7166
7979
  var MAIN_VIEWS = ["overview", "memory", "goals", "hypotheses", "agent", "chat"];
7167
7980
  async function applyGoalFix(fix, dispatch) {
7168
7981
  try {
7169
- const { runAIAnalysis, isAIAvailable: isAIAvailable2 } = await import("./client-JTU5TRLB.js");
7982
+ const { runAIAnalysis, isAIAvailable: isAIAvailable2 } = await import("./client-INNE2GGZ.js");
7170
7983
  if (!isAIAvailable2()) {
7171
7984
  dispatch({ type: "DISMISS_FIX", id: fix.id });
7172
7985
  getOutputManager().nudge("AI not available for fix", "warning");
@@ -7201,7 +8014,7 @@ ${content}
7201
8014
  fixedContent = fixedContent.replace(/^```\w*\n?/, "").replace(/\n?```$/, "");
7202
8015
  }
7203
8016
  await writeFile(fullPath, fixedContent, "utf-8");
7204
- const { recordGoalViolationFixed, getActiveGoals } = await import("./goal-validator-GISXYANK.js");
8017
+ const { recordGoalViolationFixed, getActiveGoals } = await import("./goal-validator-HNXXUCPW.js");
7205
8018
  const goals = await getActiveGoals(projectPath);
7206
8019
  const matchedGoal = goals.find((g) => g.description === fix.goalDescription);
7207
8020
  if (matchedGoal) {
@@ -7220,12 +8033,12 @@ function DashboardApp({ onReady }) {
7220
8033
  const { stdout } = useStdout11();
7221
8034
  const [showConfig, setShowConfig] = useState3(false);
7222
8035
  const [showHelp, setShowHelp] = useState3(false);
7223
- const dispatchRef = useRef2(dispatch);
8036
+ const dispatchRef = useRef4(dispatch);
7224
8037
  dispatchRef.current = dispatch;
7225
- const stateRef = useRef2(state);
8038
+ const stateRef = useRef4(state);
7226
8039
  stateRef.current = state;
7227
8040
  const configPath = join2(getTrieDirectory(getWorkingDirectory(void 0, true)), "agent.json");
7228
- const loadConfig = useCallback7(async () => {
8041
+ const loadConfig2 = useCallback7(async () => {
7229
8042
  if (!existsSync3(configPath)) return;
7230
8043
  try {
7231
8044
  const raw = await readFile2(configPath, "utf-8");
@@ -7239,10 +8052,10 @@ function DashboardApp({ onReady }) {
7239
8052
  const workDir = getWorkingDirectory(void 0, true);
7240
8053
  await mkdir(getTrieDirectory(workDir), { recursive: true });
7241
8054
  await writeFile(configPath, JSON.stringify(stateRef.current.agentConfig, null, 2), "utf-8");
7242
- const { saveAutonomyConfig, loadAutonomyConfig } = await import("./autonomy-config-TZ6HF4FA.js");
7243
- const autonomy = await loadAutonomyConfig(workDir);
8055
+ const { saveAutonomyConfig: saveAutonomyConfig2, loadAutonomyConfig: loadAutonomyConfig2 } = await import("./autonomy-config-ZCOSTMPD.js");
8056
+ const autonomy = await loadAutonomyConfig2(workDir);
7244
8057
  autonomy.aiWatcher = stateRef.current.agentConfig.aiWatcher;
7245
- await saveAutonomyConfig(workDir, autonomy);
8058
+ await saveAutonomyConfig2(workDir, autonomy);
7246
8059
  } catch {
7247
8060
  }
7248
8061
  }, [configPath]);
@@ -7281,7 +8094,7 @@ function DashboardApp({ onReady }) {
7281
8094
  dispatchRef.current({
7282
8095
  type: "SET_GOALS",
7283
8096
  goals: goals.map((g) => {
7284
- const base = { id: g.id, description: g.description, type: g.type, target: g.target, currentValue: g.currentValue, status: g.status, autoGenerated: g.autoGenerated, updatedAt: g.updatedAt, ...g.achievedAt != null ? { achievedAt: g.achievedAt } : {}, ...g.achievedBy != null ? { achievedBy: g.achievedBy } : {}, ...g.category != null ? { category: g.category } : {} };
8097
+ const base = { id: g.id, description: g.description, type: g.type, target: g.target, currentValue: g.currentValue, startValue: g.startValue, status: g.status, autoGenerated: g.autoGenerated, updatedAt: g.updatedAt, ...g.achievedAt != null ? { achievedAt: g.achievedAt } : {}, ...g.achievedBy != null ? { achievedBy: g.achievedBy } : {}, ...g.category != null ? { category: g.category } : {} };
7285
8098
  return base;
7286
8099
  })
7287
8100
  });
@@ -7328,7 +8141,7 @@ function DashboardApp({ onReady }) {
7328
8141
  }
7329
8142
  }, []);
7330
8143
  useEffect5(() => {
7331
- void loadConfig();
8144
+ void loadConfig2();
7332
8145
  void refreshGoals();
7333
8146
  void refreshHypotheses();
7334
8147
  void processInsights([]);
@@ -7344,12 +8157,6 @@ function DashboardApp({ onReady }) {
7344
8157
  dispatchRef.current({ type: "STREAM_UPDATE", update: { type: "raw_log", data: { time, level, message }, timestamp: Date.now() } });
7345
8158
  },
7346
8159
  onNudge: (nudge) => {
7347
- console.debug("[Dashboard] Nudge received:", {
7348
- message: nudge.message.slice(0, 50) + "...",
7349
- severity: nudge.severity,
7350
- file: nudge.file,
7351
- timestamp: (/* @__PURE__ */ new Date()).toISOString()
7352
- });
7353
8160
  const action = { type: "SHOW_NOTIFICATION", message: nudge.message, severity: nudge.severity };
7354
8161
  if (nudge.file !== void 0) action.file = nudge.file;
7355
8162
  if (nudge.autoHideMs !== void 0) action.autoHideMs = nudge.autoHideMs;
@@ -7368,17 +8175,8 @@ function DashboardApp({ onReady }) {
7368
8175
  relatedIssues: [],
7369
8176
  dismissed: false
7370
8177
  };
7371
- console.debug("[Dashboard] Creating insight from nudge:", {
7372
- id: insight.id,
7373
- type: insight.type,
7374
- priority: insight.priority,
7375
- category: insight.category,
7376
- isGoalViolation,
7377
- severity: nudge.severity
7378
- });
7379
8178
  dispatchRef.current({ type: "ADD_INSIGHTS", insights: [insight] });
7380
8179
  if (isGoalViolation) {
7381
- console.debug("[Dashboard] Goal violation - extending notification display");
7382
8180
  const extendedAction = { ...action };
7383
8181
  if (!extendedAction.autoHideMs || extendedAction.autoHideMs < 15e3) {
7384
8182
  extendedAction.autoHideMs = 15e3;
@@ -7407,29 +8205,32 @@ function DashboardApp({ onReady }) {
7407
8205
  outputManager.clearTUICallbacks();
7408
8206
  outputManager.setMode("console");
7409
8207
  };
7410
- }, [loadConfig, onReady, processInsights, refreshGoals, refreshHypotheses, loadPersistedNudges]);
8208
+ }, [loadConfig2, onReady, processInsights, refreshGoals, refreshHypotheses, loadPersistedNudges]);
7411
8209
  useEffect5(() => {
7412
8210
  const interval = setInterval(() => {
7413
8211
  dispatchRef.current({ type: "AUTO_DISMISS_NOTIFICATIONS" });
7414
8212
  }, 5e3);
7415
8213
  return () => clearInterval(interval);
7416
8214
  }, []);
7417
- const applyingFixIds = useRef2(/* @__PURE__ */ new Set());
8215
+ const applyingFixIds = useRef4(/* @__PURE__ */ new Set());
7418
8216
  useEffect5(() => {
7419
8217
  const toApply = state.pendingFixes.filter((f) => f.status === "applying" && !applyingFixIds.current.has(f.id));
7420
8218
  for (const fix of toApply) {
7421
8219
  applyingFixIds.current.add(fix.id);
7422
8220
  applyGoalFix(fix, dispatchRef.current).catch((error) => {
7423
- console.error(`Failed to apply fix for ${fix.file}:`, error);
7424
8221
  dispatchRef.current({ type: "DISMISS_FIX", id: fix.id });
7425
8222
  getOutputManager().nudge(`Fix failed for ${fix.file}: ${error instanceof Error ? error.message : "unknown error"}`, "warning");
7426
8223
  });
7427
8224
  }
7428
8225
  }, [state.pendingFixes]);
7429
8226
  useInput10((input, key) => {
8227
+ if (showConfig) return;
8228
+ if (state.memoryTree.pendingLedgerDelete) return;
7430
8229
  const inAddMode = state.view === "goals" && state.goalsPanel.inputMode === "add" || state.view === "hypotheses" && state.hypothesesPanel.inputMode === "add";
7431
8230
  const inChat = state.view === "chat";
7432
- if (!inAddMode && !inChat && (input === "q" || input === "Q" || key.escape)) {
8231
+ const scanningGoal = !!state.goalsPanel.scanningGoalId;
8232
+ const scanningHypothesis = !!state.hypothesesPanel.scanningHypothesisId;
8233
+ if (!inAddMode && !inChat && !scanningGoal && !scanningHypothesis && (input === "q" || input === "Q" || key.escape)) {
7433
8234
  exit();
7434
8235
  return;
7435
8236
  }
@@ -7437,7 +8238,6 @@ function DashboardApp({ onReady }) {
7437
8238
  exit();
7438
8239
  return;
7439
8240
  }
7440
- if (showConfig) return;
7441
8241
  if (inAddMode) return;
7442
8242
  if ((input === "/" || input === "?") && state.view !== "chat") {
7443
8243
  setShowHelp(!showHelp);
@@ -7595,6 +8395,8 @@ export {
7595
8395
  TrieGetRelatedDecisionsTool,
7596
8396
  TrieQueryContextTool,
7597
8397
  handleCheckpointTool,
8398
+ TriePipelineTool,
8399
+ GitHubBranchesTool,
7598
8400
  InteractiveDashboard
7599
8401
  };
7600
- //# sourceMappingURL=chunk-X3F5QDER.js.map
8402
+ //# sourceMappingURL=chunk-4O2KRHK4.js.map