@triedotdev/mcp 1.0.61 → 1.0.63

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 (56) hide show
  1. package/README.md +591 -52
  2. package/dist/agent-smith-W4HUCFGC.js +14 -0
  3. package/dist/{agent-smith-runner-ZU4R3I2Z.js → agent-smith-runner-QRVOEOBE.js} +13 -7
  4. package/dist/agent-smith-runner-QRVOEOBE.js.map +1 -0
  5. package/dist/chunk-4YSLDGBL.js +674 -0
  6. package/dist/chunk-4YSLDGBL.js.map +1 -0
  7. package/dist/chunk-7KHT2NKR.js +212 -0
  8. package/dist/chunk-7KHT2NKR.js.map +1 -0
  9. package/dist/{chunk-XSPS463E.js → chunk-ALA6733H.js} +492 -14
  10. package/dist/chunk-ALA6733H.js.map +1 -0
  11. package/dist/chunk-AQCAMIQQ.js +139 -0
  12. package/dist/chunk-AQCAMIQQ.js.map +1 -0
  13. package/dist/chunk-D3DMONAJ.js +904 -0
  14. package/dist/chunk-D3DMONAJ.js.map +1 -0
  15. package/dist/{chunk-KB5ZN6K2.js → chunk-GWSNINKX.js} +2 -2
  16. package/dist/{chunk-32WLOG6E.js → chunk-K6BQBKIR.js} +662 -633
  17. package/dist/chunk-K6BQBKIR.js.map +1 -0
  18. package/dist/{chunk-ASGSTVVF.js → chunk-KOFQ47YW.js} +10 -6
  19. package/dist/chunk-KOFQ47YW.js.map +1 -0
  20. package/dist/{chunk-XVGHO2Z5.js → chunk-N2AZH3EQ.js} +7683 -4777
  21. package/dist/chunk-N2AZH3EQ.js.map +1 -0
  22. package/dist/chunk-PBOVCPKE.js +2566 -0
  23. package/dist/chunk-PBOVCPKE.js.map +1 -0
  24. package/dist/{chunk-NUT4G5AY.js → chunk-R7Z7OHTJ.js} +493 -650
  25. package/dist/chunk-R7Z7OHTJ.js.map +1 -0
  26. package/dist/chunk-TSHZQKCM.js +933 -0
  27. package/dist/chunk-TSHZQKCM.js.map +1 -0
  28. package/dist/{chunk-S4VGGLXF.js → chunk-X2PABPBH.js} +461 -892
  29. package/dist/chunk-X2PABPBH.js.map +1 -0
  30. package/dist/cli/create-agent.js +3 -2
  31. package/dist/cli/create-agent.js.map +1 -1
  32. package/dist/cli/main.js +1120 -70
  33. package/dist/cli/main.js.map +1 -1
  34. package/dist/cli/yolo-daemon.js +151 -41
  35. package/dist/cli/yolo-daemon.js.map +1 -1
  36. package/dist/goal-manager-KFBOAP4X.js +20 -0
  37. package/dist/goal-manager-KFBOAP4X.js.map +1 -0
  38. package/dist/guardian-agent-PULK546O.js +17 -0
  39. package/dist/guardian-agent-PULK546O.js.map +1 -0
  40. package/dist/index.js +173 -39
  41. package/dist/index.js.map +1 -1
  42. package/dist/issue-store-QRDF3X55.js +22 -0
  43. package/dist/issue-store-QRDF3X55.js.map +1 -0
  44. package/dist/workers/agent-worker.js +6 -3
  45. package/dist/workers/agent-worker.js.map +1 -1
  46. package/package.json +1 -1
  47. package/dist/agent-smith-57MKX5QC.js +0 -13
  48. package/dist/agent-smith-runner-ZU4R3I2Z.js.map +0 -1
  49. package/dist/chunk-32WLOG6E.js.map +0 -1
  50. package/dist/chunk-ASGSTVVF.js.map +0 -1
  51. package/dist/chunk-NUT4G5AY.js.map +0 -1
  52. package/dist/chunk-S4VGGLXF.js.map +0 -1
  53. package/dist/chunk-XSPS463E.js.map +0 -1
  54. package/dist/chunk-XVGHO2Z5.js.map +0 -1
  55. /package/dist/{agent-smith-57MKX5QC.js.map → agent-smith-W4HUCFGC.js.map} +0 -0
  56. /package/dist/{chunk-KB5ZN6K2.js.map → chunk-GWSNINKX.js.map} +0 -0
package/dist/cli/main.js CHANGED
@@ -2,56 +2,71 @@
2
2
  import {
3
3
  ContextGraph,
4
4
  IncidentIndex,
5
- SKILL_CATEGORIES,
6
5
  TrieFeedbackTool,
7
6
  completeBootstrap,
8
- detectStack,
9
7
  exportToJson,
10
8
  formatFriendlyError,
11
- getSkillCategories,
12
- getSkillsByCategory,
9
+ getAutonomyConfig,
13
10
  handleCheckpointCommand,
14
11
  importFromJson,
15
12
  initializeBootstrapFiles,
16
13
  needsBootstrap,
17
14
  perceiveCurrentChanges,
18
- reasonAboutChangesHumanReadable
19
- } from "../chunk-NUT4G5AY.js";
20
- import "../chunk-XSPS463E.js";
15
+ reasonAboutChangesHumanReadable,
16
+ recordBypass,
17
+ shouldAutoFix,
18
+ shouldBlockPush,
19
+ trackIssueOccurrence
20
+ } from "../chunk-R7Z7OHTJ.js";
21
+ import {
22
+ SKILL_CATEGORIES,
23
+ detectStack,
24
+ getSkillCategories,
25
+ getSkillsByCategory,
26
+ isTrieInitialized
27
+ } from "../chunk-ALA6733H.js";
28
+ import {
29
+ getGuardianState
30
+ } from "../chunk-4YSLDGBL.js";
21
31
  import {
22
- findCrossProjectPatterns,
23
- getDailyLogs,
24
- getGlobalMemoryStats,
25
- getMemoryStats,
26
- getRecentIssues,
27
32
  initProjectInfo,
28
33
  installSkill,
29
34
  listInstalledSkills,
30
- listTrackedProjects,
31
35
  loadContextState,
32
36
  loadProjectInfo,
33
- markIssueResolved,
34
37
  projectInfoExists,
35
38
  recordSkillInstalled,
36
- removeSkill,
39
+ removeSkill
40
+ } from "../chunk-X2PABPBH.js";
41
+ import {
42
+ findCrossProjectPatterns,
43
+ getGlobalMemoryStats,
44
+ listTrackedProjects,
37
45
  searchGlobalPatterns,
38
- searchIssues,
39
46
  updateGlobalMemoryMd
40
- } from "../chunk-S4VGGLXF.js";
47
+ } from "../chunk-7KHT2NKR.js";
41
48
  import "../chunk-MVUCBUBR.js";
42
- import "../chunk-32WLOG6E.js";
49
+ import "../chunk-6NLHFIYA.js";
50
+ import "../chunk-K6BQBKIR.js";
51
+ import "../chunk-AQCAMIQQ.js";
52
+ import {
53
+ getDailyLogs,
54
+ getMemoryStats,
55
+ getRecentIssues,
56
+ markIssueResolved,
57
+ searchIssues
58
+ } from "../chunk-TSHZQKCM.js";
43
59
  import {
44
60
  getWorkingDirectory
45
- } from "../chunk-ASGSTVVF.js";
46
- import "../chunk-6NLHFIYA.js";
61
+ } from "../chunk-KOFQ47YW.js";
47
62
  import "../chunk-RAZUNSBI.js";
48
63
  import {
49
64
  __require
50
65
  } from "../chunk-DGUM43GV.js";
51
66
 
52
67
  // src/cli/main.ts
53
- import { resolve, join, dirname } from "path";
54
- import { existsSync, readFileSync } from "fs";
68
+ import { resolve, join as join2, dirname } from "path";
69
+ import { existsSync as existsSync3, readFileSync } from "fs";
55
70
  import { fileURLToPath } from "url";
56
71
 
57
72
  // src/cli/skills.ts
