@triedotdev/mcp 1.0.140 → 1.0.142

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 (29) hide show
  1. package/README.md +42 -7
  2. package/dist/{chunk-GXF6JOCN.js → chunk-4PAAGLKO.js} +7 -7
  3. package/dist/{chunk-OQ4A3RDY.js → chunk-N2EDZTKG.js} +6 -359
  4. package/dist/chunk-N2EDZTKG.js.map +1 -0
  5. package/dist/{chunk-75ADWWUF.js → chunk-T6PS3MXJ.js} +2 -2
  6. package/dist/{chunk-AF2APASP.js → chunk-V7AY2EJO.js} +4 -4
  7. package/dist/{chunk-UOSTOLU7.js → chunk-WMDFK7LI.js} +365 -10
  8. package/dist/chunk-WMDFK7LI.js.map +1 -0
  9. package/dist/{chunk-4O2KRHK4.js → chunk-Y2LYDCJD.js} +19 -19
  10. package/dist/cli/main.js +669 -441
  11. package/dist/cli/main.js.map +1 -1
  12. package/dist/cli/yolo-daemon.js +9 -9
  13. package/dist/{codebase-index-5SEOESWM.js → codebase-index-FMIULFZQ.js} +3 -3
  14. package/dist/{fast-analyzer-AYLZB5TW.js → fast-analyzer-MWKCDRGD.js} +5 -5
  15. package/dist/{goal-validator-HNXXUCPW.js → goal-validator-DA3JQ6JN.js} +2 -2
  16. package/dist/index.js +91 -31
  17. package/dist/index.js.map +1 -1
  18. package/dist/{trie-agent-M6PHM6UD.js → trie-agent-6A7YBNTQ.js} +6 -6
  19. package/package.json +1 -1
  20. package/dist/chunk-OQ4A3RDY.js.map +0 -1
  21. package/dist/chunk-UOSTOLU7.js.map +0 -1
  22. /package/dist/{chunk-GXF6JOCN.js.map → chunk-4PAAGLKO.js.map} +0 -0
  23. /package/dist/{chunk-75ADWWUF.js.map → chunk-T6PS3MXJ.js.map} +0 -0
  24. /package/dist/{chunk-AF2APASP.js.map → chunk-V7AY2EJO.js.map} +0 -0
  25. /package/dist/{chunk-4O2KRHK4.js.map → chunk-Y2LYDCJD.js.map} +0 -0
  26. /package/dist/{codebase-index-5SEOESWM.js.map → codebase-index-FMIULFZQ.js.map} +0 -0
  27. /package/dist/{fast-analyzer-AYLZB5TW.js.map → fast-analyzer-MWKCDRGD.js.map} +0 -0
  28. /package/dist/{goal-validator-HNXXUCPW.js.map → goal-validator-DA3JQ6JN.js.map} +0 -0
  29. /package/dist/{trie-agent-M6PHM6UD.js.map → trie-agent-6A7YBNTQ.js.map} +0 -0
package/dist/cli/main.js CHANGED
@@ -21,7 +21,7 @@ import {
21
21
  isTrieInitialized,
22
22
  perceiveCurrentChanges,
23
23
  reasonAboutChangesHumanReadable
24
- } from "../chunk-GXF6JOCN.js";
24
+ } from "../chunk-4PAAGLKO.js";
25
25
  import {
26
26
  loadConfig,
27
27
  saveConfig
@@ -32,22 +32,36 @@ import {
32
32
  import "../chunk-ZV2K6M7T.js";
33
33
  import {
34
34
  GotchaPredictor,
35
+ SlackIntegration,
35
36
  findCrossProjectPatterns,
36
37
  getGlobalMemoryStats,
37
38
  listTrackedProjects,
38
39
  searchGlobalPatterns,
39
40
  updateGlobalMemoryMd
40
- } from "../chunk-UOSTOLU7.js";
41
+ } from "../chunk-WMDFK7LI.js";
41
42
  import {
42
43
  ContextGraph
43
44
  } from "../chunk-FH335WL5.js";
44
45
  import {
45
46
  measureInitialGoalValue
46
- } from "../chunk-75ADWWUF.js";
47
+ } from "../chunk-T6PS3MXJ.js";
47
48
  import "../chunk-FPEMP54L.js";
48
49
  import {
49
50
  getProjectState
50
51
  } from "../chunk-LT6VUZG2.js";
