@triedotdev/mcp 1.0.124 → 1.0.126

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.
package/README.md CHANGED
@@ -635,6 +635,17 @@ What happens at the 10,000 issue cap: Trie will deduplicate new repeats, compact
635
635
 
636
636
  **Hooks not working**: Reinstall with `trie init`. Make sure you have write permissions to .git/hooks/.
637
637
 
638
+ **Goals showing but not detecting violations**: This happens when goals appear in the UI but aren't active in guardian state. The Goals view will show a yellow warning box. To fix:
639
+ ```bash
640
+ # Quick fix - activate a specific goal
641
+ node fix-goals.js "NO EMOJIS"
642
+
643
+ # Or use the proper CLI (recommended)
644
+ trie goal add "NO EMOJIS"
645
+ trie goal list
646
+ ```
647
+ See [Goal Detection Fix](./docs/GOAL_DETECTION_FIX.md) for details.
648
+
638
649
  ### Getting Help
639
650
  - Issues: [Report bugs and request features](https://x.com/louiskishfy)
640
651
 
@@ -294,7 +294,7 @@ import { render } from "ink";
294
294
  import React11 from "react";
295
295
 
296
296
  // src/cli/dashboard/App.tsx
297
- import { useState as useState2, useEffect as useEffect5, useCallback as useCallback7, useRef as useRef2 } from "react";
297
+ import { useState as useState3, useEffect as useEffect5, useCallback as useCallback7, useRef as useRef2 } from "react";
298
298
  import { Box as Box14, useInput as useInput10, useApp } from "ink";
299
299
 
300
300
  // src/cli/dashboard/state.tsx
@@ -667,6 +667,8 @@ function dashboardReducer(state, action) {
667
667
  timestamp: Date.now()
668
668
  };
669
669
  if (action.toolCalls && action.toolCalls.length > 0) msg.toolCalls = action.toolCalls;
670
+ if (action.pendingFix) msg.pendingFix = action.pendingFix;
671
+ if (action.pendingFixes && action.pendingFixes.length > 0) msg.pendingFixes = action.pendingFixes;
670
672
  return {
671
673
  ...state,
672
674
  chatState: {
@@ -989,7 +991,7 @@ function Footer() {
989
991
  " (",
990
992
  unreadNudgesCount,
991
993
  ")"
992
- ] }) : /* @__PURE__ */ jsx3(Text2, { color: "green", children: labels[v] }),
994
+ ] }) : /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: labels[v] }),
993
995
  !isLast && /* @__PURE__ */ jsx3(Text2, { dimColor: true, children: " \xB7 " })
994
996
  ] }, v);
995
997
  }) }),
