@triedotdev/mcp 1.0.166 → 1.0.168
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +333 -805
- package/dist/chunk-2HF65EHQ.js +311 -0
- package/dist/chunk-2HF65EHQ.js.map +1 -0
- package/dist/{chunk-JNUOW2JS.js → chunk-4MXH2ZPT.js} +12 -12
- package/dist/chunk-4MXH2ZPT.js.map +1 -0
- package/dist/{chunk-LR5M4RTN.js → chunk-575YT2SD.js} +1 -1
- package/dist/chunk-575YT2SD.js.map +1 -0
- package/dist/{chunk-ZKKKLRZZ.js → chunk-5BRRRTN6.js} +4 -4
- package/dist/{chunk-TQOO6A4G.js → chunk-7WITSO22.js} +3 -3
- package/dist/{chunk-ACU2RJUJ.js → chunk-F6WFNUAY.js} +2 -2
- package/dist/{chunk-VR4VWXXU.js → chunk-G2TGF6TR.js} +9 -2
- package/dist/chunk-G2TGF6TR.js.map +1 -0
- package/dist/{chunk-ZBXW244P.js → chunk-HVCDY3AK.js} +3 -3
- package/dist/chunk-HVCDY3AK.js.map +1 -0
- package/dist/{chunk-HOGKPDZA.js → chunk-LQIMKE3P.js} +678 -151
- package/dist/chunk-LQIMKE3P.js.map +1 -0
- package/dist/{chunk-2Z3TQNNK.js → chunk-MRHKX5M5.js} +3 -3
- package/dist/{chunk-OLNZJ3XV.js → chunk-Q63FFI6D.js} +2 -2
- package/dist/{chunk-S36IO3EE.js → chunk-XE6KQRKZ.js} +9 -8
- package/dist/chunk-XE6KQRKZ.js.map +1 -0
- package/dist/{chunk-GDWA3CH3.js → chunk-XPZZFPBZ.js} +30 -6
- package/dist/chunk-XPZZFPBZ.js.map +1 -0
- package/dist/{chunk-JEZ7XJQN.js → chunk-XTFWT2XM.js} +2 -2
- package/dist/{chunk-UXRW2YSP.js → chunk-YDHUCDHM.js} +18 -112
- package/dist/chunk-YDHUCDHM.js.map +1 -0
- package/dist/{chunk-LG5CBK6A.js → chunk-YZ6Y2H3P.js} +21 -196
- package/dist/chunk-YZ6Y2H3P.js.map +1 -0
- package/dist/{chunk-MVVPJ73K.js → chunk-ZJF5FTBX.js} +126 -358
- package/dist/chunk-ZJF5FTBX.js.map +1 -0
- package/dist/cli/create-agent.js +1 -1
- package/dist/cli/create-agent.js.map +1 -1
- package/dist/cli/main.js +194 -849
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +15 -14
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/{fast-analyzer-NJQO3TFD.js → fast-analyzer-XXYMOXRK.js} +3 -3
- package/dist/git-EO5SRFMN.js +28 -0
- package/dist/{github-ingester-TFBDUDIY.js → github-ingester-ZOKK6GRS.js} +3 -3
- package/dist/{goal-manager-DVX24UPZ.js → goal-manager-YOB7VWK7.js} +5 -4
- package/dist/{goal-validator-6Y5CDEMJ.js → goal-validator-ULKIBDPX.js} +5 -4
- package/dist/{hypothesis-UKPGOYY2.js → hypothesis-7BFFT5JY.js} +5 -4
- package/dist/index.js +19 -18
- package/dist/index.js.map +1 -1
- package/dist/{issue-store-UZAPI5DU.js → issue-store-ZIRP23EP.js} +4 -3
- package/dist/{ledger-CNFCJKHX.js → ledger-TWZTGDFA.js} +3 -2
- package/dist/{linear-ingester-PLES2BRS.js → linear-ingester-XXPAZZRW.js} +3 -3
- package/dist/{output-manager-JNMEAXFO.js → output-manager-RVJ37XKA.js} +2 -2
- package/dist/server/mcp-server.js +19 -18
- package/dist/{tiered-storage-OP74NPJY.js → tiered-storage-Z3YCR465.js} +2 -2
- package/dist/{trie-agent-6SWUHCVO.js → trie-agent-3YDPEGHJ.js} +9 -8
- package/dist/trie-agent-3YDPEGHJ.js.map +1 -0
- package/package.json +3 -2
- package/dist/chunk-GDWA3CH3.js.map +0 -1
- package/dist/chunk-HOGKPDZA.js.map +0 -1
- package/dist/chunk-JNUOW2JS.js.map +0 -1
- package/dist/chunk-LG5CBK6A.js.map +0 -1
- package/dist/chunk-LR5M4RTN.js.map +0 -1
- package/dist/chunk-MVVPJ73K.js.map +0 -1
- package/dist/chunk-S36IO3EE.js.map +0 -1
- package/dist/chunk-UXRW2YSP.js.map +0 -1
- package/dist/chunk-VR4VWXXU.js.map +0 -1
- package/dist/chunk-ZBXW244P.js.map +0 -1
- /package/dist/{chunk-ZKKKLRZZ.js.map → chunk-5BRRRTN6.js.map} +0 -0
- /package/dist/{chunk-TQOO6A4G.js.map → chunk-7WITSO22.js.map} +0 -0
- /package/dist/{chunk-ACU2RJUJ.js.map → chunk-F6WFNUAY.js.map} +0 -0
- /package/dist/{chunk-2Z3TQNNK.js.map → chunk-MRHKX5M5.js.map} +0 -0
- /package/dist/{chunk-OLNZJ3XV.js.map → chunk-Q63FFI6D.js.map} +0 -0
- /package/dist/{chunk-JEZ7XJQN.js.map → chunk-XTFWT2XM.js.map} +0 -0
- /package/dist/{fast-analyzer-NJQO3TFD.js.map → fast-analyzer-XXYMOXRK.js.map} +0 -0
- /package/dist/{github-ingester-TFBDUDIY.js.map → git-EO5SRFMN.js.map} +0 -0
- /package/dist/{goal-manager-DVX24UPZ.js.map → github-ingester-ZOKK6GRS.js.map} +0 -0
- /package/dist/{goal-validator-6Y5CDEMJ.js.map → goal-manager-YOB7VWK7.js.map} +0 -0
- /package/dist/{hypothesis-UKPGOYY2.js.map → goal-validator-ULKIBDPX.js.map} +0 -0
- /package/dist/{issue-store-UZAPI5DU.js.map → hypothesis-7BFFT5JY.js.map} +0 -0
- /package/dist/{ledger-CNFCJKHX.js.map → issue-store-ZIRP23EP.js.map} +0 -0
- /package/dist/{linear-ingester-PLES2BRS.js.map → ledger-TWZTGDFA.js.map} +0 -0
- /package/dist/{output-manager-JNMEAXFO.js.map → linear-ingester-XXPAZZRW.js.map} +0 -0
- /package/dist/{tiered-storage-OP74NPJY.js.map → output-manager-RVJ37XKA.js.map} +0 -0
- /package/dist/{trie-agent-6SWUHCVO.js.map → tiered-storage-Z3YCR465.js.map} +0 -0
package/dist/cli/main.js
CHANGED
|
@@ -7,29 +7,27 @@ import {
|
|
|
7
7
|
loadProjectInfo,
|
|
8
8
|
needsBootstrap,
|
|
9
9
|
projectInfoExists
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-HVCDY3AK.js";
|
|
11
11
|
import {
|
|
12
12
|
LinearIngester
|
|
13
|
-
} from "../chunk-
|
|
13
|
+
} from "../chunk-Q63FFI6D.js";
|
|
14
14
|
import {
|
|
15
15
|
LearningEngine,
|
|
16
16
|
formatFriendlyError,
|
|
17
|
-
handleCheckpointCommand,
|
|
18
17
|
isTrieInitialized,
|
|
19
18
|
perceiveCurrentChanges,
|
|
20
19
|
reasonAboutChangesHumanReadable
|
|
21
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-YZ6Y2H3P.js";
|
|
22
21
|
import {
|
|
23
22
|
measureInitialGoalValue
|
|
24
|
-
} from "../chunk-
|
|
23
|
+
} from "../chunk-5BRRRTN6.js";
|
|
25
24
|
import {
|
|
26
|
-
exportToJson
|
|
27
|
-
importFromJson
|
|
25
|
+
exportToJson
|
|
28
26
|
} from "../chunk-OBQ74FOU.js";
|
|
29
27
|
import {
|
|
30
28
|
loadConfig,
|
|
31
29
|
saveConfig
|
|
32
|
-
} from "../chunk-
|
|
30
|
+
} from "../chunk-XPZZFPBZ.js";
|
|
33
31
|
import {
|
|
34
32
|
IncidentIndex
|
|
35
33
|
} from "../chunk-TN5WEKWI.js";
|
|
@@ -42,7 +40,7 @@ import {
|
|
|
42
40
|
listTrackedProjects,
|
|
43
41
|
searchGlobalPatterns,
|
|
44
42
|
updateGlobalMemoryMd
|
|
45
|
-
} from "../chunk-
|
|
43
|
+
} from "../chunk-7WITSO22.js";
|
|
46
44
|
import "../chunk-SY6KQG44.js";
|
|
47
45
|
import "../chunk-OMR4YCBS.js";
|
|
48
46
|
import {
|
|
@@ -51,7 +49,7 @@ import {
|
|
|
51
49
|
import "../chunk-6NLHFIYA.js";
|
|
52
50
|
import {
|
|
53
51
|
getStorage
|
|
54
|
-
} from "../chunk-
|
|
52
|
+
} from "../chunk-575YT2SD.js";
|
|
55
53
|
import "../chunk-FQ45QP5A.js";
|
|
56
54
|
import {
|
|
57
55
|
getDailyLogs,
|
|
@@ -60,37 +58,20 @@ import {
|
|
|
60
58
|
markIssueResolved,
|
|
61
59
|
purgeIssues,
|
|
62
60
|
searchIssues
|
|
63
|
-
} from "../chunk-
|
|
64
|
-
import {
|
|
65
|
-
getProjectState
|
|
66
|
-
} from "../chunk-GTKYBOXL.js";
|
|
67
|
-
import "../chunk-EFWVF6TI.js";
|
|
68
|
-
import {
|
|
69
|
-
getAutonomyConfig,
|
|
70
|
-
recordBypass,
|
|
71
|
-
shouldAutoFix,
|
|
72
|
-
shouldBlockPush,
|
|
73
|
-
trackIssueOccurrence
|
|
74
|
-
} from "../chunk-ME2OERF5.js";
|
|
61
|
+
} from "../chunk-XE6KQRKZ.js";
|
|
75
62
|
import {
|
|
76
63
|
compressOldBlocks,
|
|
77
64
|
correctLedgerEntries,
|
|
78
65
|
detectLegacyLedger,
|
|
79
|
-
formatAuditLog,
|
|
80
66
|
generateKeyPair,
|
|
81
|
-
getAuditStatistics,
|
|
82
67
|
getCorrectionStats,
|
|
83
68
|
getEntryCorrectionHistory,
|
|
84
69
|
getLedgerBlocks,
|
|
85
70
|
getLedgerSyncStatus,
|
|
86
71
|
getPublicKey,
|
|
87
|
-
getRecentAuditLogs,
|
|
88
|
-
getStagedChanges,
|
|
89
72
|
getStorageStats,
|
|
90
|
-
getUncommittedChanges,
|
|
91
73
|
hasSigningKey,
|
|
92
74
|
initializeSharedLedger,
|
|
93
|
-
isGitRepo,
|
|
94
75
|
loadKeyPair,
|
|
95
76
|
migrateLegacyLedger,
|
|
96
77
|
pushLedgerToShared,
|
|
@@ -98,22 +79,38 @@ import {
|
|
|
98
79
|
shouldCompress,
|
|
99
80
|
syncLedgerFromShared,
|
|
100
81
|
verifyLedger
|
|
101
|
-
} from "../chunk-
|
|
82
|
+
} from "../chunk-ZJF5FTBX.js";
|
|
83
|
+
import {
|
|
84
|
+
getProjectState
|
|
85
|
+
} from "../chunk-GTKYBOXL.js";
|
|
86
|
+
import "../chunk-EFWVF6TI.js";
|
|
102
87
|
import "../chunk-43X6JBEM.js";
|
|
88
|
+
import {
|
|
89
|
+
getAutonomyConfig,
|
|
90
|
+
recordBypass,
|
|
91
|
+
shouldAutoFix,
|
|
92
|
+
shouldBlockPush,
|
|
93
|
+
trackIssueOccurrence
|
|
94
|
+
} from "../chunk-ME2OERF5.js";
|
|
103
95
|
import {
|
|
104
96
|
getTrieDirectory,
|
|
105
97
|
getWorkingDirectory
|
|
106
98
|
} from "../chunk-VVITXIHN.js";
|
|
107
99
|
import "../chunk-KDHN2ZQE.js";
|
|
100
|
+
import {
|
|
101
|
+
getStagedChanges,
|
|
102
|
+
getUncommittedChanges,
|
|
103
|
+
isGitRepo
|
|
104
|
+
} from "../chunk-2HF65EHQ.js";
|
|
108
105
|
import {
|
|
109
106
|
__require
|
|
110
107
|
} from "../chunk-DGUM43GV.js";
|
|
111
108
|
|
|
112
109
|
// src/cli/main.ts
|
|
113
|
-
import { resolve, join as
|
|
110
|
+
import { resolve, join as join4, dirname } from "path";
|
|
114
111
|
import { readFileSync as readFileSync2, realpathSync } from "fs";
|
|
115
112
|
import { fileURLToPath } from "url";
|
|
116
|
-
import
|
|
113
|
+
import pc9 from "picocolors";
|
|
117
114
|
|
|
118
115
|
// src/hooks/install.ts
|
|
119
116
|
import fs from "fs";
|
|
@@ -838,7 +835,7 @@ async function handlePrePushCommand(args) {
|
|
|
838
835
|
console.error("");
|
|
839
836
|
console.error(pc.cyan("To fix issues:"));
|
|
840
837
|
console.error(pc.dim(" trie fix # Auto-fix trivial issues"));
|
|
841
|
-
console.error(pc.dim(" trie
|
|
838
|
+
console.error(pc.dim(" trie check # See all issues"));
|
|
842
839
|
console.error("");
|
|
843
840
|
process.exit(2);
|
|
844
841
|
} else if (blockResult.bypassed) {
|
|
@@ -994,7 +991,7 @@ async function handlePreCommitCommand(_args) {
|
|
|
994
991
|
console.error(pc2.yellow("\u26A0 Could not get staged files, skipping pre-commit check"));
|
|
995
992
|
process.exit(0);
|
|
996
993
|
}
|
|
997
|
-
const { searchIssues: searchIssues2 } = await import("../issue-store-
|
|
994
|
+
const { searchIssues: searchIssues2 } = await import("../issue-store-ZIRP23EP.js");
|
|
998
995
|
let criticalIssues = 0;
|
|
999
996
|
let totalIssues = 0;
|
|
1000
997
|
const issuesByFile = /* @__PURE__ */ new Map();
|
|
@@ -2032,300 +2029,6 @@ async function handleTellCommand(args) {
|
|
|
2032
2029
|
}
|
|
2033
2030
|
}
|
|
2034
2031
|
|
|
2035
|
-
// src/cli/reconcile.ts
|
|
2036
|
-
import path4 from "path";
|
|
2037
|
-
async function removeOrphanEdges(graph) {
|
|
2038
|
-
const nodes = await graph.listNodes();
|
|
2039
|
-
const nodeIds = new Set(nodes.map((n) => n.id));
|
|
2040
|
-
const edges = await graph.listEdges();
|
|
2041
|
-
let removed = 0;
|
|
2042
|
-
for (const edge of edges) {
|
|
2043
|
-
if (!nodeIds.has(edge.from_id) || !nodeIds.has(edge.to_id)) {
|
|
2044
|
-
await graph.deleteEdge(edge.id);
|
|
2045
|
-
removed++;
|
|
2046
|
-
}
|
|
2047
|
-
}
|
|
2048
|
-
return removed;
|
|
2049
|
-
}
|
|
2050
|
-
async function handleReconcileCommand(args) {
|
|
2051
|
-
try {
|
|
2052
|
-
const projectPath = getWorkingDirectory(void 0, true);
|
|
2053
|
-
const source = args.find((a) => a.startsWith("--from="))?.replace("--from=", "") ?? path4.join(getTrieDirectory(projectPath), "context.json");
|
|
2054
|
-
const graph = new ContextGraph(projectPath);
|
|
2055
|
-
await importFromJson(graph, "", source);
|
|
2056
|
-
const removed = await removeOrphanEdges(graph);
|
|
2057
|
-
console.log(`Reconciled context from ${source}. Removed ${removed} orphaned edges.`);
|
|
2058
|
-
} catch (error) {
|
|
2059
|
-
const friendly = formatFriendlyError(error);
|
|
2060
|
-
console.error(friendly.userMessage);
|
|
2061
|
-
}
|
|
2062
|
-
}
|
|
2063
|
-
|
|
2064
|
-
// src/cli/quiet.ts
|
|
2065
|
-
import fs3 from "fs";
|
|
2066
|
-
import path5 from "path";
|
|
2067
|
-
async function handleQuietCommand() {
|
|
2068
|
-
const projectPath = getWorkingDirectory(void 0, true);
|
|
2069
|
-
const quietPath = path5.join(getTrieDirectory(projectPath), "quiet.json");
|
|
2070
|
-
const until = new Date(Date.now() + 60 * 60 * 1e3).toISOString();
|
|
2071
|
-
const payload = { until };
|
|
2072
|
-
try {
|
|
2073
|
-
const dir = path5.dirname(quietPath);
|
|
2074
|
-
fs3.mkdirSync(dir, { recursive: true });
|
|
2075
|
-
fs3.writeFileSync(quietPath, JSON.stringify(payload, null, 2));
|
|
2076
|
-
console.log("\u{1F515} Nudges snoozed for 1 hour.");
|
|
2077
|
-
} catch (error) {
|
|
2078
|
-
console.error("Failed to set quiet mode:", error);
|
|
2079
|
-
}
|
|
2080
|
-
}
|
|
2081
|
-
|
|
2082
|
-
// src/cli/ci.ts
|
|
2083
|
-
import { writeFileSync, existsSync as existsSync5, mkdirSync } from "fs";
|
|
2084
|
-
import { join as join3 } from "path";
|
|
2085
|
-
import pc6 from "picocolors";
|
|
2086
|
-
var WORKFLOW_TEMPLATE = `# Trie Security Scan with Memory Persistence
|
|
2087
|
-
# Generated by: trie ci
|
|
2088
|
-
#
|
|
2089
|
-
# This workflow scans your code and caches Trie's memory
|
|
2090
|
-
# across runs for cross-run learning and pattern recognition.
|
|
2091
|
-
|
|
2092
|
-
name: Trie Security Scan
|
|
2093
|
-
|
|
2094
|
-
on:
|
|
2095
|
-
push:
|
|
2096
|
-
branches: [main, master, develop]
|
|
2097
|
-
pull_request:
|
|
2098
|
-
branches: [main, master]
|
|
2099
|
-
|
|
2100
|
-
jobs:
|
|
2101
|
-
security-scan:
|
|
2102
|
-
runs-on: ubuntu-latest
|
|
2103
|
-
permissions:
|
|
2104
|
-
security-events: write
|
|
2105
|
-
pull-requests: write
|
|
2106
|
-
contents: read
|
|
2107
|
-
|
|
2108
|
-
steps:
|
|
2109
|
-
- name: Checkout
|
|
2110
|
-
uses: actions/checkout@v4
|
|
2111
|
-
|
|
2112
|
-
# Restore Trie memory from previous runs
|
|
2113
|
-
# This enables cross-run learning and pattern recognition
|
|
2114
|
-
- name: Restore Trie Memory
|
|
2115
|
-
uses: actions/cache@v4
|
|
2116
|
-
with:
|
|
2117
|
-
path: |
|
|
2118
|
-
.trie/memory
|
|
2119
|
-
.trie/context
|
|
2120
|
-
.trie/summaries
|
|
2121
|
-
key: trie-memory-\${{ github.repository }}-\${{ github.ref_name }}
|
|
2122
|
-
restore-keys: |
|
|
2123
|
-
trie-memory-\${{ github.repository }}-
|
|
2124
|
-
trie-memory-
|
|
2125
|
-
|
|
2126
|
-
- name: Setup Node.js
|
|
2127
|
-
uses: actions/setup-node@v4
|
|
2128
|
-
with:
|
|
2129
|
-
node-version: '20'
|
|
2130
|
-
|
|
2131
|
-
- name: Install Trie
|
|
2132
|
-
run: npm install -g @triedotdev/mcp
|
|
2133
|
-
|
|
2134
|
-
- name: Run Security Scan
|
|
2135
|
-
run: |
|
|
2136
|
-
trie scan --format sarif --output trie-results.sarif
|
|
2137
|
-
env:
|
|
2138
|
-
ANTHROPIC_API_KEY: \${{ secrets.ANTHROPIC_API_KEY }}
|
|
2139
|
-
|
|
2140
|
-
- name: Upload SARIF Results
|
|
2141
|
-
uses: github/codeql-action/upload-sarif@v3
|
|
2142
|
-
if: always()
|
|
2143
|
-
with:
|
|
2144
|
-
sarif_file: trie-results.sarif
|
|
2145
|
-
continue-on-error: true
|
|
2146
|
-
|
|
2147
|
-
# Memory is automatically saved by cache action on job completion
|
|
2148
|
-
`;
|
|
2149
|
-
var WORKFLOW_MINIMAL = `# Trie Security Scan (Minimal)
|
|
2150
|
-
# Generated by: trie ci --minimal
|
|
2151
|
-
|
|
2152
|
-
name: Trie Scan
|
|
2153
|
-
|
|
2154
|
-
on: [push, pull_request]
|
|
2155
|
-
|
|
2156
|
-
jobs:
|
|
2157
|
-
scan:
|
|
2158
|
-
runs-on: ubuntu-latest
|
|
2159
|
-
steps:
|
|
2160
|
-
- uses: actions/checkout@v4
|
|
2161
|
-
|
|
2162
|
-
# Cache Trie memory for cross-run learning
|
|
2163
|
-
- uses: actions/cache@v4
|
|
2164
|
-
with:
|
|
2165
|
-
path: .trie/memory
|
|
2166
|
-
key: trie-memory-\${{ github.repository }}
|
|
2167
|
-
|
|
2168
|
-
- run: npm install -g @triedotdev/mcp
|
|
2169
|
-
- run: trie scan
|
|
2170
|
-
env:
|
|
2171
|
-
ANTHROPIC_API_KEY: \${{ secrets.ANTHROPIC_API_KEY }}
|
|
2172
|
-
`;
|
|
2173
|
-
function handleCISetupCommand(args) {
|
|
2174
|
-
const workDir = getWorkingDirectory(void 0, true);
|
|
2175
|
-
const workflowsDir = join3(workDir, ".github", "workflows");
|
|
2176
|
-
const workflowPath = join3(workflowsDir, "trie-scan.yml");
|
|
2177
|
-
const isMinimal = args.includes("--minimal") || args.includes("-m");
|
|
2178
|
-
const isDryRun = args.includes("--dry-run") || args.includes("-n");
|
|
2179
|
-
const showHelp3 = args.includes("--help") || args.includes("-h");
|
|
2180
|
-
if (showHelp3) {
|
|
2181
|
-
console.log(`
|
|
2182
|
-
${pc6.bold("trie ci")} - Generate GitHub Actions workflow with memory caching
|
|
2183
|
-
|
|
2184
|
-
${pc6.bold("USAGE:")}
|
|
2185
|
-
trie ci [options]
|
|
2186
|
-
|
|
2187
|
-
${pc6.bold("OPTIONS:")}
|
|
2188
|
-
--minimal, -m Generate minimal workflow (simpler, fewer features)
|
|
2189
|
-
--dry-run, -n Preview workflow without creating files
|
|
2190
|
-
--help, -h Show this help
|
|
2191
|
-
|
|
2192
|
-
${pc6.bold("WHAT IT DOES:")}
|
|
2193
|
-
Creates .github/workflows/trie-scan.yml that:
|
|
2194
|
-
|
|
2195
|
-
1. ${pc6.green("Caches Trie memory")} - Patterns and fixes persist across runs
|
|
2196
|
-
2. ${pc6.green("Enables learning")} - Trie remembers issues from previous PRs
|
|
2197
|
-
3. ${pc6.green("Tracks patterns")} - Detects recurring issues across your codebase
|
|
2198
|
-
4. ${pc6.green("SARIF upload")} - Results appear in GitHub Security tab
|
|
2199
|
-
|
|
2200
|
-
${pc6.bold("MEMORY BENEFITS:")}
|
|
2201
|
-
\u2022 "This issue was introduced 3 PRs ago"
|
|
2202
|
-
\u2022 "Similar issue was fixed in PR #42"
|
|
2203
|
-
\u2022 "This pattern keeps recurring in auth code"
|
|
2204
|
-
\u2022 Trend tracking: improving, stable, or declining
|
|
2205
|
-
|
|
2206
|
-
${pc6.bold("EXAMPLES:")}
|
|
2207
|
-
trie ci # Generate full workflow
|
|
2208
|
-
trie ci --minimal # Generate simple workflow
|
|
2209
|
-
trie ci --dry-run # Preview without writing
|
|
2210
|
-
|
|
2211
|
-
${pc6.bold("REQUIRED SECRETS:")}
|
|
2212
|
-
ANTHROPIC_API_KEY Your Anthropic API key (add in GitHub repo settings)
|
|
2213
|
-
`);
|
|
2214
|
-
return;
|
|
2215
|
-
}
|
|
2216
|
-
const template = isMinimal ? WORKFLOW_MINIMAL : WORKFLOW_TEMPLATE;
|
|
2217
|
-
if (isDryRun) {
|
|
2218
|
-
console.log(pc6.bold("\nWorkflow Preview:\n"));
|
|
2219
|
-
console.log(pc6.dim("\u2500".repeat(60)));
|
|
2220
|
-
console.log(template);
|
|
2221
|
-
console.log(pc6.dim("\u2500".repeat(60)));
|
|
2222
|
-
console.log(pc6.dim("\nRun without --dry-run to create the file."));
|
|
2223
|
-
return;
|
|
2224
|
-
}
|
|
2225
|
-
if (existsSync5(workflowPath)) {
|
|
2226
|
-
console.log(pc6.yellow("Workflow already exists: .github/workflows/trie-scan.yml"));
|
|
2227
|
-
console.log(pc6.dim(" Run with --dry-run to preview what would be written."));
|
|
2228
|
-
console.log(pc6.dim(" Delete the existing file to regenerate."));
|
|
2229
|
-
return;
|
|
2230
|
-
}
|
|
2231
|
-
if (!existsSync5(workflowsDir)) {
|
|
2232
|
-
mkdirSync(workflowsDir, { recursive: true });
|
|
2233
|
-
}
|
|
2234
|
-
writeFileSync(workflowPath, template);
|
|
2235
|
-
console.log(pc6.green("\u2713") + " Created .github/workflows/trie-scan.yml");
|
|
2236
|
-
console.log("");
|
|
2237
|
-
console.log(pc6.bold("Next steps:"));
|
|
2238
|
-
console.log("");
|
|
2239
|
-
console.log(" 1. Add your Anthropic API key to GitHub Secrets:");
|
|
2240
|
-
console.log(pc6.dim(" Settings \u2192 Secrets \u2192 Actions \u2192 New repository secret"));
|
|
2241
|
-
console.log(pc6.dim(" Name: ANTHROPIC_API_KEY"));
|
|
2242
|
-
console.log("");
|
|
2243
|
-
console.log(" 2. Commit and push:");
|
|
2244
|
-
console.log(pc6.dim(" git add .github/workflows/trie-scan.yml"));
|
|
2245
|
-
console.log(pc6.dim(' git commit -m "Add Trie security scan with memory"'));
|
|
2246
|
-
console.log(pc6.dim(" git push"));
|
|
2247
|
-
console.log("");
|
|
2248
|
-
console.log(pc6.bold("Memory caching benefits:"));
|
|
2249
|
-
console.log(pc6.dim(" \u2022 Trie learns from past scans"));
|
|
2250
|
-
console.log(pc6.dim(" \u2022 Tracks issue trends over time"));
|
|
2251
|
-
console.log(pc6.dim(" \u2022 Remembers when issues were introduced"));
|
|
2252
|
-
console.log(pc6.dim(" \u2022 Recognizes recurring patterns"));
|
|
2253
|
-
}
|
|
2254
|
-
|
|
2255
|
-
// src/cli/audit.ts
|
|
2256
|
-
async function handleAuditCommand(args) {
|
|
2257
|
-
const [cmd, ...rest] = args;
|
|
2258
|
-
switch (cmd) {
|
|
2259
|
-
case "logs":
|
|
2260
|
-
case "list": {
|
|
2261
|
-
const limit = rest[0] ? parseInt(rest[0], 10) : 20;
|
|
2262
|
-
const logs = await getRecentAuditLogs(limit);
|
|
2263
|
-
if (logs.length === 0) {
|
|
2264
|
-
console.log("\nNo audit logs found.");
|
|
2265
|
-
console.log("Audit logs are created when tools execute commands.\n");
|
|
2266
|
-
return;
|
|
2267
|
-
}
|
|
2268
|
-
console.log(`
|
|
2269
|
-
Recent Executions (last ${logs.length}):
|
|
2270
|
-
`);
|
|
2271
|
-
for (const log of logs) {
|
|
2272
|
-
console.log(formatAuditLog(log));
|
|
2273
|
-
console.log("");
|
|
2274
|
-
}
|
|
2275
|
-
break;
|
|
2276
|
-
}
|
|
2277
|
-
case "stats":
|
|
2278
|
-
case "statistics": {
|
|
2279
|
-
const stats = await getAuditStatistics();
|
|
2280
|
-
console.log("\n\u{1F4CA} Audit Statistics\n");
|
|
2281
|
-
console.log(`Total executions: ${stats.totalExecutions}`);
|
|
2282
|
-
console.log(` \u2705 Successful: ${stats.successfulExecutions}`);
|
|
2283
|
-
console.log(` \u274C Failed: ${stats.failedExecutions}`);
|
|
2284
|
-
console.log("");
|
|
2285
|
-
console.log(`Unique tools executed: ${stats.uniqueSkills}`);
|
|
2286
|
-
console.log("");
|
|
2287
|
-
console.log(`Commands executed: ${stats.totalCommands}`);
|
|
2288
|
-
if (stats.blockedCommands > 0) {
|
|
2289
|
-
console.log(` \u26A0\uFE0F Blocked: ${stats.blockedCommands}`);
|
|
2290
|
-
}
|
|
2291
|
-
console.log("");
|
|
2292
|
-
console.log(`Network calls: ${stats.totalNetworkCalls}`);
|
|
2293
|
-
if (stats.blockedNetworkCalls > 0) {
|
|
2294
|
-
console.log(` \u26A0\uFE0F Blocked: ${stats.blockedNetworkCalls}`);
|
|
2295
|
-
}
|
|
2296
|
-
console.log("");
|
|
2297
|
-
if (stats.blockedCommands > 0 || stats.blockedNetworkCalls > 0) {
|
|
2298
|
-
console.log("\u26A0\uFE0F Some operations were blocked by security policies.");
|
|
2299
|
-
console.log('Run "trie audit logs" to see details.\n');
|
|
2300
|
-
}
|
|
2301
|
-
break;
|
|
2302
|
-
}
|
|
2303
|
-
default: {
|
|
2304
|
-
console.log(`
|
|
2305
|
-
Audit - View security audit logs
|
|
2306
|
-
|
|
2307
|
-
Trie logs tool operations for security auditing. View what
|
|
2308
|
-
commands were executed and any blocked operations.
|
|
2309
|
-
|
|
2310
|
-
Commands:
|
|
2311
|
-
trie audit logs [count] Show recent audit logs (default: 20)
|
|
2312
|
-
trie audit stats Show audit statistics
|
|
2313
|
-
|
|
2314
|
-
Examples:
|
|
2315
|
-
trie audit logs 50 Show last 50 executions
|
|
2316
|
-
trie audit stats View overall statistics
|
|
2317
|
-
|
|
2318
|
-
Audit logs are stored in .trie/audit/ and include:
|
|
2319
|
-
\u2022 Tool name and source
|
|
2320
|
-
\u2022 Commands executed
|
|
2321
|
-
\u2022 Network calls made
|
|
2322
|
-
\u2022 Files accessed/modified
|
|
2323
|
-
\u2022 Any blocked operations
|
|
2324
|
-
`);
|
|
2325
|
-
}
|
|
2326
|
-
}
|
|
2327
|
-
}
|
|
2328
|
-
|
|
2329
2032
|
// src/cli/linear.ts
|
|
2330
2033
|
async function handleLinearCommand(args) {
|
|
2331
2034
|
try {
|
|
@@ -2467,334 +2170,8 @@ async function handleLearnCommand(args) {
|
|
|
2467
2170
|
}
|
|
2468
2171
|
}
|
|
2469
2172
|
|
|
2470
|
-
// src/cli/patterns.ts
|
|
2471
|
-
import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
2472
|
-
import { existsSync as existsSync7 } from "fs";
|
|
2473
|
-
import { basename as basename2 } from "path";
|
|
2474
|
-
import picocolors3 from "picocolors";
|
|
2475
|
-
|
|
2476
|
-
// src/patterns/saved-patterns.ts
|
|
2477
|
-
import { createHash } from "crypto";
|
|
2478
|
-
import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
2479
|
-
import { existsSync as existsSync6 } from "fs";
|
|
2480
|
-
import { join as join4, basename } from "path";
|
|
2481
|
-
async function loadSavedPatterns(workDir) {
|
|
2482
|
-
const patternsPath = join4(getTrieDirectory(workDir), "saved-patterns.json");
|
|
2483
|
-
try {
|
|
2484
|
-
if (existsSync6(patternsPath)) {
|
|
2485
|
-
const content = await readFile3(patternsPath, "utf-8");
|
|
2486
|
-
return JSON.parse(content);
|
|
2487
|
-
}
|
|
2488
|
-
} catch {
|
|
2489
|
-
}
|
|
2490
|
-
return [];
|
|
2491
|
-
}
|
|
2492
|
-
async function savePatternsToProject(patterns, workDir) {
|
|
2493
|
-
const { mkdir: mkdir2 } = await import("fs/promises");
|
|
2494
|
-
const patternsPath = join4(getTrieDirectory(workDir), "saved-patterns.json");
|
|
2495
|
-
await mkdir2(getTrieDirectory(workDir), { recursive: true });
|
|
2496
|
-
await writeFile3(patternsPath, JSON.stringify(patterns, null, 2));
|
|
2497
|
-
}
|
|
2498
|
-
async function savePatternToProject(pattern, workDir) {
|
|
2499
|
-
const patterns = await loadSavedPatterns(workDir);
|
|
2500
|
-
const existing = patterns.findIndex((p) => p.id === pattern.id);
|
|
2501
|
-
if (existing >= 0) {
|
|
2502
|
-
patterns[existing] = {
|
|
2503
|
-
...patterns[existing],
|
|
2504
|
-
...pattern,
|
|
2505
|
-
occurrences: patterns[existing].occurrences + 1
|
|
2506
|
-
};
|
|
2507
|
-
} else {
|
|
2508
|
-
patterns.push(pattern);
|
|
2509
|
-
}
|
|
2510
|
-
await savePatternsToProject(patterns, workDir);
|
|
2511
|
-
}
|
|
2512
|
-
function detectPatternType(target, workDir) {
|
|
2513
|
-
const scoutNames = [
|
|
2514
|
-
"security",
|
|
2515
|
-
"legal",
|
|
2516
|
-
"accessibility",
|
|
2517
|
-
"bug-finding",
|
|
2518
|
-
"architecture",
|
|
2519
|
-
"types",
|
|
2520
|
-
"clean",
|
|
2521
|
-
"devops",
|
|
2522
|
-
"performance",
|
|
2523
|
-
"ux",
|
|
2524
|
-
"design",
|
|
2525
|
-
"production-ready",
|
|
2526
|
-
"agent-smith"
|
|
2527
|
-
];
|
|
2528
|
-
if (scoutNames.includes(target.toLowerCase())) {
|
|
2529
|
-
return "detection-rule";
|
|
2530
|
-
}
|
|
2531
|
-
const fullPath = join4(workDir, target);
|
|
2532
|
-
if (existsSync6(fullPath) || target.includes("/") || target.includes("*") || target.endsWith(".ts") || target.endsWith(".js")) {
|
|
2533
|
-
return "file-structure";
|
|
2534
|
-
}
|
|
2535
|
-
return "code-pattern";
|
|
2536
|
-
}
|
|
2537
|
-
function generatePatternId(target, type) {
|
|
2538
|
-
const hash = createHash("sha256").update(`${type}:${target}`).digest("hex").slice(0, 12);
|
|
2539
|
-
return `${type}-${hash}`;
|
|
2540
|
-
}
|
|
2541
|
-
async function createSavedPattern(target, note, workDir) {
|
|
2542
|
-
const projectName = basename(workDir);
|
|
2543
|
-
const patternType = detectPatternType(target, workDir);
|
|
2544
|
-
const savedPattern = {
|
|
2545
|
-
id: generatePatternId(target, patternType),
|
|
2546
|
-
type: patternType,
|
|
2547
|
-
name: target,
|
|
2548
|
-
description: note || `Pattern saved from ${projectName}`,
|
|
2549
|
-
validated: false,
|
|
2550
|
-
projects: [projectName],
|
|
2551
|
-
occurrences: 1,
|
|
2552
|
-
savedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2553
|
-
savedBy: projectName
|
|
2554
|
-
};
|
|
2555
|
-
if (patternType === "file-structure") {
|
|
2556
|
-
savedPattern.filePatterns = [target];
|
|
2557
|
-
savedPattern.architecture = {
|
|
2558
|
-
structure: `Files matching ${target}`,
|
|
2559
|
-
rationale: note || "File structure pattern that worked well"
|
|
2560
|
-
};
|
|
2561
|
-
} else if (patternType === "code-pattern") {
|
|
2562
|
-
const issues = await searchIssues(target, { limit: 5 });
|
|
2563
|
-
if (issues.length > 0) {
|
|
2564
|
-
const latestIssue = issues[0];
|
|
2565
|
-
savedPattern.codePattern = {
|
|
2566
|
-
pattern: latestIssue?.issue.issue || target,
|
|
2567
|
-
fix: latestIssue?.issue.fix || "Review and apply similar fix",
|
|
2568
|
-
context: note || "Code pattern that worked well"
|
|
2569
|
-
};
|
|
2570
|
-
} else {
|
|
2571
|
-
savedPattern.codePattern = {
|
|
2572
|
-
pattern: target,
|
|
2573
|
-
fix: "Review and apply similar fix",
|
|
2574
|
-
context: note || "Code pattern that worked well"
|
|
2575
|
-
};
|
|
2576
|
-
}
|
|
2577
|
-
} else if (patternType === "detection-rule") {
|
|
2578
|
-
savedPattern.detectionRule = {
|
|
2579
|
-
agent: target,
|
|
2580
|
-
rule: `Detection rules from ${target} scout`,
|
|
2581
|
-
severity: "moderate"
|
|
2582
|
-
};
|
|
2583
|
-
}
|
|
2584
|
-
return savedPattern;
|
|
2585
|
-
}
|
|
2586
|
-
|
|
2587
|
-
// src/cli/patterns.ts
|
|
2588
|
-
async function handlePatternsCommand(args) {
|
|
2589
|
-
const subcommand = args[0]?.toLowerCase();
|
|
2590
|
-
const workDir = getWorkingDirectory(void 0, true);
|
|
2591
|
-
try {
|
|
2592
|
-
switch (subcommand) {
|
|
2593
|
-
case "save":
|
|
2594
|
-
await handleSavePattern(args.slice(1), workDir);
|
|
2595
|
-
break;
|
|
2596
|
-
case "list":
|
|
2597
|
-
await handleListPatterns(args.slice(1), workDir);
|
|
2598
|
-
break;
|
|
2599
|
-
case "export":
|
|
2600
|
-
await handleExportPatterns(args.slice(1), workDir);
|
|
2601
|
-
break;
|
|
2602
|
-
case "import":
|
|
2603
|
-
await handleImportPatterns(args.slice(1), workDir);
|
|
2604
|
-
break;
|
|
2605
|
-
case "validate":
|
|
2606
|
-
await handleValidatePattern(args.slice(1), workDir);
|
|
2607
|
-
break;
|
|
2608
|
-
default:
|
|
2609
|
-
showPatternsHelp();
|
|
2610
|
-
}
|
|
2611
|
-
} catch (error) {
|
|
2612
|
-
const friendly = formatFriendlyError(error);
|
|
2613
|
-
console.error(picocolors3.red(`Error: ${friendly.userMessage}`));
|
|
2614
|
-
process.exit(1);
|
|
2615
|
-
}
|
|
2616
|
-
}
|
|
2617
|
-
async function handleSavePattern(args, workDir) {
|
|
2618
|
-
const target = args[0];
|
|
2619
|
-
const note = args.slice(1).join(" ") || void 0;
|
|
2620
|
-
if (!target) {
|
|
2621
|
-
console.error(picocolors3.red("Usage: trie patterns save <target> [note]"));
|
|
2622
|
-
console.log(picocolors3.dim("\nExamples:"));
|
|
2623
|
-
console.log(' trie patterns save "path/to/file.ts" "Short note about why it worked"');
|
|
2624
|
-
console.log(' trie patterns save "path/*" "Folder structure that worked well"');
|
|
2625
|
-
console.log(' trie patterns save security "Scout that caught issues early"');
|
|
2626
|
-
process.exit(1);
|
|
2627
|
-
}
|
|
2628
|
-
const savedPattern = await createSavedPattern(target, note, workDir);
|
|
2629
|
-
await savePatternToProject(savedPattern, workDir);
|
|
2630
|
-
console.log(picocolors3.green(`\u2713 Pattern saved: ${target}`));
|
|
2631
|
-
if (note) {
|
|
2632
|
-
console.log(picocolors3.dim(` Note: ${note}`));
|
|
2633
|
-
}
|
|
2634
|
-
console.log(picocolors3.dim(` Type: ${savedPattern.type}`));
|
|
2635
|
-
console.log(picocolors3.dim(` Export with: trie patterns export`));
|
|
2636
|
-
}
|
|
2637
|
-
async function handleListPatterns(args, workDir) {
|
|
2638
|
-
const filter = args[0]?.toLowerCase();
|
|
2639
|
-
const patterns = await loadSavedPatterns(workDir);
|
|
2640
|
-
let filtered = patterns;
|
|
2641
|
-
if (filter === "validated" || filter === "saved") {
|
|
2642
|
-
filtered = patterns.filter((p) => filter === "validated" ? p.validated : true);
|
|
2643
|
-
}
|
|
2644
|
-
if (filtered.length === 0) {
|
|
2645
|
-
console.log(picocolors3.yellow("No saved patterns found."));
|
|
2646
|
-
console.log(picocolors3.dim("Save patterns with: trie patterns save <target> [note]"));
|
|
2647
|
-
return;
|
|
2648
|
-
}
|
|
2649
|
-
console.log(picocolors3.bold(`
|
|
2650
|
-
\u{1F4CB} Saved Patterns (${filtered.length})
|
|
2651
|
-
`));
|
|
2652
|
-
for (const pattern of filtered) {
|
|
2653
|
-
const typeEmoji = {
|
|
2654
|
-
"file-structure": "\u{1F4C1}",
|
|
2655
|
-
"code-pattern": "\u{1F4BB}",
|
|
2656
|
-
"detection-rule": "\u{1F50D}"
|
|
2657
|
-
}[pattern.type] || "\u{1F4CC}";
|
|
2658
|
-
console.log(`${typeEmoji} ${picocolors3.bold(pattern.name)}`);
|
|
2659
|
-
console.log(` Type: ${pattern.type}`);
|
|
2660
|
-
if (pattern.description) {
|
|
2661
|
-
console.log(` ${picocolors3.dim(pattern.description)}`);
|
|
2662
|
-
}
|
|
2663
|
-
if (pattern.validated) {
|
|
2664
|
-
console.log(` ${picocolors3.green("\u2713 Validated")}`);
|
|
2665
|
-
if (pattern.validationNotes) {
|
|
2666
|
-
console.log(` ${picocolors3.dim(pattern.validationNotes)}`);
|
|
2667
|
-
}
|
|
2668
|
-
}
|
|
2669
|
-
console.log(` Projects: ${pattern.projects.join(", ")}`);
|
|
2670
|
-
console.log("");
|
|
2671
|
-
}
|
|
2672
|
-
}
|
|
2673
|
-
async function handleExportPatterns(args, workDir) {
|
|
2674
|
-
const outputPath = args[0] || "trie-patterns.json";
|
|
2675
|
-
const filter = args[1]?.toLowerCase();
|
|
2676
|
-
let patterns = await loadSavedPatterns(workDir);
|
|
2677
|
-
if (filter === "validated" || filter === "saved") {
|
|
2678
|
-
patterns = patterns.filter((p) => filter === "validated" ? p.validated : true);
|
|
2679
|
-
}
|
|
2680
|
-
if (patterns.length === 0) {
|
|
2681
|
-
console.error(picocolors3.yellow("No patterns to export."));
|
|
2682
|
-
return;
|
|
2683
|
-
}
|
|
2684
|
-
const exportData = {
|
|
2685
|
-
version: "1.0",
|
|
2686
|
-
exportedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
2687
|
-
exportedFrom: basename2(workDir),
|
|
2688
|
-
patterns
|
|
2689
|
-
};
|
|
2690
|
-
await writeFile4(outputPath, JSON.stringify(exportData, null, 2));
|
|
2691
|
-
console.log(picocolors3.green(`\u2713 Exported ${patterns.length} patterns to ${outputPath}`));
|
|
2692
|
-
console.log(picocolors3.dim(` Import to another project with: trie patterns import ${outputPath}`));
|
|
2693
|
-
}
|
|
2694
|
-
async function handleImportPatterns(args, workDir) {
|
|
2695
|
-
const inputPath = args[0];
|
|
2696
|
-
if (!inputPath) {
|
|
2697
|
-
console.error(picocolors3.red("Usage: trie patterns import <path-to-patterns.json>"));
|
|
2698
|
-
process.exit(1);
|
|
2699
|
-
}
|
|
2700
|
-
if (!existsSync7(inputPath)) {
|
|
2701
|
-
console.error(picocolors3.red(`File not found: ${inputPath}`));
|
|
2702
|
-
process.exit(1);
|
|
2703
|
-
}
|
|
2704
|
-
const content = await readFile4(inputPath, "utf-8");
|
|
2705
|
-
const importData = JSON.parse(content);
|
|
2706
|
-
if (!importData.patterns || !Array.isArray(importData.patterns)) {
|
|
2707
|
-
console.error(picocolors3.red("Invalid pattern file format."));
|
|
2708
|
-
process.exit(1);
|
|
2709
|
-
}
|
|
2710
|
-
const existingPatterns = await loadSavedPatterns(workDir);
|
|
2711
|
-
const projectName = basename2(workDir);
|
|
2712
|
-
let imported = 0;
|
|
2713
|
-
let skipped = 0;
|
|
2714
|
-
for (const pattern of importData.patterns) {
|
|
2715
|
-
const existing = existingPatterns.find((p) => p.id === pattern.id);
|
|
2716
|
-
if (existing) {
|
|
2717
|
-
if (!existing.projects.includes(projectName)) {
|
|
2718
|
-
existing.projects.push(projectName);
|
|
2719
|
-
}
|
|
2720
|
-
existing.occurrences++;
|
|
2721
|
-
skipped++;
|
|
2722
|
-
} else {
|
|
2723
|
-
const newPattern = {
|
|
2724
|
-
...pattern,
|
|
2725
|
-
projects: [...pattern.projects, projectName],
|
|
2726
|
-
savedBy: importData.exportedFrom || "unknown"
|
|
2727
|
-
};
|
|
2728
|
-
existingPatterns.push(newPattern);
|
|
2729
|
-
imported++;
|
|
2730
|
-
}
|
|
2731
|
-
}
|
|
2732
|
-
await savePatternsToProject(existingPatterns, workDir);
|
|
2733
|
-
console.log(picocolors3.green(`\u2713 Imported ${imported} new patterns`));
|
|
2734
|
-
if (skipped > 0) {
|
|
2735
|
-
console.log(picocolors3.dim(` Updated ${skipped} existing patterns`));
|
|
2736
|
-
}
|
|
2737
|
-
console.log(picocolors3.dim(` Total patterns: ${existingPatterns.length}`));
|
|
2738
|
-
}
|
|
2739
|
-
async function handleValidatePattern(args, workDir) {
|
|
2740
|
-
const patternId = args[0];
|
|
2741
|
-
const note = args.slice(1).join(" ") || "Validated - worked well";
|
|
2742
|
-
if (!patternId) {
|
|
2743
|
-
console.error(picocolors3.red("Usage: trie patterns validate <pattern-id> [note]"));
|
|
2744
|
-
process.exit(1);
|
|
2745
|
-
}
|
|
2746
|
-
const patterns = await loadSavedPatterns(workDir);
|
|
2747
|
-
const pattern = patterns.find((p) => p.id === patternId || p.name === patternId);
|
|
2748
|
-
if (!pattern) {
|
|
2749
|
-
console.error(picocolors3.red(`Pattern not found: ${patternId}`));
|
|
2750
|
-
console.log(picocolors3.dim("List patterns with: trie patterns list"));
|
|
2751
|
-
process.exit(1);
|
|
2752
|
-
}
|
|
2753
|
-
pattern.validated = true;
|
|
2754
|
-
pattern.validationNotes = note;
|
|
2755
|
-
await savePatternsToProject(patterns, workDir);
|
|
2756
|
-
console.log(picocolors3.green(`\u2713 Pattern validated: ${pattern.name}`));
|
|
2757
|
-
console.log(picocolors3.dim(` Note: ${note}`));
|
|
2758
|
-
}
|
|
2759
|
-
function showPatternsHelp() {
|
|
2760
|
-
console.log(`
|
|
2761
|
-
${picocolors3.bold("Pattern Management")}
|
|
2762
|
-
|
|
2763
|
-
Save, validate, and share patterns that worked well across projects.
|
|
2764
|
-
|
|
2765
|
-
${picocolors3.bold("Commands:")}
|
|
2766
|
-
trie patterns save <target> [note] Save a pattern (file, code, or scout)
|
|
2767
|
-
trie patterns list [--validated] List saved patterns
|
|
2768
|
-
trie patterns export [file] [--validated] Export patterns to JSON
|
|
2769
|
-
trie patterns import <file> Import patterns from JSON
|
|
2770
|
-
trie patterns validate <id> [note] Mark pattern as validated
|
|
2771
|
-
|
|
2772
|
-
${picocolors3.bold("Examples:")}
|
|
2773
|
-
# Save a file structure pattern
|
|
2774
|
-
trie patterns save "path/*" "This folder structure worked well"
|
|
2775
|
-
|
|
2776
|
-
# Save a code pattern
|
|
2777
|
-
trie patterns save path/to/file.ts "This error handling prevented bugs"
|
|
2778
|
-
|
|
2779
|
-
# Save a detection rule
|
|
2780
|
-
trie patterns save security "This scout caught issues early"
|
|
2781
|
-
|
|
2782
|
-
# Validate a pattern
|
|
2783
|
-
trie patterns validate pattern-abc123 "Worked great in production"
|
|
2784
|
-
|
|
2785
|
-
# Export validated patterns
|
|
2786
|
-
trie patterns export patterns.json --validated
|
|
2787
|
-
|
|
2788
|
-
# Import to another project
|
|
2789
|
-
cd ../another-project
|
|
2790
|
-
trie patterns import ../source-project/patterns.json
|
|
2791
|
-
|
|
2792
|
-
${picocolors3.dim("Patterns are saved in .trie/saved-patterns.json")}
|
|
2793
|
-
`);
|
|
2794
|
-
}
|
|
2795
|
-
|
|
2796
2173
|
// src/cli/sync.ts
|
|
2797
|
-
import
|
|
2174
|
+
import pc6 from "picocolors";
|
|
2798
2175
|
import { Command } from "commander";
|
|
2799
2176
|
function createSyncCommand() {
|
|
2800
2177
|
const sync = new Command("sync").description("Sync ledger with shared storage");
|
|
@@ -2803,9 +2180,9 @@ function createSyncCommand() {
|
|
|
2803
2180
|
const workDir = getWorkingDirectory(void 0, true);
|
|
2804
2181
|
console.log(`Initializing shared ledger in ${workDir}...`);
|
|
2805
2182
|
await initializeSharedLedger();
|
|
2806
|
-
console.log(
|
|
2183
|
+
console.log(pc6.green("\u2713 Shared ledger initialized successfully"));
|
|
2807
2184
|
} catch (error) {
|
|
2808
|
-
console.error(
|
|
2185
|
+
console.error(pc6.red("Failed to initialize shared ledger:"), error);
|
|
2809
2186
|
process.exit(1);
|
|
2810
2187
|
}
|
|
2811
2188
|
});
|
|
@@ -2818,17 +2195,17 @@ function createSyncCommand() {
|
|
|
2818
2195
|
await migrateLegacyLedger();
|
|
2819
2196
|
}
|
|
2820
2197
|
const result = await syncLedgerFromShared();
|
|
2821
|
-
console.log(
|
|
2198
|
+
console.log(pc6.green("\u2713 Sync completed"));
|
|
2822
2199
|
console.log(`Merged ${result.stats.mergedBlocks} blocks`);
|
|
2823
2200
|
if (result.conflicts.length > 0) {
|
|
2824
|
-
console.log(
|
|
2201
|
+
console.log(pc6.yellow(`\u26A0 ${result.conflicts.length} conflicts detected`));
|
|
2825
2202
|
console.log('Run "trie sync status" to see details');
|
|
2826
2203
|
}
|
|
2827
2204
|
if (result.stats.duplicatesRemoved > 0) {
|
|
2828
2205
|
console.log(`Removed ${result.stats.duplicatesRemoved} duplicate entries`);
|
|
2829
2206
|
}
|
|
2830
2207
|
} catch (error) {
|
|
2831
|
-
console.error(
|
|
2208
|
+
console.error(pc6.red("Failed to sync from shared ledger:"), error);
|
|
2832
2209
|
process.exit(1);
|
|
2833
2210
|
}
|
|
2834
2211
|
});
|
|
@@ -2841,45 +2218,45 @@ function createSyncCommand() {
|
|
|
2841
2218
|
await migrateLegacyLedger();
|
|
2842
2219
|
}
|
|
2843
2220
|
await pushLedgerToShared();
|
|
2844
|
-
console.log(
|
|
2221
|
+
console.log(pc6.green("\u2713 Push completed"));
|
|
2845
2222
|
} catch (error) {
|
|
2846
|
-
console.error(
|
|
2223
|
+
console.error(pc6.red("Failed to push to shared ledger:"), error);
|
|
2847
2224
|
process.exit(1);
|
|
2848
2225
|
}
|
|
2849
2226
|
});
|
|
2850
2227
|
sync.command("status").description("Show ledger sync status").action(async () => {
|
|
2851
2228
|
try {
|
|
2852
2229
|
const status = await getLedgerSyncStatus();
|
|
2853
|
-
console.log(
|
|
2230
|
+
console.log(pc6.bold("Ledger Sync Status\n"));
|
|
2854
2231
|
if (!status.isInitialized) {
|
|
2855
|
-
console.log(
|
|
2232
|
+
console.log(pc6.yellow('\u26A0 Shared ledger not initialized. Run "trie sync init" first.'));
|
|
2856
2233
|
return;
|
|
2857
2234
|
}
|
|
2858
2235
|
if (status.hasLegacyLedger) {
|
|
2859
|
-
console.log(
|
|
2236
|
+
console.log(pc6.yellow('\u26A0 Legacy ledger detected. Run "trie sync pull" to migrate.'));
|
|
2860
2237
|
}
|
|
2861
|
-
console.log(`Local blocks: ${
|
|
2862
|
-
console.log(`Shared blocks: ${
|
|
2238
|
+
console.log(`Local blocks: ${pc6.cyan(status.localBlocks.toString())}`);
|
|
2239
|
+
console.log(`Shared blocks: ${pc6.cyan(status.sharedBlocks.toString())}`);
|
|
2863
2240
|
if (status.syncState) {
|
|
2864
2241
|
const lastSync = new Date(status.syncState.lastSyncTimestamp);
|
|
2865
|
-
console.log(`Last sync: ${
|
|
2242
|
+
console.log(`Last sync: ${pc6.dim(lastSync.toLocaleString())}`);
|
|
2866
2243
|
if (status.conflicts > 0) {
|
|
2867
|
-
console.log(
|
|
2244
|
+
console.log(pc6.yellow(`Conflicts: ${status.conflicts}`));
|
|
2868
2245
|
console.log("\nConflicts:");
|
|
2869
2246
|
for (const conflict of status.syncState.conflicts) {
|
|
2870
2247
|
console.log(` \u2022 ${conflict.type}: ${conflict.description}`);
|
|
2871
2248
|
}
|
|
2872
2249
|
} else {
|
|
2873
|
-
console.log(
|
|
2250
|
+
console.log(pc6.green("\u2713 No conflicts"));
|
|
2874
2251
|
}
|
|
2875
2252
|
}
|
|
2876
2253
|
if (status.manifest) {
|
|
2877
2254
|
console.log(`
|
|
2878
|
-
Total entries: ${
|
|
2879
|
-
console.log(`Compression: ${status.manifest.compressionConfig.enabled ?
|
|
2255
|
+
Total entries: ${pc6.cyan(status.manifest.totalEntries.toString())}`);
|
|
2256
|
+
console.log(`Compression: ${status.manifest.compressionConfig.enabled ? pc6.green("enabled") : pc6.red("disabled")}`);
|
|
2880
2257
|
}
|
|
2881
2258
|
} catch (error) {
|
|
2882
|
-
console.error(
|
|
2259
|
+
console.error(pc6.red("Failed to get sync status:"), error);
|
|
2883
2260
|
process.exit(1);
|
|
2884
2261
|
}
|
|
2885
2262
|
});
|
|
@@ -2887,19 +2264,19 @@ Total entries: ${pc7.cyan(status.manifest.totalEntries.toString())}`);
|
|
|
2887
2264
|
try {
|
|
2888
2265
|
const hasLegacy = await detectLegacyLedger();
|
|
2889
2266
|
if (!hasLegacy) {
|
|
2890
|
-
console.log(
|
|
2267
|
+
console.log(pc6.yellow("No legacy ledger found to migrate"));
|
|
2891
2268
|
return;
|
|
2892
2269
|
}
|
|
2893
2270
|
console.log("Migrating legacy ledger...");
|
|
2894
2271
|
const success = await migrateLegacyLedger();
|
|
2895
2272
|
if (success) {
|
|
2896
|
-
console.log(
|
|
2273
|
+
console.log(pc6.green("\u2713 Migration completed successfully"));
|
|
2897
2274
|
} else {
|
|
2898
|
-
console.log(
|
|
2275
|
+
console.log(pc6.red("Migration failed"));
|
|
2899
2276
|
process.exit(1);
|
|
2900
2277
|
}
|
|
2901
2278
|
} catch (error) {
|
|
2902
|
-
console.error(
|
|
2279
|
+
console.error(pc6.red("Failed to migrate legacy ledger:"), error);
|
|
2903
2280
|
process.exit(1);
|
|
2904
2281
|
}
|
|
2905
2282
|
});
|
|
@@ -2911,18 +2288,18 @@ Total entries: ${pc7.cyan(status.manifest.totalEntries.toString())}`);
|
|
|
2911
2288
|
}
|
|
2912
2289
|
const status = await checkGitHooks();
|
|
2913
2290
|
if (!status.isGitRepo) {
|
|
2914
|
-
console.log(
|
|
2291
|
+
console.log(pc6.yellow("Not a git repository"));
|
|
2915
2292
|
return;
|
|
2916
2293
|
}
|
|
2917
|
-
console.log(
|
|
2918
|
-
console.log(`Pre-push hook: ${status.prePushInstalled ?
|
|
2919
|
-
console.log(`Post-merge hook: ${status.postMergeInstalled ?
|
|
2294
|
+
console.log(pc6.bold("Git Hooks Status\n"));
|
|
2295
|
+
console.log(`Pre-push hook: ${status.prePushInstalled ? pc6.green("\u2713 installed") : pc6.red("\u2717 not installed")}`);
|
|
2296
|
+
console.log(`Post-merge hook: ${status.postMergeInstalled ? pc6.green("\u2713 installed") : pc6.red("\u2717 not installed")}`);
|
|
2920
2297
|
if (!status.prePushInstalled || !status.postMergeInstalled) {
|
|
2921
2298
|
console.log(`
|
|
2922
|
-
${
|
|
2299
|
+
${pc6.yellow("\u{1F4A1} Tip:")} Run ${pc6.bold("trie sync hooks --install")} to install missing hooks`);
|
|
2923
2300
|
}
|
|
2924
2301
|
} catch (error) {
|
|
2925
|
-
console.error(
|
|
2302
|
+
console.error(pc6.red("Failed to manage git hooks:"), error);
|
|
2926
2303
|
process.exit(1);
|
|
2927
2304
|
}
|
|
2928
2305
|
});
|
|
@@ -2930,7 +2307,7 @@ ${pc7.yellow("\u{1F4A1} Tip:")} Run ${pc7.bold("trie sync hooks --install")} to
|
|
|
2930
2307
|
}
|
|
2931
2308
|
|
|
2932
2309
|
// src/cli/ledger.ts
|
|
2933
|
-
import
|
|
2310
|
+
import pc7 from "picocolors";
|
|
2934
2311
|
import { Command as Command2 } from "commander";
|
|
2935
2312
|
function createLedgerCommand() {
|
|
2936
2313
|
const ledger = new Command2("ledger").description("Manage and inspect the ledger");
|
|
@@ -2942,14 +2319,14 @@ function createLedgerCommand() {
|
|
|
2942
2319
|
console.log(" \u2022 Validating Ed25519 signatures");
|
|
2943
2320
|
const result = await verifyLedger();
|
|
2944
2321
|
if (result.valid) {
|
|
2945
|
-
console.log(
|
|
2946
|
-
console.log(
|
|
2322
|
+
console.log(pc7.green("\u2713 Ledger chain is valid"));
|
|
2323
|
+
console.log(pc7.dim(" All blocks, hashes, and signatures verified"));
|
|
2947
2324
|
} else {
|
|
2948
|
-
console.log(
|
|
2325
|
+
console.log(pc7.red(`\u2717 Ledger chain is invalid: ${result.error}`));
|
|
2949
2326
|
process.exit(1);
|
|
2950
2327
|
}
|
|
2951
2328
|
} catch (error) {
|
|
2952
|
-
console.error(
|
|
2329
|
+
console.error(pc7.red("Failed to verify ledger:"), error);
|
|
2953
2330
|
process.exit(1);
|
|
2954
2331
|
}
|
|
2955
2332
|
});
|
|
@@ -2961,35 +2338,35 @@ function createLedgerCommand() {
|
|
|
2961
2338
|
console.log("No ledger blocks found");
|
|
2962
2339
|
return;
|
|
2963
2340
|
}
|
|
2964
|
-
console.log(
|
|
2341
|
+
console.log(pc7.bold(`Ledger History (last ${Math.min(limit, blocks.length)} blocks)
|
|
2965
2342
|
`));
|
|
2966
2343
|
const recentBlocks = blocks.slice(-limit).reverse();
|
|
2967
2344
|
for (const block of recentBlocks) {
|
|
2968
2345
|
const syncableBlock = block;
|
|
2969
|
-
console.log(
|
|
2346
|
+
console.log(pc7.bold(pc7.cyan(`Block ${block.date}`)));
|
|
2970
2347
|
if (syncableBlock.author) {
|
|
2971
|
-
console.log(`Author: ${
|
|
2348
|
+
console.log(`Author: ${pc7.dim(syncableBlock.author)}`);
|
|
2972
2349
|
}
|
|
2973
2350
|
if (syncableBlock.gitCommit) {
|
|
2974
|
-
console.log(`Git: ${
|
|
2351
|
+
console.log(`Git: ${pc7.dim(syncableBlock.gitCommit.slice(0, 8))}`);
|
|
2975
2352
|
}
|
|
2976
2353
|
console.log(`Entries: ${block.entries.length}`);
|
|
2977
|
-
console.log(`Hash: ${
|
|
2354
|
+
console.log(`Hash: ${pc7.dim(block.blockHash.slice(0, 16))}...`);
|
|
2978
2355
|
const signedEntries = block.entries.filter((e) => e.signature);
|
|
2979
2356
|
if (signedEntries.length > 0) {
|
|
2980
|
-
console.log(`Signed: ${
|
|
2357
|
+
console.log(`Signed: ${pc7.green(`${signedEntries.length}/${block.entries.length}`)}`);
|
|
2981
2358
|
}
|
|
2982
2359
|
if (block.entries.length > 0) {
|
|
2983
2360
|
console.log("Issues:");
|
|
2984
2361
|
for (const entry of block.entries) {
|
|
2985
|
-
const signatureIndicator = entry.signature ?
|
|
2362
|
+
const signatureIndicator = entry.signature ? pc7.green("\u2713") : pc7.dim("\u25CB");
|
|
2986
2363
|
console.log(` ${signatureIndicator} ${entry.severity} - ${entry.file} (${entry.agent})`);
|
|
2987
2364
|
}
|
|
2988
2365
|
}
|
|
2989
2366
|
console.log("");
|
|
2990
2367
|
}
|
|
2991
2368
|
} catch (error) {
|
|
2992
|
-
console.error(
|
|
2369
|
+
console.error(pc7.red("Failed to show ledger history:"), error);
|
|
2993
2370
|
process.exit(1);
|
|
2994
2371
|
}
|
|
2995
2372
|
});
|
|
@@ -2997,23 +2374,23 @@ function createLedgerCommand() {
|
|
|
2997
2374
|
try {
|
|
2998
2375
|
const status = await getLedgerSyncStatus();
|
|
2999
2376
|
const blocks = await getLedgerBlocks();
|
|
3000
|
-
console.log(
|
|
3001
|
-
console.log(`Total blocks: ${
|
|
2377
|
+
console.log(pc7.bold("Ledger Statistics\n"));
|
|
2378
|
+
console.log(`Total blocks: ${pc7.cyan(blocks.length.toString())}`);
|
|
3002
2379
|
if (status.manifest) {
|
|
3003
|
-
console.log(`Total entries: ${
|
|
3004
|
-
console.log(`Active blocks: ${
|
|
3005
|
-
console.log(`Archived blocks: ${
|
|
2380
|
+
console.log(`Total entries: ${pc7.cyan(status.manifest.totalEntries.toString())}`);
|
|
2381
|
+
console.log(`Active blocks: ${pc7.cyan(status.manifest.activeBlocks.length.toString())}`);
|
|
2382
|
+
console.log(`Archived blocks: ${pc7.cyan(status.manifest.archivedBlocks.length.toString())}`);
|
|
3006
2383
|
if (status.manifest.compressionConfig.enabled) {
|
|
3007
2384
|
const hotSize = Math.round(status.manifest.compressionConfig.maxHotStorageSize / 1024 / 1024);
|
|
3008
|
-
console.log(`Hot storage limit: ${
|
|
3009
|
-
console.log(`Archive after: ${
|
|
2385
|
+
console.log(`Hot storage limit: ${pc7.cyan(`${hotSize}MB`)}`);
|
|
2386
|
+
console.log(`Archive after: ${pc7.cyan(`${status.manifest.compressionConfig.archiveAfterDays} days`)}`);
|
|
3010
2387
|
}
|
|
3011
2388
|
}
|
|
3012
2389
|
if (blocks.length > 0) {
|
|
3013
2390
|
const firstBlock = blocks[0];
|
|
3014
2391
|
const lastBlock = blocks[blocks.length - 1];
|
|
3015
2392
|
if (firstBlock && lastBlock) {
|
|
3016
|
-
console.log(`Date range: ${
|
|
2393
|
+
console.log(`Date range: ${pc7.dim(`${firstBlock.date} to ${lastBlock.date}`)}`);
|
|
3017
2394
|
}
|
|
3018
2395
|
}
|
|
3019
2396
|
const authorCounts = /* @__PURE__ */ new Map();
|
|
@@ -3027,7 +2404,7 @@ function createLedgerCommand() {
|
|
|
3027
2404
|
console.log("\nBlocks by author:");
|
|
3028
2405
|
const sortedAuthors = Array.from(authorCounts.entries()).sort((a, b) => b[1] - a[1]);
|
|
3029
2406
|
for (const [author, count] of sortedAuthors.slice(0, 10)) {
|
|
3030
|
-
console.log(` ${author}: ${
|
|
2407
|
+
console.log(` ${author}: ${pc7.cyan(count.toString())}`);
|
|
3031
2408
|
}
|
|
3032
2409
|
}
|
|
3033
2410
|
const severityCounts = /* @__PURE__ */ new Map();
|
|
@@ -3042,39 +2419,39 @@ function createLedgerCommand() {
|
|
|
3042
2419
|
for (const severity of severityOrder) {
|
|
3043
2420
|
const count = severityCounts.get(severity);
|
|
3044
2421
|
if (count) {
|
|
3045
|
-
const color = severity === "critical" ?
|
|
3046
|
-
console.log(` ${color(severity)}: ${
|
|
2422
|
+
const color = severity === "critical" ? pc7.red : severity === "high" ? pc7.yellow : severity === "medium" ? pc7.blue : pc7.gray;
|
|
2423
|
+
console.log(` ${color(severity)}: ${pc7.cyan(count.toString())}`);
|
|
3047
2424
|
}
|
|
3048
2425
|
}
|
|
3049
2426
|
}
|
|
3050
2427
|
} catch (error) {
|
|
3051
|
-
console.error(
|
|
2428
|
+
console.error(pc7.red("Failed to show ledger stats:"), error);
|
|
3052
2429
|
process.exit(1);
|
|
3053
2430
|
}
|
|
3054
2431
|
});
|
|
3055
2432
|
ledger.command("diff").description("Compare local and shared ledger state").action(async () => {
|
|
3056
2433
|
try {
|
|
3057
2434
|
const status = await getLedgerSyncStatus();
|
|
3058
|
-
console.log(
|
|
2435
|
+
console.log(pc7.bold("Ledger Diff\n"));
|
|
3059
2436
|
if (!status.isInitialized) {
|
|
3060
|
-
console.log(
|
|
2437
|
+
console.log(pc7.yellow("Shared ledger not initialized"));
|
|
3061
2438
|
return;
|
|
3062
2439
|
}
|
|
3063
|
-
console.log(`Local blocks: ${
|
|
3064
|
-
console.log(`Shared blocks: ${
|
|
2440
|
+
console.log(`Local blocks: ${pc7.cyan(status.localBlocks.toString())}`);
|
|
2441
|
+
console.log(`Shared blocks: ${pc7.cyan(status.sharedBlocks.toString())}`);
|
|
3065
2442
|
const diff = status.sharedBlocks - status.localBlocks;
|
|
3066
2443
|
if (diff > 0) {
|
|
3067
|
-
console.log(
|
|
2444
|
+
console.log(pc7.green(`\u2193 ${diff} blocks available to pull`));
|
|
3068
2445
|
} else if (diff < 0) {
|
|
3069
|
-
console.log(
|
|
2446
|
+
console.log(pc7.blue(`\u2191 ${-diff} local blocks not yet pushed`));
|
|
3070
2447
|
} else {
|
|
3071
|
-
console.log(
|
|
2448
|
+
console.log(pc7.green("\u2713 Local and shared ledgers are in sync"));
|
|
3072
2449
|
}
|
|
3073
2450
|
if (status.conflicts > 0) {
|
|
3074
|
-
console.log(
|
|
2451
|
+
console.log(pc7.red(`\u26A0 ${status.conflicts} conflicts detected`));
|
|
3075
2452
|
}
|
|
3076
2453
|
} catch (error) {
|
|
3077
|
-
console.error(
|
|
2454
|
+
console.error(pc7.red("Failed to diff ledgers:"), error);
|
|
3078
2455
|
process.exit(1);
|
|
3079
2456
|
}
|
|
3080
2457
|
});
|
|
@@ -3088,66 +2465,66 @@ function createLedgerCommand() {
|
|
|
3088
2465
|
console.log("Compressing old ledger blocks...");
|
|
3089
2466
|
const result = await compressOldBlocks();
|
|
3090
2467
|
if (result.archived > 0) {
|
|
3091
|
-
console.log(
|
|
2468
|
+
console.log(pc7.green(`\u2713 Compressed ${result.archived} blocks`));
|
|
3092
2469
|
console.log(`Space saved: ${result.sizeReduction}%`);
|
|
3093
2470
|
} else {
|
|
3094
2471
|
console.log("No blocks were archived");
|
|
3095
2472
|
}
|
|
3096
2473
|
} catch (error) {
|
|
3097
|
-
console.error(
|
|
2474
|
+
console.error(pc7.red("Failed to compress blocks:"), error);
|
|
3098
2475
|
process.exit(1);
|
|
3099
2476
|
}
|
|
3100
2477
|
});
|
|
3101
2478
|
ledger.command("storage").description("Show detailed storage statistics").action(async () => {
|
|
3102
2479
|
try {
|
|
3103
2480
|
const stats = await getStorageStats();
|
|
3104
|
-
console.log(
|
|
3105
|
-
console.log(
|
|
3106
|
-
console.log(` Active blocks: ${
|
|
3107
|
-
console.log(` Archived blocks: ${
|
|
3108
|
-
console.log(
|
|
2481
|
+
console.log(pc7.bold("Ledger Storage Statistics\n"));
|
|
2482
|
+
console.log(pc7.bold("Block Storage:"));
|
|
2483
|
+
console.log(` Active blocks: ${pc7.cyan(stats.activeBlocks.toString())}`);
|
|
2484
|
+
console.log(` Archived blocks: ${pc7.cyan(stats.archivedBlocks.toString())}`);
|
|
2485
|
+
console.log(pc7.bold("\nStorage Usage:"));
|
|
3109
2486
|
const activeMB = (stats.activeSize / 1024 / 1024).toFixed(2);
|
|
3110
2487
|
const archivedMB = (stats.archivedSize / 1024 / 1024).toFixed(2);
|
|
3111
2488
|
const totalMB = (Number(activeMB) + Number(archivedMB)).toFixed(2);
|
|
3112
|
-
console.log(` Active storage: ${
|
|
3113
|
-
console.log(` Archived storage: ${
|
|
3114
|
-
console.log(` Total storage: ${
|
|
2489
|
+
console.log(` Active storage: ${pc7.cyan(`${activeMB} MB`)}`);
|
|
2490
|
+
console.log(` Archived storage: ${pc7.cyan(`${archivedMB} MB`)}`);
|
|
2491
|
+
console.log(` Total storage: ${pc7.bold(pc7.cyan(`${totalMB} MB`))}`);
|
|
3115
2492
|
if (stats.compressionRatio > 0) {
|
|
3116
|
-
console.log(` Compression ratio: ${
|
|
2493
|
+
console.log(` Compression ratio: ${pc7.green(`${stats.compressionRatio}%`)}`);
|
|
3117
2494
|
}
|
|
3118
|
-
console.log(
|
|
3119
|
-
console.log(` Total entries: ${
|
|
2495
|
+
console.log(pc7.bold("\nData:"));
|
|
2496
|
+
console.log(` Total entries: ${pc7.cyan(stats.totalEntries.toString())}`);
|
|
3120
2497
|
const needsCompression = await shouldCompress();
|
|
3121
2498
|
if (needsCompression) {
|
|
3122
2499
|
console.log(`
|
|
3123
|
-
${
|
|
2500
|
+
${pc7.yellow("\u{1F4A1} Tip:")} Run ${pc7.bold("trie ledger compress")} to archive old blocks`);
|
|
3124
2501
|
}
|
|
3125
2502
|
} catch (error) {
|
|
3126
|
-
console.error(
|
|
2503
|
+
console.error(pc7.red("Failed to get storage stats:"), error);
|
|
3127
2504
|
process.exit(1);
|
|
3128
2505
|
}
|
|
3129
2506
|
});
|
|
3130
2507
|
ledger.command("correct").description("Mark ledger entries as corrected (maintains immutability)").argument("<entry-ids...>", "Entry IDs to mark as corrected").option("-r, --reason <reason>", "Reason for the correction (required)").option("-t, --type <type>", "Correction type: corrected or false-positive", "corrected").action(async (entryIds, options) => {
|
|
3131
2508
|
try {
|
|
3132
2509
|
if (!options.reason) {
|
|
3133
|
-
console.error(
|
|
2510
|
+
console.error(pc7.red("\u2717 Correction reason is required"));
|
|
3134
2511
|
console.log("");
|
|
3135
2512
|
console.log("Usage:");
|
|
3136
|
-
console.log(` ${
|
|
2513
|
+
console.log(` ${pc7.dim('trie ledger correct <entry-id> -r "reason for correction"')}`);
|
|
3137
2514
|
console.log("");
|
|
3138
2515
|
console.log("Examples:");
|
|
3139
|
-
console.log(` ${
|
|
3140
|
-
console.log(` ${
|
|
2516
|
+
console.log(` ${pc7.dim('trie ledger correct abc123 -r "False positive - this is expected behavior"')}`);
|
|
2517
|
+
console.log(` ${pc7.dim('trie ledger correct xyz789 -r "Duplicate detection" -t false-positive')}`);
|
|
3141
2518
|
process.exit(1);
|
|
3142
2519
|
}
|
|
3143
2520
|
const validTypes = ["corrected", "false-positive"];
|
|
3144
2521
|
if (!validTypes.includes(options.type)) {
|
|
3145
|
-
console.error(
|
|
2522
|
+
console.error(pc7.red(`\u2717 Invalid correction type: ${options.type}`));
|
|
3146
2523
|
console.log(`Valid types: ${validTypes.join(", ")}`);
|
|
3147
2524
|
process.exit(1);
|
|
3148
2525
|
}
|
|
3149
|
-
console.log(
|
|
3150
|
-
console.log(`Reason: ${
|
|
2526
|
+
console.log(pc7.yellow(`\u{1F4DD} Marking ${entryIds.length} entry(ies) as ${options.type}...`));
|
|
2527
|
+
console.log(`Reason: ${pc7.dim(options.reason)}`);
|
|
3151
2528
|
console.log("");
|
|
3152
2529
|
const result = await correctLedgerEntries(
|
|
3153
2530
|
entryIds,
|
|
@@ -3155,16 +2532,16 @@ ${pc8.yellow("\u{1F4A1} Tip:")} Run ${pc8.bold("trie ledger compress")} to archi
|
|
|
3155
2532
|
options.type
|
|
3156
2533
|
);
|
|
3157
2534
|
if (result.success) {
|
|
3158
|
-
console.log(
|
|
2535
|
+
console.log(pc7.green(`\u2713 Successfully corrected ${result.correctedEntries} entry(ies)`));
|
|
3159
2536
|
console.log("");
|
|
3160
|
-
console.log(
|
|
3161
|
-
console.log(
|
|
2537
|
+
console.log(pc7.dim("Note: Original entries remain in the ledger for audit trail."));
|
|
2538
|
+
console.log(pc7.dim(" Queries will automatically filter out corrected entries."));
|
|
3162
2539
|
} else {
|
|
3163
|
-
console.error(
|
|
2540
|
+
console.error(pc7.red("\u2717 Correction failed:"), result.error);
|
|
3164
2541
|
process.exit(1);
|
|
3165
2542
|
}
|
|
3166
2543
|
} catch (error) {
|
|
3167
|
-
console.error(
|
|
2544
|
+
console.error(pc7.red("Failed to correct entries:"), error);
|
|
3168
2545
|
process.exit(1);
|
|
3169
2546
|
}
|
|
3170
2547
|
});
|
|
@@ -3176,17 +2553,17 @@ ${pc8.yellow("\u{1F4A1} Tip:")} Run ${pc8.bold("trie ledger compress")} to archi
|
|
|
3176
2553
|
console.log("No correction history found for the specified entries");
|
|
3177
2554
|
return;
|
|
3178
2555
|
}
|
|
3179
|
-
console.log(
|
|
2556
|
+
console.log(pc7.bold("Correction History\n"));
|
|
3180
2557
|
for (const [entryId, data] of history) {
|
|
3181
|
-
console.log(
|
|
3182
|
-
console.log(`Status: ${
|
|
3183
|
-
console.log(`File: ${
|
|
3184
|
-
console.log(`Agent: ${
|
|
2558
|
+
console.log(pc7.bold(pc7.cyan(`Entry: ${entryId}`)));
|
|
2559
|
+
console.log(`Status: ${pc7.yellow(data.original.status || "active")}`);
|
|
2560
|
+
console.log(`File: ${pc7.dim(data.original.file)}`);
|
|
2561
|
+
console.log(`Agent: ${pc7.dim(data.original.agent)}`);
|
|
3185
2562
|
if (data.original.correction) {
|
|
3186
2563
|
console.log(`Correction: ${data.original.correction}`);
|
|
3187
2564
|
}
|
|
3188
2565
|
if (data.original.correctionTimestamp) {
|
|
3189
|
-
console.log(`Corrected at: ${
|
|
2566
|
+
console.log(`Corrected at: ${pc7.dim(data.original.correctionTimestamp)}`);
|
|
3190
2567
|
}
|
|
3191
2568
|
if (data.corrections.length > 0) {
|
|
3192
2569
|
console.log("\nCorrection Entries:");
|
|
@@ -3198,17 +2575,17 @@ ${pc8.yellow("\u{1F4A1} Tip:")} Run ${pc8.bold("trie ledger compress")} to archi
|
|
|
3198
2575
|
}
|
|
3199
2576
|
} else {
|
|
3200
2577
|
const stats = await getCorrectionStats();
|
|
3201
|
-
console.log(
|
|
3202
|
-
console.log(`Total entries: ${
|
|
3203
|
-
console.log(`Active entries: ${
|
|
3204
|
-
console.log(`Corrected entries: ${
|
|
3205
|
-
console.log(`False positives: ${
|
|
3206
|
-
console.log(`Correction rate: ${
|
|
2578
|
+
console.log(pc7.bold("Correction Statistics\n"));
|
|
2579
|
+
console.log(`Total entries: ${pc7.cyan(stats.totalEntries.toString())}`);
|
|
2580
|
+
console.log(`Active entries: ${pc7.green(stats.activeEntries.toString())}`);
|
|
2581
|
+
console.log(`Corrected entries: ${pc7.yellow(stats.correctedEntries.toString())}`);
|
|
2582
|
+
console.log(`False positives: ${pc7.yellow(stats.falsePositives.toString())}`);
|
|
2583
|
+
console.log(`Correction rate: ${pc7.cyan(`${stats.correctionRate}%`)}`);
|
|
3207
2584
|
console.log("");
|
|
3208
|
-
console.log(
|
|
2585
|
+
console.log(pc7.dim("\u{1F4A1} Tip: Use --entries <id> to see correction history for specific entries"));
|
|
3209
2586
|
}
|
|
3210
2587
|
} catch (error) {
|
|
3211
|
-
console.error(
|
|
2588
|
+
console.error(pc7.red("Failed to show corrections:"), error);
|
|
3212
2589
|
process.exit(1);
|
|
3213
2590
|
}
|
|
3214
2591
|
});
|
|
@@ -3216,8 +2593,8 @@ ${pc8.yellow("\u{1F4A1} Tip:")} Run ${pc8.bold("trie ledger compress")} to archi
|
|
|
3216
2593
|
}
|
|
3217
2594
|
|
|
3218
2595
|
// src/cli/keys.ts
|
|
3219
|
-
import
|
|
3220
|
-
import { join as
|
|
2596
|
+
import pc8 from "picocolors";
|
|
2597
|
+
import { join as join3 } from "path";
|
|
3221
2598
|
async function handleKeysCommand(args) {
|
|
3222
2599
|
const subcommand = args[0]?.toLowerCase() || "status";
|
|
3223
2600
|
const workDir = getWorkingDirectory(void 0, true);
|
|
@@ -3241,7 +2618,7 @@ async function handleKeysCommand(args) {
|
|
|
3241
2618
|
showKeysHelp();
|
|
3242
2619
|
break;
|
|
3243
2620
|
default:
|
|
3244
|
-
console.error(
|
|
2621
|
+
console.error(pc8.red(`Unknown subcommand: ${subcommand}`));
|
|
3245
2622
|
showKeysHelp();
|
|
3246
2623
|
process.exit(1);
|
|
3247
2624
|
}
|
|
@@ -3249,34 +2626,34 @@ async function handleKeysCommand(args) {
|
|
|
3249
2626
|
async function handleKeysGenerate(workDir, force) {
|
|
3250
2627
|
const hasKey = hasSigningKey(workDir);
|
|
3251
2628
|
if (hasKey && !force) {
|
|
3252
|
-
console.log(
|
|
3253
|
-
console.log(
|
|
2629
|
+
console.log(pc8.yellow("Signing key already exists."));
|
|
2630
|
+
console.log(pc8.dim("Use --force to regenerate (WARNING: will invalidate existing signatures)"));
|
|
3254
2631
|
const pubKey = getPublicKey(workDir);
|
|
3255
2632
|
if (pubKey) {
|
|
3256
2633
|
console.log(`
|
|
3257
|
-
Public key: ${
|
|
2634
|
+
Public key: ${pc8.cyan(pubKey.slice(0, 16))}...${pc8.cyan(pubKey.slice(-8))}`);
|
|
3258
2635
|
}
|
|
3259
2636
|
return;
|
|
3260
2637
|
}
|
|
3261
2638
|
if (hasKey && force) {
|
|
3262
|
-
console.log(
|
|
3263
|
-
console.log(
|
|
2639
|
+
console.log(pc8.yellow("Regenerating signing key..."));
|
|
2640
|
+
console.log(pc8.red("WARNING: This will invalidate all existing signatures in the ledger."));
|
|
3264
2641
|
}
|
|
3265
2642
|
console.log("Generating Ed25519 signing key pair...\n");
|
|
3266
2643
|
const keyPair = await generateKeyPair();
|
|
3267
2644
|
saveKeyPair(keyPair, workDir);
|
|
3268
|
-
const keysDir =
|
|
3269
|
-
console.log(
|
|
3270
|
-
console.log(`Location: ${
|
|
3271
|
-
console.log(`Public key: ${
|
|
3272
|
-
console.log(`Algorithm: ${
|
|
2645
|
+
const keysDir = join3(getTrieDirectory(workDir), "keys");
|
|
2646
|
+
console.log(pc8.green("\u2713 Signing key generated successfully\n"));
|
|
2647
|
+
console.log(`Location: ${pc8.dim(keysDir)}`);
|
|
2648
|
+
console.log(`Public key: ${pc8.cyan(keyPair.publicKey.slice(0, 16))}...${pc8.cyan(keyPair.publicKey.slice(-8))}`);
|
|
2649
|
+
console.log(`Algorithm: ${pc8.dim("Ed25519")}
|
|
3273
2650
|
`);
|
|
3274
|
-
console.log(
|
|
2651
|
+
console.log(pc8.bold("What this means:"));
|
|
3275
2652
|
console.log(" \u2022 All new ledger entries will be signed automatically");
|
|
3276
2653
|
console.log(" \u2022 Signatures prove who created each entry");
|
|
3277
2654
|
console.log(" \u2022 Tampering with entries will be detectable");
|
|
3278
2655
|
console.log(" \u2022 Your private key stays local (never committed to git)\n");
|
|
3279
|
-
console.log(
|
|
2656
|
+
console.log(pc8.yellow("Security notes:"));
|
|
3280
2657
|
console.log(" \u2022 The private key is stored in .trie/keys/signing-key.json");
|
|
3281
2658
|
console.log(" \u2022 This directory is automatically added to .gitignore");
|
|
3282
2659
|
console.log(" \u2022 Back up this key if you need to prove authorship later");
|
|
@@ -3284,63 +2661,63 @@ Public key: ${pc9.cyan(pubKey.slice(0, 16))}...${pc9.cyan(pubKey.slice(-8))}`);
|
|
|
3284
2661
|
}
|
|
3285
2662
|
async function handleKeysStatus(workDir) {
|
|
3286
2663
|
const hasKey = hasSigningKey(workDir);
|
|
3287
|
-
const keysDir =
|
|
3288
|
-
console.log(
|
|
2664
|
+
const keysDir = join3(getTrieDirectory(workDir), "keys");
|
|
2665
|
+
console.log(pc8.bold("Signing Key Status\n"));
|
|
3289
2666
|
if (hasKey) {
|
|
3290
2667
|
const keyPair = loadKeyPair(workDir);
|
|
3291
|
-
const keyPath =
|
|
3292
|
-
console.log(`Status: ${
|
|
3293
|
-
console.log(`Location: ${
|
|
2668
|
+
const keyPath = join3(keysDir, "signing-key.json");
|
|
2669
|
+
console.log(`Status: ${pc8.green("\u2713 Active")}`);
|
|
2670
|
+
console.log(`Location: ${pc8.dim(keyPath)}`);
|
|
3294
2671
|
if (keyPair) {
|
|
3295
|
-
console.log(`Public key: ${
|
|
2672
|
+
console.log(`Public key: ${pc8.cyan(keyPair.publicKey.slice(0, 16))}...${pc8.cyan(keyPair.publicKey.slice(-8))}`);
|
|
3296
2673
|
}
|
|
3297
|
-
console.log(`Algorithm: ${
|
|
2674
|
+
console.log(`Algorithm: ${pc8.dim("Ed25519")}`);
|
|
3298
2675
|
console.log(`
|
|
3299
|
-
New ledger entries will be ${
|
|
2676
|
+
New ledger entries will be ${pc8.green("signed automatically")}.`);
|
|
3300
2677
|
} else {
|
|
3301
|
-
console.log(`Status: ${
|
|
2678
|
+
console.log(`Status: ${pc8.yellow("\u25CB Not configured")}`);
|
|
3302
2679
|
console.log(`
|
|
3303
|
-
Ledger entries are ${
|
|
2680
|
+
Ledger entries are ${pc8.yellow("not being signed")}.`);
|
|
3304
2681
|
console.log(`
|
|
3305
2682
|
To enable signing, run:`);
|
|
3306
|
-
console.log(` ${
|
|
2683
|
+
console.log(` ${pc8.cyan("trie keys generate")}`);
|
|
3307
2684
|
}
|
|
3308
2685
|
}
|
|
3309
2686
|
async function handleKeysPublic(workDir) {
|
|
3310
2687
|
const pubKey = getPublicKey(workDir);
|
|
3311
2688
|
if (!pubKey) {
|
|
3312
|
-
console.error(
|
|
3313
|
-
console.error(`Run ${
|
|
2689
|
+
console.error(pc8.yellow("No signing key found."));
|
|
2690
|
+
console.error(`Run ${pc8.cyan("trie keys generate")} to create one.`);
|
|
3314
2691
|
process.exit(1);
|
|
3315
2692
|
}
|
|
3316
2693
|
console.log(pubKey);
|
|
3317
2694
|
}
|
|
3318
2695
|
function showKeysHelp() {
|
|
3319
2696
|
console.log(`
|
|
3320
|
-
${
|
|
2697
|
+
${pc8.bold("trie keys")} - Manage Ed25519 signing keys for the governance ledger
|
|
3321
2698
|
|
|
3322
|
-
${
|
|
2699
|
+
${pc8.bold("USAGE:")}
|
|
3323
2700
|
trie keys <command> [options]
|
|
3324
2701
|
|
|
3325
|
-
${
|
|
2702
|
+
${pc8.bold("COMMANDS:")}
|
|
3326
2703
|
generate Generate a new Ed25519 signing key pair
|
|
3327
2704
|
status Show current key status (default)
|
|
3328
2705
|
public Print the public key (for sharing/verification)
|
|
3329
2706
|
help Show this help message
|
|
3330
2707
|
|
|
3331
|
-
${
|
|
2708
|
+
${pc8.bold("OPTIONS:")}
|
|
3332
2709
|
--force, -f Force regenerate key (WARNING: invalidates signatures)
|
|
3333
2710
|
|
|
3334
|
-
${
|
|
2711
|
+
${pc8.bold("EXAMPLES:")}
|
|
3335
2712
|
trie keys # Check if signing is configured
|
|
3336
2713
|
trie keys generate # Generate a new signing key
|
|
3337
2714
|
trie keys public # Get your public key for verification
|
|
3338
2715
|
|
|
3339
|
-
${
|
|
2716
|
+
${pc8.bold("ABOUT SIGNING:")}
|
|
3340
2717
|
Ed25519 signatures provide:
|
|
3341
|
-
\u2022 ${
|
|
3342
|
-
\u2022 ${
|
|
3343
|
-
\u2022 ${
|
|
2718
|
+
\u2022 ${pc8.green("Authenticity")} - Prove who created each ledger entry
|
|
2719
|
+
\u2022 ${pc8.green("Tamper-evidence")} - Detect if entries are modified
|
|
2720
|
+
\u2022 ${pc8.green("Accountability")} - Track decisions to humans or agents
|
|
3344
2721
|
|
|
3345
2722
|
Keys are stored locally in .trie/keys/ and never committed to git.
|
|
3346
2723
|
Each team member should generate their own key.
|
|
@@ -3394,23 +2771,16 @@ COMMANDS:
|
|
|
3394
2771
|
learn Train Trie from git history or feedback (alias: train)
|
|
3395
2772
|
ok Mark current pattern as good (alias: learn ok)
|
|
3396
2773
|
bad Mark current pattern as bad (alias: learn bad)
|
|
3397
|
-
quiet Snooze nudges for 1 hour
|
|
3398
2774
|
|
|
3399
|
-
checkpoint Save work context to .trie/ (aliases: cp, save)
|
|
3400
2775
|
linear sync Sync active tickets from Linear
|
|
3401
2776
|
gotcha Predict problems with current changes (alias: predict)
|
|
3402
|
-
reconcile Reconcile context graph from JSON backup
|
|
3403
2777
|
|
|
3404
|
-
audit View security audit logs
|
|
3405
2778
|
memory Search and manage issue memory
|
|
3406
|
-
patterns Save, validate, and share patterns across projects
|
|
3407
2779
|
status Quick health check (project health + memory stats)
|
|
3408
2780
|
project View/manage project info (.trie/PROJECT.md)
|
|
3409
2781
|
setup Configure API key and environment
|
|
3410
2782
|
keys Manage Ed25519 signing keys (for ledger signatures)
|
|
3411
2783
|
|
|
3412
|
-
ci Generate GitHub Actions workflow with memory caching
|
|
3413
|
-
|
|
3414
2784
|
help Show this help message
|
|
3415
2785
|
version Show version information
|
|
3416
2786
|
|
|
@@ -3422,7 +2792,6 @@ EXAMPLES:
|
|
|
3422
2792
|
trie tell "users couldn't log in" # Report an incident
|
|
3423
2793
|
trie ok # Mark current pattern as good
|
|
3424
2794
|
trie bad # Mark current pattern as bad
|
|
3425
|
-
trie quiet # Snooze nudges for 1 hour
|
|
3426
2795
|
|
|
3427
2796
|
trie linear sync # Sync active tickets from Linear
|
|
3428
2797
|
trie learn # Scan history for precedents
|
|
@@ -3433,7 +2802,6 @@ EXAMPLES:
|
|
|
3433
2802
|
trie memory search "SQL injection"
|
|
3434
2803
|
trie memory stats # View memory statistics
|
|
3435
2804
|
trie status # Quick health check (project + memory)
|
|
3436
|
-
trie ci # Generate CI workflow with memory caching
|
|
3437
2805
|
|
|
3438
2806
|
MCP TOOLS (use via Cursor/Claude Desktop):
|
|
3439
2807
|
trie_linear_sync Sync active tickets from Linear
|
|
@@ -3459,47 +2827,47 @@ async function handleStatusCommand() {
|
|
|
3459
2827
|
const lastScanDate = new Date(state.lastScan.timestamp);
|
|
3460
2828
|
const daysAgo = Math.floor((Date.now() - lastScanDate.getTime()) / (1e3 * 60 * 60 * 24));
|
|
3461
2829
|
console.log(`
|
|
3462
|
-
${
|
|
3463
|
-
console.log(
|
|
3464
|
-
console.log(
|
|
2830
|
+
${pc9.bold("Last Scan:")} ${lastScanDate.toLocaleDateString()} (${daysAgo === 0 ? "today" : daysAgo === 1 ? "yesterday" : `${daysAgo} days ago`})`);
|
|
2831
|
+
console.log(pc9.dim(` Files scanned: ${state.lastScan.filesScanned}`));
|
|
2832
|
+
console.log(pc9.dim(` Issues found: ${state.lastScan.issues.total} (${state.lastScan.issues.critical} critical, ${state.lastScan.issues.serious} serious)`));
|
|
3465
2833
|
} else {
|
|
3466
2834
|
console.log(`
|
|
3467
|
-
${
|
|
2835
|
+
${pc9.bold("Last Scan:")} Never ${pc9.dim("(run `trie watch` to get started)")}`);
|
|
3468
2836
|
}
|
|
3469
2837
|
console.log(`
|
|
3470
|
-
${
|
|
3471
|
-
console.log(
|
|
3472
|
-
console.log(
|
|
3473
|
-
console.log(
|
|
2838
|
+
${pc9.bold("Memory Stats:")}`);
|
|
2839
|
+
console.log(pc9.dim(` Active Issues: ${memoryStats.activeIssues}`));
|
|
2840
|
+
console.log(pc9.dim(` Resolved: ${memoryStats.resolvedCount}`));
|
|
2841
|
+
console.log(pc9.dim(` Total (all-time): ${memoryStats.totalIssues}`));
|
|
3474
2842
|
const cap = memoryStats.capacityInfo;
|
|
3475
|
-
const capIndicator = cap.isAtCap ?
|
|
3476
|
-
console.log(` ${capIndicator} Memory Usage: ${
|
|
2843
|
+
const capIndicator = cap.isAtCap ? pc9.red("\u25CB") : cap.percentFull >= 80 ? pc9.yellow("\u25C9") : pc9.green("\u25CF");
|
|
2844
|
+
console.log(` ${capIndicator} Memory Usage: ${pc9.bold(cap.percentFull + "%")} ${pc9.dim(`(${cap.current}/${cap.max})`)}`);
|
|
3477
2845
|
if (memoryStats.activeIssues > 0) {
|
|
3478
2846
|
console.log(`
|
|
3479
|
-
${
|
|
2847
|
+
${pc9.bold("Active Issues by Severity:")}`);
|
|
3480
2848
|
const severityOrder = ["critical", "serious", "moderate", "low", "info"];
|
|
3481
2849
|
for (const severity of severityOrder) {
|
|
3482
2850
|
const count = memoryStats.activeIssuesBySeverity[severity] || 0;
|
|
3483
2851
|
if (count > 0) {
|
|
3484
|
-
console.log(
|
|
2852
|
+
console.log(pc9.dim(` ${severity}: ${count}`));
|
|
3485
2853
|
}
|
|
3486
2854
|
}
|
|
3487
2855
|
} else if (memoryStats.totalIssues > 0) {
|
|
3488
2856
|
console.log(`
|
|
3489
|
-
${
|
|
2857
|
+
${pc9.green("\u25CF")} All issues have been resolved`);
|
|
3490
2858
|
}
|
|
3491
2859
|
if (cap.isAtCap) {
|
|
3492
2860
|
console.log(`
|
|
3493
|
-
${
|
|
2861
|
+
${pc9.yellow("\u2B22 Warning:")} Memory at capacity - consider running: ${pc9.bold("trie memory purge smart")}`);
|
|
3494
2862
|
} else if (cap.percentFull >= 80) {
|
|
3495
2863
|
console.log(`
|
|
3496
|
-
${
|
|
2864
|
+
${pc9.yellow("\u2B22 Notice:")} Memory usage high - consider running: ${pc9.bold("trie memory purge smart")}`);
|
|
3497
2865
|
}
|
|
3498
2866
|
console.log(`
|
|
3499
|
-
${
|
|
3500
|
-
console.log(
|
|
3501
|
-
console.log(
|
|
3502
|
-
console.log(
|
|
2867
|
+
${pc9.bold("Quick Commands:")}`);
|
|
2868
|
+
console.log(pc9.dim(" trie watch - Start watching for nudges"));
|
|
2869
|
+
console.log(pc9.dim(" trie memory stats - Detailed memory statistics"));
|
|
2870
|
+
console.log(pc9.dim(" trie project - View project information"));
|
|
3503
2871
|
console.log("");
|
|
3504
2872
|
} catch (error) {
|
|
3505
2873
|
console.error("Error loading status:", error);
|
|
@@ -3517,7 +2885,7 @@ async function handleProject(args) {
|
|
|
3517
2885
|
\u2551 PROJECT.md Created \u2551
|
|
3518
2886
|
\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
|
|
3519
2887
|
|
|
3520
|
-
${
|
|
2888
|
+
${pc9.bold("Path:")} ${result.path}
|
|
3521
2889
|
|
|
3522
2890
|
A template has been created with sections for:
|
|
3523
2891
|
\u2022 Project Overview
|
|
@@ -3542,7 +2910,7 @@ Next steps:
|
|
|
3542
2910
|
}
|
|
3543
2911
|
if (subcommand === "edit") {
|
|
3544
2912
|
const editor = process.env.EDITOR || process.env.VISUAL || "nano";
|
|
3545
|
-
const projectPath =
|
|
2913
|
+
const projectPath = join4(getTrieDirectory(workDir), "PROJECT.md");
|
|
3546
2914
|
if (!projectInfoExists(workDir)) {
|
|
3547
2915
|
console.log("No PROJECT.md found. Creating one first...");
|
|
3548
2916
|
await initProjectInfo(workDir);
|
|
@@ -3560,7 +2928,7 @@ Next steps:
|
|
|
3560
2928
|
\u2551 Project Information \u2551
|
|
3561
2929
|
\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
|
|
3562
2930
|
|
|
3563
|
-
${
|
|
2931
|
+
${pc9.bold("No PROJECT.md found in this project.")}
|
|
3564
2932
|
|
|
3565
2933
|
COMMANDS:
|
|
3566
2934
|
trie project init Create PROJECT.md from template
|
|
@@ -3588,7 +2956,7 @@ This info is available via trie://project MCP resource.
|
|
|
3588
2956
|
\u2551 Project Information \u2551
|
|
3589
2957
|
\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
|
|
3590
2958
|
|
|
3591
|
-
${
|
|
2959
|
+
${pc9.bold("Path:")} ${join4(getTrieDirectory(workDir), "PROJECT.md")}
|
|
3592
2960
|
|
|
3593
2961
|
${"-".repeat(68)}
|
|
3594
2962
|
`);
|
|
@@ -3647,19 +3015,11 @@ async function main() {
|
|
|
3647
3015
|
case "stats":
|
|
3648
3016
|
await handleStatusCommand();
|
|
3649
3017
|
break;
|
|
3650
|
-
case "checkpoint":
|
|
3651
|
-
case "cp":
|
|
3652
|
-
case "save":
|
|
3653
|
-
handleCheckpointCommand(restArgs);
|
|
3654
|
-
break;
|
|
3655
3018
|
case "project":
|
|
3656
3019
|
case "info":
|
|
3657
3020
|
case "project-info":
|
|
3658
3021
|
handleProject(restArgs);
|
|
3659
3022
|
break;
|
|
3660
|
-
case "audit":
|
|
3661
|
-
handleAuditCommand(restArgs);
|
|
3662
|
-
break;
|
|
3663
3023
|
case "version":
|
|
3664
3024
|
case "--version":
|
|
3665
3025
|
case "-v":
|
|
@@ -3697,9 +3057,6 @@ async function main() {
|
|
|
3697
3057
|
case "tell":
|
|
3698
3058
|
handleTellCommand(restArgs);
|
|
3699
3059
|
break;
|
|
3700
|
-
case "reconcile":
|
|
3701
|
-
handleReconcileCommand(restArgs);
|
|
3702
|
-
break;
|
|
3703
3060
|
case "learn":
|
|
3704
3061
|
case "train":
|
|
3705
3062
|
handleLearnCommand(restArgs);
|
|
@@ -3712,14 +3069,6 @@ async function main() {
|
|
|
3712
3069
|
case "thumbs-down":
|
|
3713
3070
|
handleLearnCommand(["bad", ...restArgs]);
|
|
3714
3071
|
break;
|
|
3715
|
-
case "quiet":
|
|
3716
|
-
case "snooze":
|
|
3717
|
-
handleQuietCommand();
|
|
3718
|
-
break;
|
|
3719
|
-
case "ci":
|
|
3720
|
-
case "ci-setup":
|
|
3721
|
-
handleCISetupCommand(restArgs);
|
|
3722
|
-
break;
|
|
3723
3072
|
case "linear":
|
|
3724
3073
|
handleLinearCommand(restArgs);
|
|
3725
3074
|
break;
|
|
@@ -3727,10 +3076,6 @@ async function main() {
|
|
|
3727
3076
|
case "predict":
|
|
3728
3077
|
handleGotchaCommand();
|
|
3729
3078
|
break;
|
|
3730
|
-
case "patterns":
|
|
3731
|
-
case "pattern":
|
|
3732
|
-
handlePatternsCommand(restArgs);
|
|
3733
|
-
break;
|
|
3734
3079
|
case "sync":
|
|
3735
3080
|
{
|
|
3736
3081
|
const syncCommand = createSyncCommand();
|