52
+ import "../chunk-F4NJ4CBP.js";
53
+ import "../chunk-IXO4G4D3.js";
54
+ import "../chunk-6NLHFIYA.js";
55
+ import {
56
+ getStorage
57
+ } from "../chunk-FG467PDD.js";
58
+ import {
59
+ getAutonomyConfig,
60
+ recordBypass,
61
+ shouldAutoFix,
62
+ shouldBlockPush,
63
+ trackIssueOccurrence
64
+ } from "../chunk-5KJ4UJOY.js";
51
65
  import {
52
66
  compressOldBlocks,
53
67
  deleteAllBlocks,
@@ -78,19 +92,6 @@ import {
78
92
  } from "../chunk-62POBLFC.js";
79
93
  import "../chunk-4MJ52WBH.js";
80
94
  import "../chunk-43X6JBEM.js";
81
- import "../chunk-F4NJ4CBP.js";
82
- import "../chunk-IXO4G4D3.js";
83
- import "../chunk-6NLHFIYA.js";
84
- import {
85
- getStorage
86
- } from "../chunk-FG467PDD.js";
87
- import {
88
- getAutonomyConfig,
89
- recordBypass,
90
- shouldAutoFix,
91
- shouldBlockPush,
92
- trackIssueOccurrence
93
- } from "../chunk-5KJ4UJOY.js";
94
95
  import {
95
96
  getTrieDirectory,
96
97
  getWorkingDirectory
@@ -101,10 +102,10 @@ import {
101
102
  } from "../chunk-DGUM43GV.js";
102
103
 
103
104
  // src/cli/main.ts
104
- import { resolve, join as join4, dirname } from "path";
105
- import { readFileSync, realpathSync } from "fs";
106
- import { fileURLToPath } from "url";
107
- import pc8 from "picocolors";
105
+ import { resolve as resolve2, join as join5, dirname as dirname2 } from "path";
106
+ import { readFileSync as readFileSync2, realpathSync } from "fs";
107
+ import { fileURLToPath as fileURLToPath2 } from "url";
108
+ import pc9 from "picocolors";
108
109
 
109
110
  // src/hooks/install.ts
110
111
  import fs from "fs";
@@ -879,18 +880,371 @@ function collectIssuesForBlocking(reasoning) {
879
880
  return issues;
880
881
  }
881
882
 
883
+ // src/cli/hooks.ts
884
+ import { writeFile, mkdir, chmod } from "fs/promises";
885
+ import { join } from "path";
886
+ import { existsSync } from "fs";
887
+ import pc2 from "picocolors";
888
+ import { resolve, dirname } from "path";
889
+ import { fileURLToPath } from "url";
890
+ async function installGitHooks2() {
891
+ const workDir = getWorkingDirectory(void 0, true);
892
+ const isRepo = await isGitRepo(workDir);
893
+ if (!isRepo) {
894
+ console.log(pc2.yellow("\u26A0 Not a git repository. Git hooks not installed."));
895
+ return;
896
+ }
897
+ const hooksDir = join(workDir, ".git", "hooks");
898
+ if (!existsSync(hooksDir)) {
899
+ await mkdir(hooksDir, { recursive: true });
900
+ }
901
+ const prePushHook = `#!/bin/sh
902
+ # Auto-sync ledger to shared storage before push
903
+
904
+ # Only run if trie is initialized
905
+ if [ ! -d ".trie" ]; then
906
+ exit 0
907
+ fi
908
+
909
+ # Check if trie command is available
910
+ if ! command -v trie >/dev/null 2>&1; then
911
+ echo "Warning: trie command not found, skipping ledger sync"
912
+ exit 0
913
+ fi
914
+
915
+ # Sync ledger to shared storage
916
+ echo "Syncing ledger to shared storage..."
917
+ trie sync push 2>/dev/null || true
918
+
919
+ exit 0
920
+ `;
921
+ const postMergeHook = `#!/bin/sh
922
+ # Auto-sync ledger from shared storage after merge
923
+
924
+ # Only run if trie is initialized
925
+ if [ ! -d ".trie" ]; then
926
+ exit 0
927
+ fi
928
+
929
+ # Check if trie command is available
930
+ if ! command -v trie >/dev/null 2>&1; then
931
+ exit 0
932
+ fi
933
+
934
+ # Sync ledger from shared storage
935
+ echo "Syncing ledger from shared storage..."
936
+ trie sync pull 2>/dev/null || true
937
+
938
+ exit 0
939
+ `;
940
+ const prePushPath = join(hooksDir, "pre-push");
941
+ const postMergePath = join(hooksDir, "post-merge");
942
+ await writeFile(prePushPath, prePushHook);
943
+ await writeFile(postMergePath, postMergeHook);
944
+ await chmod(prePushPath, 493);
945
+ await chmod(postMergePath, 493);
946
+ console.log(pc2.green("\u2713 Git hooks installed successfully"));
947
+ console.log(pc2.dim(" pre-push: Syncs ledger to shared storage"));
948
+ console.log(pc2.dim(" post-merge: Syncs ledger from shared storage"));
949
+ }
950
+ async function checkGitHooks() {
951
+ const workDir = getWorkingDirectory(void 0, true);
952
+ const isRepo = await isGitRepo(workDir);
953
+ if (!isRepo) {
954
+ return {
955
+ isGitRepo: false,
956
+ prePushInstalled: false,
957
+ postMergeInstalled: false
958
+ };
959
+ }
960
+ const hooksDir = join(workDir, ".git", "hooks");
961
+ const prePushPath = join(hooksDir, "pre-push");
962
+ const postMergePath = join(hooksDir, "post-merge");
963
+ return {
964
+ isGitRepo: true,
965
+ prePushInstalled: existsSync(prePushPath),
966
+ postMergeInstalled: existsSync(postMergePath)
967
+ };
968
+ }
969
+ var __filename2 = fileURLToPath(import.meta.url);
970
+ var __dirname2 = dirname(__filename2);
971
+ async function handlePreCommitCommand(_args) {
972
+ console.log(pc2.cyan("\u{1F50D} Running pre-commit hook..."));
973
+ try {
974
+ const { spawn } = await import("child_process");
975
+ let daemonPath;
976
+ if (__filename2.endsWith(".ts")) {
977
+ daemonPath = resolve(__dirname2, "yolo-daemon.ts");
978
+ } else {
979
+ daemonPath = resolve(__dirname2, "yolo-daemon.js");
980
+ }
981
+ const daemonArgs = ["--once", "--staged-only", "--fail-on", "critical"];
982
+ const executor = daemonPath.endsWith(".ts") ? "npx" : "node";
983
+ const execArgs = daemonPath.endsWith(".ts") ? ["tsx", daemonPath, ...daemonArgs] : [daemonPath, ...daemonArgs];
984
+ const child = spawn(executor, execArgs, {
985
+ stdio: "inherit",
986
+ env: process.env
987
+ });
988
+ child.on("close", (code) => {
989
+ if (code === 0) {
990
+ console.log(pc2.green("\u2713 Pre-commit hook completed successfully"));
991
+ } else {
992
+ console.log(pc2.red("\u2717 Pre-commit hook found critical issues"));
993
+ console.log(pc2.dim(" Commit blocked. Fix issues and try again."));
994
+ }
995
+ process.exit(code || 0);
996
+ });
997
+ } catch (error) {
998
+ console.error(pc2.red("Error in pre-commit hook:"), error);
999
+ process.exit(0);
1000
+ }
1001
+ }
1002
+ async function handlePostCommitCommand(_args) {
1003
+ console.log(pc2.cyan("\u{1F4DD} Running post-commit hook..."));
1004
+ try {
1005
+ const workDir = getWorkingDirectory(void 0, true);
1006
+ const { spawn } = await import("child_process");
1007
+ const updateProcess = spawn("node", [
1008
+ "-e",
1009
+ `
1010
+ const { updateContextAfterCommit } = require('./context.js');
1011
+ updateContextAfterCommit('${workDir}').catch(console.error);
1012
+ `
1013
+ ], {
1014
+ stdio: "pipe",
1015
+ env: process.env
1016
+ });
1017
+ updateProcess.on("close", (code) => {
1018
+ if (code === 0) {
1019
+ console.log(pc2.green("\u2713 Post-commit hook completed - context updated"));
1020
+ } else {
1021
+ console.log(pc2.yellow("\u26A0 Post-commit hook completed with warnings"));
1022
+ }
1023
+ });
1024
+ updateProcess.unref();
1025
+ } catch (error) {
1026
+ console.error(pc2.yellow("Warning in post-commit hook:"), error);
1027
+ }
1028
+ }
1029
+
1030
+ // src/cli/setup.ts
1031
+ import pc3 from "picocolors";
1032
+ import { readFileSync, existsSync as existsSync2 } from "fs";
1033
+ import { join as join2 } from "path";
1034
+ async function handleSetupCommand(args) {
1035
+ const subcommand = args[0]?.toLowerCase();
1036
+ if (subcommand === "slack") {
1037
+ await setupSlackIntegration(args.slice(1));
1038
+ return;
1039
+ }
1040
+ if (subcommand === "test-slack") {
1041
+ await testSlackIntegration();
1042
+ return;
1043
+ }
1044
+ showSetup();
1045
+ }
1046
+ async function setupSlackIntegration(args) {
1047
+ const webhookUrl = args[0];
1048
+ if (!webhookUrl) {
1049
+ console.log(`
1050
+ \u2554\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\u2557
1051
+ \u2551 Slack Integration Setup \u2551
1052
+ \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
1053
+
1054
+ STEP 1: Create a Slack Webhook
1055
+ ${pc3.dim("\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")}
1056
+ 1. Go to https://api.slack.com/apps
1057
+ 2. Click "Create New App" > "From scratch"
1058
+ 3. Name your app (e.g. "Trie Security Bot")
1059
+ 4. Choose your workspace
1060
+ 5. Go to "Incoming Webhooks" in the sidebar
1061
+ 6. Toggle "Activate Incoming Webhooks" to On
1062
+ 7. Click "Add New Webhook to Workspace"
1063
+ 8. Choose a channel (e.g. #security, #alerts)
1064
+ 9. Copy the webhook URL
1065
+
1066
+ STEP 2: Configure Trie
1067
+ ${pc3.dim("\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")}
1068
+ Run: trie setup slack <webhook-url> [channel]
1069
+
1070
+ EXAMPLES:
1071
+ trie setup slack https://hooks.slack.com/services/T.../B.../... #security
1072
+ trie setup slack https://hooks.slack.com/services/T.../B.../...
1073
+
1074
+ STEP 3: Test the Integration
1075
+ ${pc3.dim("\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")}
1076
+ Run: trie setup test-slack
1077
+
1078
+ WHAT TRIE SENDS TO SLACK:
1079
+ \u2022 Decision extractions from incidents
1080
+ \u2022 Active blockers and risk predictions
1081
+ \u2022 Daily/weekly team summaries
1082
+ \u2022 Critical security findings
1083
+ \u2022 Auto-escalation notifications
1084
+ `);
1085
+ return;
1086
+ }
1087
+ const channel = args[1];
1088
+ try {
1089
+ if (!webhookUrl.startsWith("https://hooks.slack.com/services/")) {
1090
+ console.error(pc3.red("Error:"), "Invalid Slack webhook URL format");
1091
+ console.error("Expected: https://hooks.slack.com/services/...");
1092
+ process.exit(1);
1093
+ }
1094
+ const config = await loadConfig();
1095
+ const updatedConfig = {
1096
+ ...config,
1097
+ integrations: {
1098
+ ...config.integrations,
1099
+ slack: {
1100
+ enabled: true,
1101
+ webhook: webhookUrl,
1102
+ channel: channel || void 0
1103
+ }
1104
+ }
1105
+ };
1106
+ await saveConfig(updatedConfig);
1107
+ console.log(pc3.green("\u2713"), "Slack integration configured successfully!");
1108
+ if (channel) {
1109
+ console.log(pc3.dim(` Channel: ${channel}`));
1110
+ }
1111
+ console.log(pc3.dim(` Webhook: ${webhookUrl.substring(0, 50)}...`));
1112
+ console.log(`
1113
+ ${pc3.bold("Next steps:")}
1114
+ 1. Test the integration: ${pc3.cyan("trie setup test-slack")}
1115
+ 2. Configure auto-escalation (optional):
1116
+ ${pc3.dim("Add to .trie/config.json:")}
1117
+ ${pc3.dim(`{
1118
+ "autoEscalation": {
1119
+ "enabled": true,
1120
+ "webhookUrl": "${webhookUrl}",
1121
+ "quietHours": { "start": "21:00", "end": "08:00" }
1122
+ }
1123
+ }`)}
1124
+ 3. Notifications will be sent for:
1125
+ \u2022 Critical security issues
1126
+ \u2022 Team assignments and escalations
1127
+ \u2022 Daily/weekly summaries
1128
+ `);
1129
+ } catch (error) {
1130
+ console.error(pc3.red("Error configuring Slack integration:"), error);
1131
+ process.exit(1);
1132
+ }
1133
+ }
1134
+ async function testSlackIntegration() {
1135
+ try {
1136
+ const config = await loadConfig();
1137
+ if (!config.integrations?.slack?.enabled || !config.integrations.slack.webhook) {
1138
+ console.error(pc3.red("Error:"), "Slack integration not configured");
1139
+ console.error("Run:", pc3.cyan("trie setup slack <webhook-url>"));
1140
+ process.exit(1);
1141
+ }
1142
+ console.log(pc3.cyan("\u{1F50D}"), "Testing Slack integration...");
1143
+ const slack = new SlackIntegration({
1144
+ webhookUrl: config.integrations.slack.webhook,
1145
+ channel: config.integrations.slack.channel
1146
+ });
1147
+ const success = await slack.testConnection();
1148
+ if (success) {
1149
+ console.log(pc3.green("\u2713"), "Slack integration test successful!");
1150
+ console.log(pc3.dim(" Check your Slack channel for the test message"));
1151
+ } else {
1152
+ console.log(pc3.red("\u2717"), "Slack integration test failed");
1153
+ console.log(pc3.dim(" Check your webhook URL and network connection"));
1154
+ process.exit(1);
1155
+ }
1156
+ } catch (error) {
1157
+ console.error(pc3.red("Error testing Slack integration:"), error);
1158
+ process.exit(1);
1159
+ }
1160
+ }
1161
+ function showSetup() {
1162
+ const config = getCurrentConfig();
1163
+ const hasSlack = config?.integrations?.slack?.enabled;
1164
+ const hasGitHub = config?.apiKeys?.github;
1165
+ const hasLinear = config?.apiKeys?.linear;
1166
+ console.log(`
1167
+ \u2554\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\u2557
1168
+ \u2551 Trie Agent Setup \u2551
1169
+ \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
1170
+
1171
+ STEP 1: API Keys
1172
+ ${pc3.dim("\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")}
1173
+ Trie can work offline, but performs best with these keys:
1174
+
1175
+ 1. ANTHROPIC_API_KEY (Required for AI analysis)
1176
+ Get it: https://console.anthropic.com/
1177
+
1178
+ 2. LINEAR_API_KEY (Required for JIT defect prediction)
1179
+ Get it: https://linear.app/settings/api
1180
+
1181
+ 3. GITHUB_TOKEN (Optional for GitHub integration)
1182
+ Get it: https://github.com/settings/tokens
1183
+
1184
+ Set them in your environment (~/.zshrc) or .trie/config.json:
1185
+ export ANTHROPIC_API_KEY=sk-ant-...
1186
+ export LINEAR_API_KEY=lin_api_...
1187
+ export GITHUB_TOKEN=ghp_...
1188
+
1189
+ STEP 2: Team Integrations
1190
+ ${pc3.dim("\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")}
1191
+ ${hasSlack ? pc3.green("\u2713") : pc3.red("\u2717")} Slack: ${hasSlack ? "Configured" : "trie setup slack <webhook>"}
1192
+ ${hasGitHub ? pc3.green("\u2713") : pc3.red("\u2717")} GitHub: ${hasGitHub ? "Configured" : "Set GITHUB_TOKEN"}
1193
+ ${hasLinear ? pc3.green("\u2713") : pc3.red("\u2717")} Linear: ${hasLinear ? "Configured" : "Set LINEAR_API_KEY"}
1194
+
1195
+ SLACK SETUP:
1196
+ trie setup slack # Show Slack setup guide
1197
+ trie setup slack <webhook> [channel] # Configure Slack webhook
1198
+ trie setup test-slack # Test Slack integration
1199
+
1200
+ STEP 3: Configure for your AI tool
1201
+ ${pc3.dim("\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")}
1202
+
1203
+ For CLAUDE CODE:
1204
+ claude mcp add Trie -- npx @triedotdev/mcp
1205
+
1206
+ For CURSOR (~/.cursor/mcp.json):
1207
+ {
1208
+ "mcpServers": {
1209
+ "Trie": {
1210
+ "command": "npx",
1211
+ "args": ["-y", "@triedotdev/mcp"],
1212
+ "env": {
1213
+ "ANTHROPIC_API_KEY": "your-key-here",
1214
+ "LINEAR_API_KEY": "your-key-here"
1215
+ }
1216
+ }
1217
+ }
1218
+ }
1219
+
1220
+ STEP 4: Start scanning!
1221
+ ${pc3.dim("\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")}
1222
+ Ask your AI assistant: "Scan this with Trie" or "Use trie_scan"
1223
+ `);
1224
+ }
1225
+ function getCurrentConfig() {
1226
+ try {
1227
+ const configPath = join2(getTrieDirectory(getWorkingDirectory(void 0, true)), "config.json");
1228
+ if (existsSync2(configPath)) {
1229
+ return JSON.parse(readFileSync(configPath, "utf-8"));
1230
+ }
1231
+ } catch {
1232
+ }
1233
+ return null;
1234
+ }
1235
+
882
1236
  // src/cli/auto-fix.ts
883
1237
  import { readFile as readFile2 } from "fs/promises";
884
- import { existsSync as existsSync2 } from "fs";
1238
+ import { existsSync as existsSync4 } from "fs";
885
1239
  import { createInterface } from "readline";
886
- import pc2 from "picocolors";
1240
+ import pc4 from "picocolors";
887
1241
 
888
1242
  // src/utils/auto-fix-apply.ts
889
- import { readFile, writeFile } from "fs/promises";
890
- import { existsSync } from "fs";
1243
+ import { readFile, writeFile as writeFile2 } from "fs/promises";
1244
+ import { existsSync as existsSync3 } from "fs";
891
1245
  async function applyAutoFix(fix) {
892
1246
  try {
893
- if (!existsSync(fix.file)) {
1247
+ if (!existsSync3(fix.file)) {
894
1248
  return false;
895
1249
  }
896
1250
  const content = await readFile(fix.file, "utf-8");
@@ -913,7 +1267,7 @@ async function applyAutoFix(fix) {
913
1267
  } else {
914
1268
  return false;
915
1269
  }
916
- await writeFile(fix.file, newContent);
1270
+ await writeFile2(fix.file, newContent);
917
1271
  return true;
918
1272
  } catch {
919
1273
  return false;
@@ -968,34 +1322,34 @@ async function promptUser(question) {
968
1322
  input: process.stdin,
969
1323
  output: process.stderr
970
1324
  });
971
- return new Promise((resolve2) => {
1325
+ return new Promise((resolve3) => {
972
1326
  rl.question(question, (answer) => {
973
1327
  rl.close();
974
- resolve2(answer.toLowerCase().trim());
1328
+ resolve3(answer.toLowerCase().trim());
975
1329
  });
976
1330
  });
977
1331
  }
978
1332
  function displayFixPreview(fix, index, total) {
979
1333
  console.error("");
980
- console.error(pc2.cyan(`\u2501\u2501\u2501 Fix ${index + 1}/${total} \u2501\u2501\u2501`));
981
- console.error(pc2.dim(`File: ${fix.file}${fix.line ? `:${fix.line}` : ""}`));
982
- console.error(pc2.dim(`Type: ${fix.type}`));
983
- console.error(pc2.yellow(`Description: ${fix.description}`));
1334
+ console.error(pc4.cyan(`\u2501\u2501\u2501 Fix ${index + 1}/${total} \u2501\u2501\u2501`));
1335
+ console.error(pc4.dim(`File: ${fix.file}${fix.line ? `:${fix.line}` : ""}`));
1336
+ console.error(pc4.dim(`Type: ${fix.type}`));
1337
+ console.error(pc4.yellow(`Description: ${fix.description}`));
984
1338
  console.error("");
985
1339
  if (fix.original) {
986
- console.error(pc2.red("- " + fix.original));
1340
+ console.error(pc4.red("- " + fix.original));
987
1341
  }
988
1342
  if (fix.fixed) {
989
- console.error(pc2.green("+ " + fix.fixed));
1343
+ console.error(pc4.green("+ " + fix.fixed));
990
1344
  } else if (fix.original) {
991
- console.error(pc2.dim(" (line will be removed)"));
1345
+ console.error(pc4.dim(" (line will be removed)"));
992
1346
  }
993
1347
  console.error("");
994
1348
  }
995
1349
  async function loadFixContent(fixes) {
996
1350
  const enrichedFixes = [];
997
1351
  for (const fix of fixes) {
998
- if (!fix.line || !existsSync2(fix.file)) {
1352
+ if (!fix.line || !existsSync4(fix.file)) {
999
1353
  continue;
1000
1354
  }
1001
1355
  try {
@@ -1017,39 +1371,39 @@ async function handleAutoFixCommand(args, issues) {
1017
1371
  const projectPath = getWorkingDirectory(void 0, true);
1018
1372
  const config = await getAutonomyConfig(projectPath);
1019
1373
  if (!config.autoFix.enabled) {
1020
- console.error(pc2.yellow("Auto-fix is disabled in config."));
1021
- console.error(pc2.dim("Enable it with: trie config set autoFix.enabled true"));
1374
+ console.error(pc4.yellow("Auto-fix is disabled in config."));
1375
+ console.error(pc4.dim("Enable it with: trie config set autoFix.enabled true"));
1022
1376
  return;
1023
1377
  }
1024
1378
  const dryRun = args.includes("--dry-run");
1025
1379
  const skipConfirm = args.includes("--yes") || args.includes("-y");
1026
1380
  if (!issues || issues.length === 0) {
1027
- console.error(pc2.yellow("No issues provided. Run a scan first:"));
1028
- console.error(pc2.dim(" trie scan --fix"));
1381
+ console.error(pc4.yellow("No issues provided. Run a scan first:"));
1382
+ console.error(pc4.dim(" trie scan --fix"));
1029
1383
  return;
1030
1384
  }
1031
1385
  let fixes = detectAutoFixes(issues);
1032
1386
  if (fixes.length === 0) {
1033
- console.error(pc2.green("\u2713 No auto-fixable issues found."));
1387
+ console.error(pc4.green("\u2713 No auto-fixable issues found."));
1034
1388
  return;
1035
1389
  }
1036
1390
  fixes = fixes.filter((fix) => shouldAutoFix(fix, config));
1037
1391
  if (fixes.length === 0) {
1038
- console.error(pc2.yellow("Found fixable issues but they are not in allowed categories."));
1039
- console.error(pc2.dim("Allowed categories: " + config.autoFix.categories.join(", ")));
1392
+ console.error(pc4.yellow("Found fixable issues but they are not in allowed categories."));
1393
+ console.error(pc4.dim("Allowed categories: " + config.autoFix.categories.join(", ")));
1040
1394
  return;
1041
1395
  }
1042
1396
  fixes = await loadFixContent(fixes);
1043
1397
  if (fixes.length === 0) {
1044
- console.error(pc2.yellow("Could not load fix content from files."));
1398
+ console.error(pc4.yellow("Could not load fix content from files."));
1045
1399
  return;
1046
1400
  }
1047
1401
  console.error("");
1048
- 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"));
1049
- console.error(pc2.bold("Auto-Fix: Human-in-the-Loop"));
1050
- 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"));
1402
+ console.error(pc4.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"));
1403
+ console.error(pc4.bold("Auto-Fix: Human-in-the-Loop"));
1404
+ console.error(pc4.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"));
1051
1405
  console.error("");
1052
- console.error(`Found ${pc2.bold(fixes.length.toString())} auto-fixable issues:`);
1406
+ console.error(`Found ${pc4.bold(fixes.length.toString())} auto-fixable issues:`);
1053
1407
  const byCategory = /* @__PURE__ */ new Map();
1054
1408
  for (const fix of fixes) {
1055
1409
  byCategory.set(fix.category, (byCategory.get(fix.category) || 0) + 1);
@@ -1059,7 +1413,7 @@ async function handleAutoFixCommand(args, issues) {
1059
1413
  }
1060
1414
  console.error("");
1061
1415
  if (dryRun) {
1062
- console.error(pc2.yellow("[DRY RUN] No changes will be made."));
1416
+ console.error(pc4.yellow("[DRY RUN] No changes will be made."));
1063
1417
  console.error("");
1064
1418
  for (let i = 0; i < fixes.length; i++) {
1065
1419
  displayFixPreview(fixes[i], i, fixes.length);
@@ -1067,13 +1421,13 @@ async function handleAutoFixCommand(args, issues) {
1067
1421
  return;
1068
1422
  }
1069
1423
  if (config.autoFix.askFirst && !skipConfirm) {
1070
- console.error(pc2.yellow("Trie will ask before applying each fix."));
1424
+ console.error(pc4.yellow("Trie will ask before applying each fix."));
1071
1425
  console.error("");
1072
1426
  const response = await promptUser(
1073
1427
  `Apply all ${fixes.length} fixes? (y)es / (n)o / (r)eview each: `
1074
1428
  );
1075
1429
  if (response === "n" || response === "no") {
1076
- console.error(pc2.dim("Cancelled."));
1430
+ console.error(pc4.dim("Cancelled."));
1077
1431
  return;
1078
1432
  }
1079
1433
  if (response === "r" || response === "review") {
@@ -1084,54 +1438,54 @@ async function handleAutoFixCommand(args, issues) {
1084
1438
  displayFixPreview(fix, i, fixes.length);
1085
1439
  const answer = await promptUser("Apply this fix? (y/n/q): ");
1086
1440
  if (answer === "q" || answer === "quit") {
1087
- console.error(pc2.dim("Stopped."));
1441
+ console.error(pc4.dim("Stopped."));
1088
1442
  break;
1089
1443
  }
1090
1444
  if (answer === "y" || answer === "yes") {
1091
1445
  const success = await applyAutoFix(fix);
1092
1446
  if (success) {
1093
- console.error(pc2.green(`\u2713 Applied fix to ${fix.file}:${fix.line}`));
1447
+ console.error(pc4.green(`\u2713 Applied fix to ${fix.file}:${fix.line}`));
1094
1448
  applied2++;
1095
1449
  } else {
1096
- console.error(pc2.red(`\u2717 Failed to apply fix`));
1450
+ console.error(pc4.red(`\u2717 Failed to apply fix`));
1097
1451
  }
1098
1452
  } else {
1099
- console.error(pc2.dim("Skipped."));
1453
+ console.error(pc4.dim("Skipped."));
1100
1454
  skipped++;
1101
1455
  }
1102
1456
  }
1103
1457
  console.error("");
1104
- console.error(pc2.cyan("\u2501\u2501\u2501 Summary \u2501\u2501\u2501"));
1105
- console.error(`Applied: ${pc2.green(applied2.toString())}`);
1106
- console.error(`Skipped: ${pc2.dim(skipped.toString())}`);
1458
+ console.error(pc4.cyan("\u2501\u2501\u2501 Summary \u2501\u2501\u2501"));
1459
+ console.error(`Applied: ${pc4.green(applied2.toString())}`);
1460
+ console.error(`Skipped: ${pc4.dim(skipped.toString())}`);
1107
1461
  return;
1108
1462
  }
1109
1463
  }
1110
1464
  console.error("");
1111
- console.error(pc2.cyan("Applying fixes..."));
1465
+ console.error(pc4.cyan("Applying fixes..."));
1112
1466
  console.error("");
1113
1467
  let applied = 0;
1114
1468
  let failed = 0;
1115
1469
  for (const fix of fixes) {
1116
1470
  const success = await applyAutoFix(fix);
1117
1471
  if (success) {
1118
- console.error(pc2.green(`\u2713 Applied fix to ${fix.file}:${fix.line}`));
1472
+ console.error(pc4.green(`\u2713 Applied fix to ${fix.file}:${fix.line}`));
1119
1473
  applied++;
1120
1474
  } else {
1121
- console.error(pc2.red(`\u2717 Failed to apply fix to ${fix.file}:${fix.line}`));
1475
+ console.error(pc4.red(`\u2717 Failed to apply fix to ${fix.file}:${fix.line}`));
1122
1476
  failed++;
1123
1477
  }
1124
1478
  }
1125
1479
  console.error("");
1126
- console.error(pc2.cyan("\u2501\u2501\u2501 Complete \u2501\u2501\u2501"));
1127
- console.error(`Applied: ${pc2.green(applied.toString())}`);
1480
+ console.error(pc4.cyan("\u2501\u2501\u2501 Complete \u2501\u2501\u2501"));
1481
+ console.error(`Applied: ${pc4.green(applied.toString())}`);
1128
1482
  if (failed > 0) {
1129
- console.error(`Failed: ${pc2.red(failed.toString())}`);
1483
+ console.error(`Failed: ${pc4.red(failed.toString())}`);
1130
1484
  }
1131
1485
  }
1132
1486
 
1133
1487
  // src/cli/goal.ts
1134
- import pc3 from "picocolors";
1488
+ import pc5 from "picocolors";
1135
1489
  async function handleGoalCommand(args) {
1136
1490
  const projectPath = getWorkingDirectory(void 0, true);
1137
1491
  const projectState = getProjectState(projectPath);
@@ -1166,8 +1520,8 @@ async function handleGoalCommand(args) {
1166
1520
  async function addGoal(projectState, args) {
1167
1521
  const description = args.join(" ").replace(/^["']|["']$/g, "");
1168
1522
  if (!description) {
1169
- console.error(pc3.red("Please provide a goal description."));
1170
- console.error(pc3.dim('Example: trie goal add "Reduce auth issues by 50%"'));
1523
+ console.error(pc5.red("Please provide a goal description."));
1524
+ console.error(pc5.dim('Example: trie goal add "Reduce auth issues by 50%"'));
1171
1525
  return;
1172
1526
  }
1173
1527
  const categoryMatch = description.match(/--category[=\s](\w+)/);
@@ -1224,51 +1578,51 @@ async function addGoal(projectState, args) {
1224
1578
  };
1225
1579
  await projectState.addGoal(goal);
1226
1580
  console.error("");
1227
- console.error(pc3.green("\u2713 Goal created"));
1581
+ console.error(pc5.green("\u2713 Goal created"));
1228
1582
  console.error("");
1229
- console.error(pc3.bold(cleanDesc));
1230
- console.error(pc3.dim(`ID: ${goal.id}`));
1231
- console.error(pc3.dim(`Type: ${goalType} | Target: ${target} | Category: ${category}`));
1583
+ console.error(pc5.bold(cleanDesc));
1584
+ console.error(pc5.dim(`ID: ${goal.id}`));
1585
+ console.error(pc5.dim(`Type: ${goalType} | Target: ${target} | Category: ${category}`));
1232
1586
  if (initialValue > 0) {
1233
- console.error(pc3.dim(`Starting value: ${initialValue} issues found`));
1587
+ console.error(pc5.dim(`Starting value: ${initialValue} issues found`));
1234
1588
  }
1235
- console.error(pc3.dim(`Deadline: ${deadline.toLocaleDateString()}`));
1589
+ console.error(pc5.dim(`Deadline: ${deadline.toLocaleDateString()}`));
1236
1590
  console.error("");
1237
- console.error(pc3.cyan("Progress will be tracked and you'll be notified when you achieve it!"));
1591
+ console.error(pc5.cyan("Progress will be tracked and you'll be notified when you achieve it!"));
1238
1592
  }
1239
1593
  async function listGoals(projectState) {
1240
1594
  const goals = projectState.getAllGoals();
1241
1595
  if (goals.length === 0) {
1242
- console.error(pc3.dim("No goals yet."));
1243
- console.error(pc3.dim('Create one: trie goal add "Reduce auth issues by 50%"'));
1596
+ console.error(pc5.dim("No goals yet."));
1597
+ console.error(pc5.dim('Create one: trie goal add "Reduce auth issues by 50%"'));
1244
1598
  return;
1245
1599
  }
1246
1600
  console.error("");
1247
- console.error(pc3.bold("Goals"));
1601
+ console.error(pc5.bold("Goals"));
1248
1602
  console.error("");
1249
1603
  const active = goals.filter((g) => g.status === "active");
1250
1604
  const achieved = goals.filter((g) => g.status === "achieved");
1251
1605
  const other = goals.filter((g) => g.status !== "active" && g.status !== "achieved");
1252
1606
  if (active.length > 0) {
1253
- console.error(pc3.cyan("Active:"));
1607
+ console.error(pc5.cyan("Active:"));
1254
1608
  for (const goal of active) {
1255
1609
  const progress = calculateGoalProgress(goal);
1256
1610
  const bar = renderProgressBar(progress);
1257
- const source = goal.autoGenerated ? pc3.dim("[auto]") : pc3.dim("[manual]");
1611
+ const source = goal.autoGenerated ? pc5.dim("[auto]") : pc5.dim("[manual]");
1258
1612
  console.error(` ${bar} ${goal.description} ${source}`);
1259
- console.error(pc3.dim(` ID: ${goal.id} | ${progress}% complete`));
1613
+ console.error(pc5.dim(` ID: ${goal.id} | ${progress}% complete`));
1260
1614
  }
1261
1615
  console.error("");
1262
1616
  }
1263
1617
  if (achieved.length > 0) {
1264
- console.error(pc3.green("Achieved:"));
1618
+ console.error(pc5.green("Achieved:"));
1265
1619
  for (const goal of achieved) {
1266
1620
  console.error(` [+] ${goal.description}`);
1267
1621
  }
1268
1622
  console.error("");
1269
1623
  }
1270
1624
  if (other.length > 0) {
1271
- console.error(pc3.dim("Other:"));
1625
+ console.error(pc5.dim("Other:"));
1272
1626
  for (const goal of other) {
1273
1627
  const icon = goal.status === "failed" ? "[X]" : goal.status === "paused" ? "[P]" : "\u2022";
1274
1628
  console.error(` ${icon} ${goal.description} (${goal.status})`);
@@ -1277,14 +1631,14 @@ async function listGoals(projectState) {
1277
1631
  }
1278
1632
  async function completeGoal(projectState, goalId) {
1279
1633
  if (!goalId) {
1280
- console.error(pc3.red("Please provide a goal ID."));
1281
- console.error(pc3.dim('Run "trie goal list" to see IDs.'));
1634
+ console.error(pc5.red("Please provide a goal ID."));
1635
+ console.error(pc5.dim('Run "trie goal list" to see IDs.'));
1282
1636
  return;
1283
1637
  }
1284
1638
  const goals = projectState.getAllGoals();
1285
1639
  const goal = goals.find((g) => g.id === goalId || g.id.startsWith(goalId));
1286
1640
  if (!goal) {
1287
- console.error(pc3.red(`Goal not found: ${goalId}`));
1641
+ console.error(pc5.red(`Goal not found: ${goalId}`));
1288
1642
  return;
1289
1643
  }
1290
1644
  await projectState.updateGoal(goal.id, {
@@ -1293,23 +1647,23 @@ async function completeGoal(projectState, goalId) {
1293
1647
  achievedAt: (/* @__PURE__ */ new Date()).toISOString()
1294
1648
  });
1295
1649
  console.error("");
1296
- console.error(pc3.green("Goal achieved!"));
1297
- console.error(pc3.bold(goal.description));
1650
+ console.error(pc5.green("Goal achieved!"));
1651
+ console.error(pc5.bold(goal.description));
1298
1652
  console.error("");
1299
1653
  }
1300
1654
  async function deleteGoal(projectState, goalId) {
1301
1655
  if (!goalId) {
1302
- console.error(pc3.red("Please provide a goal ID."));
1656
+ console.error(pc5.red("Please provide a goal ID."));
1303
1657
  return;
1304
1658
  }
1305
1659
  const goals = projectState.getAllGoals();
1306
1660
  const goal = goals.find((g) => g.id === goalId || g.id.startsWith(goalId));
1307
1661
  if (!goal) {
1308
- console.error(pc3.red(`Goal not found: ${goalId}`));
1662
+ console.error(pc5.red(`Goal not found: ${goalId}`));
1309
1663
  return;
1310
1664
  }
1311
1665
  await projectState.updateGoal(goal.id, { status: "rejected" });
1312
- console.error(pc3.dim(`Removed goal: ${goal.description}`));
1666
+ console.error(pc5.dim(`Removed goal: ${goal.description}`));
1313
1667
  }
1314
1668
  function calculateGoalProgress(goal) {
1315
1669
  if (goal.target <= 0) return 0;
@@ -1327,7 +1681,7 @@ function renderProgressBar(percent) {
1327
1681
  const clamped = Math.max(0, Math.min(100, percent));
1328
1682
  const filled = Math.round(clamped / 100 * width);
1329
1683
  const empty = width - filled;
1330
- return `[${pc3.green("\u2588".repeat(filled))}${pc3.gray("\u2591".repeat(empty))}]`;
1684
+ return `[${pc5.green("\u2588".repeat(filled))}${pc5.gray("\u2591".repeat(empty))}]`;
1331
1685
  }
1332
1686
  function detectCategory(description) {
1333
1687
  const lower = description.toLowerCase();
@@ -1339,20 +1693,20 @@ function detectCategory(description) {
1339
1693
  }
1340
1694
  function printGoalHelp() {
1341
1695
  console.error("");
1342
- console.error(pc3.bold("trie goal - Manage guardian goals"));
1696
+ console.error(pc5.bold("trie goal - Manage guardian goals"));
1343
1697
  console.error("");
1344
- console.error(pc3.cyan("Usage:"));
1698
+ console.error(pc5.cyan("Usage:"));
1345
1699
  console.error(' trie goal add "Reduce auth issues by 50%"');
1346
1700
  console.error(" trie goal list");
1347
1701
  console.error(" trie goal complete <id>");
1348
1702
  console.error(" trie goal delete <id>");
1349
1703
  console.error("");
1350
- console.error(pc3.cyan("Options for add:"));
1704
+ console.error(pc5.cyan("Options for add:"));
1351
1705
  console.error(" --category=security|quality|performance|coverage|general");
1352
1706
  console.error(" --target=<number>");
1353
1707
  console.error(" --deadline=<days>");
1354
1708
  console.error("");
1355
- console.error(pc3.cyan("Examples:"));
1709
+ console.error(pc5.cyan("Examples:"));
1356
1710
  console.error(' trie goal add "Eliminate all critical security issues"');
1357
1711
  console.error(' trie goal add "7 days streak of clean builds"');
1358
1712
  console.error(' trie goal add "Reduce test flakiness by 80%" --category=quality');
@@ -1394,8 +1748,8 @@ async function handleHypothesisCommand(args) {
1394
1748
  async function addHypothesis(projectState, args) {
1395
1749
  const statement = args.join(" ").replace(/^["']|["']$/g, "");
1396
1750
  if (!statement) {
1397
- console.error(pc3.red("Please provide a hypothesis statement."));
1398
- console.error(pc3.dim('Example: trie hypothesis add "Mondays have more bugs than Fridays"'));
1751
+ console.error(pc5.red("Please provide a hypothesis statement."));
1752
+ console.error(pc5.dim('Example: trie hypothesis add "Mondays have more bugs than Fridays"'));
1399
1753
  return;
1400
1754
  }
1401
1755
  const categoryMatch = statement.match(/--category[=\s](\w+)/);
@@ -1418,47 +1772,47 @@ async function addHypothesis(projectState, args) {
1418
1772
  };
1419
1773
  await projectState.addHypothesis(hypothesis);
1420
1774
  console.error("");
1421
- console.error(pc3.green("\u2713 Hypothesis created"));
1775
+ console.error(pc5.green("\u2713 Hypothesis created"));
1422
1776
  console.error("");
1423
- console.error(pc3.bold(`"${cleanStatement}"`));
1424
- console.error(pc3.dim(`ID: ${hypothesis.id}`));
1425
- console.error(pc3.dim(`Status: testing | Confidence: untested | Category: ${category}`));
1777
+ console.error(pc5.bold(`"${cleanStatement}"`));
1778
+ console.error(pc5.dim(`ID: ${hypothesis.id}`));
1779
+ console.error(pc5.dim(`Status: testing | Confidence: untested | Category: ${category}`));
1426
1780
  console.error("");
1427
- console.error(pc3.cyan("The agent will collect evidence and update confidence over time."));
1428
- console.error(pc3.dim(`Test criteria: ${testCriteria}`));
1781
+ console.error(pc5.cyan("The agent will collect evidence and update confidence over time."));
1782
+ console.error(pc5.dim(`Test criteria: ${testCriteria}`));
1429
1783
  }
1430
1784
  async function listHypotheses(projectState) {
1431
1785
  const hypotheses = projectState.getAllHypotheses();
1432
1786
  if (hypotheses.length === 0) {
1433
- console.error(pc3.dim("No hypotheses yet."));
1434
- console.error(pc3.dim('Create one: trie hypothesis add "Mondays have more bugs"'));
1787
+ console.error(pc5.dim("No hypotheses yet."));
1788
+ console.error(pc5.dim('Create one: trie hypothesis add "Mondays have more bugs"'));
1435
1789
  return;
1436
1790
  }
1437
1791
  console.error("");
1438
- console.error(pc3.bold("Hypotheses"));
1792
+ console.error(pc5.bold("Hypotheses"));
1439
1793
  console.error("");
1440
1794
  const testing = hypotheses.filter((h) => h.status === "testing");
1441
1795
  const validated = hypotheses.filter((h) => h.status === "validated");
1442
1796
  const invalidated = hypotheses.filter((h) => h.status === "invalidated");
1443
1797
  if (testing.length > 0) {
1444
- console.error(pc3.cyan("Testing:"));
1798
+ console.error(pc5.cyan("Testing:"));
1445
1799
  for (const hypo of testing) {
1446
1800
  const conf = Math.round(hypo.confidence * 100);
1447
- const confColor = conf >= 70 ? pc3.green : conf >= 40 ? pc3.yellow : pc3.red;
1801
+ const confColor = conf >= 70 ? pc5.green : conf >= 40 ? pc5.yellow : pc5.red;
1448
1802
  console.error(` [?] "${hypo.statement}" ${confColor(`(${conf}% confidence)`)}`);
1449
- console.error(pc3.dim(` ID: ${hypo.id} | Evidence: ${hypo.evidence.length} points`));
1803
+ console.error(pc5.dim(` ID: ${hypo.id} | Evidence: ${hypo.evidence.length} points`));
1450
1804
  }
1451
1805
  console.error("");
1452
1806
  }
1453
1807
  if (validated.length > 0) {
1454
- console.error(pc3.green("Validated:"));
1808
+ console.error(pc5.green("Validated:"));
1455
1809
  for (const hypo of validated) {
1456
1810
  console.error(` [+] "${hypo.statement}" (${Math.round(hypo.confidence * 100)}%)`);
1457
1811
  }
1458
1812
  console.error("");
1459
1813
  }
1460
1814
  if (invalidated.length > 0) {
1461
- console.error(pc3.red("Invalidated:"));
1815
+ console.error(pc5.red("Invalidated:"));
1462
1816
  for (const hypo of invalidated) {
1463
1817
  console.error(` [X] "${hypo.statement}"`);
1464
1818
  }
@@ -1466,13 +1820,13 @@ async function listHypotheses(projectState) {
1466
1820
  }
1467
1821
  async function validateHypothesis(projectState, hypoId) {
1468
1822
  if (!hypoId) {
1469
- console.error(pc3.red("Please provide a hypothesis ID."));
1823
+ console.error(pc5.red("Please provide a hypothesis ID."));
1470
1824
  return;
1471
1825
  }
1472
1826
  const hypotheses = projectState.getAllHypotheses();
1473
1827
  const hypo = hypotheses.find((h) => h.id === hypoId || h.id.startsWith(hypoId));
1474
1828
  if (!hypo) {
1475
- console.error(pc3.red(`Hypothesis not found: ${hypoId}`));
1829
+ console.error(pc5.red(`Hypothesis not found: ${hypoId}`));
1476
1830
  return;
1477
1831
  }
1478
1832
  await projectState.updateHypothesis(hypo.id, {
@@ -1480,38 +1834,38 @@ async function validateHypothesis(projectState, hypoId) {
1480
1834
  confidence: 0.9,
1481
1835
  validatedAt: (/* @__PURE__ */ new Date()).toISOString()
1482
1836
  });
1483
- console.error(pc3.green(`Hypothesis validated: "${hypo.statement}"`));
1837
+ console.error(pc5.green(`Hypothesis validated: "${hypo.statement}"`));
1484
1838
  }
1485
1839
  async function invalidateHypothesis(projectState, hypoId) {
1486
1840
  if (!hypoId) {
1487
- console.error(pc3.red("Please provide a hypothesis ID."));
1841
+ console.error(pc5.red("Please provide a hypothesis ID."));
1488
1842
  return;
1489
1843
  }
1490
1844
  const hypotheses = projectState.getAllHypotheses();
1491
1845
  const hypo = hypotheses.find((h) => h.id === hypoId || h.id.startsWith(hypoId));
1492
1846
  if (!hypo) {
1493
- console.error(pc3.red(`Hypothesis not found: ${hypoId}`));
1847
+ console.error(pc5.red(`Hypothesis not found: ${hypoId}`));
1494
1848
  return;
1495
1849
  }
1496
1850
  await projectState.updateHypothesis(hypo.id, {
1497
1851
  status: "invalidated",
1498
1852
  confidence: 0.1
1499
1853
  });
1500
- console.error(pc3.red(`Hypothesis invalidated: "${hypo.statement}"`));
1854
+ console.error(pc5.red(`Hypothesis invalidated: "${hypo.statement}"`));
1501
1855
  }
1502
1856
  async function deleteHypothesis(projectState, hypoId) {
1503
1857
  if (!hypoId) {
1504
- console.error(pc3.red("Please provide a hypothesis ID."));
1858
+ console.error(pc5.red("Please provide a hypothesis ID."));
1505
1859
  return;
1506
1860
  }
1507
1861
  const hypotheses = projectState.getAllHypotheses();
1508
1862
  const hypo = hypotheses.find((h) => h.id === hypoId || h.id.startsWith(hypoId));
1509
1863
  if (!hypo) {
1510
- console.error(pc3.red(`Hypothesis not found: ${hypoId}`));
1864
+ console.error(pc5.red(`Hypothesis not found: ${hypoId}`));
1511
1865
  return;
1512
1866
  }
1513
1867
  await projectState.updateHypothesis(hypo.id, { status: "retired" });
1514
- console.error(pc3.dim(`Removed hypothesis: "${hypo.statement}"`));
1868
+ console.error(pc5.dim(`Removed hypothesis: "${hypo.statement}"`));
1515
1869
  }
1516
1870
  function detectHypothesisCategory(statement) {
1517
1871
  const lower = statement.toLowerCase();
@@ -1539,20 +1893,20 @@ function generateTestCriteria(statement) {
1539
1893
  }
1540
1894
  function printHypothesisHelp() {
1541
1895
  console.error("");
1542
- console.error(pc3.bold("trie hypothesis - Manage project hypotheses"));
1896
+ console.error(pc5.bold("trie hypothesis - Manage project hypotheses"));
1543
1897
  console.error("");
1544
- console.error(pc3.cyan("Usage:"));
1898
+ console.error(pc5.cyan("Usage:"));
1545
1899
  console.error(' trie hypothesis add "Mondays have more bugs than Fridays"');
1546
1900
  console.error(" trie hypothesis list");
1547
1901
  console.error(" trie hypothesis validate <id>");
1548
1902
  console.error(" trie hypothesis invalidate <id>");
1549
1903
  console.error(" trie hypothesis delete <id>");
1550
1904
  console.error("");
1551
- console.error(pc3.cyan("Options for add:"));
1905
+ console.error(pc5.cyan("Options for add:"));
1552
1906
  console.error(" --category=timing|pattern|team|code|general");
1553
1907
  console.error(' --test="<test criteria>"');
1554
1908
  console.error("");
1555
- console.error(pc3.cyan("Examples:"));
1909
+ console.error(pc5.cyan("Examples:"));
1556
1910
  console.error(' trie hypothesis add "Code reviews reduce bug rate"');
1557
1911
  console.error(' trie hypothesis add "Auth module has highest churn"');
1558
1912
  console.error(' trie hypothesis add "Deploy Fridays cause weekend incidents"');
@@ -1677,9 +2031,9 @@ async function handleQuietCommand() {
1677
2031
  }
1678
2032
 
1679
2033
  // src/cli/ci.ts
1680
- import { writeFileSync, existsSync as existsSync3, mkdirSync } from "fs";
1681
- import { join } from "path";
1682
- import pc4 from "picocolors";
2034
+ import { writeFileSync, existsSync as existsSync5, mkdirSync } from "fs";
2035
+ import { join as join3 } from "path";
2036
+ import pc6 from "picocolors";
1683
2037
  var WORKFLOW_TEMPLATE = `# Trie Security Scan with Memory Persistence
1684
2038
  # Generated by: trie ci
1685
2039
  #
@@ -1769,84 +2123,84 @@ jobs:
1769
2123
  `;
1770
2124
  function handleCISetupCommand(args) {
1771
2125
  const workDir = getWorkingDirectory(void 0, true);
1772
- const workflowsDir = join(workDir, ".github", "workflows");
1773
- const workflowPath = join(workflowsDir, "trie-scan.yml");
2126
+ const workflowsDir = join3(workDir, ".github", "workflows");
2127
+ const workflowPath = join3(workflowsDir, "trie-scan.yml");
1774
2128
  const isMinimal = args.includes("--minimal") || args.includes("-m");
1775
2129
  const isDryRun = args.includes("--dry-run") || args.includes("-n");
1776
2130
  const showHelp3 = args.includes("--help") || args.includes("-h");
1777
2131
  if (showHelp3) {
1778
2132
  console.log(`
1779
- ${pc4.bold("trie ci")} - Generate GitHub Actions workflow with memory caching
2133
+ ${pc6.bold("trie ci")} - Generate GitHub Actions workflow with memory caching
1780
2134
 
1781
- ${pc4.bold("USAGE:")}
2135
+ ${pc6.bold("USAGE:")}
1782
2136
  trie ci [options]
1783
2137
 
1784
- ${pc4.bold("OPTIONS:")}
2138
+ ${pc6.bold("OPTIONS:")}
1785
2139
  --minimal, -m Generate minimal workflow (simpler, fewer features)
1786
2140
  --dry-run, -n Preview workflow without creating files
1787
2141
  --help, -h Show this help
1788
2142
 
1789
- ${pc4.bold("WHAT IT DOES:")}
2143
+ ${pc6.bold("WHAT IT DOES:")}
1790
2144
  Creates .github/workflows/trie-scan.yml that:
1791
2145
 
1792
- 1. ${pc4.green("Caches Trie memory")} - Patterns and fixes persist across runs
1793
- 2. ${pc4.green("Enables learning")} - Trie remembers issues from previous PRs
1794
- 3. ${pc4.green("Tracks patterns")} - Detects recurring issues across your codebase
1795
- 4. ${pc4.green("SARIF upload")} - Results appear in GitHub Security tab
2146
+ 1. ${pc6.green("Caches Trie memory")} - Patterns and fixes persist across runs
2147
+ 2. ${pc6.green("Enables learning")} - Trie remembers issues from previous PRs
2148
+ 3. ${pc6.green("Tracks patterns")} - Detects recurring issues across your codebase
2149
+ 4. ${pc6.green("SARIF upload")} - Results appear in GitHub Security tab
1796
2150
 
1797
- ${pc4.bold("MEMORY BENEFITS:")}
2151
+ ${pc6.bold("MEMORY BENEFITS:")}
1798
2152
  \u2022 "This issue was introduced 3 PRs ago"
1799
2153
  \u2022 "Similar issue was fixed in PR #42"
1800
2154
  \u2022 "This pattern keeps recurring in auth code"
1801
2155
  \u2022 Trend tracking: improving, stable, or declining
1802
2156
 
1803
- ${pc4.bold("EXAMPLES:")}
2157
+ ${pc6.bold("EXAMPLES:")}
1804
2158
  trie ci # Generate full workflow
1805
2159
  trie ci --minimal # Generate simple workflow
1806
2160
  trie ci --dry-run # Preview without writing
1807
2161
 
1808
- ${pc4.bold("REQUIRED SECRETS:")}
2162
+ ${pc6.bold("REQUIRED SECRETS:")}
1809
2163
  ANTHROPIC_API_KEY Your Anthropic API key (add in GitHub repo settings)
1810
2164
  `);
1811
2165
  return;
1812
2166
  }
1813
2167
  const template = isMinimal ? WORKFLOW_MINIMAL : WORKFLOW_TEMPLATE;
1814
2168
  if (isDryRun) {
1815
- console.log(pc4.bold("\nWorkflow Preview:\n"));
1816
- console.log(pc4.dim("\u2500".repeat(60)));
2169
+ console.log(pc6.bold("\nWorkflow Preview:\n"));
2170
+ console.log(pc6.dim("\u2500".repeat(60)));
1817
2171
  console.log(template);
1818
- console.log(pc4.dim("\u2500".repeat(60)));
1819
- console.log(pc4.dim("\nRun without --dry-run to create the file."));
2172
+ console.log(pc6.dim("\u2500".repeat(60)));
2173
+ console.log(pc6.dim("\nRun without --dry-run to create the file."));
1820
2174
  return;
1821
2175
  }
1822
- if (existsSync3(workflowPath)) {
1823
- console.log(pc4.yellow("Workflow already exists: .github/workflows/trie-scan.yml"));
1824
- console.log(pc4.dim(" Run with --dry-run to preview what would be written."));
1825
- console.log(pc4.dim(" Delete the existing file to regenerate."));
2176
+ if (existsSync5(workflowPath)) {
2177
+ console.log(pc6.yellow("Workflow already exists: .github/workflows/trie-scan.yml"));
2178
+ console.log(pc6.dim(" Run with --dry-run to preview what would be written."));
2179
+ console.log(pc6.dim(" Delete the existing file to regenerate."));
1826
2180
  return;
1827
2181
  }
1828
- if (!existsSync3(workflowsDir)) {
2182
+ if (!existsSync5(workflowsDir)) {
1829
2183
  mkdirSync(workflowsDir, { recursive: true });
1830
2184
  }
1831
2185
  writeFileSync(workflowPath, template);
1832
- console.log(pc4.green("\u2713") + " Created .github/workflows/trie-scan.yml");
2186
+ console.log(pc6.green("\u2713") + " Created .github/workflows/trie-scan.yml");
1833
2187
  console.log("");
1834
- console.log(pc4.bold("Next steps:"));
2188
+ console.log(pc6.bold("Next steps:"));
1835
2189
  console.log("");
1836
2190
  console.log(" 1. Add your Anthropic API key to GitHub Secrets:");
1837
- console.log(pc4.dim(" Settings \u2192 Secrets \u2192 Actions \u2192 New repository secret"));
1838
- console.log(pc4.dim(" Name: ANTHROPIC_API_KEY"));
2191
+ console.log(pc6.dim(" Settings \u2192 Secrets \u2192 Actions \u2192 New repository secret"));
2192
+ console.log(pc6.dim(" Name: ANTHROPIC_API_KEY"));
1839
2193
  console.log("");
1840
2194
  console.log(" 2. Commit and push:");
1841
- console.log(pc4.dim(" git add .github/workflows/trie-scan.yml"));
1842
- console.log(pc4.dim(' git commit -m "Add Trie security scan with memory"'));
1843
- console.log(pc4.dim(" git push"));
2195
+ console.log(pc6.dim(" git add .github/workflows/trie-scan.yml"));
2196
+ console.log(pc6.dim(' git commit -m "Add Trie security scan with memory"'));
2197
+ console.log(pc6.dim(" git push"));
1844
2198
  console.log("");
1845
- console.log(pc4.bold("Memory caching benefits:"));
1846
- console.log(pc4.dim(" \u2022 Trie learns from past scans"));
1847
- console.log(pc4.dim(" \u2022 Tracks issue trends over time"));
1848
- console.log(pc4.dim(" \u2022 Remembers when issues were introduced"));
1849
- console.log(pc4.dim(" \u2022 Recognizes recurring patterns"));
2199
+ console.log(pc6.bold("Memory caching benefits:"));
2200
+ console.log(pc6.dim(" \u2022 Trie learns from past scans"));
2201
+ console.log(pc6.dim(" \u2022 Tracks issue trends over time"));
2202
+ console.log(pc6.dim(" \u2022 Remembers when issues were introduced"));
2203
+ console.log(pc6.dim(" \u2022 Recognizes recurring patterns"));
1850
2204
  }
1851
2205
 
1852
2206
  // src/cli/audit.ts
@@ -2091,20 +2445,20 @@ async function handleLearnCommand(args) {
2091
2445
  }
2092
2446
 
2093
2447
  // src/cli/patterns.ts
2094
- import { readFile as readFile4, writeFile as writeFile3 } from "fs/promises";
2095
- import { existsSync as existsSync5 } from "fs";
2448
+ import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
2449
+ import { existsSync as existsSync7 } from "fs";
2096
2450
  import { basename as basename2 } from "path";
2097
2451
  import picocolors3 from "picocolors";
2098
2452
 
2099
2453
  // src/patterns/saved-patterns.ts
2100
2454
  import { createHash } from "crypto";
2101
- import { readFile as readFile3, writeFile as writeFile2 } from "fs/promises";
2102
- import { existsSync as existsSync4 } from "fs";
2103
- import { join as join2, basename } from "path";
2455
+ import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
2456
+ import { existsSync as existsSync6 } from "fs";
2457
+ import { join as join4, basename } from "path";
2104
2458
  async function loadSavedPatterns(workDir) {
2105
- const patternsPath = join2(getTrieDirectory(workDir), "saved-patterns.json");
2459
+ const patternsPath = join4(getTrieDirectory(workDir), "saved-patterns.json");
2106
2460
  try {
2107
- if (existsSync4(patternsPath)) {
2461
+ if (existsSync6(patternsPath)) {
2108
2462
  const content = await readFile3(patternsPath, "utf-8");
2109
2463
  return JSON.parse(content);
2110
2464
  }
@@ -2114,9 +2468,9 @@ async function loadSavedPatterns(workDir) {
2114
2468
  }
2115
2469
  async function savePatternsToProject(patterns, workDir) {
2116
2470
  const { mkdir: mkdir2 } = await import("fs/promises");
2117
- const patternsPath = join2(getTrieDirectory(workDir), "saved-patterns.json");
2471
+ const patternsPath = join4(getTrieDirectory(workDir), "saved-patterns.json");
2118
2472
  await mkdir2(getTrieDirectory(workDir), { recursive: true });
2119
- await writeFile2(patternsPath, JSON.stringify(patterns, null, 2));
2473
+ await writeFile3(patternsPath, JSON.stringify(patterns, null, 2));
2120
2474
  }
2121
2475
  async function savePatternToProject(pattern, workDir) {
2122
2476
  const patterns = await loadSavedPatterns(workDir);
@@ -2151,8 +2505,8 @@ function detectPatternType(target, workDir) {
2151
2505
  if (scoutNames.includes(target.toLowerCase())) {
2152
2506
  return "detection-rule";
2153
2507
  }
2154
- const fullPath = join2(workDir, target);
2155
- if (existsSync4(fullPath) || target.includes("/") || target.includes("*") || target.endsWith(".ts") || target.endsWith(".js")) {
2508
+ const fullPath = join4(workDir, target);
2509
+ if (existsSync6(fullPath) || target.includes("/") || target.includes("*") || target.endsWith(".ts") || target.endsWith(".js")) {
2156
2510
  return "file-structure";
2157
2511
  }
2158
2512
  return "code-pattern";
@@ -2310,7 +2664,7 @@ async function handleExportPatterns(args, workDir) {
2310
2664
  exportedFrom: basename2(workDir),
2311
2665
  patterns
2312
2666
  };
2313
- await writeFile3(outputPath, JSON.stringify(exportData, null, 2));
2667
+ await writeFile4(outputPath, JSON.stringify(exportData, null, 2));
2314
2668
  console.log(picocolors3.green(`\u2713 Exported ${patterns.length} patterns to ${outputPath}`));
2315
2669
  console.log(picocolors3.dim(` Import to another project with: trie patterns import ${outputPath}`));
2316
2670
  }
@@ -2320,7 +2674,7 @@ async function handleImportPatterns(args, workDir) {
2320
2674
  console.error(picocolors3.red("Usage: trie patterns import <path-to-patterns.json>"));
2321
2675
  process.exit(1);
2322
2676
  }
2323
- if (!existsSync5(inputPath)) {
2677
+ if (!existsSync7(inputPath)) {
2324
2678
  console.error(picocolors3.red(`File not found: ${inputPath}`));
2325
2679
  process.exit(1);
2326
2680
  }
@@ -2417,95 +2771,8 @@ ${picocolors3.dim("Patterns are saved in .trie/saved-patterns.json")}
2417
2771
  }
2418
2772
 
2419
2773
  // src/cli/sync.ts
2420
- import pc6 from "picocolors";
2774
+ import pc7 from "picocolors";
2421
2775
  import { Command } from "commander";
2422
-
2423
- // src/cli/hooks.ts
2424
- import { writeFile as writeFile4, mkdir, chmod } from "fs/promises";
2425
- import { join as join3 } from "path";
2426
- import { existsSync as existsSync6 } from "fs";
2427
- import pc5 from "picocolors";
2428
- async function installGitHooks2() {
2429
- const workDir = getWorkingDirectory(void 0, true);
2430
- const isRepo = await isGitRepo(workDir);
2431
- if (!isRepo) {
2432
- console.log(pc5.yellow("\u26A0 Not a git repository. Git hooks not installed."));
2433
- return;
2434
- }
2435
- const hooksDir = join3(workDir, ".git", "hooks");
2436
- if (!existsSync6(hooksDir)) {
2437
- await mkdir(hooksDir, { recursive: true });
2438
- }
2439
- const prePushHook = `#!/bin/sh
2440
- # Auto-sync ledger to shared storage before push
2441
-
2442
- # Only run if trie is initialized
2443
- if [ ! -d ".trie" ]; then
2444
- exit 0
2445
- fi
2446
-
2447
- # Check if trie command is available
2448
- if ! command -v trie >/dev/null 2>&1; then
2449
- echo "Warning: trie command not found, skipping ledger sync"
2450
- exit 0
2451
- fi
2452
-
2453
- # Sync ledger to shared storage
2454
- echo "Syncing ledger to shared storage..."
2455
- trie sync push 2>/dev/null || true
2456
-
2457
- exit 0
2458
- `;
2459
- const postMergeHook = `#!/bin/sh
2460
- # Auto-sync ledger from shared storage after merge
2461
-
2462
- # Only run if trie is initialized
2463
- if [ ! -d ".trie" ]; then
2464
- exit 0
2465
- fi
2466
-
2467
- # Check if trie command is available
2468
- if ! command -v trie >/dev/null 2>&1; then
2469
- exit 0
2470
- fi
2471
-
2472
- # Sync ledger from shared storage
2473
- echo "Syncing ledger from shared storage..."
2474
- trie sync pull 2>/dev/null || true
2475
-
2476
- exit 0
2477
- `;
2478
- const prePushPath = join3(hooksDir, "pre-push");
2479
- const postMergePath = join3(hooksDir, "post-merge");
2480
- await writeFile4(prePushPath, prePushHook);
2481
- await writeFile4(postMergePath, postMergeHook);
2482
- await chmod(prePushPath, 493);
2483
- await chmod(postMergePath, 493);
2484
- console.log(pc5.green("\u2713 Git hooks installed successfully"));
2485
- console.log(pc5.dim(" pre-push: Syncs ledger to shared storage"));
2486
- console.log(pc5.dim(" post-merge: Syncs ledger from shared storage"));
2487
- }
2488
- async function checkGitHooks() {
2489
- const workDir = getWorkingDirectory(void 0, true);
2490
- const isRepo = await isGitRepo(workDir);
2491
- if (!isRepo) {
2492
- return {
2493
- isGitRepo: false,
2494
- prePushInstalled: false,
2495
- postMergeInstalled: false
2496
- };
2497
- }
2498
- const hooksDir = join3(workDir, ".git", "hooks");
2499
- const prePushPath = join3(hooksDir, "pre-push");
2500
- const postMergePath = join3(hooksDir, "post-merge");
2501
- return {
2502
- isGitRepo: true,
2503
- prePushInstalled: existsSync6(prePushPath),
2504
- postMergeInstalled: existsSync6(postMergePath)
2505
- };
2506
- }
2507
-
2508
- // src/cli/sync.ts
2509
2776
  function createSyncCommand() {
2510
2777
  const sync = new Command("sync").description("Sync ledger with shared storage");
2511
2778
  sync.command("init").description("Initialize shared ledger storage").action(async () => {
@@ -2513,9 +2780,9 @@ function createSyncCommand() {
2513
2780
  const workDir = getWorkingDirectory(void 0, true);
2514
2781
  console.log(`Initializing shared ledger in ${workDir}...`);
2515
2782
  await initializeSharedLedger();
2516
- console.log(pc6.green("\u2713 Shared ledger initialized successfully"));
2783
+ console.log(pc7.green("\u2713 Shared ledger initialized successfully"));
2517
2784
  } catch (error) {
2518
- console.error(pc6.red("Failed to initialize shared ledger:"), error);
2785
+ console.error(pc7.red("Failed to initialize shared ledger:"), error);
2519
2786
  process.exit(1);
2520
2787
  }
2521
2788
  });
@@ -2528,17 +2795,17 @@ function createSyncCommand() {
2528
2795
  await migrateLegacyLedger();
2529
2796
  }
2530
2797
  const result = await syncLedgerFromShared();
2531
- console.log(pc6.green("\u2713 Sync completed"));
2798
+ console.log(pc7.green("\u2713 Sync completed"));
2532
2799
  console.log(`Merged ${result.stats.mergedBlocks} blocks`);
2533
2800
  if (result.conflicts.length > 0) {
2534
- console.log(pc6.yellow(`\u26A0 ${result.conflicts.length} conflicts detected`));
2801
+ console.log(pc7.yellow(`\u26A0 ${result.conflicts.length} conflicts detected`));
2535
2802
  console.log('Run "trie sync status" to see details');
2536
2803
  }
2537
2804
  if (result.stats.duplicatesRemoved > 0) {
2538
2805
  console.log(`Removed ${result.stats.duplicatesRemoved} duplicate entries`);
2539
2806
  }
2540
2807
  } catch (error) {
2541
- console.error(pc6.red("Failed to sync from shared ledger:"), error);
2808
+ console.error(pc7.red("Failed to sync from shared ledger:"), error);
2542
2809
  process.exit(1);
2543
2810
  }
2544
2811
  });
@@ -2551,45 +2818,45 @@ function createSyncCommand() {
2551
2818
  await migrateLegacyLedger();
2552
2819
  }
2553
2820
  await pushLedgerToShared();
2554
- console.log(pc6.green("\u2713 Push completed"));
2821
+ console.log(pc7.green("\u2713 Push completed"));
2555
2822
  } catch (error) {
2556
- console.error(pc6.red("Failed to push to shared ledger:"), error);
2823
+ console.error(pc7.red("Failed to push to shared ledger:"), error);
2557
2824
  process.exit(1);
2558
2825
  }
2559
2826
  });
2560
2827
  sync.command("status").description("Show ledger sync status").action(async () => {
2561
2828
  try {
2562
2829
  const status = await getLedgerSyncStatus();
2563
- console.log(pc6.bold("Ledger Sync Status\n"));
2830
+ console.log(pc7.bold("Ledger Sync Status\n"));
2564
2831
  if (!status.isInitialized) {
2565
- console.log(pc6.yellow('\u26A0 Shared ledger not initialized. Run "trie sync init" first.'));
2832
+ console.log(pc7.yellow('\u26A0 Shared ledger not initialized. Run "trie sync init" first.'));
2566
2833
  return;
2567
2834
  }
2568
2835
  if (status.hasLegacyLedger) {
2569
- console.log(pc6.yellow('\u26A0 Legacy ledger detected. Run "trie sync pull" to migrate.'));
2836
+ console.log(pc7.yellow('\u26A0 Legacy ledger detected. Run "trie sync pull" to migrate.'));
2570
2837
  }
2571
- console.log(`Local blocks: ${pc6.cyan(status.localBlocks.toString())}`);
2572
- console.log(`Shared blocks: ${pc6.cyan(status.sharedBlocks.toString())}`);
2838
+ console.log(`Local blocks: ${pc7.cyan(status.localBlocks.toString())}`);
2839
+ console.log(`Shared blocks: ${pc7.cyan(status.sharedBlocks.toString())}`);
2573
2840
  if (status.syncState) {
2574
2841
  const lastSync = new Date(status.syncState.lastSyncTimestamp);
2575
- console.log(`Last sync: ${pc6.dim(lastSync.toLocaleString())}`);
2842
+ console.log(`Last sync: ${pc7.dim(lastSync.toLocaleString())}`);
2576
2843
  if (status.conflicts > 0) {
2577
- console.log(pc6.yellow(`Conflicts: ${status.conflicts}`));
2844
+ console.log(pc7.yellow(`Conflicts: ${status.conflicts}`));
2578
2845
  console.log("\nConflicts:");
2579
2846
  for (const conflict of status.syncState.conflicts) {
2580
2847
  console.log(` \u2022 ${conflict.type}: ${conflict.description}`);
2581
2848
  }
2582
2849
  } else {
2583
- console.log(pc6.green("\u2713 No conflicts"));
2850
+ console.log(pc7.green("\u2713 No conflicts"));
2584
2851
  }
2585
2852
  }
2586
2853
  if (status.manifest) {
2587
2854
  console.log(`
2588
- Total entries: ${pc6.cyan(status.manifest.totalEntries.toString())}`);
2589
- console.log(`Compression: ${status.manifest.compressionConfig.enabled ? pc6.green("enabled") : pc6.red("disabled")}`);
2855
+ Total entries: ${pc7.cyan(status.manifest.totalEntries.toString())}`);
2856
+ console.log(`Compression: ${status.manifest.compressionConfig.enabled ? pc7.green("enabled") : pc7.red("disabled")}`);
2590
2857
  }
2591
2858
  } catch (error) {
2592
- console.error(pc6.red("Failed to get sync status:"), error);
2859
+ console.error(pc7.red("Failed to get sync status:"), error);
2593
2860
  process.exit(1);
2594
2861
  }
2595
2862
  });
@@ -2597,19 +2864,19 @@ Total entries: ${pc6.cyan(status.manifest.totalEntries.toString())}`);
2597
2864
  try {
2598
2865
  const hasLegacy = await detectLegacyLedger();
2599
2866
  if (!hasLegacy) {
2600
- console.log(pc6.yellow("No legacy ledger found to migrate"));
2867
+ console.log(pc7.yellow("No legacy ledger found to migrate"));
2601
2868
  return;
2602
2869
  }
2603
2870
  console.log("Migrating legacy ledger...");
2604
2871
  const success = await migrateLegacyLedger();
2605
2872
  if (success) {
2606
- console.log(pc6.green("\u2713 Migration completed successfully"));
2873
+ console.log(pc7.green("\u2713 Migration completed successfully"));
2607
2874
  } else {
2608
- console.log(pc6.red("Migration failed"));
2875
+ console.log(pc7.red("Migration failed"));
2609
2876
  process.exit(1);
2610
2877
  }
2611
2878
  } catch (error) {
2612
- console.error(pc6.red("Failed to migrate legacy ledger:"), error);
2879
+ console.error(pc7.red("Failed to migrate legacy ledger:"), error);
2613
2880
  process.exit(1);
2614
2881
  }
2615
2882
  });
@@ -2621,18 +2888,18 @@ Total entries: ${pc6.cyan(status.manifest.totalEntries.toString())}`);
2621
2888
  }
2622
2889
  const status = await checkGitHooks();
2623
2890
  if (!status.isGitRepo) {
2624
- console.log(pc6.yellow("Not a git repository"));
2891
+ console.log(pc7.yellow("Not a git repository"));
2625
2892
  return;
2626
2893
  }
2627
- console.log(pc6.bold("Git Hooks Status\n"));
2628
- console.log(`Pre-push hook: ${status.prePushInstalled ? pc6.green("\u2713 installed") : pc6.red("\u2717 not installed")}`);
2629
- console.log(`Post-merge hook: ${status.postMergeInstalled ? pc6.green("\u2713 installed") : pc6.red("\u2717 not installed")}`);
2894
+ console.log(pc7.bold("Git Hooks Status\n"));
2895
+ console.log(`Pre-push hook: ${status.prePushInstalled ? pc7.green("\u2713 installed") : pc7.red("\u2717 not installed")}`);
2896
+ console.log(`Post-merge hook: ${status.postMergeInstalled ? pc7.green("\u2713 installed") : pc7.red("\u2717 not installed")}`);
2630
2897
  if (!status.prePushInstalled || !status.postMergeInstalled) {
2631
2898
  console.log(`
2632
- ${pc6.yellow("\u{1F4A1} Tip:")} Run ${pc6.bold("trie sync hooks --install")} to install missing hooks`);
2899
+ ${pc7.yellow("\u{1F4A1} Tip:")} Run ${pc7.bold("trie sync hooks --install")} to install missing hooks`);
2633
2900
  }
2634
2901
  } catch (error) {
2635
- console.error(pc6.red("Failed to manage git hooks:"), error);
2902
+ console.error(pc7.red("Failed to manage git hooks:"), error);
2636
2903
  process.exit(1);
2637
2904
  }
2638
2905
  });
@@ -2640,7 +2907,7 @@ ${pc6.yellow("\u{1F4A1} Tip:")} Run ${pc6.bold("trie sync hooks --install")} to
2640
2907
  }
2641
2908
 
2642
2909
  // src/cli/ledger.ts
2643
- import pc7 from "picocolors";
2910
+ import pc8 from "picocolors";
2644
2911
  import { Command as Command2 } from "commander";
2645
2912
  function createLedgerCommand() {
2646
2913
  const ledger = new Command2("ledger").description("Manage and inspect the ledger");
@@ -2649,13 +2916,13 @@ function createLedgerCommand() {
2649
2916
  console.log("Verifying ledger chain...");
2650
2917
  const result = await verifyLedger();
2651
2918
  if (result.valid) {
2652
- console.log(pc7.green("\u2713 Ledger chain is valid"));
2919
+ console.log(pc8.green("\u2713 Ledger chain is valid"));
2653
2920
  } else {
2654
- console.log(pc7.red(`\u2717 Ledger chain is invalid: ${result.error}`));
2921
+ console.log(pc8.red(`\u2717 Ledger chain is invalid: ${result.error}`));
2655
2922
  process.exit(1);
2656
2923
  }
2657
2924
  } catch (error) {
2658
- console.error(pc7.red("Failed to verify ledger:"), error);
2925
+ console.error(pc8.red("Failed to verify ledger:"), error);
2659
2926
  process.exit(1);
2660
2927
  }
2661
2928
  });
@@ -2667,20 +2934,20 @@ function createLedgerCommand() {
2667
2934
  console.log("No ledger blocks found");
2668
2935
  return;
2669
2936
  }
2670
- console.log(pc7.bold(`Ledger History (last ${Math.min(limit, blocks.length)} blocks)
2937
+ console.log(pc8.bold(`Ledger History (last ${Math.min(limit, blocks.length)} blocks)
2671
2938
  `));
2672
2939
  const recentBlocks = blocks.slice(-limit).reverse();
2673
2940
  for (const block of recentBlocks) {
2674
2941
  const syncableBlock = block;
2675
- console.log(pc7.bold(pc7.cyan(`Block ${block.date}`)));
2942
+ console.log(pc8.bold(pc8.cyan(`Block ${block.date}`)));
2676
2943
  if (syncableBlock.author) {
2677
- console.log(`Author: ${pc7.dim(syncableBlock.author)}`);
2944
+ console.log(`Author: ${pc8.dim(syncableBlock.author)}`);
2678
2945
  }
2679
2946
  if (syncableBlock.gitCommit) {
2680
- console.log(`Git: ${pc7.dim(syncableBlock.gitCommit.slice(0, 8))}`);
2947
+ console.log(`Git: ${pc8.dim(syncableBlock.gitCommit.slice(0, 8))}`);
2681
2948
  }
2682
2949
  console.log(`Entries: ${block.entries.length}`);
2683
- console.log(`Hash: ${pc7.dim(block.blockHash.slice(0, 16))}...`);
2950
+ console.log(`Hash: ${pc8.dim(block.blockHash.slice(0, 16))}...`);
2684
2951
  if (block.entries.length > 0) {
2685
2952
  console.log("Issues:");
2686
2953
  for (const entry of block.entries) {
@@ -2690,7 +2957,7 @@ function createLedgerCommand() {
2690
2957
  console.log("");
2691
2958
  }
2692
2959
  } catch (error) {
2693
- console.error(pc7.red("Failed to show ledger history:"), error);
2960
+ console.error(pc8.red("Failed to show ledger history:"), error);
2694
2961
  process.exit(1);
2695
2962
  }
2696
2963
  });
@@ -2698,22 +2965,22 @@ function createLedgerCommand() {
2698
2965
  try {
2699
2966
  const status = await getLedgerSyncStatus();
2700
2967
  const blocks = await getLedgerBlocks();
2701
- console.log(pc7.bold("Ledger Statistics\n"));
2702
- console.log(`Total blocks: ${pc7.cyan(blocks.length.toString())}`);
2968
+ console.log(pc8.bold("Ledger Statistics\n"));
2969
+ console.log(`Total blocks: ${pc8.cyan(blocks.length.toString())}`);
2703
2970
  if (status.manifest) {
2704
- console.log(`Total entries: ${pc7.cyan(status.manifest.totalEntries.toString())}`);
2705
- console.log(`Active blocks: ${pc7.cyan(status.manifest.activeBlocks.length.toString())}`);
2706
- console.log(`Archived blocks: ${pc7.cyan(status.manifest.archivedBlocks.length.toString())}`);
2971
+ console.log(`Total entries: ${pc8.cyan(status.manifest.totalEntries.toString())}`);
2972
+ console.log(`Active blocks: ${pc8.cyan(status.manifest.activeBlocks.length.toString())}`);
2973
+ console.log(`Archived blocks: ${pc8.cyan(status.manifest.archivedBlocks.length.toString())}`);
2707
2974
  if (status.manifest.compressionConfig.enabled) {
2708
2975
  const hotSize = Math.round(status.manifest.compressionConfig.maxHotStorageSize / 1024 / 1024);
2709
- console.log(`Hot storage limit: ${pc7.cyan(`${hotSize}MB`)}`);
2710
- console.log(`Archive after: ${pc7.cyan(`${status.manifest.compressionConfig.archiveAfterDays} days`)}`);
2976
+ console.log(`Hot storage limit: ${pc8.cyan(`${hotSize}MB`)}`);
2977
+ console.log(`Archive after: ${pc8.cyan(`${status.manifest.compressionConfig.archiveAfterDays} days`)}`);
2711
2978
  }
2712
2979
  }
2713
2980
  if (blocks.length > 0) {
2714
2981
  const firstBlock = blocks[0];
2715
2982
  const lastBlock = blocks[blocks.length - 1];
2716
- console.log(`Date range: ${pc7.dim(`${firstBlock.date} to ${lastBlock.date}`)}`);
2983
+ console.log(`Date range: ${pc8.dim(`${firstBlock.date} to ${lastBlock.date}`)}`);
2717
2984
  }
2718
2985
  const authorCounts = /* @__PURE__ */ new Map();
2719
2986
  for (const block of blocks) {
@@ -2726,7 +2993,7 @@ function createLedgerCommand() {
2726
2993
  console.log("\nBlocks by author:");
2727
2994
  const sortedAuthors = Array.from(authorCounts.entries()).sort((a, b) => b[1] - a[1]);
2728
2995
  for (const [author, count] of sortedAuthors.slice(0, 10)) {
2729
- console.log(` ${author}: ${pc7.cyan(count.toString())}`);
2996
+ console.log(` ${author}: ${pc8.cyan(count.toString())}`);
2730
2997
  }
2731
2998
  }
2732
2999
  const severityCounts = /* @__PURE__ */ new Map();
@@ -2741,39 +3008,39 @@ function createLedgerCommand() {
2741
3008
  for (const severity of severityOrder) {
2742
3009
  const count = severityCounts.get(severity);
2743
3010
  if (count) {
2744
- const color = severity === "critical" ? pc7.red : severity === "high" ? pc7.yellow : severity === "medium" ? pc7.blue : pc7.gray;
2745
- console.log(` ${color(severity)}: ${pc7.cyan(count.toString())}`);
3011
+ const color = severity === "critical" ? pc8.red : severity === "high" ? pc8.yellow : severity === "medium" ? pc8.blue : pc8.gray;
3012
+ console.log(` ${color(severity)}: ${pc8.cyan(count.toString())}`);
2746
3013
  }
2747
3014
  }
2748
3015
  }
2749
3016
  } catch (error) {
2750
- console.error(pc7.red("Failed to show ledger stats:"), error);
3017
+ console.error(pc8.red("Failed to show ledger stats:"), error);
2751
3018
  process.exit(1);
2752
3019
  }
2753
3020
  });
2754
3021
  ledger.command("diff").description("Compare local and shared ledger state").action(async () => {
2755
3022
  try {
2756
3023
  const status = await getLedgerSyncStatus();
2757
- console.log(pc7.bold("Ledger Diff\n"));
3024
+ console.log(pc8.bold("Ledger Diff\n"));
2758
3025
  if (!status.isInitialized) {
2759
- console.log(pc7.yellow("Shared ledger not initialized"));
3026
+ console.log(pc8.yellow("Shared ledger not initialized"));
2760
3027
  return;
2761
3028
  }
2762
- console.log(`Local blocks: ${pc7.cyan(status.localBlocks.toString())}`);
2763
- console.log(`Shared blocks: ${pc7.cyan(status.sharedBlocks.toString())}`);
3029
+ console.log(`Local blocks: ${pc8.cyan(status.localBlocks.toString())}`);
3030
+ console.log(`Shared blocks: ${pc8.cyan(status.sharedBlocks.toString())}`);
2764
3031
  const diff = status.sharedBlocks - status.localBlocks;
2765
3032
  if (diff > 0) {
2766
- console.log(pc7.green(`\u2193 ${diff} blocks available to pull`));
3033
+ console.log(pc8.green(`\u2193 ${diff} blocks available to pull`));
2767
3034
  } else if (diff < 0) {
2768
- console.log(pc7.blue(`\u2191 ${-diff} local blocks not yet pushed`));
3035
+ console.log(pc8.blue(`\u2191 ${-diff} local blocks not yet pushed`));
2769
3036
  } else {
2770
- console.log(pc7.green("\u2713 Local and shared ledgers are in sync"));
3037
+ console.log(pc8.green("\u2713 Local and shared ledgers are in sync"));
2771
3038
  }
2772
3039
  if (status.conflicts > 0) {
2773
- console.log(pc7.red(`\u26A0 ${status.conflicts} conflicts detected`));
3040
+ console.log(pc8.red(`\u26A0 ${status.conflicts} conflicts detected`));
2774
3041
  }
2775
3042
  } catch (error) {
2776
- console.error(pc7.red("Failed to diff ledgers:"), error);
3043
+ console.error(pc8.red("Failed to diff ledgers:"), error);
2777
3044
  process.exit(1);
2778
3045
  }
2779
3046
  });
@@ -2787,42 +3054,42 @@ function createLedgerCommand() {
2787
3054
  console.log("Compressing old ledger blocks...");
2788
3055
  const result = await compressOldBlocks();
2789
3056
  if (result.archived > 0) {
2790
- console.log(pc7.green(`\u2713 Compressed ${result.archived} blocks`));
3057
+ console.log(pc8.green(`\u2713 Compressed ${result.archived} blocks`));
2791
3058
  console.log(`Space saved: ${result.sizeReduction}%`);
2792
3059
  } else {
2793
3060
  console.log("No blocks were archived");
2794
3061
  }
2795
3062
  } catch (error) {
2796
- console.error(pc7.red("Failed to compress blocks:"), error);
3063
+ console.error(pc8.red("Failed to compress blocks:"), error);
2797
3064
  process.exit(1);
2798
3065
  }
2799
3066
  });
2800
3067
  ledger.command("storage").description("Show detailed storage statistics").action(async () => {
2801
3068
  try {
2802
3069
  const stats = await getStorageStats();
2803
- console.log(pc7.bold("Ledger Storage Statistics\n"));
2804
- console.log(pc7.bold("Block Storage:"));
2805
- console.log(` Active blocks: ${pc7.cyan(stats.activeBlocks.toString())}`);
2806
- console.log(` Archived blocks: ${pc7.cyan(stats.archivedBlocks.toString())}`);
2807
- console.log(pc7.bold("\nStorage Usage:"));
3070
+ console.log(pc8.bold("Ledger Storage Statistics\n"));
3071
+ console.log(pc8.bold("Block Storage:"));
3072
+ console.log(` Active blocks: ${pc8.cyan(stats.activeBlocks.toString())}`);
3073
+ console.log(` Archived blocks: ${pc8.cyan(stats.archivedBlocks.toString())}`);
3074
+ console.log(pc8.bold("\nStorage Usage:"));
2808
3075
  const activeMB = (stats.activeSize / 1024 / 1024).toFixed(2);
2809
3076
  const archivedMB = (stats.archivedSize / 1024 / 1024).toFixed(2);
2810
3077
  const totalMB = (Number(activeMB) + Number(archivedMB)).toFixed(2);
2811
- console.log(` Active storage: ${pc7.cyan(`${activeMB} MB`)}`);
2812
- console.log(` Archived storage: ${pc7.cyan(`${archivedMB} MB`)}`);
2813
- console.log(` Total storage: ${pc7.bold(pc7.cyan(`${totalMB} MB`))}`);
3078
+ console.log(` Active storage: ${pc8.cyan(`${activeMB} MB`)}`);
3079
+ console.log(` Archived storage: ${pc8.cyan(`${archivedMB} MB`)}`);
3080
+ console.log(` Total storage: ${pc8.bold(pc8.cyan(`${totalMB} MB`))}`);
2814
3081
  if (stats.compressionRatio > 0) {
2815
- console.log(` Compression ratio: ${pc7.green(`${stats.compressionRatio}%`)}`);
3082
+ console.log(` Compression ratio: ${pc8.green(`${stats.compressionRatio}%`)}`);
2816
3083
  }
2817
- console.log(pc7.bold("\nData:"));
2818
- console.log(` Total entries: ${pc7.cyan(stats.totalEntries.toString())}`);
3084
+ console.log(pc8.bold("\nData:"));
3085
+ console.log(` Total entries: ${pc8.cyan(stats.totalEntries.toString())}`);
2819
3086
  const needsCompression = await shouldCompress();
2820
3087
  if (needsCompression) {
2821
3088
  console.log(`
2822
- ${pc7.yellow("\u{1F4A1} Tip:")} Run ${pc7.bold("trie ledger compress")} to archive old blocks`);
3089
+ ${pc8.yellow("\u{1F4A1} Tip:")} Run ${pc8.bold("trie ledger compress")} to archive old blocks`);
2823
3090
  }
2824
3091
  } catch (error) {
2825
- console.error(pc7.red("Failed to get storage stats:"), error);
3092
+ console.error(pc8.red("Failed to get storage stats:"), error);
2826
3093
  process.exit(1);
2827
3094
  }
2828
3095
  });
@@ -2831,69 +3098,69 @@ ${pc7.yellow("\u{1F4A1} Tip:")} Run ${pc7.bold("trie ledger compress")} to archi
2831
3098
  const datePattern = /^\d{4}-\d{2}-\d{2}$/;
2832
3099
  const invalidDates = dates.filter((date) => !datePattern.test(date));
2833
3100
  if (invalidDates.length > 0) {
2834
- console.error(pc7.red("Invalid date format(s):"), invalidDates.join(", "));
3101
+ console.error(pc8.red("Invalid date format(s):"), invalidDates.join(", "));
2835
3102
  console.error("Please use YYYY-MM-DD format");
2836
3103
  process.exit(1);
2837
3104
  }
2838
3105
  if (!options.confirm) {
2839
- console.log(pc7.bold(pc7.red("\u26A0\uFE0F DANGER: PERMANENT DELETION")));
3106
+ console.log(pc8.bold(pc8.red("\u26A0\uFE0F DANGER: PERMANENT DELETION")));
2840
3107
  console.log("");
2841
3108
  console.log(`You are about to permanently delete ${dates.length} block(s):`);
2842
3109
  for (const date of dates) {
2843
- console.log(` \u2022 ${pc7.cyan(date)}`);
3110
+ console.log(` \u2022 ${pc8.cyan(date)}`);
2844
3111
  }
2845
3112
  console.log("");
2846
- console.log(pc7.red("This operation cannot be undone and will permanently remove"));
2847
- console.log(pc7.red("all issues and data from these blocks."));
3113
+ console.log(pc8.red("This operation cannot be undone and will permanently remove"));
3114
+ console.log(pc8.red("all issues and data from these blocks."));
2848
3115
  console.log("");
2849
- console.log(`To proceed, add the ${pc7.bold("--confirm")} flag:`);
2850
- console.log(` ${pc7.dim("trie ledger delete " + dates.join(" ") + " --confirm")}`);
3116
+ console.log(`To proceed, add the ${pc8.bold("--confirm")} flag:`);
3117
+ console.log(` ${pc8.dim("trie ledger delete " + dates.join(" ") + " --confirm")}`);
2851
3118
  return;
2852
3119
  }
2853
- console.log(pc7.yellow("\u{1F5D1}\uFE0F Deleting blocks..."));
3120
+ console.log(pc8.yellow("\u{1F5D1}\uFE0F Deleting blocks..."));
2854
3121
  const result = await deleteBlocks(dates, void 0, true);
2855
3122
  if (result.success) {
2856
- console.log(pc7.green(`\u2713 Successfully deleted ${result.deletedBlocks} block(s)`));
3123
+ console.log(pc8.green(`\u2713 Successfully deleted ${result.deletedBlocks} block(s)`));
2857
3124
  if (result.warning) {
2858
- console.log(pc7.yellow(`\u26A0\uFE0F ${result.warning}`));
3125
+ console.log(pc8.yellow(`\u26A0\uFE0F ${result.warning}`));
2859
3126
  }
2860
3127
  } else {
2861
- console.error(pc7.red("\u2717 Deletion failed:"), result.error);
3128
+ console.error(pc8.red("\u2717 Deletion failed:"), result.error);
2862
3129
  process.exit(1);
2863
3130
  }
2864
3131
  } catch (error) {
2865
- console.error(pc7.red("Failed to delete blocks:"), error);
3132
+ console.error(pc8.red("Failed to delete blocks:"), error);
2866
3133
  process.exit(1);
2867
3134
  }
2868
3135
  });
2869
3136
  ledger.command("clear").description("Delete ALL blocks from the ledger (PERMANENT)").option("--confirm", "Confirm the permanent deletion of all blocks").action(async (options) => {
2870
3137
  try {
2871
3138
  if (!options.confirm) {
2872
- console.log(pc7.bold(pc7.red("\u{1F6A8} DANGER: COMPLETE LEDGER DELETION")));
3139
+ console.log(pc8.bold(pc8.red("\u{1F6A8} DANGER: COMPLETE LEDGER DELETION")));
2873
3140
  console.log("");
2874
- console.log(pc7.red("You are about to permanently delete ALL blocks in the ledger."));
2875
- console.log(pc7.red("This will completely erase the entire ledger history."));
3141
+ console.log(pc8.red("You are about to permanently delete ALL blocks in the ledger."));
3142
+ console.log(pc8.red("This will completely erase the entire ledger history."));
2876
3143
  console.log("");
2877
- console.log(pc7.red("This operation cannot be undone and will permanently remove"));
2878
- console.log(pc7.red("ALL issues and historical data."));
3144
+ console.log(pc8.red("This operation cannot be undone and will permanently remove"));
3145
+ console.log(pc8.red("ALL issues and historical data."));
2879
3146
  console.log("");
2880
- console.log(`To proceed, add the ${pc7.bold("--confirm")} flag:`);
2881
- console.log(` ${pc7.dim("trie ledger clear --confirm")}`);
3147
+ console.log(`To proceed, add the ${pc8.bold("--confirm")} flag:`);
3148
+ console.log(` ${pc8.dim("trie ledger clear --confirm")}`);
2882
3149
  return;
2883
3150
  }
2884
- console.log(pc7.yellow("\u{1F5D1}\uFE0F Clearing entire ledger..."));
3151
+ console.log(pc8.yellow("\u{1F5D1}\uFE0F Clearing entire ledger..."));
2885
3152
  const result = await deleteAllBlocks(void 0, true);
2886
3153
  if (result.success) {
2887
- console.log(pc7.green(`\u2713 Successfully deleted ${result.deletedBlocks} block(s)`));
3154
+ console.log(pc8.green(`\u2713 Successfully deleted ${result.deletedBlocks} block(s)`));
2888
3155
  if (result.warning) {
2889
- console.log(pc7.yellow(`\u26A0\uFE0F ${result.warning}`));
3156
+ console.log(pc8.yellow(`\u26A0\uFE0F ${result.warning}`));
2890
3157
  }
2891
3158
  } else {
2892
- console.error(pc7.red("\u2717 Clear operation failed:"), result.error);
3159
+ console.error(pc8.red("\u2717 Clear operation failed:"), result.error);
2893
3160
  process.exit(1);
2894
3161
  }
2895
3162
  } catch (error) {
2896
- console.error(pc7.red("Failed to clear ledger:"), error);
3163
+ console.error(pc8.red("Failed to clear ledger:"), error);
2897
3164
  process.exit(1);
2898
3165
  }
2899
3166
  });
@@ -2901,13 +3168,13 @@ ${pc7.yellow("\u{1F4A1} Tip:")} Run ${pc7.bold("trie ledger compress")} to archi
2901
3168
  }
2902
3169
 
2903
3170
  // src/cli/main.ts
2904
- var __filename2 = fileURLToPath(import.meta.url);
2905
- var __dirname2 = dirname(__filename2);
3171
+ var __filename3 = fileURLToPath2(import.meta.url);
3172
+ var __dirname3 = dirname2(__filename3);
2906
3173
  var DEFAULT_VERSION = "0.0.0";
2907
3174
  function getCliVersion() {
2908
3175
  try {
2909
- const pkgPath = resolve(__dirname2, "..", "..", "package.json");
2910
- const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"));
3176
+ const pkgPath = resolve2(__dirname3, "..", "..", "package.json");
3177
+ const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
2911
3178
  return typeof pkg.version === "string" && pkg.version.trim() ? pkg.version.trim() : DEFAULT_VERSION;
2912
3179
  } catch {
2913
3180
  return DEFAULT_VERSION;
@@ -2996,51 +3263,6 @@ MCP TOOLS (use via Cursor/Claude Desktop):
2996
3263
  trie_explain Explain code, issues, or changes
2997
3264
  trie_watch Watch mode for autonomous reporting
2998
3265
 
2999
- `);
3000
- }
3001
- function showSetup() {
3002
- console.log(`
3003
- \u2554\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\u2557
3004
- \u2551 Trie Agent Setup \u2551
3005
- \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
3006
-
3007
- STEP 1: API Keys
3008
- \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
3009
- Trie can work offline, but performs best with these keys:
3010
-
3011
- 1. ANTHROPIC_API_KEY (Required for AI analysis)
3012
- Get it: https://console.anthropic.com/
3013
-
3014
- 2. LINEAR_API_KEY (Required for JIT defect prediction)
3015
- Get it: https://linear.app/settings/api
3016
-
3017
- Set them in your environment (~/.zshrc) or MCP config:
3018
- export ANTHROPIC_API_KEY=sk-ant-...
3019
- export LINEAR_API_KEY=lin_api_...
3020
-
3021
- STEP 2: Configure for your AI tool
3022
- \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
3023
-
3024
- For CLAUDE CODE:
3025
- claude mcp add Trie -- npx @triedotdev/mcp
3026
-
3027
- For CURSOR (~/.cursor/mcp.json):
3028
- {
3029
- "mcpServers": {
3030
- "Trie": {
3031
- "command": "npx",
3032
- "args": ["-y", "@triedotdev/mcp"],
3033
- "env": {
3034
- "ANTHROPIC_API_KEY": "your-key-here",
3035
- "LINEAR_API_KEY": "your-key-here"
3036
- }
3037
- }
3038
- }
3039
- }
3040
-
3041
- STEP 3: Start scanning!
3042
- \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
3043
- Ask your AI assistant: "Scan this with Trie" or "Use trie_scan"
3044
3266
  `);
3045
3267
  }
3046
3268
  function showVersion() {
@@ -3059,47 +3281,47 @@ async function handleStatusCommand() {
3059
3281
  const lastScanDate = new Date(state.lastScan.timestamp);
3060
3282
  const daysAgo = Math.floor((Date.now() - lastScanDate.getTime()) / (1e3 * 60 * 60 * 24));
3061
3283
  console.log(`
3062
- ${pc8.bold("Last Scan:")} ${lastScanDate.toLocaleDateString()} (${daysAgo === 0 ? "today" : daysAgo === 1 ? "yesterday" : `${daysAgo} days ago`})`);
3063
- console.log(pc8.dim(` Files scanned: ${state.lastScan.filesScanned}`));
3064
- console.log(pc8.dim(` Issues found: ${state.lastScan.issues.total} (${state.lastScan.issues.critical} critical, ${state.lastScan.issues.serious} serious)`));
3284
+ ${pc9.bold("Last Scan:")} ${lastScanDate.toLocaleDateString()} (${daysAgo === 0 ? "today" : daysAgo === 1 ? "yesterday" : `${daysAgo} days ago`})`);
3285
+ console.log(pc9.dim(` Files scanned: ${state.lastScan.filesScanned}`));
3286
+ console.log(pc9.dim(` Issues found: ${state.lastScan.issues.total} (${state.lastScan.issues.critical} critical, ${state.lastScan.issues.serious} serious)`));
3065
3287
  } else {
3066
3288
  console.log(`
3067
- ${pc8.bold("Last Scan:")} Never ${pc8.dim("(run `trie scan` to get started)")}`);
3289
+ ${pc9.bold("Last Scan:")} Never ${pc9.dim("(run `trie scan` to get started)")}`);
3068
3290
  }
3069
3291
  console.log(`
3070
- ${pc8.bold("Memory Stats:")}`);
3071
- console.log(pc8.dim(` Active Issues: ${memoryStats.activeIssues}`));
3072
- console.log(pc8.dim(` Resolved: ${memoryStats.resolvedCount}`));
3073
- console.log(pc8.dim(` Total (all-time): ${memoryStats.totalIssues}`));
3292
+ ${pc9.bold("Memory Stats:")}`);
3293
+ console.log(pc9.dim(` Active Issues: ${memoryStats.activeIssues}`));
3294
+ console.log(pc9.dim(` Resolved: ${memoryStats.resolvedCount}`));
3295
+ console.log(pc9.dim(` Total (all-time): ${memoryStats.totalIssues}`));
3074
3296
  const cap = memoryStats.capacityInfo;
3075
- const capIndicator = cap.isAtCap ? pc8.red("\u25CB") : cap.percentFull >= 80 ? pc8.yellow("\u25C9") : pc8.green("\u25CF");
3076
- console.log(` ${capIndicator} Memory Usage: ${pc8.bold(cap.percentFull + "%")} ${pc8.dim(`(${cap.current}/${cap.max})`)}`);
3297
+ const capIndicator = cap.isAtCap ? pc9.red("\u25CB") : cap.percentFull >= 80 ? pc9.yellow("\u25C9") : pc9.green("\u25CF");
3298
+ console.log(` ${capIndicator} Memory Usage: ${pc9.bold(cap.percentFull + "%")} ${pc9.dim(`(${cap.current}/${cap.max})`)}`);
3077
3299
  if (memoryStats.activeIssues > 0) {
3078
3300
  console.log(`
3079
- ${pc8.bold("Active Issues by Severity:")}`);
3301
+ ${pc9.bold("Active Issues by Severity:")}`);
3080
3302
  const severityOrder = ["critical", "serious", "moderate", "low", "info"];
3081
3303
  for (const severity of severityOrder) {
3082
3304
  const count = memoryStats.activeIssuesBySeverity[severity] || 0;
3083
3305
  if (count > 0) {
3084
- console.log(pc8.dim(` ${severity}: ${count}`));
3306
+ console.log(pc9.dim(` ${severity}: ${count}`));
3085
3307
  }
3086
3308
  }
3087
3309
  } else if (memoryStats.totalIssues > 0) {
3088
3310
  console.log(`
3089
- ${pc8.green("\u25CF")} All issues have been resolved`);
3311
+ ${pc9.green("\u25CF")} All issues have been resolved`);
3090
3312
  }
3091
3313
  if (cap.isAtCap) {
3092
3314
  console.log(`
3093
- ${pc8.yellow("\u2B22 Warning:")} Memory at capacity - consider running: ${pc8.bold("trie memory purge smart")}`);
3315
+ ${pc9.yellow("\u2B22 Warning:")} Memory at capacity - consider running: ${pc9.bold("trie memory purge smart")}`);
3094
3316
  } else if (cap.percentFull >= 80) {
3095
3317
  console.log(`
3096
- ${pc8.yellow("\u2B22 Notice:")} Memory usage high - consider running: ${pc8.bold("trie memory purge smart")}`);
3318
+ ${pc9.yellow("\u2B22 Notice:")} Memory usage high - consider running: ${pc9.bold("trie memory purge smart")}`);
3097
3319
  }
3098
3320
  console.log(`
3099
- ${pc8.bold("Quick Commands:")}`);
3100
- console.log(pc8.dim(" trie scan - Scan codebase now"));
3101
- console.log(pc8.dim(" trie memory stats - Detailed memory statistics"));
3102
- console.log(pc8.dim(" trie project - View project information"));
3321
+ ${pc9.bold("Quick Commands:")}`);
3322
+ console.log(pc9.dim(" trie scan - Scan codebase now"));
3323
+ console.log(pc9.dim(" trie memory stats - Detailed memory statistics"));
3324
+ console.log(pc9.dim(" trie project - View project information"));
3103
3325
  console.log("");
3104
3326
  } catch (error) {
3105
3327
  console.error("Error loading status:", error);
@@ -3117,7 +3339,7 @@ async function handleProject(args) {
3117
3339
  \u2551 PROJECT.md Created \u2551
3118
3340
  \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
3119
3341
 
3120
- ${pc8.bold("Path:")} ${result.path}
3342
+ ${pc9.bold("Path:")} ${result.path}
3121
3343
 
3122
3344
  A template has been created with sections for:
3123
3345
  \u2022 Project Overview
@@ -3142,7 +3364,7 @@ Next steps:
3142
3364
  }
3143
3365
  if (subcommand === "edit") {
3144
3366
  const editor = process.env.EDITOR || process.env.VISUAL || "nano";
3145
- const projectPath = join4(getTrieDirectory(workDir), "PROJECT.md");
3367
+ const projectPath = join5(getTrieDirectory(workDir), "PROJECT.md");
3146
3368
  if (!projectInfoExists(workDir)) {
3147
3369
  console.log("No PROJECT.md found. Creating one first...");
3148
3370
  await initProjectInfo(workDir);
@@ -3160,7 +3382,7 @@ Next steps:
3160
3382
  \u2551 Project Information \u2551
3161
3383
  \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
3162
3384
 
3163
- ${pc8.bold("No PROJECT.md found in this project.")}
3385
+ ${pc9.bold("No PROJECT.md found in this project.")}
3164
3386
 
3165
3387
  COMMANDS:
3166
3388
  trie project init Create PROJECT.md from template
@@ -3188,7 +3410,7 @@ This info is available via trie://project MCP resource.
3188
3410
  \u2551 Project Information \u2551
3189
3411
  \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
3190
3412
 
3191
- ${pc8.bold("Path:")} ${join4(getTrieDirectory(workDir), "PROJECT.md")}
3413
+ ${pc9.bold("Path:")} ${join5(getTrieDirectory(workDir), "PROJECT.md")}
3192
3414
 
3193
3415
  ${"-".repeat(68)}
3194
3416
  `);
@@ -3197,10 +3419,10 @@ ${"-".repeat(68)}
3197
3419
  async function runScan(args) {
3198
3420
  const { spawn } = await import("child_process");
3199
3421
  let daemonPath;
3200
- if (__filename2.endsWith(".ts")) {
3201
- daemonPath = resolve(__dirname2, "yolo-daemon.ts");
3422
+ if (__filename3.endsWith(".ts")) {
3423
+ daemonPath = resolve2(__dirname3, "yolo-daemon.ts");
3202
3424
  } else {
3203
- daemonPath = resolve(__dirname2, "yolo-daemon.js");
3425
+ daemonPath = resolve2(__dirname3, "yolo-daemon.js");
3204
3426
  }
3205
3427
  const daemonArgs = ["--once", ...args];
3206
3428
  const executor = daemonPath.endsWith(".ts") ? "npx" : "node";
@@ -3216,10 +3438,10 @@ async function runScan(args) {
3216
3438
  async function runWatch(args) {
3217
3439
  const { spawn } = await import("child_process");
3218
3440
  let daemonPath;
3219
- if (__filename2.endsWith(".ts")) {
3220
- daemonPath = resolve(__dirname2, "yolo-daemon.ts");
3441
+ if (__filename3.endsWith(".ts")) {
3442
+ daemonPath = resolve2(__dirname3, "yolo-daemon.ts");
3221
3443
  } else {
3222
- daemonPath = resolve(__dirname2, "yolo-daemon.js");
3444
+ daemonPath = resolve2(__dirname3, "yolo-daemon.js");
3223
3445
  }
3224
3446
  const executor = daemonPath.endsWith(".ts") ? "npx" : "node";
3225
3447
  const execArgs = daemonPath.endsWith(".ts") ? ["tsx", daemonPath, ...args] : [daemonPath, ...args];
@@ -3252,7 +3474,7 @@ async function main() {
3252
3474
  case "setup":
3253
3475
  case "config":
3254
3476
  case "configure":
3255
- showSetup();
3477
+ await handleSetupCommand(restArgs);
3256
3478
  break;
3257
3479
  case "init":
3258
3480
  case "bootstrap":
@@ -3296,6 +3518,12 @@ async function main() {
3296
3518
  case "pre-push":
3297
3519
  handlePrePushCommand(restArgs);
3298
3520
  break;
3521
+ case "pre-commit":
3522
+ handlePreCommitCommand(restArgs);
3523
+ break;
3524
+ case "post-commit":
3525
+ handlePostCommitCommand(restArgs);
3526
+ break;
3299
3527
  case "fix":
3300
3528
  case "auto-fix":
3301
3529
  case "autofix":
@@ -3362,7 +3590,7 @@ async function main() {
3362
3590
  default:
3363
3591
  if (command.startsWith("-")) {
3364
3592
  const { spawn } = __require("child_process");
3365
- const daemonPath = resolve(__dirname2, "yolo-daemon.js");
3593
+ const daemonPath = resolve2(__dirname3, "yolo-daemon.js");
3366
3594
  const child = spawn("node", [daemonPath, ...args], {
3367
3595
  stdio: "inherit",
3368
3596
  env: process.env
@@ -3382,7 +3610,7 @@ var isEntryPoint = (() => {
3382
3610
  if (!entry) return false;
3383
3611
  try {
3384
3612
  const realEntry = realpathSync(entry);
3385
- const realThis = fileURLToPath(import.meta.url);
3613
+ const realThis = fileURLToPath2(import.meta.url);
3386
3614
  return realEntry === realThis;
3387
3615
  } catch {
3388
3616
  return !process.env.VITEST && !process.env.VITEST_WORKER_ID;