@triedotdev/mcp 1.0.110 → 1.0.111
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/dist/{chunk-OTTR5JX4.js → chunk-6QR6QZIX.js} +70 -1
- package/dist/chunk-6QR6QZIX.js.map +1 -0
- package/dist/{chunk-OD4SLUIV.js → chunk-HGEKZ2VS.js} +2919 -371
- package/dist/chunk-HGEKZ2VS.js.map +1 -0
- package/dist/chunk-QYOACM2C.js +1923 -0
- package/dist/chunk-QYOACM2C.js.map +1 -0
- package/dist/{chunk-SUHYYM2J.js → chunk-SDS3UVFY.js} +2 -2
- package/dist/chunk-TKMV7JKN.js +1562 -0
- package/dist/chunk-TKMV7JKN.js.map +1 -0
- package/dist/cli/main.js +320 -57
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +4 -4
- package/dist/{guardian-agent-4UJN5QGX.js → guardian-agent-XEYNG7RH.js} +3 -3
- package/dist/index.js +357 -2593
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-FLBK5ILJ.js +0 -3729
- package/dist/chunk-FLBK5ILJ.js.map +0 -1
- package/dist/chunk-HIKONDDO.js +0 -26
- package/dist/chunk-HIKONDDO.js.map +0 -1
- package/dist/chunk-OD4SLUIV.js.map +0 -1
- package/dist/chunk-OTTR5JX4.js.map +0 -1
- /package/dist/{chunk-SUHYYM2J.js.map → chunk-SDS3UVFY.js.map} +0 -0
- /package/dist/{guardian-agent-4UJN5QGX.js.map → guardian-agent-XEYNG7RH.js.map} +0 -0
package/dist/cli/main.js
CHANGED
|
@@ -1,39 +1,34 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
|
-
IncidentIndex,
|
|
4
|
-
LearningEngine,
|
|
5
3
|
LinearIngester,
|
|
6
4
|
completeBootstrap,
|
|
5
|
+
getSkillCategories,
|
|
6
|
+
initProjectInfo,
|
|
7
|
+
initializeBootstrapFiles,
|
|
8
|
+
loadConfig,
|
|
9
|
+
loadContextState,
|
|
10
|
+
loadProjectInfo,
|
|
11
|
+
needsBootstrap,
|
|
12
|
+
projectInfoExists,
|
|
13
|
+
saveConfig
|
|
14
|
+
} from "../chunk-TKMV7JKN.js";
|
|
15
|
+
import {
|
|
16
|
+
IncidentIndex,
|
|
17
|
+
LearningEngine,
|
|
7
18
|
exportToJson,
|
|
8
19
|
formatAuditLog,
|
|
9
20
|
formatFriendlyError,
|
|
10
21
|
getAuditStatistics,
|
|
11
|
-
getAutonomyConfig,
|
|
12
22
|
getRecentAuditLogs,
|
|
13
23
|
getSkillAuditLogs,
|
|
14
|
-
getSkillCategories,
|
|
15
24
|
getStagedChanges,
|
|
16
25
|
getUncommittedChanges,
|
|
17
26
|
handleCheckpointCommand,
|
|
18
27
|
importFromJson,
|
|
19
|
-
|
|
20
|
-
initializeBootstrapFiles,
|
|
21
|
-
loadConfig,
|
|
22
|
-
loadContextState,
|
|
23
|
-
loadProjectInfo,
|
|
24
|
-
needsBootstrap,
|
|
28
|
+
isTrieInitialized,
|
|
25
29
|
perceiveCurrentChanges,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
recordBypass,
|
|
29
|
-
saveConfig,
|
|
30
|
-
shouldAutoFix,
|
|
31
|
-
shouldBlockPush,
|
|
32
|
-
trackIssueOccurrence
|
|
33
|
-
} from "../chunk-FLBK5ILJ.js";
|
|
34
|
-
import {
|
|
35
|
-
isTrieInitialized
|
|
36
|
-
} from "../chunk-HIKONDDO.js";
|
|
30
|
+
reasonAboutChangesHumanReadable
|
|
31
|
+
} from "../chunk-QYOACM2C.js";
|
|
37
32
|
import {
|
|
38
33
|
ContextGraph,
|
|
39
34
|
GotchaPredictor,
|
|
@@ -42,7 +37,7 @@ import {
|
|
|
42
37
|
listTrackedProjects,
|
|
43
38
|
searchGlobalPatterns,
|
|
44
39
|
updateGlobalMemoryMd
|
|
45
|
-
} from "../chunk-
|
|
40
|
+
} from "../chunk-6QR6QZIX.js";
|
|
46
41
|
import "../chunk-IXO4G4D3.js";
|
|
47
42
|
import {
|
|
48
43
|
getDailyLogs,
|
|
@@ -65,7 +60,7 @@ import {
|
|
|
65
60
|
} from "../chunk-DGUM43GV.js";
|
|
66
61
|
|
|
67
62
|
// src/cli/main.ts
|
|
68
|
-
import { resolve, join as
|
|
63
|
+
import { resolve, join as join4, dirname } from "path";
|
|
69
64
|
import { readFileSync } from "fs";
|
|
70
65
|
import { fileURLToPath } from "url";
|
|
71
66
|
|
|
@@ -710,6 +705,274 @@ async function handleCheckCommand(args) {
|
|
|
710
705
|
}
|
|
711
706
|
}
|
|
712
707
|
|
|
708
|
+
// src/utils/autonomy-config.ts
|
|
709
|
+
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
710
|
+
import { existsSync } from "fs";
|
|
711
|
+
import { join } from "path";
|
|
712
|
+
|
|
713
|
+
// src/types/autonomy.ts
|
|
714
|
+
var DEFAULT_AUTONOMY_CONFIG = {
|
|
715
|
+
level: "proactive",
|
|
716
|
+
autoCheck: {
|
|
717
|
+
enabled: true,
|
|
718
|
+
threshold: 5,
|
|
719
|
+
onCritical: true,
|
|
720
|
+
cooldownMs: 3e4
|
|
721
|
+
// 30 seconds
|
|
722
|
+
},
|
|
723
|
+
autoFix: {
|
|
724
|
+
enabled: true,
|
|
725
|
+
askFirst: true,
|
|
726
|
+
// Always ask (human-in-the-loop)
|
|
727
|
+
categories: ["trivial", "safe"],
|
|
728
|
+
allowedFixTypes: [
|
|
729
|
+
"remove-console-log",
|
|
730
|
+
"remove-unused-import",
|
|
731
|
+
"add-missing-await",
|
|
732
|
+
"fix-typo"
|
|
733
|
+
]
|
|
734
|
+
},
|
|
735
|
+
pushBlocking: {
|
|
736
|
+
enabled: true,
|
|
737
|
+
allowBypass: true,
|
|
738
|
+
blockOn: ["critical"],
|
|
739
|
+
bypassMethods: ["env", "flag", "confirm"],
|
|
740
|
+
logBypasses: true
|
|
741
|
+
},
|
|
742
|
+
progressiveEscalation: {
|
|
743
|
+
enabled: true,
|
|
744
|
+
thresholds: {
|
|
745
|
+
suggest: 1,
|
|
746
|
+
autoCheck: 3,
|
|
747
|
+
escalate: 5,
|
|
748
|
+
block: 10
|
|
749
|
+
},
|
|
750
|
+
windowMs: 24 * 60 * 60 * 1e3
|
|
751
|
+
// 24 hours
|
|
752
|
+
}
|
|
753
|
+
};
|
|
754
|
+
|
|
755
|
+
// src/utils/autonomy-config.ts
|
|
756
|
+
import { createHash } from "crypto";
|
|
757
|
+
async function loadAutonomyConfig(projectPath) {
|
|
758
|
+
const configPath = join(getTrieDirectory(projectPath), "config.json");
|
|
759
|
+
try {
|
|
760
|
+
if (!existsSync(configPath)) {
|
|
761
|
+
return { ...DEFAULT_AUTONOMY_CONFIG };
|
|
762
|
+
}
|
|
763
|
+
const content = await readFile(configPath, "utf-8");
|
|
764
|
+
const config = JSON.parse(content);
|
|
765
|
+
return mergeWithDefaults(config.autonomy || {});
|
|
766
|
+
} catch (error) {
|
|
767
|
+
console.error("Failed to load autonomy config:", error);
|
|
768
|
+
return { ...DEFAULT_AUTONOMY_CONFIG };
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
function mergeWithDefaults(partial) {
|
|
772
|
+
return {
|
|
773
|
+
level: partial.level ?? DEFAULT_AUTONOMY_CONFIG.level,
|
|
774
|
+
autoCheck: {
|
|
775
|
+
...DEFAULT_AUTONOMY_CONFIG.autoCheck,
|
|
776
|
+
...partial.autoCheck || {}
|
|
777
|
+
},
|
|
778
|
+
autoFix: {
|
|
779
|
+
...DEFAULT_AUTONOMY_CONFIG.autoFix,
|
|
780
|
+
...partial.autoFix || {}
|
|
781
|
+
},
|
|
782
|
+
pushBlocking: {
|
|
783
|
+
...DEFAULT_AUTONOMY_CONFIG.pushBlocking,
|
|
784
|
+
...partial.pushBlocking || {}
|
|
785
|
+
},
|
|
786
|
+
progressiveEscalation: {
|
|
787
|
+
...DEFAULT_AUTONOMY_CONFIG.progressiveEscalation,
|
|
788
|
+
...partial.progressiveEscalation || {},
|
|
789
|
+
thresholds: {
|
|
790
|
+
...DEFAULT_AUTONOMY_CONFIG.progressiveEscalation.thresholds,
|
|
791
|
+
...partial.progressiveEscalation?.thresholds || {}
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
};
|
|
795
|
+
}
|
|
796
|
+
var occurrenceCache = /* @__PURE__ */ new Map();
|
|
797
|
+
async function getOccurrences(projectPath) {
|
|
798
|
+
if (occurrenceCache.has(projectPath)) {
|
|
799
|
+
return occurrenceCache.get(projectPath);
|
|
800
|
+
}
|
|
801
|
+
const occurrencesPath = join(getTrieDirectory(projectPath), "memory", "occurrences.json");
|
|
802
|
+
const occurrences = /* @__PURE__ */ new Map();
|
|
803
|
+
try {
|
|
804
|
+
if (existsSync(occurrencesPath)) {
|
|
805
|
+
const content = await readFile(occurrencesPath, "utf-8");
|
|
806
|
+
const data = JSON.parse(content);
|
|
807
|
+
for (const [hash, occ] of Object.entries(data)) {
|
|
808
|
+
occurrences.set(hash, occ);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
} catch {
|
|
812
|
+
}
|
|
813
|
+
occurrenceCache.set(projectPath, occurrences);
|
|
814
|
+
return occurrences;
|
|
815
|
+
}
|
|
816
|
+
async function saveOccurrences(projectPath) {
|
|
817
|
+
const occurrences = occurrenceCache.get(projectPath);
|
|
818
|
+
if (!occurrences) return;
|
|
819
|
+
const occurrencesPath = join(getTrieDirectory(projectPath), "memory", "occurrences.json");
|
|
820
|
+
const memoryDir = join(getTrieDirectory(projectPath), "memory");
|
|
821
|
+
try {
|
|
822
|
+
if (!existsSync(memoryDir)) {
|
|
823
|
+
await mkdir(memoryDir, { recursive: true });
|
|
824
|
+
}
|
|
825
|
+
const data = {};
|
|
826
|
+
for (const [hash, occ] of occurrences.entries()) {
|
|
827
|
+
data[hash] = occ;
|
|
828
|
+
}
|
|
829
|
+
await writeFile(occurrencesPath, JSON.stringify(data, null, 2));
|
|
830
|
+
} catch (error) {
|
|
831
|
+
console.error("Failed to save occurrences:", error);
|
|
832
|
+
}
|
|
833
|
+
}
|
|
834
|
+
function createIssueHash(file, line, issueType) {
|
|
835
|
+
const input = `${file}:${line || 0}:${issueType}`;
|
|
836
|
+
return createHash("md5").update(input).digest("hex").slice(0, 12);
|
|
837
|
+
}
|
|
838
|
+
async function trackIssueOccurrence(projectPath, file, line, issueType, config) {
|
|
839
|
+
const occurrences = await getOccurrences(projectPath);
|
|
840
|
+
const hash = createIssueHash(file, line, issueType);
|
|
841
|
+
const now = Date.now();
|
|
842
|
+
let occurrence = occurrences.get(hash);
|
|
843
|
+
if (occurrence) {
|
|
844
|
+
const windowMs = config.progressiveEscalation.windowMs;
|
|
845
|
+
if (now - occurrence.firstSeen > windowMs) {
|
|
846
|
+
occurrence = {
|
|
847
|
+
hash,
|
|
848
|
+
firstSeen: now,
|
|
849
|
+
lastSeen: now,
|
|
850
|
+
count: 1,
|
|
851
|
+
escalationLevel: "suggest",
|
|
852
|
+
notified: false,
|
|
853
|
+
bypassed: false,
|
|
854
|
+
bypassHistory: occurrence.bypassHistory
|
|
855
|
+
// Keep bypass history
|
|
856
|
+
};
|
|
857
|
+
} else {
|
|
858
|
+
occurrence.lastSeen = now;
|
|
859
|
+
occurrence.count++;
|
|
860
|
+
const thresholds = config.progressiveEscalation.thresholds;
|
|
861
|
+
if (occurrence.count >= thresholds.block) {
|
|
862
|
+
occurrence.escalationLevel = "block";
|
|
863
|
+
} else if (occurrence.count >= thresholds.escalate) {
|
|
864
|
+
occurrence.escalationLevel = "escalate";
|
|
865
|
+
} else if (occurrence.count >= thresholds.autoCheck) {
|
|
866
|
+
occurrence.escalationLevel = "autoCheck";
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
} else {
|
|
870
|
+
occurrence = {
|
|
871
|
+
hash,
|
|
872
|
+
firstSeen: now,
|
|
873
|
+
lastSeen: now,
|
|
874
|
+
count: 1,
|
|
875
|
+
escalationLevel: "suggest",
|
|
876
|
+
notified: false,
|
|
877
|
+
bypassed: false,
|
|
878
|
+
bypassHistory: []
|
|
879
|
+
};
|
|
880
|
+
}
|
|
881
|
+
occurrences.set(hash, occurrence);
|
|
882
|
+
await saveOccurrences(projectPath);
|
|
883
|
+
return occurrence;
|
|
884
|
+
}
|
|
885
|
+
async function recordBypass(projectPath, file, line, issueType, method, reason) {
|
|
886
|
+
const occurrences = await getOccurrences(projectPath);
|
|
887
|
+
const hash = createIssueHash(file, line, issueType);
|
|
888
|
+
const occurrence = occurrences.get(hash);
|
|
889
|
+
if (occurrence) {
|
|
890
|
+
occurrence.bypassed = true;
|
|
891
|
+
occurrence.bypassHistory.push({
|
|
892
|
+
timestamp: Date.now(),
|
|
893
|
+
method,
|
|
894
|
+
...reason !== void 0 ? { reason } : {}
|
|
895
|
+
});
|
|
896
|
+
await saveOccurrences(projectPath);
|
|
897
|
+
}
|
|
898
|
+
}
|
|
899
|
+
function shouldAutoFix(fix, config) {
|
|
900
|
+
if (!config.autoFix.enabled) {
|
|
901
|
+
return false;
|
|
902
|
+
}
|
|
903
|
+
const allowedCategories = config.autoFix.categories;
|
|
904
|
+
if (!allowedCategories.includes(fix.category) && !allowedCategories.includes("all")) {
|
|
905
|
+
return false;
|
|
906
|
+
}
|
|
907
|
+
if (config.autoFix.allowedFixTypes.length > 0 && !config.autoFix.allowedFixTypes.includes(fix.type)) {
|
|
908
|
+
return false;
|
|
909
|
+
}
|
|
910
|
+
if (fix.confidence < 0.9) {
|
|
911
|
+
return false;
|
|
912
|
+
}
|
|
913
|
+
return true;
|
|
914
|
+
}
|
|
915
|
+
function shouldBlockPush(issues, config) {
|
|
916
|
+
if (!config.pushBlocking.enabled) {
|
|
917
|
+
return {
|
|
918
|
+
blocked: false,
|
|
919
|
+
blockingIssues: [],
|
|
920
|
+
bypassed: false
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
const blockingIssues = issues.filter(
|
|
924
|
+
(issue) => config.pushBlocking.blockOn.includes(issue.severity)
|
|
925
|
+
);
|
|
926
|
+
if (blockingIssues.length === 0) {
|
|
927
|
+
return {
|
|
928
|
+
blocked: false,
|
|
929
|
+
blockingIssues: [],
|
|
930
|
+
bypassed: false
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
const envBypass = process.env.TRIE_BYPASS === "1" || process.env.TRIE_BYPASS === "true";
|
|
934
|
+
if (envBypass && config.pushBlocking.allowBypass) {
|
|
935
|
+
return {
|
|
936
|
+
blocked: false,
|
|
937
|
+
blockingIssues,
|
|
938
|
+
bypassed: true,
|
|
939
|
+
bypassMethod: "env"
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
const bypassInstructions = buildBypassInstructions(config);
|
|
943
|
+
return {
|
|
944
|
+
blocked: true,
|
|
945
|
+
reason: `${blockingIssues.length} ${blockingIssues[0]?.severity || "critical"} issue(s) must be fixed before pushing`,
|
|
946
|
+
blockingIssues,
|
|
947
|
+
bypassInstructions,
|
|
948
|
+
bypassed: false
|
|
949
|
+
};
|
|
950
|
+
}
|
|
951
|
+
function buildBypassInstructions(config) {
|
|
952
|
+
const instructions = [];
|
|
953
|
+
if (config.pushBlocking.bypassMethods.includes("env")) {
|
|
954
|
+
instructions.push("\u2022 Set TRIE_BYPASS=1 to bypass: TRIE_BYPASS=1 git push");
|
|
955
|
+
}
|
|
956
|
+
if (config.pushBlocking.bypassMethods.includes("flag")) {
|
|
957
|
+
instructions.push("\u2022 Use --no-verify flag: git push --no-verify");
|
|
958
|
+
}
|
|
959
|
+
if (config.pushBlocking.bypassMethods.includes("confirm")) {
|
|
960
|
+
instructions.push("\u2022 Run: trie bypass --confirm to bypass this push");
|
|
961
|
+
}
|
|
962
|
+
return instructions.join("\n");
|
|
963
|
+
}
|
|
964
|
+
var configCache = /* @__PURE__ */ new Map();
|
|
965
|
+
var CACHE_TTL = 6e4;
|
|
966
|
+
async function getAutonomyConfig(projectPath) {
|
|
967
|
+
const cached = configCache.get(projectPath);
|
|
968
|
+
if (cached && Date.now() - cached.loadedAt < CACHE_TTL) {
|
|
969
|
+
return cached.config;
|
|
970
|
+
}
|
|
971
|
+
const config = await loadAutonomyConfig(projectPath);
|
|
972
|
+
configCache.set(projectPath, { config, loadedAt: Date.now() });
|
|
973
|
+
return config;
|
|
974
|
+
}
|
|
975
|
+
|
|
713
976
|
// src/cli/pre-push.ts
|
|
714
977
|
import pc from "picocolors";
|
|
715
978
|
function parseArgs2(args) {
|
|
@@ -843,8 +1106,8 @@ function collectIssuesForBlocking(reasoning) {
|
|
|
843
1106
|
}
|
|
844
1107
|
|
|
845
1108
|
// src/cli/auto-fix.ts
|
|
846
|
-
import { readFile, writeFile } from "fs/promises";
|
|
847
|
-
import { existsSync } from "fs";
|
|
1109
|
+
import { readFile as readFile2, writeFile as writeFile2 } from "fs/promises";
|
|
1110
|
+
import { existsSync as existsSync2 } from "fs";
|
|
848
1111
|
import { createInterface } from "readline";
|
|
849
1112
|
import pc2 from "picocolors";
|
|
850
1113
|
function detectAutoFixes(issues) {
|
|
@@ -920,11 +1183,11 @@ function displayFixPreview(fix, index, total) {
|
|
|
920
1183
|
}
|
|
921
1184
|
async function applyFix(fix) {
|
|
922
1185
|
try {
|
|
923
|
-
if (!
|
|
1186
|
+
if (!existsSync2(fix.file)) {
|
|
924
1187
|
console.error(pc2.red(`File not found: ${fix.file}`));
|
|
925
1188
|
return false;
|
|
926
1189
|
}
|
|
927
|
-
const content = await
|
|
1190
|
+
const content = await readFile2(fix.file, "utf-8");
|
|
928
1191
|
const lines = content.split("\n");
|
|
929
1192
|
if (fix.line === void 0 || fix.line < 1 || fix.line > lines.length) {
|
|
930
1193
|
console.error(pc2.red(`Invalid line number: ${fix.line}`));
|
|
@@ -943,7 +1206,7 @@ async function applyFix(fix) {
|
|
|
943
1206
|
console.error(pc2.red(`Unknown fix type: ${fix.type}`));
|
|
944
1207
|
return false;
|
|
945
1208
|
}
|
|
946
|
-
await
|
|
1209
|
+
await writeFile2(fix.file, newContent);
|
|
947
1210
|
console.error(pc2.green(`\u2713 Applied fix to ${fix.file}:${fix.line}`));
|
|
948
1211
|
if (originalLine) {
|
|
949
1212
|
console.error(pc2.dim(` Removed: ${originalLine.trim().slice(0, 60)}...`));
|
|
@@ -957,11 +1220,11 @@ async function applyFix(fix) {
|
|
|
957
1220
|
async function loadFixContent(fixes) {
|
|
958
1221
|
const enrichedFixes = [];
|
|
959
1222
|
for (const fix of fixes) {
|
|
960
|
-
if (!fix.line || !
|
|
1223
|
+
if (!fix.line || !existsSync2(fix.file)) {
|
|
961
1224
|
continue;
|
|
962
1225
|
}
|
|
963
1226
|
try {
|
|
964
|
-
const content = await
|
|
1227
|
+
const content = await readFile2(fix.file, "utf-8");
|
|
965
1228
|
const lines = content.split("\n");
|
|
966
1229
|
const originalLine = lines[fix.line - 1];
|
|
967
1230
|
if (originalLine) {
|
|
@@ -1625,8 +1888,8 @@ async function handleQuietCommand() {
|
|
|
1625
1888
|
}
|
|
1626
1889
|
|
|
1627
1890
|
// src/cli/ci.ts
|
|
1628
|
-
import { writeFileSync, existsSync as
|
|
1629
|
-
import { join } from "path";
|
|
1891
|
+
import { writeFileSync, existsSync as existsSync3, mkdirSync } from "fs";
|
|
1892
|
+
import { join as join2 } from "path";
|
|
1630
1893
|
import pc4 from "picocolors";
|
|
1631
1894
|
var WORKFLOW_TEMPLATE = `# Trie Security Scan with Memory Persistence
|
|
1632
1895
|
# Generated by: trie ci
|
|
@@ -1717,8 +1980,8 @@ jobs:
|
|
|
1717
1980
|
`;
|
|
1718
1981
|
function handleCISetupCommand(args) {
|
|
1719
1982
|
const workDir = getWorkingDirectory(void 0, true);
|
|
1720
|
-
const workflowsDir =
|
|
1721
|
-
const workflowPath =
|
|
1983
|
+
const workflowsDir = join2(workDir, ".github", "workflows");
|
|
1984
|
+
const workflowPath = join2(workflowsDir, "trie-scan.yml");
|
|
1722
1985
|
const isMinimal = args.includes("--minimal") || args.includes("-m");
|
|
1723
1986
|
const isDryRun = args.includes("--dry-run") || args.includes("-n");
|
|
1724
1987
|
const showHelp3 = args.includes("--help") || args.includes("-h");
|
|
@@ -1767,13 +2030,13 @@ ${pc4.bold("REQUIRED SECRETS:")}
|
|
|
1767
2030
|
console.log(pc4.dim("\nRun without --dry-run to create the file."));
|
|
1768
2031
|
return;
|
|
1769
2032
|
}
|
|
1770
|
-
if (
|
|
2033
|
+
if (existsSync3(workflowPath)) {
|
|
1771
2034
|
console.log(pc4.yellow("Workflow already exists: .github/workflows/trie-scan.yml"));
|
|
1772
2035
|
console.log(pc4.dim(" Run with --dry-run to preview what would be written."));
|
|
1773
2036
|
console.log(pc4.dim(" Delete the existing file to regenerate."));
|
|
1774
2037
|
return;
|
|
1775
2038
|
}
|
|
1776
|
-
if (!
|
|
2039
|
+
if (!existsSync3(workflowsDir)) {
|
|
1777
2040
|
mkdirSync(workflowsDir, { recursive: true });
|
|
1778
2041
|
}
|
|
1779
2042
|
writeFileSync(workflowPath, template);
|
|
@@ -2019,21 +2282,21 @@ async function handleLearnCommand(args) {
|
|
|
2019
2282
|
}
|
|
2020
2283
|
|
|
2021
2284
|
// src/cli/patterns.ts
|
|
2022
|
-
import { readFile as
|
|
2023
|
-
import { existsSync as
|
|
2285
|
+
import { readFile as readFile4, writeFile as writeFile4 } from "fs/promises";
|
|
2286
|
+
import { existsSync as existsSync5 } from "fs";
|
|
2024
2287
|
import { basename as basename2 } from "path";
|
|
2025
2288
|
import picocolors3 from "picocolors";
|
|
2026
2289
|
|
|
2027
2290
|
// src/patterns/saved-patterns.ts
|
|
2028
|
-
import { createHash } from "crypto";
|
|
2029
|
-
import { readFile as
|
|
2030
|
-
import { existsSync as
|
|
2031
|
-
import { join as
|
|
2291
|
+
import { createHash as createHash2 } from "crypto";
|
|
2292
|
+
import { readFile as readFile3, writeFile as writeFile3 } from "fs/promises";
|
|
2293
|
+
import { existsSync as existsSync4 } from "fs";
|
|
2294
|
+
import { join as join3, basename } from "path";
|
|
2032
2295
|
async function loadSavedPatterns(workDir) {
|
|
2033
|
-
const patternsPath =
|
|
2296
|
+
const patternsPath = join3(getTrieDirectory(workDir), "saved-patterns.json");
|
|
2034
2297
|
try {
|
|
2035
|
-
if (
|
|
2036
|
-
const content = await
|
|
2298
|
+
if (existsSync4(patternsPath)) {
|
|
2299
|
+
const content = await readFile3(patternsPath, "utf-8");
|
|
2037
2300
|
return JSON.parse(content);
|
|
2038
2301
|
}
|
|
2039
2302
|
} catch {
|
|
@@ -2041,10 +2304,10 @@ async function loadSavedPatterns(workDir) {
|
|
|
2041
2304
|
return [];
|
|
2042
2305
|
}
|
|
2043
2306
|
async function savePatternsToProject(patterns, workDir) {
|
|
2044
|
-
const { mkdir } = await import("fs/promises");
|
|
2045
|
-
const patternsPath =
|
|
2046
|
-
await
|
|
2047
|
-
await
|
|
2307
|
+
const { mkdir: mkdir2 } = await import("fs/promises");
|
|
2308
|
+
const patternsPath = join3(getTrieDirectory(workDir), "saved-patterns.json");
|
|
2309
|
+
await mkdir2(getTrieDirectory(workDir), { recursive: true });
|
|
2310
|
+
await writeFile3(patternsPath, JSON.stringify(patterns, null, 2));
|
|
2048
2311
|
}
|
|
2049
2312
|
async function savePatternToProject(pattern, workDir) {
|
|
2050
2313
|
const patterns = await loadSavedPatterns(workDir);
|
|
@@ -2079,14 +2342,14 @@ function detectPatternType(target, workDir) {
|
|
|
2079
2342
|
if (scoutNames.includes(target.toLowerCase())) {
|
|
2080
2343
|
return "detection-rule";
|
|
2081
2344
|
}
|
|
2082
|
-
const fullPath =
|
|
2083
|
-
if (
|
|
2345
|
+
const fullPath = join3(workDir, target);
|
|
2346
|
+
if (existsSync4(fullPath) || target.includes("/") || target.includes("*") || target.endsWith(".ts") || target.endsWith(".js")) {
|
|
2084
2347
|
return "file-structure";
|
|
2085
2348
|
}
|
|
2086
2349
|
return "code-pattern";
|
|
2087
2350
|
}
|
|
2088
2351
|
function generatePatternId(target, type) {
|
|
2089
|
-
const hash =
|
|
2352
|
+
const hash = createHash2("sha256").update(`${type}:${target}`).digest("hex").slice(0, 12);
|
|
2090
2353
|
return `${type}-${hash}`;
|
|
2091
2354
|
}
|
|
2092
2355
|
async function createSavedPattern(target, note, workDir) {
|
|
@@ -2238,7 +2501,7 @@ async function handleExportPatterns(args, workDir) {
|
|
|
2238
2501
|
exportedFrom: basename2(workDir),
|
|
2239
2502
|
patterns
|
|
2240
2503
|
};
|
|
2241
|
-
await
|
|
2504
|
+
await writeFile4(outputPath, JSON.stringify(exportData, null, 2));
|
|
2242
2505
|
console.log(picocolors3.green(`\u2713 Exported ${patterns.length} patterns to ${outputPath}`));
|
|
2243
2506
|
console.log(picocolors3.dim(` Import to another project with: trie patterns import ${outputPath}`));
|
|
2244
2507
|
}
|
|
@@ -2248,11 +2511,11 @@ async function handleImportPatterns(args, workDir) {
|
|
|
2248
2511
|
console.error(picocolors3.red("Usage: trie patterns import <path-to-patterns.json>"));
|
|
2249
2512
|
process.exit(1);
|
|
2250
2513
|
}
|
|
2251
|
-
if (!
|
|
2514
|
+
if (!existsSync5(inputPath)) {
|
|
2252
2515
|
console.error(picocolors3.red(`File not found: ${inputPath}`));
|
|
2253
2516
|
process.exit(1);
|
|
2254
2517
|
}
|
|
2255
|
-
const content = await
|
|
2518
|
+
const content = await readFile4(inputPath, "utf-8");
|
|
2256
2519
|
const importData = JSON.parse(content);
|
|
2257
2520
|
if (!importData.patterns || !Array.isArray(importData.patterns)) {
|
|
2258
2521
|
console.error(picocolors3.red("Invalid pattern file format."));
|
|
@@ -2581,7 +2844,7 @@ Next steps:
|
|
|
2581
2844
|
}
|
|
2582
2845
|
if (subcommand === "edit") {
|
|
2583
2846
|
const editor = process.env.EDITOR || process.env.VISUAL || "nano";
|
|
2584
|
-
const projectPath =
|
|
2847
|
+
const projectPath = join4(getTrieDirectory(workDir), "PROJECT.md");
|
|
2585
2848
|
if (!projectInfoExists(workDir)) {
|
|
2586
2849
|
console.log("No PROJECT.md found. Creating one first...");
|
|
2587
2850
|
await initProjectInfo(workDir);
|
|
@@ -2627,7 +2890,7 @@ This info is available via trie://project MCP resource.
|
|
|
2627
2890
|
\u2551 \u{1F4CB} Project Information \u2551
|
|
2628
2891
|
\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
|
|
2629
2892
|
|
|
2630
|
-
Path: ${
|
|
2893
|
+
Path: ${join4(getTrieDirectory(workDir), "PROJECT.md")}
|
|
2631
2894
|
|
|
2632
2895
|
${"-".repeat(68)}
|
|
2633
2896
|
`);
|