@@ -1005,7 +1007,7 @@ function Footer() {
1005
1007
  const isCurrent = v === view;
1006
1008
  const isLast = idx === TAB_VIEWS.length - 1;
1007
1009
  return /* @__PURE__ */ jsxs2(React2.Fragment, { children: [
1008
- isCurrent ? /* @__PURE__ */ jsx3(Text2, { color: "white", bold: true, children: labels[v] }) : isAgent && hasUnreadNudges ? /* @__PURE__ */ jsxs2(Text2, { color: "yellow", bold: true, children: [
1010
+ isCurrent ? /* @__PURE__ */ jsx3(Text2, { color: "green", bold: true, children: labels[v] }) : isAgent && hasUnreadNudges ? /* @__PURE__ */ jsxs2(Text2, { color: "yellow", bold: true, children: [
1009
1011
  labels[v],
1010
1012
  " (",
1011
1013
  unreadNudgesCount,
@@ -1776,7 +1778,7 @@ function GoalsView() {
1776
1778
  const { goalsPanel } = state;
1777
1779
  const activeGoals = goalsPanel.goals.filter((g) => g.status === "active");
1778
1780
  const achievedGoals = goalsPanel.goals.filter((g) => g.status === "achieved");
1779
- const otherGoals = goalsPanel.goals.filter((g) => g.status !== "active" && g.status !== "achieved");
1781
+ const otherGoals = goalsPanel.goals.filter((g) => g.status !== "active" && g.status !== "achieved" && g.status !== "rejected");
1780
1782
  const refreshGoals = useCallback2(async () => {
1781
1783
  try {
1782
1784
  const workDir = getWorkingDirectory(void 0, true);
@@ -1884,8 +1886,8 @@ function GoalsView() {
1884
1886
  const goal = goalsPanel.goals.find((g) => g.id === goalId);
1885
1887
  if (!goal) return;
1886
1888
  dispatch({ type: "ADD_ACTIVITY", message: `Checking goal: ${goal.description.slice(0, 30)}...` });
1887
- dispatch({ type: "SHOW_NOTIFICATION", message: `Scanning files for violations...`, severity: "info", autoHideMs: 3e3 });
1888
- const { checkFilesForGoalViolations } = await import("./goal-validator-CKFKJ46J.js");
1889
+ dispatch({ type: "SHOW_NOTIFICATION", message: `Scanning files... This may take a moment for large codebases`, severity: "info", autoHideMs: 5e3 });
1890
+ const { checkFilesForGoalViolations } = await import("./goal-validator-4RA64F37.js");
1889
1891
  const violations = await checkFilesForGoalViolations([goal], workDir);
1890
1892
  if (violations.length === 0) {
1891
1893
  dispatch({ type: "SHOW_NOTIFICATION", message: `\u2713 No violations found for: ${goal.description.slice(0, 40)}`, severity: "info", autoHideMs: 5e3 });
@@ -1954,6 +1956,11 @@ function GoalsView() {
1954
1956
  ] }) }),
1955
1957
  /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " enter save \xB7 esc cancel" })
1956
1958
  ] }) : /* @__PURE__ */ jsx9(Fragment2, { children: goalsPanel.goals.length === 0 ? /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: " No goals yet. Press a to add one." }) : /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", children: [
1959
+ activeGoals.length === 0 && goalsPanel.goals.length > 0 && /* @__PURE__ */ jsxs8(Box8, { flexDirection: "column", marginBottom: 1, paddingX: 1, borderStyle: "round", borderColor: "yellow", children: [
1960
+ /* @__PURE__ */ jsx9(Text8, { color: "yellow", bold: true, children: "\u26A0 No Active Goals" }),
1961
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: "Goals exist but none are active. Violations won't be detected." }),
1962
+ /* @__PURE__ */ jsx9(Text8, { dimColor: true, children: 'Press a to add a new goal, or run: trie goal add "your goal"' })
1963
+ ] }),
1957
1964
  activeGoals.map((goal, idx) => {
1958
1965
  const isSelected = goalsPanel.selectedIndex === idx;
1959
1966
  const progress = calculateGoalProgress(goal);
@@ -2430,7 +2437,7 @@ function RawLogView() {
2430
2437
  }
2431
2438
 
2432
2439
  // src/cli/dashboard/views/ChatView.tsx
2433
- import { useCallback as useCallback5, useRef, useEffect as useEffect3 } from "react";
2440
+ import { useCallback as useCallback5, useRef, useEffect as useEffect3, useState as useState2 } from "react";
2434
2441
  import { Box as Box12, Text as Text12, useInput as useInput8 } from "ink";
2435
2442
 
2436
2443
  // src/tools/tell.ts
@@ -5242,7 +5249,7 @@ ${truncated}`;
5242
5249
  case "trie_scan_for_goal_violations": {
5243
5250
  const goalId = input.goalId ? String(input.goalId).trim() : void 0;
5244
5251
  try {
5245
- const { checkFilesForGoalViolations, getActiveGoals } = await import("./goal-validator-CKFKJ46J.js");
5252
+ const { checkFilesForGoalViolations, getActiveGoals } = await import("./goal-validator-4RA64F37.js");
5246
5253
  const agentState = getGuardianState(directory);
5247
5254
  await agentState.load();
5248
5255
  const allGoals = await getActiveGoals(directory);
@@ -5281,6 +5288,7 @@ ${truncated}`;
5281
5288
 
5282
5289
  // src/cli/dashboard/views/ChatView.tsx
5283
5290
  import { jsx as jsx13, jsxs as jsxs12 } from "react/jsx-runtime";
5291
+ var VISIBLE_MESSAGES = 8;
5284
5292
  async function buildContext(workDir, dashboardState) {
5285
5293
  const parts = [];
5286
5294
  if (dashboardState?.agentInsights) {
@@ -5419,6 +5427,21 @@ function ChatView() {
5419
5427
  const { chatState } = state;
5420
5428
  const { messages, inputBuffer, loading, currentSessionId, currentSessionTitle } = chatState;
5421
5429
  const loadingRef = useRef(false);
5430
+ const [cursorVisible, setCursorVisible] = useState2(true);
5431
+ const [scrollOffset, setScrollOffset] = useState2(0);
5432
+ useEffect3(() => {
5433
+ if (loading) {
5434
+ setCursorVisible(true);
5435
+ return;
5436
+ }
5437
+ const interval = setInterval(() => {
5438
+ setCursorVisible((v) => !v);
5439
+ }, 500);
5440
+ return () => clearInterval(interval);
5441
+ }, [loading]);
5442
+ useEffect3(() => {
5443
+ setScrollOffset(0);
5444
+ }, [messages.length]);
5422
5445
  useEffect3(() => {
5423
5446
  if (messages.length === 0) return;
5424
5447
  const saveChat = async () => {
@@ -5449,47 +5472,82 @@ function ChatView() {
5449
5472
  dispatch({ type: "SET_CHAT_LOADING", loading: true });
5450
5473
  try {
5451
5474
  const workDir = getWorkingDirectory(void 0, true);
5475
+ const response = question.trim().toLowerCase();
5476
+ const isYesToAll = response === "yes to all" || response === "y to all" || response === "yes all";
5477
+ const isYes = response === "yes" || response === "y";
5478
+ const isNo = response === "no" || response === "n";
5479
+ const collectPendingFixes = () => {
5480
+ const fixes = [];
5481
+ const recentAssistantMessages = messages.filter((m) => m.role === "assistant").slice(-5);
5482
+ for (const msg of recentAssistantMessages) {
5483
+ if (msg.pendingFixes && msg.pendingFixes.length > 0) {
5484
+ fixes.push(...msg.pendingFixes);
5485
+ } else if (msg.pendingFix) {
5486
+ fixes.push(msg.pendingFix);
5487
+ }
5488
+ }
5489
+ return fixes;
5490
+ };
5491
+ const allPendingFixes = collectPendingFixes();
5452
5492
  const lastAssistantMessage = messages.filter((m) => m.role === "assistant").pop();
5453
- if (lastAssistantMessage?.pendingFix) {
5454
- const response = question.trim().toLowerCase();
5455
- if (response === "yes" || response === "y") {
5493
+ const lastFixes = lastAssistantMessage?.pendingFixes || (lastAssistantMessage?.pendingFix ? [lastAssistantMessage.pendingFix] : []);
5494
+ if (allPendingFixes.length > 0 && (isYes || isYesToAll || isNo)) {
5495
+ if (isNo) {
5496
+ dispatch({
5497
+ type: "ADD_CHAT_MESSAGE",
5498
+ role: "assistant",
5499
+ content: "Fix cancelled. Let me know if you need anything else!"
5500
+ });
5501
+ dispatch({ type: "SET_CHAT_LOADING", loading: false });
5502
+ loadingRef.current = false;
5503
+ return;
5504
+ }
5505
+ const fixesToApply = isYesToAll ? allPendingFixes : lastFixes;
5506
+ if (fixesToApply.length > 0) {
5456
5507
  const { spawnClaudeCodeFix } = await import("./terminal-spawn-P5M5PHAV.js");
5457
- try {
5458
- await spawnClaudeCodeFix({
5459
- ...lastAssistantMessage.pendingFix,
5460
- cwd: lastAssistantMessage.pendingFix.directory
5461
- });
5462
- dispatch({
5463
- type: "ADD_CHAT_MESSAGE",
5464
- role: "assistant",
5465
- content: `\u2713 Spawned Claude Code in a new terminal to fix "${lastAssistantMessage.pendingFix.file}".
5508
+ const results = [];
5509
+ const errors = [];
5510
+ for (const fix of fixesToApply) {
5511
+ try {
5512
+ await spawnClaudeCodeFix({
5513
+ ...fix,
5514
+ cwd: fix.directory
5515
+ });
5516
+ results.push(`"${fix.file}"`);
5517
+ } catch (error) {
5518
+ errors.push(`${fix.file}: ${error instanceof Error ? error.message : "unknown error"}`);
5519
+ }
5520
+ }
5521
+ let message = "";
5522
+ if (results.length > 0) {
5523
+ if (results.length === 1 && fixesToApply[0]) {
5524
+ const fix = fixesToApply[0];
5525
+ message = `Spawned Claude Code in a new terminal to fix ${results[0]}.
5466
5526
 
5467
5527
  Claude Code will:
5468
5528
  1. Review the file
5469
- 2. Understand the goal: "${lastAssistantMessage.pendingFix.goal}"
5470
- 3. Fix the violation: "${lastAssistantMessage.pendingFix.violation}"
5529
+ 2. Understand the goal: "${fix.goal}"
5530
+ 3. Fix the violation: "${fix.violation}"
5471
5531
  4. Preserve all functionality
5472
5532
 
5473
- Check the new terminal window to see the fix in progress.`
5474
- });
5475
- dispatch({ type: "SET_CHAT_LOADING", loading: false });
5476
- loadingRef.current = false;
5477
- return;
5478
- } catch (error) {
5479
- dispatch({
5480
- type: "ADD_CHAT_MESSAGE",
5481
- role: "assistant",
5482
- content: `Failed to spawn Claude Code: ${error instanceof Error ? error.message : "unknown error"}`
5483
- });
5484
- dispatch({ type: "SET_CHAT_LOADING", loading: false });
5485
- loadingRef.current = false;
5486
- return;
5533
+ Check the new terminal window to see the fix in progress.`;
5534
+ } else {
5535
+ message = `Spawned Claude Code to fix ${results.length} files:
5536
+ ${results.map((r) => `- ${r}`).join("\n")}
5537
+
5538
+ Check the new terminal windows to see the fixes in progress.`;
5539
+ }
5540
+ }
5541
+ if (errors.length > 0) {
5542
+ message += `
5543
+
5544
+ Failed to spawn fixes for:
5545
+ ${errors.map((e) => `- ${e}`).join("\n")}`;
5487
5546
  }
5488
- } else if (response === "no" || response === "n") {
5489
5547
  dispatch({
5490
5548
  type: "ADD_CHAT_MESSAGE",
5491
5549
  role: "assistant",
5492
- content: "Fix cancelled. Let me know if you need anything else!"
5550
+ content: message
5493
5551
  });
5494
5552
  dispatch({ type: "SET_CHAT_LOADING", loading: false });
5495
5553
  loadingRef.current = false;
@@ -5519,15 +5577,28 @@ ${contextBlock}`;
5519
5577
  role: "assistant",
5520
5578
  content: result.content
5521
5579
  };
5522
- const pendingFixMatch = result.content.match(/\[PENDING_FIX:(.+?)\]/);
5523
- if (pendingFixMatch) {
5580
+ const pendingFixRegex = /\[PENDING_FIX:(.+?)\]/g;
5581
+ const pendingFixes = [];
5582
+ let match;
5583
+ while ((match = pendingFixRegex.exec(result.content)) !== null) {
5524
5584
  try {
5525
- const fixData = JSON.parse(pendingFixMatch[1]);
5526
- action.pendingFix = fixData;
5527
- action.content = result.content.replace(/\[PENDING_FIX:.+?\]/, "").trim();
5585
+ const jsonStr = match[1];
5586
+ if (jsonStr) {
5587
+ const fixData = JSON.parse(jsonStr);
5588
+ pendingFixes.push(fixData);
5589
+ }
5528
5590
  } catch {
5529
5591
  }
5530
5592
  }
5593
+ if (pendingFixes.length > 0) {
5594
+ action.content = result.content.replace(/\[PENDING_FIX:.+?\]/g, "").trim();
5595
+ const firstFix = pendingFixes[0];
5596
+ if (pendingFixes.length === 1 && firstFix) {
5597
+ action.pendingFix = firstFix;
5598
+ } else {
5599
+ action.pendingFixes = pendingFixes;
5600
+ }
5601
+ }
5531
5602
  if (result.toolCalls && result.toolCalls.length > 0) {
5532
5603
  action.toolCalls = result.toolCalls;
5533
5604
  const toolNames = new Set(result.toolCalls.map((tc) => tc.name));
@@ -5581,6 +5652,14 @@ ${contextBlock}`;
5581
5652
  }, [dispatch, messages, state]);
5582
5653
  useInput8((input, key) => {
5583
5654
  if (loading) return;
5655
+ if (key.upArrow) {
5656
+ const maxScroll = Math.max(0, messages.length - VISIBLE_MESSAGES);
5657
+ setScrollOffset((prev) => Math.min(prev + 1, maxScroll));
5658
+ return;
5659
+ } else if (key.downArrow) {
5660
+ setScrollOffset((prev) => Math.max(prev - 1, 0));
5661
+ return;
5662
+ }
5584
5663
  if (key.return && inputBuffer.trim().length > 0) {
5585
5664
  void sendMessage(inputBuffer.trim());
5586
5665
  } else if (key.escape) {
@@ -5597,18 +5676,34 @@ ${contextBlock}`;
5597
5676
  /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " AI is not available. Press s to open settings and add your Anthropic API key." })
5598
5677
  ] });
5599
5678
  }
5600
- return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingX: 1, flexGrow: 1, children: [
5601
- /* @__PURE__ */ jsxs12(Text12, { children: [
5679
+ const visibleMessages = (() => {
5680
+ if (messages.length <= VISIBLE_MESSAGES) return messages;
5681
+ const endIdx = messages.length - scrollOffset;
5682
+ const startIdx = Math.max(0, endIdx - VISIBLE_MESSAGES);
5683
+ return messages.slice(startIdx, endIdx);
5684
+ })();
5685
+ const canScrollUp = scrollOffset < messages.length - VISIBLE_MESSAGES;
5686
+ const canScrollDown = scrollOffset > 0;
5687
+ const cursor = cursorVisible ? "|" : " ";
5688
+ return /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", paddingX: 1, flexGrow: 1, flexShrink: 1, children: [
5689
+ /* @__PURE__ */ jsx13(Box12, { flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { children: [
5602
5690
  /* @__PURE__ */ jsx13(Text12, { bold: true, children: "Chat" }),
5603
5691
  currentSessionTitle && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
5604
5692
  " ",
5605
5693
  currentSessionTitle
5606
5694
  ] }),
5607
- /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " (h for history)" })
5608
- ] }),
5609
- /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", flexGrow: 1, overflow: "hidden", marginTop: 1, children: [
5695
+ /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " (h for history)" }),
5696
+ messages.length > VISIBLE_MESSAGES && /* @__PURE__ */ jsxs12(Text12, { dimColor: true, children: [
5697
+ " [",
5698
+ canScrollUp ? "\u2191" : " ",
5699
+ canScrollDown ? "\u2193" : " ",
5700
+ "]"
5701
+ ] })
5702
+ ] }) }),
5703
+ /* @__PURE__ */ jsxs12(Box12, { flexDirection: "column", flexGrow: 1, flexShrink: 1, overflow: "hidden", marginTop: 1, marginBottom: 1, children: [
5610
5704
  messages.length === 0 && !loading && /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " Ask about your codebase, decisions, patterns, or risks." }),
5611
- messages.map((msg, idx) => /* @__PURE__ */ jsx13(Box12, { flexDirection: "column", marginTop: idx === 0 ? 0 : 1, marginBottom: 1, children: msg.role === "user" ? /* @__PURE__ */ jsxs12(Text12, { children: [
5705
+ canScrollUp && /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " \u2191 more messages above" }),
5706
+ visibleMessages.map((msg, idx) => /* @__PURE__ */ jsx13(Box12, { flexDirection: "column", marginTop: idx === 0 ? 0 : 1, children: msg.role === "user" ? /* @__PURE__ */ jsxs12(Text12, { children: [
5612
5707
  " ",
5613
5708
  /* @__PURE__ */ jsx13(Text12, { bold: true, color: "green", children: "You:" }),
5614
5709
  " ",
@@ -5629,11 +5724,12 @@ ${contextBlock}`;
5629
5724
  line
5630
5725
  ] }, li))
5631
5726
  ] }) }, idx)),
5727
+ canScrollDown && /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " \u2193 more messages below" }),
5632
5728
  loading && /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: " Thinking..." })
5633
5729
  ] }),
5634
- /* @__PURE__ */ jsx13(Box12, { borderStyle: "single", borderColor: "green", paddingX: 1, flexShrink: 0, children: /* @__PURE__ */ jsxs12(Text12, { children: [
5635
- inputBuffer || /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: "Ask a question..." }),
5636
- /* @__PURE__ */ jsx13(Text12, { bold: true, color: "green", children: "|" })
5730
+ /* @__PURE__ */ jsx13(Box12, { borderStyle: "single", borderColor: "green", paddingX: 1, flexShrink: 0, flexGrow: 0, children: /* @__PURE__ */ jsxs12(Text12, { children: [
5731
+ /* @__PURE__ */ jsx13(Text12, { bold: true, color: "green", children: cursor }),
5732
+ inputBuffer || /* @__PURE__ */ jsx13(Text12, { dimColor: true, children: "Ask a question..." })
5637
5733
  ] }) })
5638
5734
  ] });
5639
5735
  }
@@ -5898,7 +5994,7 @@ ${content}
5898
5994
  fixedContent = fixedContent.replace(/^```\w*\n?/, "").replace(/\n?```$/, "");
5899
5995
  }
5900
5996
  await writeFile(fullPath, fixedContent, "utf-8");
5901
- const { recordGoalViolationFixed, getActiveGoals } = await import("./goal-validator-CKFKJ46J.js");
5997
+ const { recordGoalViolationFixed, getActiveGoals } = await import("./goal-validator-4RA64F37.js");
5902
5998
  const goals = await getActiveGoals(projectPath);
5903
5999
  const matchedGoal = goals.find((g) => g.description === fix.goalDescription);
5904
6000
  if (matchedGoal) {
@@ -5914,8 +6010,8 @@ ${content}
5914
6010
  function DashboardApp({ onReady }) {
5915
6011
  const { state, dispatch } = useDashboard();
5916
6012
  const { exit } = useApp();
5917
- const [showConfig, setShowConfig] = useState2(false);
5918
- const [showHelp, setShowHelp] = useState2(false);
6013
+ const [showConfig, setShowConfig] = useState3(false);
6014
+ const [showHelp, setShowHelp] = useState3(false);
5919
6015
  const dispatchRef = useRef2(dispatch);
5920
6016
  dispatchRef.current = dispatch;
5921
6017
  const stateRef = useRef2(state);
@@ -6260,4 +6356,4 @@ export {
6260
6356
  handleCheckpointTool,
6261
6357
  InteractiveDashboard
6262
6358
  };
6263
- //# sourceMappingURL=chunk-7J4ZOOAD.js.map
6359
+ //# sourceMappingURL=chunk-KCVXTYHO.js.map