@@ -61,12 +76,12 @@ async function handleSkillsCommand(args) {
61
76
  case "add":
62
77
  case "install": {
63
78
  if (!rest[0]) {
64
- console.log("Usage: trie-agent skills add <owner/repo> [skill-name]");
79
+ console.log("Usage: trie skills add <owner/repo> [skill-name]");
65
80
  console.log("");
66
81
  console.log("Examples:");
67
- console.log(" trie-agent skills add vercel-labs/agent-skills react-best-practices");
68
- console.log(" trie-agent skills add anthropics/skills claude-code-review");
69
- console.log(" trie-agent skills add myorg/internal-standards");
82
+ console.log(" trie skills add vercel-labs/agent-skills react-best-practices");
83
+ console.log(" trie skills add anthropics/skills claude-code-review");
84
+ console.log(" trie skills add myorg/internal-standards");
70
85
  return;
71
86
  }
72
87
  console.log(`Installing skill from ${rest[0]}...`);
@@ -77,7 +92,7 @@ async function handleSkillsCommand(args) {
77
92
  console.log(`Path: ${result.path}`);
78
93
  console.log("");
79
94
  console.log("This skill is now a capability the skill-review agent can apply.");
80
- console.log('Run "trie-agent scan" to apply skills to your codebase.');
95
+ console.log('Run "trie scan" to apply skills to your codebase.');
81
96
  } else {
82
97
  console.error(`Failed to install: ${result.error}`);
83
98
  process.exit(1);
@@ -164,7 +179,7 @@ async function handleSkillsCommand(args) {
164
179
  case "rm":
165
180
  case "uninstall": {
166
181
  if (!rest[0]) {
167
- console.log("Usage: trie-agent skills remove <skill-name>");
182
+ console.log("Usage: trie skills remove <skill-name>");
168
183
  return;
169
184
  }
170
185
  const removed = await removeSkill(rest[0]);
@@ -206,7 +221,7 @@ async function handleSkillsCommand(args) {
206
221
  }
207
222
  case "info": {
208
223
  if (!rest[0]) {
209
- console.log("Usage: trie-agent skills info <skill-name>");
224
+ console.log("Usage: trie skills info <skill-name>");
210
225
  return;
211
226
  }
212
227
  const skills = await listInstalledSkills();
@@ -290,6 +305,46 @@ else
290
305
  fi
291
306
  `;
292
307
  }
308
+ function prePushCommand() {
309
+ return `
310
+ TRIE_BIN="$(command -v trie || command -v trie-agent || true)"
311
+ if [ -n "$TRIE_BIN" ]; then
312
+ # Check for bypass
313
+ if [ "$TRIE_BYPASS" = "1" ] || [ "$TRIE_BYPASS" = "true" ]; then
314
+ echo "\u26A0\uFE0F Trie push blocking bypassed (TRIE_BYPASS=1)"
315
+ "$TRIE_BIN" pre-push --bypassed || true
316
+ exit 0
317
+ fi
318
+
319
+ # Run pre-push check with blocking enabled
320
+ "$TRIE_BIN" pre-push --block
321
+ EXIT_CODE=$?
322
+
323
+ if [ $EXIT_CODE -eq 0 ]; then
324
+ exit 0
325
+ elif [ $EXIT_CODE -eq 2 ]; then
326
+ # Exit code 2 = blocked but bypassable
327
+ echo ""
328
+ echo "\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"
329
+ echo "\u{1F6D1} Push blocked by Trie due to critical issues."
330
+ echo ""
331
+ echo "To bypass (not recommended):"
332
+ echo " TRIE_BYPASS=1 git push"
333
+ echo " OR: git push --no-verify"
334
+ echo ""
335
+ echo "To fix issues first:"
336
+ echo " trie fix"
337
+ echo "\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"
338
+ exit 1
339
+ else
340
+ # Other errors - don't block
341
+ exit 0
342
+ fi
343
+ else
344
+ echo "Trie not available; skipping pre-push hook."
345
+ fi
346
+ `;
347
+ }
293
348
  function preCommitTemplate() {
294
349
  return (hookHeader() + "# Trie pre-commit hook\n" + trieCommand("pre-commit")).trim() + "\n";
295
350
  }
@@ -297,7 +352,7 @@ function postCommitTemplate() {
297
352
  return (hookHeader() + "# Trie post-commit hook\n" + trieCommand("post-commit")).trim() + "\n";
298
353
  }
299
354
  function prePushTemplate() {
300
- return (hookHeader() + "# Trie pre-push hook\n" + trieCommand("check --quick")).trim() + "\n";
355
+ return (hookHeader() + "# Trie pre-push hook with blocking support\n# Bypass with: TRIE_BYPASS=1 git push\n" + prePushCommand()).trim() + "\n";
301
356
  }
302
357
 
303
358
  // src/hooks/install.ts
@@ -767,6 +822,792 @@ async function handleCheckCommand(args) {
767
822
  }
768
823
  }
769
824
 
825
+ // src/cli/pre-push.ts
826
+ import pc from "picocolors";
827
+ function parseArgs2(args) {
828
+ return {
829
+ block: args.includes("--block"),
830
+ bypassed: args.includes("--bypassed"),
831
+ quick: args.includes("--quick") || args.includes("-q")
832
+ };
833
+ }
834
+ async function handlePrePushCommand(args) {
835
+ const options = parseArgs2(args);
836
+ const projectPath = getWorkingDirectory(void 0, true);
837
+ try {
838
+ const autonomyConfig = await getAutonomyConfig(projectPath);
839
+ if (options.bypassed) {
840
+ console.error(pc.yellow("\u26A0\uFE0F Pre-push check bypassed by user"));
841
+ if (autonomyConfig.pushBlocking.logBypasses) {
842
+ await recordBypass(
843
+ projectPath,
844
+ "git-push",
845
+ void 0,
846
+ "pre-push-bypass",
847
+ "env",
848
+ "User set TRIE_BYPASS=1"
849
+ );
850
+ }
851
+ process.exit(0);
852
+ }
853
+ const perception = await perceiveCurrentChanges(projectPath);
854
+ const files = perception.diffSummary.files.map((f) => f.filePath);
855
+ if (files.length === 0) {
856
+ console.error(pc.green("\u2713 No changes to check"));
857
+ process.exit(0);
858
+ }
859
+ console.error(pc.cyan(`
860
+ \u{1F50D} Checking ${files.length} file(s) before push...
861
+ `));
862
+ const reasoning = await reasonAboutChangesHumanReadable(projectPath, files, {
863
+ runAgents: !options.quick,
864
+ scanContext: {
865
+ config: { timeoutMs: options.quick ? 15e3 : 3e4 }
866
+ }
867
+ });
868
+ if (options.block && autonomyConfig.pushBlocking.enabled) {
869
+ const issues = collectIssuesForBlocking(reasoning);
870
+ for (const issue of issues) {
871
+ await trackIssueOccurrence(
872
+ projectPath,
873
+ issue.file,
874
+ issue.line,
875
+ issue.severity,
876
+ autonomyConfig
877
+ );
878
+ }
879
+ const blockResult = shouldBlockPush(issues, autonomyConfig);
880
+ if (blockResult.blocked) {
881
+ console.error("");
882
+ console.error(pc.red("\u2501".repeat(60)));
883
+ console.error(pc.bold(pc.red("\u{1F6D1} PUSH BLOCKED")));
884
+ console.error(pc.red("\u2501".repeat(60)));
885
+ console.error("");
886
+ console.error(pc.yellow(`Found ${blockResult.blockingIssues.length} blocking issue(s):`));
887
+ console.error("");
888
+ for (const issue of blockResult.blockingIssues.slice(0, 5)) {
889
+ const icon = issue.severity === "critical" ? "\u{1F534}" : "\u{1F7E1}";
890
+ console.error(` ${icon} ${pc.dim(issue.file)}${issue.line ? `:${issue.line}` : ""}`);
891
+ console.error(` ${issue.issue.slice(0, 80)}${issue.issue.length > 80 ? "..." : ""}`);
892
+ }
893
+ if (blockResult.blockingIssues.length > 5) {
894
+ console.error(` ... and ${blockResult.blockingIssues.length - 5} more`);
895
+ }
896
+ console.error("");
897
+ console.error(pc.dim("\u2500".repeat(60)));
898
+ if (blockResult.bypassInstructions) {
899
+ console.error("");
900
+ console.error(pc.yellow("To bypass (not recommended):"));
901
+ for (const line of blockResult.bypassInstructions.split("\n")) {
902
+ console.error(pc.dim(line));
903
+ }
904
+ }
905
+ console.error("");
906
+ console.error(pc.cyan("To fix issues:"));
907
+ console.error(pc.dim(" trie fix # Auto-fix trivial issues"));
908
+ console.error(pc.dim(" trie scan # See all issues"));
909
+ console.error("");
910
+ process.exit(2);
911
+ } else if (blockResult.bypassed) {
912
+ console.error(pc.yellow(`\u26A0\uFE0F Bypassed: ${blockResult.blockingIssues.length} issue(s) ignored`));
913
+ }
914
+ }
915
+ const riskLevel = reasoning.original?.riskLevel || "low";
916
+ const riskColor = riskLevel === "critical" ? pc.red : riskLevel === "high" ? pc.yellow : riskLevel === "medium" ? pc.blue : pc.green;
917
+ console.error("");
918
+ console.error(riskColor(`Risk: ${riskLevel.toUpperCase()}`));
919
+ console.error(pc.dim(reasoning.summary || "No significant risks detected"));
920
+ console.error("");
921
+ process.exit(0);
922
+ } catch (error) {
923
+ const friendly = formatFriendlyError(error);
924
+ console.error(pc.yellow(`\u26A0\uFE0F Pre-push check error: ${friendly.userMessage}`));
925
+ console.error(pc.dim("Allowing push to continue."));
926
+ process.exit(0);
927
+ }
928
+ }
929
+ function collectIssuesForBlocking(reasoning) {
930
+ const issues = [];
931
+ if (reasoning.original?.files) {
932
+ for (const file of reasoning.original.files) {
933
+ if (file.level === "critical" || file.level === "high") {
934
+ issues.push({
935
+ file: file.file,
936
+ severity: file.level === "critical" ? "critical" : "serious",
937
+ issue: file.reasons?.join("; ") || "High-risk file"
938
+ });
939
+ }
940
+ }
941
+ }
942
+ if (reasoning.scanResults?.issues) {
943
+ for (const issue of reasoning.scanResults.issues) {
944
+ if (issue.severity === "critical" || issue.severity === "serious") {
945
+ issues.push({
946
+ file: issue.file,
947
+ line: issue.line,
948
+ severity: issue.severity,
949
+ issue: issue.issue
950
+ });
951
+ }
952
+ }
953
+ }
954
+ return issues;
955
+ }
956
+
957
+ // src/cli/auto-fix.ts
958
+ import { readFile, writeFile } from "fs/promises";
959
+ import { existsSync } from "fs";
960
+ import { createInterface } from "readline";
961
+ import pc2 from "picocolors";
962
+ function detectAutoFixes(issues) {
963
+ const fixes = [];
964
+ for (const issue of issues) {
965
+ const fix = generateFixForIssue(issue);
966
+ if (fix) {
967
+ fixes.push(fix);
968
+ }
969
+ }
970
+ return fixes;
971
+ }
972
+ function generateFixForIssue(issue) {
973
+ if (!issue.line) return null;
974
+ if (issue.issue.toLowerCase().includes("console.log") || issue.issue.toLowerCase().includes("console log")) {
975
+ return {
976
+ id: `fix-${issue.id}`,
977
+ file: issue.file,
978
+ line: issue.line,
979
+ original: "",
980
+ // Will be filled when reading file
981
+ fixed: "",
982
+ // Will be deletion
983
+ type: "remove-console-log",
984
+ category: "trivial",
985
+ description: "Remove console.log statement",
986
+ confidence: 0.95
987
+ };
988
+ }
989
+ if (issue.issue.toLowerCase().includes("debugger")) {
990
+ return {
991
+ id: `fix-${issue.id}`,
992
+ file: issue.file,
993
+ line: issue.line,
994
+ original: "",
995
+ fixed: "",
996
+ type: "remove-debugger",
997
+ category: "trivial",
998
+ description: "Remove debugger statement",
999
+ confidence: 0.98
1000
+ };
1001
+ }
1002
+ return null;
1003
+ }
1004
+ async function promptUser(question) {
1005
+ const rl = createInterface({
1006
+ input: process.stdin,
1007
+ output: process.stderr
1008
+ });
1009
+ return new Promise((resolve2) => {
1010
+ rl.question(question, (answer) => {
1011
+ rl.close();
1012
+ resolve2(answer.toLowerCase().trim());
1013
+ });
1014
+ });
1015
+ }
1016
+ function displayFixPreview(fix, index, total) {
1017
+ console.error("");
1018
+ console.error(pc2.cyan(`\u2501\u2501\u2501 Fix ${index + 1}/${total} \u2501\u2501\u2501`));
1019
+ console.error(pc2.dim(`File: ${fix.file}${fix.line ? `:${fix.line}` : ""}`));
1020
+ console.error(pc2.dim(`Type: ${fix.type}`));
1021
+ console.error(pc2.yellow(`Description: ${fix.description}`));
1022
+ console.error("");
1023
+ if (fix.original) {
1024
+ console.error(pc2.red("- " + fix.original));
1025
+ }
1026
+ if (fix.fixed) {
1027
+ console.error(pc2.green("+ " + fix.fixed));
1028
+ } else if (fix.original) {
1029
+ console.error(pc2.dim(" (line will be removed)"));
1030
+ }
1031
+ console.error("");
1032
+ }
1033
+ async function applyFix(fix) {
1034
+ try {
1035
+ if (!existsSync(fix.file)) {
1036
+ console.error(pc2.red(`File not found: ${fix.file}`));
1037
+ return false;
1038
+ }
1039
+ const content = await readFile(fix.file, "utf-8");
1040
+ const lines = content.split("\n");
1041
+ if (fix.line === void 0 || fix.line < 1 || fix.line > lines.length) {
1042
+ console.error(pc2.red(`Invalid line number: ${fix.line}`));
1043
+ return false;
1044
+ }
1045
+ const lineIndex = fix.line - 1;
1046
+ const originalLine = lines[lineIndex];
1047
+ let newContent;
1048
+ if (fix.type === "remove-console-log" || fix.type === "remove-debugger") {
1049
+ lines.splice(lineIndex, 1);
1050
+ newContent = lines.join("\n");
1051
+ } else if (fix.fixed) {
1052
+ lines[lineIndex] = fix.fixed;
1053
+ newContent = lines.join("\n");
1054
+ } else {
1055
+ console.error(pc2.red(`Unknown fix type: ${fix.type}`));
1056
+ return false;
1057
+ }
1058
+ await writeFile(fix.file, newContent);
1059
+ console.error(pc2.green(`\u2713 Applied fix to ${fix.file}:${fix.line}`));
1060
+ if (originalLine) {
1061
+ console.error(pc2.dim(` Removed: ${originalLine.trim().slice(0, 60)}...`));
1062
+ }
1063
+ return true;
1064
+ } catch (error) {
1065
+ console.error(pc2.red(`Failed to apply fix: ${error}`));
1066
+ return false;
1067
+ }
1068
+ }
1069
+ async function loadFixContent(fixes) {
1070
+ const enrichedFixes = [];
1071
+ for (const fix of fixes) {
1072
+ if (!fix.line || !existsSync(fix.file)) {
1073
+ continue;
1074
+ }
1075
+ try {
1076
+ const content = await readFile(fix.file, "utf-8");
1077
+ const lines = content.split("\n");
1078
+ const originalLine = lines[fix.line - 1];
1079
+ if (originalLine) {
1080
+ enrichedFixes.push({
1081
+ ...fix,
1082
+ original: originalLine
1083
+ });
1084
+ }
1085
+ } catch {
1086
+ }
1087
+ }
1088
+ return enrichedFixes;
1089
+ }
1090
+ async function handleAutoFixCommand(args, issues) {
1091
+ const projectPath = getWorkingDirectory(void 0, true);
1092
+ const config = await getAutonomyConfig(projectPath);
1093
+ if (!config.autoFix.enabled) {
1094
+ console.error(pc2.yellow("Auto-fix is disabled in config."));
1095
+ console.error(pc2.dim("Enable it with: trie config set autoFix.enabled true"));
1096
+ return;
1097
+ }
1098
+ const dryRun = args.includes("--dry-run");
1099
+ const skipConfirm = args.includes("--yes") || args.includes("-y");
1100
+ if (!issues || issues.length === 0) {
1101
+ console.error(pc2.yellow("No issues provided. Run a scan first:"));
1102
+ console.error(pc2.dim(" trie scan --fix"));
1103
+ return;
1104
+ }
1105
+ let fixes = detectAutoFixes(issues);
1106
+ if (fixes.length === 0) {
1107
+ console.error(pc2.green("\u2713 No auto-fixable issues found."));
1108
+ return;
1109
+ }
1110
+ fixes = fixes.filter((fix) => shouldAutoFix(fix, config));
1111
+ if (fixes.length === 0) {
1112
+ console.error(pc2.yellow("Found fixable issues but they are not in allowed categories."));
1113
+ console.error(pc2.dim("Allowed categories: " + config.autoFix.categories.join(", ")));
1114
+ return;
1115
+ }
1116
+ fixes = await loadFixContent(fixes);
1117
+ if (fixes.length === 0) {
1118
+ console.error(pc2.yellow("Could not load fix content from files."));
1119
+ return;
1120
+ }
1121
+ console.error("");
1122
+ console.error(pc2.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
1123
+ console.error(pc2.bold("Auto-Fix: Human-in-the-Loop"));
1124
+ console.error(pc2.cyan("\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501\u2501"));
1125
+ console.error("");
1126
+ console.error(`Found ${pc2.bold(fixes.length.toString())} auto-fixable issues:`);
1127
+ const byCategory = /* @__PURE__ */ new Map();
1128
+ for (const fix of fixes) {
1129
+ byCategory.set(fix.category, (byCategory.get(fix.category) || 0) + 1);
1130
+ }
1131
+ for (const [cat, count] of byCategory) {
1132
+ console.error(` \u2022 ${cat}: ${count}`);
1133
+ }
1134
+ console.error("");
1135
+ if (dryRun) {
1136
+ console.error(pc2.yellow("[DRY RUN] No changes will be made."));
1137
+ console.error("");
1138
+ for (let i = 0; i < fixes.length; i++) {
1139
+ displayFixPreview(fixes[i], i, fixes.length);
1140
+ }
1141
+ return;
1142
+ }
1143
+ if (config.autoFix.askFirst && !skipConfirm) {
1144
+ console.error(pc2.yellow("Trie will ask before applying each fix."));
1145
+ console.error("");
1146
+ const response = await promptUser(
1147
+ `Apply all ${fixes.length} fixes? (y)es / (n)o / (r)eview each: `
1148
+ );
1149
+ if (response === "n" || response === "no") {
1150
+ console.error(pc2.dim("Cancelled."));
1151
+ return;
1152
+ }
1153
+ if (response === "r" || response === "review") {
1154
+ let applied2 = 0;
1155
+ let skipped = 0;
1156
+ for (let i = 0; i < fixes.length; i++) {
1157
+ const fix = fixes[i];
1158
+ displayFixPreview(fix, i, fixes.length);
1159
+ const answer = await promptUser("Apply this fix? (y/n/q): ");
1160
+ if (answer === "q" || answer === "quit") {
1161
+ console.error(pc2.dim("Stopped."));
1162
+ break;
1163
+ }
1164
+ if (answer === "y" || answer === "yes") {
1165
+ const success = await applyFix(fix);
1166
+ if (success) applied2++;
1167
+ } else {
1168
+ console.error(pc2.dim("Skipped."));
1169
+ skipped++;
1170
+ }
1171
+ }
1172
+ console.error("");
1173
+ console.error(pc2.cyan("\u2501\u2501\u2501 Summary \u2501\u2501\u2501"));
1174
+ console.error(`Applied: ${pc2.green(applied2.toString())}`);
1175
+ console.error(`Skipped: ${pc2.dim(skipped.toString())}`);
1176
+ return;
1177
+ }
1178
+ }
1179
+ console.error("");
1180
+ console.error(pc2.cyan("Applying fixes..."));
1181
+ console.error("");
1182
+ let applied = 0;
1183
+ let failed = 0;
1184
+ for (const fix of fixes) {
1185
+ const success = await applyFix(fix);
1186
+ if (success) {
1187
+ applied++;
1188
+ } else {
1189
+ failed++;
1190
+ }
1191
+ }
1192
+ console.error("");
1193
+ console.error(pc2.cyan("\u2501\u2501\u2501 Complete \u2501\u2501\u2501"));
1194
+ console.error(`Applied: ${pc2.green(applied.toString())}`);
1195
+ if (failed > 0) {
1196
+ console.error(`Failed: ${pc2.red(failed.toString())}`);
1197
+ }
1198
+ }
1199
+
1200
+ // src/cli/goal.ts
1201
+ import pc3 from "picocolors";
1202
+ async function handleGoalCommand(args) {
1203
+ const projectPath = getWorkingDirectory(void 0, true);
1204
+ const guardianState = getGuardianState(projectPath);
1205
+ await guardianState.load();
1206
+ const subcommand = args[0];
1207
+ const restArgs = args.slice(1);
1208
+ switch (subcommand) {
1209
+ case "add":
1210
+ case "create":
1211
+ await addGoal(guardianState, restArgs);
1212
+ break;
1213
+ case "list":
1214
+ case "ls":
1215
+ await listGoals(guardianState);
1216
+ break;
1217
+ case "complete":
1218
+ case "done":
1219
+ await completeGoal(guardianState, restArgs[0]);
1220
+ break;
1221
+ case "delete":
1222
+ case "rm":
1223
+ await deleteGoal(guardianState, restArgs[0]);
1224
+ break;
1225
+ default:
1226
+ if (subcommand && !subcommand.startsWith("-")) {
1227
+ await addGoal(guardianState, [subcommand, ...restArgs]);
1228
+ } else {
1229
+ printGoalHelp();
1230
+ }
1231
+ }
1232
+ }
1233
+ async function addGoal(guardianState, args) {
1234
+ const description = args.join(" ").replace(/^["']|["']$/g, "");
1235
+ if (!description) {
1236
+ console.error(pc3.red("Please provide a goal description."));
1237
+ console.error(pc3.dim('Example: trie goal add "Reduce auth issues by 50%"'));
1238
+ return;
1239
+ }
1240
+ const categoryMatch = description.match(/--category[=\s](\w+)/);
1241
+ const targetMatch = description.match(/--target[=\s](\d+)/);
1242
+ const deadlineMatch = description.match(/--deadline[=\s](\S+)/);
1243
+ let cleanDesc = description.replace(/--category[=\s]\w+/g, "").replace(/--target[=\s]\d+/g, "").replace(/--deadline[=\s]\S+/g, "").trim();
1244
+ const reductionMatch = cleanDesc.match(/reduce.*?(\d+)%/i);
1245
+ const eliminateMatch = cleanDesc.match(/eliminate|remove all|zero/i);
1246
+ const streakMatch = cleanDesc.match(/(\d+)\s*days?\s*(streak|in a row|consecutive)/i);
1247
+ let goalType = "custom";
1248
+ let target = 100;
1249
+ let metric = "progress";
1250
+ if (reductionMatch && reductionMatch[1]) {
1251
+ goalType = "reduction";
1252
+ target = parseInt(reductionMatch[1], 10);
1253
+ metric = "reduction_percent";
1254
+ } else if (eliminateMatch) {
1255
+ goalType = "reduction";
1256
+ target = 100;
1257
+ metric = "elimination";
1258
+ } else if (streakMatch && streakMatch[1]) {
1259
+ goalType = "streak";
1260
+ target = parseInt(streakMatch[1], 10);
1261
+ metric = "days_streak";
1262
+ }
1263
+ if (targetMatch && targetMatch[1]) {
1264
+ target = parseInt(targetMatch[1], 10);
1265
+ }
1266
+ const category = categoryMatch?.[1] || detectCategory(cleanDesc);
1267
+ const deadline = /* @__PURE__ */ new Date();
1268
+ if (deadlineMatch && deadlineMatch[1]) {
1269
+ const days = parseInt(deadlineMatch[1], 10);
1270
+ deadline.setDate(deadline.getDate() + (isNaN(days) ? 14 : days));
1271
+ } else {
1272
+ deadline.setDate(deadline.getDate() + 14);
1273
+ }
1274
+ const goal = {
1275
+ id: `goal-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
1276
+ description: cleanDesc,
1277
+ type: goalType,
1278
+ metric,
1279
+ target,
1280
+ currentValue: 0,
1281
+ startValue: 0,
1282
+ status: "active",
1283
+ autoGenerated: false,
1284
+ // User-created
1285
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1286
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1287
+ deadline: deadline.toISOString(),
1288
+ category
1289
+ };
1290
+ await guardianState.addGoal(goal);
1291
+ console.error("");
1292
+ console.error(pc3.green("\u2713 Goal created"));
1293
+ console.error("");
1294
+ console.error(pc3.bold(cleanDesc));
1295
+ console.error(pc3.dim(`ID: ${goal.id}`));
1296
+ console.error(pc3.dim(`Type: ${goalType} | Target: ${target} | Category: ${category}`));
1297
+ console.error(pc3.dim(`Deadline: ${deadline.toLocaleDateString()}`));
1298
+ console.error("");
1299
+ console.error(pc3.cyan("The guardian will track progress and celebrate when you achieve it!"));
1300
+ }
1301
+ async function listGoals(guardianState) {
1302
+ const goals = guardianState.getAllGoals();
1303
+ if (goals.length === 0) {
1304
+ console.error(pc3.dim("No goals yet."));
1305
+ console.error(pc3.dim('Create one: trie goal add "Reduce auth issues by 50%"'));
1306
+ return;
1307
+ }
1308
+ console.error("");
1309
+ console.error(pc3.bold("\u{1F3AF} Goals"));
1310
+ console.error("");
1311
+ const active = goals.filter((g) => g.status === "active");
1312
+ const achieved = goals.filter((g) => g.status === "achieved");
1313
+ const other = goals.filter((g) => g.status !== "active" && g.status !== "achieved");
1314
+ if (active.length > 0) {
1315
+ console.error(pc3.cyan("Active:"));
1316
+ for (const goal of active) {
1317
+ const progress = goal.target > 0 ? Math.round(goal.currentValue / goal.target * 100) : 0;
1318
+ const bar = renderProgressBar(progress);
1319
+ const source = goal.autoGenerated ? pc3.dim("[auto]") : pc3.dim("[manual]");
1320
+ console.error(` ${bar} ${goal.description} ${source}`);
1321
+ console.error(pc3.dim(` ID: ${goal.id} | ${progress}% complete`));
1322
+ }
1323
+ console.error("");
1324
+ }
1325
+ if (achieved.length > 0) {
1326
+ console.error(pc3.green("Achieved:"));
1327
+ for (const goal of achieved) {
1328
+ console.error(` \u2705 ${goal.description}`);
1329
+ }
1330
+ console.error("");
1331
+ }
1332
+ if (other.length > 0) {
1333
+ console.error(pc3.dim("Other:"));
1334
+ for (const goal of other) {
1335
+ const icon = goal.status === "failed" ? "\u274C" : goal.status === "paused" ? "\u23F8\uFE0F" : "\u2022";
1336
+ console.error(` ${icon} ${goal.description} (${goal.status})`);
1337
+ }
1338
+ }
1339
+ }
1340
+ async function completeGoal(guardianState, goalId) {
1341
+ if (!goalId) {
1342
+ console.error(pc3.red("Please provide a goal ID."));
1343
+ console.error(pc3.dim('Run "trie goal list" to see IDs.'));
1344
+ return;
1345
+ }
1346
+ const goals = guardianState.getAllGoals();
1347
+ const goal = goals.find((g) => g.id === goalId || g.id.includes(goalId));
1348
+ if (!goal) {
1349
+ console.error(pc3.red(`Goal not found: ${goalId}`));
1350
+ return;
1351
+ }
1352
+ await guardianState.updateGoal(goal.id, {
1353
+ status: "achieved",
1354
+ currentValue: goal.target,
1355
+ achievedAt: (/* @__PURE__ */ new Date()).toISOString()
1356
+ });
1357
+ console.error("");
1358
+ console.error(pc3.green("\u{1F389} Goal achieved!"));
1359
+ console.error(pc3.bold(goal.description));
1360
+ console.error("");
1361
+ }
1362
+ async function deleteGoal(guardianState, goalId) {
1363
+ if (!goalId) {
1364
+ console.error(pc3.red("Please provide a goal ID."));
1365
+ return;
1366
+ }
1367
+ const goals = guardianState.getAllGoals();
1368
+ const goal = goals.find((g) => g.id === goalId || g.id.includes(goalId));
1369
+ if (!goal) {
1370
+ console.error(pc3.red(`Goal not found: ${goalId}`));
1371
+ return;
1372
+ }
1373
+ await guardianState.updateGoal(goal.id, { status: "rejected" });
1374
+ console.error(pc3.dim(`Removed goal: ${goal.description}`));
1375
+ }
1376
+ function renderProgressBar(percent) {
1377
+ const width = 10;
1378
+ const filled = Math.round(percent / 100 * width);
1379
+ const empty = width - filled;
1380
+ return `[${pc3.green("\u2588".repeat(filled))}${pc3.dim("\u2591".repeat(empty))}]`;
1381
+ }
1382
+ function detectCategory(description) {
1383
+ const lower = description.toLowerCase();
1384
+ if (/security|auth|password|token|xss|sql|inject/i.test(lower)) return "security";
1385
+ if (/quality|bug|issue|error|fix/i.test(lower)) return "quality";
1386
+ if (/performance|speed|fast|slow|latency/i.test(lower)) return "performance";
1387
+ if (/coverage|test|spec/i.test(lower)) return "coverage";
1388
+ return "general";
1389
+ }
1390
+ function printGoalHelp() {
1391
+ console.error("");
1392
+ console.error(pc3.bold("trie goal - Manage guardian goals"));
1393
+ console.error("");
1394
+ console.error(pc3.cyan("Usage:"));
1395
+ console.error(' trie goal add "Reduce auth issues by 50%"');
1396
+ console.error(" trie goal list");
1397
+ console.error(" trie goal complete <id>");
1398
+ console.error(" trie goal delete <id>");
1399
+ console.error("");
1400
+ console.error(pc3.cyan("Options for add:"));
1401
+ console.error(" --category=security|quality|performance|coverage|general");
1402
+ console.error(" --target=<number>");
1403
+ console.error(" --deadline=<days>");
1404
+ console.error("");
1405
+ console.error(pc3.cyan("Examples:"));
1406
+ console.error(' trie goal add "Eliminate all critical security issues"');
1407
+ console.error(' trie goal add "7 days streak of clean builds"');
1408
+ console.error(' trie goal add "Reduce test flakiness by 80%" --category=quality');
1409
+ console.error("");
1410
+ }
1411
+ async function handleHypothesisCommand(args) {
1412
+ const projectPath = getWorkingDirectory(void 0, true);
1413
+ const guardianState = getGuardianState(projectPath);
1414
+ await guardianState.load();
1415
+ const subcommand = args[0];
1416
+ const restArgs = args.slice(1);
1417
+ switch (subcommand) {
1418
+ case "add":
1419
+ case "create":
1420
+ await addHypothesis(guardianState, restArgs);
1421
+ break;
1422
+ case "list":
1423
+ case "ls":
1424
+ await listHypotheses(guardianState);
1425
+ break;
1426
+ case "validate":
1427
+ await validateHypothesis(guardianState, restArgs[0]);
1428
+ break;
1429
+ case "invalidate":
1430
+ await invalidateHypothesis(guardianState, restArgs[0]);
1431
+ break;
1432
+ case "delete":
1433
+ case "rm":
1434
+ await deleteHypothesis(guardianState, restArgs[0]);
1435
+ break;
1436
+ default:
1437
+ if (subcommand && !subcommand.startsWith("-")) {
1438
+ await addHypothesis(guardianState, [subcommand, ...restArgs]);
1439
+ } else {
1440
+ printHypothesisHelp();
1441
+ }
1442
+ }
1443
+ }
1444
+ async function addHypothesis(guardianState, args) {
1445
+ const statement = args.join(" ").replace(/^["']|["']$/g, "");
1446
+ if (!statement) {
1447
+ console.error(pc3.red("Please provide a hypothesis statement."));
1448
+ console.error(pc3.dim('Example: trie hypothesis add "Mondays have more bugs than Fridays"'));
1449
+ return;
1450
+ }
1451
+ const categoryMatch = statement.match(/--category[=\s](\w+)/);
1452
+ const testMatch = statement.match(/--test[=\s]["']([^"']+)["']/);
1453
+ let cleanStatement = statement.replace(/--category[=\s]\w+/g, "").replace(/--test[=\s]["'][^"']+["']/g, "").trim();
1454
+ const category = categoryMatch?.[1] || detectHypothesisCategory(cleanStatement);
1455
+ const testCriteria = testMatch?.[1] || generateTestCriteria(cleanStatement);
1456
+ const hypothesis = {
1457
+ id: `hypo-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,
1458
+ statement: cleanStatement,
1459
+ confidence: 0.5,
1460
+ // Start neutral
1461
+ status: "testing",
1462
+ evidence: [],
1463
+ createdAt: (/* @__PURE__ */ new Date()).toISOString(),
1464
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString(),
1465
+ testCriteria,
1466
+ category
1467
+ };
1468
+ await guardianState.addHypothesis(hypothesis);
1469
+ console.error("");
1470
+ console.error(pc3.green("\u2713 Hypothesis created"));
1471
+ console.error("");
1472
+ console.error(pc3.bold(`"${cleanStatement}"`));
1473
+ console.error(pc3.dim(`ID: ${hypothesis.id}`));
1474
+ console.error(pc3.dim(`Status: testing | Confidence: 50% | Category: ${category}`));
1475
+ console.error("");
1476
+ console.error(pc3.cyan("The guardian will collect evidence and update confidence over time."));
1477
+ console.error(pc3.dim(`Test criteria: ${testCriteria}`));
1478
+ }
1479
+ async function listHypotheses(guardianState) {
1480
+ const hypotheses = guardianState.getAllHypotheses();
1481
+ if (hypotheses.length === 0) {
1482
+ console.error(pc3.dim("No hypotheses yet."));
1483
+ console.error(pc3.dim('Create one: trie hypothesis add "Mondays have more bugs"'));
1484
+ return;
1485
+ }
1486
+ console.error("");
1487
+ console.error(pc3.bold("\u{1F52E} Hypotheses"));
1488
+ console.error("");
1489
+ const testing = hypotheses.filter((h) => h.status === "testing");
1490
+ const validated = hypotheses.filter((h) => h.status === "validated");
1491
+ const invalidated = hypotheses.filter((h) => h.status === "invalidated");
1492
+ if (testing.length > 0) {
1493
+ console.error(pc3.cyan("Testing:"));
1494
+ for (const hypo of testing) {
1495
+ const conf = Math.round(hypo.confidence * 100);
1496
+ const confColor = conf >= 70 ? pc3.green : conf >= 40 ? pc3.yellow : pc3.red;
1497
+ console.error(` \u{1F9EA} "${hypo.statement}" ${confColor(`(${conf}% confidence)`)}`);
1498
+ console.error(pc3.dim(` ID: ${hypo.id} | Evidence: ${hypo.evidence.length} points`));
1499
+ }
1500
+ console.error("");
1501
+ }
1502
+ if (validated.length > 0) {
1503
+ console.error(pc3.green("Validated:"));
1504
+ for (const hypo of validated) {
1505
+ console.error(` \u2705 "${hypo.statement}" (${Math.round(hypo.confidence * 100)}%)`);
1506
+ }
1507
+ console.error("");
1508
+ }
1509
+ if (invalidated.length > 0) {
1510
+ console.error(pc3.red("Invalidated:"));
1511
+ for (const hypo of invalidated) {
1512
+ console.error(` \u274C "${hypo.statement}"`);
1513
+ }
1514
+ }
1515
+ }
1516
+ async function validateHypothesis(guardianState, hypoId) {
1517
+ if (!hypoId) {
1518
+ console.error(pc3.red("Please provide a hypothesis ID."));
1519
+ return;
1520
+ }
1521
+ const hypotheses = guardianState.getAllHypotheses();
1522
+ const hypo = hypotheses.find((h) => h.id === hypoId || h.id.includes(hypoId));
1523
+ if (!hypo) {
1524
+ console.error(pc3.red(`Hypothesis not found: ${hypoId}`));
1525
+ return;
1526
+ }
1527
+ await guardianState.updateHypothesis(hypo.id, {
1528
+ status: "validated",
1529
+ confidence: 0.9,
1530
+ validatedAt: (/* @__PURE__ */ new Date()).toISOString()
1531
+ });
1532
+ console.error(pc3.green(`\u2705 Hypothesis validated: "${hypo.statement}"`));
1533
+ }
1534
+ async function invalidateHypothesis(guardianState, hypoId) {
1535
+ if (!hypoId) {
1536
+ console.error(pc3.red("Please provide a hypothesis ID."));
1537
+ return;
1538
+ }
1539
+ const hypotheses = guardianState.getAllHypotheses();
1540
+ const hypo = hypotheses.find((h) => h.id === hypoId || h.id.includes(hypoId));
1541
+ if (!hypo) {
1542
+ console.error(pc3.red(`Hypothesis not found: ${hypoId}`));
1543
+ return;
1544
+ }
1545
+ await guardianState.updateHypothesis(hypo.id, {
1546
+ status: "invalidated",
1547
+ confidence: 0.1
1548
+ });
1549
+ console.error(pc3.red(`\u274C Hypothesis invalidated: "${hypo.statement}"`));
1550
+ }
1551
+ async function deleteHypothesis(guardianState, hypoId) {
1552
+ if (!hypoId) {
1553
+ console.error(pc3.red("Please provide a hypothesis ID."));
1554
+ return;
1555
+ }
1556
+ const hypotheses = guardianState.getAllHypotheses();
1557
+ const hypo = hypotheses.find((h) => h.id === hypoId || h.id.includes(hypoId));
1558
+ if (!hypo) {
1559
+ console.error(pc3.red(`Hypothesis not found: ${hypoId}`));
1560
+ return;
1561
+ }
1562
+ await guardianState.updateHypothesis(hypo.id, { status: "retired" });
1563
+ console.error(pc3.dim(`Removed hypothesis: "${hypo.statement}"`));
1564
+ }
1565
+ function detectHypothesisCategory(statement) {
1566
+ const lower = statement.toLowerCase();
1567
+ if (/monday|friday|weekend|morning|night|time|day|hour/i.test(lower)) return "timing";
1568
+ if (/pattern|recurring|always|never|consistently/i.test(lower)) return "pattern";
1569
+ if (/team|developer|engineer|review/i.test(lower)) return "team";
1570
+ if (/code|file|function|class|module|refactor/i.test(lower)) return "code";
1571
+ return "general";
1572
+ }
1573
+ function generateTestCriteria(statement) {
1574
+ const lower = statement.toLowerCase();
1575
+ if (lower.includes("monday")) {
1576
+ return "Compare Monday issue counts to weekly average";
1577
+ }
1578
+ if (lower.includes("friday")) {
1579
+ return "Compare Friday issue introduction rate to other days";
1580
+ }
1581
+ if (lower.includes("more bug") || lower.includes("more issue")) {
1582
+ return "Compare issue counts between conditions over time";
1583
+ }
1584
+ if (lower.includes("causes") || lower.includes("leads to")) {
1585
+ return "Track correlation between trigger and outcome events";
1586
+ }
1587
+ return "Collect supporting and contradicting evidence from scans";
1588
+ }
1589
+ function printHypothesisHelp() {
1590
+ console.error("");
1591
+ console.error(pc3.bold("trie hypothesis - Manage guardian hypotheses"));
1592
+ console.error("");
1593
+ console.error(pc3.cyan("Usage:"));
1594
+ console.error(' trie hypothesis add "Mondays have more bugs than Fridays"');
1595
+ console.error(" trie hypothesis list");
1596
+ console.error(" trie hypothesis validate <id>");
1597
+ console.error(" trie hypothesis invalidate <id>");
1598
+ console.error(" trie hypothesis delete <id>");
1599
+ console.error("");
1600
+ console.error(pc3.cyan("Options for add:"));
1601
+ console.error(" --category=timing|pattern|team|code|general");
1602
+ console.error(' --test="<test criteria>"');
1603
+ console.error("");
1604
+ console.error(pc3.cyan("Examples:"));
1605
+ console.error(' trie hypothesis add "Code reviews reduce bug rate"');
1606
+ console.error(' trie hypothesis add "Auth module has highest churn"');
1607
+ console.error(' trie hypothesis add "Deploy Fridays cause weekend incidents"');
1608
+ console.error("");
1609
+ }
1610
+
770
1611
  // src/cli/tell.ts
771
1612
  import path3 from "path";
772
1613
  function escalateRisk(level) {
@@ -908,10 +1749,192 @@ async function handleQuietCommand() {
908
1749
  }
909
1750
  }
910
1751
 
1752
+ // src/cli/ci.ts
1753
+ import { writeFileSync, existsSync as existsSync2, mkdirSync } from "fs";
1754
+ import { join } from "path";
1755
+ import pc4 from "picocolors";
1756
+ var WORKFLOW_TEMPLATE = `# Trie Security Scan with Memory Persistence
1757
+ # Generated by: trie ci
1758
+ #
1759
+ # This workflow scans your code and caches Trie's memory
1760
+ # across runs for cross-run learning and pattern recognition.
1761
+
1762
+ name: Trie Security Scan
1763
+
1764
+ on:
1765
+ push:
1766
+ branches: [main, master, develop]
1767
+ pull_request:
1768
+ branches: [main, master]
1769
+
1770
+ jobs:
1771
+ security-scan:
1772
+ runs-on: ubuntu-latest
1773
+ permissions:
1774
+ security-events: write
1775
+ pull-requests: write
1776
+ contents: read
1777
+
1778
+ steps:
1779
+ - name: Checkout
1780
+ uses: actions/checkout@v4
1781
+
1782
+ # Restore Trie memory from previous runs
1783
+ # This enables cross-run learning and pattern recognition
1784
+ - name: Restore Trie Memory
1785
+ uses: actions/cache@v4
1786
+ with:
1787
+ path: |
1788
+ .trie/memory
1789
+ .trie/context
1790
+ .trie/summaries
1791
+ key: trie-memory-\${{ github.repository }}-\${{ github.ref_name }}
1792
+ restore-keys: |
1793
+ trie-memory-\${{ github.repository }}-
1794
+ trie-memory-
1795
+
1796
+ - name: Setup Node.js
1797
+ uses: actions/setup-node@v4
1798
+ with:
1799
+ node-version: '20'
1800
+
1801
+ - name: Install Trie
1802
+ run: npm install -g @triedotdev/mcp
1803
+
1804
+ - name: Run Security Scan
1805
+ run: |
1806
+ trie scan --format sarif --output trie-results.sarif
1807
+ env:
1808
+ ANTHROPIC_API_KEY: \${{ secrets.ANTHROPIC_API_KEY }}
1809
+
1810
+ - name: Upload SARIF Results
1811
+ uses: github/codeql-action/upload-sarif@v3
1812
+ if: always()
1813
+ with:
1814
+ sarif_file: trie-results.sarif
1815
+ continue-on-error: true
1816
+
1817
+ # Memory is automatically saved by cache action on job completion
1818
+ `;
1819
+ var WORKFLOW_MINIMAL = `# Trie Security Scan (Minimal)
1820
+ # Generated by: trie ci --minimal
1821
+
1822
+ name: Trie Scan
1823
+
1824
+ on: [push, pull_request]
1825
+
1826
+ jobs:
1827
+ scan:
1828
+ runs-on: ubuntu-latest
1829
+ steps:
1830
+ - uses: actions/checkout@v4
1831
+
1832
+ # Cache Trie memory for cross-run learning
1833
+ - uses: actions/cache@v4
1834
+ with:
1835
+ path: .trie/memory
1836
+ key: trie-memory-\${{ github.repository }}
1837
+
1838
+ - run: npm install -g @triedotdev/mcp
1839
+ - run: trie scan
1840
+ env:
1841
+ ANTHROPIC_API_KEY: \${{ secrets.ANTHROPIC_API_KEY }}
1842
+ `;
1843
+ function handleCISetupCommand(args) {
1844
+ const workDir = getWorkingDirectory(void 0, true);
1845
+ const workflowsDir = join(workDir, ".github", "workflows");
1846
+ const workflowPath = join(workflowsDir, "trie-scan.yml");
1847
+ const isMinimal = args.includes("--minimal") || args.includes("-m");
1848
+ const isDryRun = args.includes("--dry-run") || args.includes("-n");
1849
+ const showHelp3 = args.includes("--help") || args.includes("-h");
1850
+ if (showHelp3) {
1851
+ console.log(`
1852
+ ${pc4.bold("trie ci")} - Generate GitHub Actions workflow with memory caching
1853
+
1854
+ ${pc4.bold("USAGE:")}
1855
+ trie ci [options]
1856
+
1857
+ ${pc4.bold("OPTIONS:")}
1858
+ --minimal, -m Generate minimal workflow (simpler, fewer features)
1859
+ --dry-run, -n Preview workflow without creating files
1860
+ --help, -h Show this help
1861
+
1862
+ ${pc4.bold("WHAT IT DOES:")}
1863
+ Creates .github/workflows/trie-scan.yml that:
1864
+
1865
+ 1. ${pc4.green("Caches Trie memory")} - Patterns and fixes persist across runs
1866
+ 2. ${pc4.green("Enables learning")} - Trie remembers issues from previous PRs
1867
+ 3. ${pc4.green("Tracks patterns")} - Detects recurring issues across your codebase
1868
+ 4. ${pc4.green("SARIF upload")} - Results appear in GitHub Security tab
1869
+
1870
+ ${pc4.bold("MEMORY BENEFITS:")}
1871
+ \u2022 "This issue was introduced 3 PRs ago"
1872
+ \u2022 "Similar issue was fixed in PR #42"
1873
+ \u2022 "This pattern keeps recurring in auth code"
1874
+ \u2022 Trend tracking: improving, stable, or declining
1875
+
1876
+ ${pc4.bold("EXAMPLES:")}
1877
+ trie ci # Generate full workflow
1878
+ trie ci --minimal # Generate simple workflow
1879
+ trie ci --dry-run # Preview without writing
1880
+
1881
+ ${pc4.bold("REQUIRED SECRETS:")}
1882
+ ANTHROPIC_API_KEY Your Anthropic API key (add in GitHub repo settings)
1883
+ `);
1884
+ return;
1885
+ }
1886
+ const template = isMinimal ? WORKFLOW_MINIMAL : WORKFLOW_TEMPLATE;
1887
+ if (isDryRun) {
1888
+ console.log(pc4.bold("\n\u{1F4CB} Workflow Preview:\n"));
1889
+ console.log(pc4.dim("\u2500".repeat(60)));
1890
+ console.log(template);
1891
+ console.log(pc4.dim("\u2500".repeat(60)));
1892
+ console.log(pc4.dim("\nRun without --dry-run to create the file."));
1893
+ return;
1894
+ }
1895
+ if (existsSync2(workflowPath)) {
1896
+ console.log(pc4.yellow("\u26A0\uFE0F Workflow already exists: .github/workflows/trie-scan.yml"));
1897
+ console.log(pc4.dim(" Run with --dry-run to preview what would be written."));
1898
+ console.log(pc4.dim(" Delete the existing file to regenerate."));
1899
+ return;
1900
+ }
1901
+ if (!existsSync2(workflowsDir)) {
1902
+ mkdirSync(workflowsDir, { recursive: true });
1903
+ }
1904
+ writeFileSync(workflowPath, template);
1905
+ console.log(pc4.green("\u2713") + " Created .github/workflows/trie-scan.yml");
1906
+ console.log("");
1907
+ console.log(pc4.bold("Next steps:"));
1908
+ console.log("");
1909
+ console.log(" 1. Add your Anthropic API key to GitHub Secrets:");
1910
+ console.log(pc4.dim(" Settings \u2192 Secrets \u2192 Actions \u2192 New repository secret"));
1911
+ console.log(pc4.dim(" Name: ANTHROPIC_API_KEY"));
1912
+ console.log("");
1913
+ console.log(" 2. Commit and push:");
1914
+ console.log(pc4.dim(" git add .github/workflows/trie-scan.yml"));
1915
+ console.log(pc4.dim(' git commit -m "Add Trie security scan with memory"'));
1916
+ console.log(pc4.dim(" git push"));
1917
+ console.log("");
1918
+ console.log(pc4.bold("Memory caching benefits:"));
1919
+ console.log(pc4.dim(" \u2022 Trie learns from past scans"));
1920
+ console.log(pc4.dim(" \u2022 Tracks issue trends over time"));
1921
+ console.log(pc4.dim(" \u2022 Remembers when issues were introduced"));
1922
+ console.log(pc4.dim(" \u2022 Recognizes recurring patterns"));
1923
+ }
1924
+
911
1925
  // src/cli/main.ts
912
1926
  var __filename2 = fileURLToPath(import.meta.url);
913
1927
  var __dirname2 = dirname(__filename2);
914
- var VERSION = "1.0.0";
1928
+ var DEFAULT_VERSION = "0.0.0";
1929
+ function getCliVersion() {
1930
+ try {
1931
+ const pkgPath = resolve(__dirname2, "..", "..", "package.json");
1932
+ const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
1933
+ return typeof pkg.version === "string" && pkg.version.trim() ? pkg.version.trim() : DEFAULT_VERSION;
1934
+ } catch {
1935
+ return DEFAULT_VERSION;
1936
+ }
1937
+ }
915
1938
  function showBanner() {
916
1939
  console.log(`
917
1940
  \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557
@@ -931,20 +1954,24 @@ function showBanner() {
931
1954
  }
932
1955
  function showHelp2() {
933
1956
  showBanner();
934
- console.log(`Version: ${VERSION}
1957
+ console.log(`Version: ${getCliVersion()}
935
1958
 
936
1959
  USAGE:
937
- trie-agent <command> [options]
1960
+ trie <command> [options]
938
1961
 
939
1962
  COMMANDS:
940
1963
  init Initialize Trie in your project
941
1964
  scan Scan codebase once and exit
942
1965
  watch Start the guardian (watches + nudges as you code)
943
1966
  check Run risk check before pushing
1967
+
944
1968
  tell "<incident>" Report an incident ("users can't log in")
945
1969
  ok Mark last warning as helpful (thumbs up)
946
1970
  bad Mark last warning as not helpful (thumbs down)
947
1971
  quiet Snooze nudges for 1 hour
1972
+
1973
+ checkpoint Save work context to .trie/ (aliases: cp, save)
1974
+ reconcile Reconcile context graph from JSON backup
948
1975
 
949
1976
  skills Manage external skills from skills.sh
950
1977
  memory Search and manage issue memory
@@ -955,38 +1982,31 @@ COMMANDS:
955
1982
  agent-smith Run Agent Smith (35 vibe code hunters)
956
1983
  super-reviewer Run interactive PR review
957
1984
 
1985
+ ci Generate GitHub Actions workflow with memory caching
1986
+
958
1987
  help Show this help message
959
1988
  version Show version information
960
1989
 
961
1990
  EXAMPLES:
962
- # Initialize Trie in your project
963
- trie init
964
-
965
- # Start the guardian (watches + nudges as you code)
966
- trie watch
967
-
968
- # Scan your codebase now
969
- trie scan
970
-
971
- # Report an incident to teach Trie
972
- trie tell "users couldn't log in after my last push"
973
-
974
- # Give feedback on warnings
975
- trie ok # Warning was helpful
976
- trie bad # Warning was noise
977
-
978
- # Check before pushing (also runs via git hooks)
979
- trie check
980
-
981
- # Install skills from skills.sh
1991
+ trie init # Initialize Trie in your project
1992
+ trie watch # Start the guardian (watches + nudges)
1993
+ trie scan # Scan your codebase now
1994
+ trie scan --agents security,privacy # Scan with specific agents
1995
+
1996
+ trie tell "users couldn't log in" # Report an incident
1997
+ trie ok # Warning was helpful (thumbs up)
1998
+ trie bad # Warning was noise (thumbs down)
1999
+ trie quiet # Snooze nudges for 1 hour
2000
+
2001
+ trie check # Risk check before pushing
2002
+ trie checkpoint "finished auth" # Save work context
2003
+ trie checkpoint list # List recent checkpoints
2004
+
982
2005
  trie skills add vercel-labs/agent-skills react-best-practices
983
-
984
- # Search your incident memory
985
2006
  trie memory search "SQL injection"
986
-
987
- # Run specialized scans
988
- trie agent-smith # 35 vibe code hunters
989
- trie super-reviewer # Interactive PR review
2007
+ trie agent-smith # 35 vibe code hunters
2008
+ trie super-reviewer # Interactive PR review
2009
+ trie ci # Generate CI workflow with memory caching
990
2010
 
991
2011
  MCP TOOLS (use via Cursor/Claude Desktop):
992
2012
  trie_scan Intelligent scan with agent selection
@@ -1085,14 +2105,14 @@ BUILT-IN AGENTS:
1085
2105
 
1086
2106
  Custom Skills:
1087
2107
  \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500`);
1088
- const skillsDir = join(getWorkingDirectory(void 0, true), ".trie", "agents");
1089
- if (existsSync(skillsDir)) {
2108
+ const skillsDir = join2(getWorkingDirectory(void 0, true), ".trie", "agents");
2109
+ if (existsSync3(skillsDir)) {
1090
2110
  try {
1091
2111
  const { readdirSync } = __require("fs");
1092
2112
  const files = readdirSync(skillsDir).filter((f) => f.endsWith(".json"));
1093
2113
  if (files.length > 0) {
1094
2114
  for (const file of files) {
1095
- const config = JSON.parse(readFileSync(join(skillsDir, file), "utf-8"));
2115
+ const config = JSON.parse(readFileSync(join2(skillsDir, file), "utf-8"));
1096
2116
  console.log(` ${config.name.padEnd(18)} ${config.description || "Custom skill"}`);
1097
2117
  }
1098
2118
  } else {
@@ -1118,7 +2138,7 @@ to code reviews. Great for style guides, compliance docs, etc.
1118
2138
  }
1119
2139
  function showVersion() {
1120
2140
  showBanner();
1121
- console.error(`v${VERSION}`);
2141
+ console.error(`v${getCliVersion()}`);
1122
2142
  }
1123
2143
  async function handleProject(args) {
1124
2144
  const subcommand = args[0]?.toLowerCase();
@@ -1150,13 +2170,13 @@ Next steps:
1150
2170
  `);
1151
2171
  } else {
1152
2172
  console.log(`PROJECT.md already exists at: ${result.path}`);
1153
- console.log('Use "trie-agent project" to view it.');
2173
+ console.log('Use "trie project" to view it.');
1154
2174
  }
1155
2175
  return;
1156
2176
  }
1157
2177
  if (subcommand === "edit") {
1158
2178
  const editor = process.env.EDITOR || process.env.VISUAL || "nano";
1159
- const projectPath = join(workDir, ".trie", "PROJECT.md");
2179
+ const projectPath = join2(workDir, ".trie", "PROJECT.md");
1160
2180
  if (!projectInfoExists(workDir)) {
1161
2181
  console.log("No PROJECT.md found. Creating one first...");
1162
2182
  await initProjectInfo(workDir);
@@ -1177,9 +2197,9 @@ Next steps:
1177
2197
  No PROJECT.md found in this project.
1178
2198
 
1179
2199
  COMMANDS:
1180
- trie-agent project init Create PROJECT.md from template
1181
- trie-agent project edit Open PROJECT.md in $EDITOR
1182
- trie-agent project View PROJECT.md contents
2200
+ trie project init Create PROJECT.md from template
2201
+ trie project edit Open PROJECT.md in $EDITOR
2202
+ trie project View PROJECT.md contents
1183
2203
 
1184
2204
  WHAT IS PROJECT.MD?
1185
2205
  PROJECT.md stores important project context for AI assistants:
@@ -1202,7 +2222,7 @@ This info is available via trie://project MCP resource.
1202
2222
  \u2551 \u{1F4CB} Project Information \u2551
1203
2223
  \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D
1204
2224
 
1205
- Path: ${join(workDir, ".trie", "PROJECT.md")}
2225
+ Path: ${join2(workDir, ".trie", "PROJECT.md")}
1206
2226
 
1207
2227
  ${"-".repeat(68)}
1208
2228
  `);
@@ -1253,6 +2273,15 @@ function main() {
1253
2273
  showHelp2();
1254
2274
  process.exit(0);
1255
2275
  }
2276
+ const initRequired = !["init", "version", "--version", "-v"].includes(command);
2277
+ if (initRequired) {
2278
+ const workDir = getWorkingDirectory(void 0, true);
2279
+ if (!isTrieInitialized(workDir)) {
2280
+ console.error("Trie is not initialized for this project.");
2281
+ console.error("Run `trie init` first.");
2282
+ process.exit(1);
2283
+ }
2284
+ }
1256
2285
  switch (command) {
1257
2286
  case "setup":
1258
2287
  case "config":
@@ -1300,6 +2329,23 @@ function main() {
1300
2329
  case "check":
1301
2330
  handleCheckCommand(restArgs);
1302
2331
  break;
2332
+ case "pre-push":
2333
+ handlePrePushCommand(restArgs);
2334
+ break;
2335
+ case "fix":
2336
+ case "auto-fix":
2337
+ case "autofix":
2338
+ handleAutoFixCommand(restArgs);
2339
+ break;
2340
+ case "goal":
2341
+ case "goals":
2342
+ handleGoalCommand(restArgs);
2343
+ break;
2344
+ case "hypothesis":
2345
+ case "hypo":
2346
+ case "hypotheses":
2347
+ handleHypothesisCommand(restArgs);
2348
+ break;
1303
2349
  case "tell":
1304
2350
  handleTellCommand(restArgs);
1305
2351
  break;
@@ -1328,6 +2374,10 @@ function main() {
1328
2374
  case "trie_super_reviewer":
1329
2375
  runScan(["--agents", "super-reviewer", ...restArgs]);
1330
2376
  break;
2377
+ case "ci":
2378
+ case "ci-setup":
2379
+ handleCISetupCommand(restArgs);
2380
+ break;
1331
2381
  default:
1332
2382
  if (command.startsWith("-")) {
1333
2383
  const { spawn } = __require("child_process");
@@ -1341,7 +2391,7 @@ function main() {
1341
2391
  });
1342
2392
  } else {
1343
2393
  console.error(`Unknown command: ${command}`);
1344
- console.error(`Run 'trie-agent help' for usage information.`);
2394
+ console.error(`Run 'trie help' for usage information.`);
1345
2395
  process.exit(1);
1346
2396
  }
1347
2397
  }