@triedotdev/mcp 1.0.50 → 1.0.51

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/README.md +545 -406
  2. package/dist/agent-smith-BECRZH73.js +12 -0
  3. package/dist/{agent-smith-runner-3AWGEOZC.js → agent-smith-runner-LZRXM2Q2.js} +7 -7
  4. package/dist/agent-smith-runner-LZRXM2Q2.js.map +1 -0
  5. package/dist/{chunk-3SQK2RKF.js → chunk-A43476GB.js} +9 -9
  6. package/dist/chunk-A43476GB.js.map +1 -0
  7. package/dist/{chunk-IMFD4SJC.js → chunk-ASGSTVVF.js} +1 -1
  8. package/dist/chunk-ASGSTVVF.js.map +1 -0
  9. package/dist/chunk-C3AS5OXW.js +1177 -0
  10. package/dist/chunk-C3AS5OXW.js.map +1 -0
  11. package/dist/chunk-IEFAQFDQ.js +2061 -0
  12. package/dist/chunk-IEFAQFDQ.js.map +1 -0
  13. package/dist/{chunk-GLC62PGD.js → chunk-KB5ZN6K2.js} +2 -2
  14. package/dist/{chunk-37U65YW7.js → chunk-TOE75CFZ.js} +1855 -206
  15. package/dist/chunk-TOE75CFZ.js.map +1 -0
  16. package/dist/{chunk-GERAB55E.js → chunk-YKUCIKTU.js} +94 -1259
  17. package/dist/chunk-YKUCIKTU.js.map +1 -0
  18. package/dist/cli/create-agent.js +2 -2
  19. package/dist/cli/main.js +406 -68
  20. package/dist/cli/main.js.map +1 -1
  21. package/dist/cli/yolo-daemon.js +5 -5
  22. package/dist/comprehension-46F7ZNKL.js +821 -0
  23. package/dist/comprehension-46F7ZNKL.js.map +1 -0
  24. package/dist/index.js +448 -123
  25. package/dist/index.js.map +1 -1
  26. package/dist/workers/agent-worker.js +10 -11
  27. package/dist/workers/agent-worker.js.map +1 -1
  28. package/package.json +3 -1
  29. package/dist/agent-smith-RVXIMAL6.js +0 -11
  30. package/dist/agent-smith-runner-3AWGEOZC.js.map +0 -1
  31. package/dist/chunk-37U65YW7.js.map +0 -1
  32. package/dist/chunk-3SQK2RKF.js.map +0 -1
  33. package/dist/chunk-6T7S77U7.js +0 -852
  34. package/dist/chunk-6T7S77U7.js.map +0 -1
  35. package/dist/chunk-GERAB55E.js.map +0 -1
  36. package/dist/chunk-IMFD4SJC.js.map +0 -1
  37. package/dist/chunk-PZDQIFKO.js +0 -1598
  38. package/dist/chunk-PZDQIFKO.js.map +0 -1
  39. /package/dist/{agent-smith-RVXIMAL6.js.map → agent-smith-BECRZH73.js.map} +0 -0
  40. /package/dist/{chunk-GLC62PGD.js.map → chunk-KB5ZN6K2.js.map} +0 -0
@@ -1,24 +1,235 @@
1
- import {
2
- listInstalledSkills,
3
- parseSkillMd,
4
- recordSkillUsage
5
- } from "./chunk-PZDQIFKO.js";
6
1
  import {
7
2
  checkFileLevelIssues,
8
3
  getVibeCodeTrie,
9
4
  scanForVibeCodeIssues
10
5
  } from "./chunk-3CS6Z2SL.js";
11
6
  import {
12
- AgentSmithAgent,
13
- BaseAgent,
7
+ AgentSmithSkill,
8
+ BaseSkill,
14
9
  isAIAvailable,
15
10
  runAIAnalysis
16
- } from "./chunk-3SQK2RKF.js";
11
+ } from "./chunk-A43476GB.js";
17
12
  import {
18
13
  getWorkingDirectory
19
- } from "./chunk-IMFD4SJC.js";
14
+ } from "./chunk-ASGSTVVF.js";
15
+
16
+ // src/utils/project-info.ts
17
+ import { readFile, writeFile, mkdir } from "fs/promises";
18
+ import { existsSync } from "fs";
19
+ import { join } from "path";
20
+ var PROJECT_MD_PATH = ".trie/PROJECT.md";
21
+ function getProjectTemplate() {
22
+ return `# Project Information
23
+
24
+ > This file stores important project context for AI assistants.
25
+ > Edit freely - this file is yours, not auto-generated.
26
+ > Available via MCP resource: \`trie://project\`
27
+
28
+ ---
29
+
30
+ ## Project Overview
31
+
32
+ <!-- Describe your project's purpose and goals -->
33
+
34
+ [Add project description here]
35
+
36
+ ---
37
+
38
+ ## Technology Stack
39
+
40
+ <!-- List frameworks, languages, databases, cloud services, etc. -->
41
+
42
+ - **Language:**
43
+ - **Framework:**
44
+ - **Database:**
45
+ - **Hosting:**
46
+
47
+ ---
48
+
49
+ ## Architecture
50
+
51
+ <!-- Key patterns, architectural decisions, and system design -->
52
+
53
+ [Describe your architecture here]
54
+
55
+ ---
56
+
57
+ ## Coding Conventions
20
58
 
21
- // src/agents/security.ts
59
+ <!-- Style guidelines, naming conventions, patterns to follow -->
60
+
61
+ -
62
+ -
63
+ -
64
+
65
+ ---
66
+
67
+ ## Environment
68
+
69
+ <!-- URLs, API endpoints, deployment info -->
70
+
71
+ | Environment | URL | Notes |
72
+ |-------------|-----|-------|
73
+ | Development | | |
74
+ | Staging | | |
75
+ | Production | | |
76
+
77
+ ---
78
+
79
+ ## Team
80
+
81
+ <!-- Ownership, contacts, responsibilities -->
82
+
83
+ - **Owner:**
84
+ - **Team:**
85
+
86
+ ---
87
+
88
+ ## Compliance
89
+
90
+ <!-- HIPAA, SOC2, GDPR, PCI-DSS requirements if applicable -->
91
+
92
+ - [ ] GDPR
93
+ - [ ] SOC2
94
+ - [ ] HIPAA
95
+ - [ ] PCI-DSS
96
+
97
+ ---
98
+
99
+ ## AI Instructions
100
+
101
+ <!-- Special instructions for AI assistants working on this project -->
102
+
103
+ When working on this project, AI assistants should:
104
+
105
+ 1.
106
+ 2.
107
+ 3.
108
+
109
+ ---
110
+
111
+ *This file is read by Trie agents and exposed via \`trie://project\` MCP resource.*
112
+ *Edit this file to provide context to Claude Code, Cursor, GitHub Actions, and other AI tools.*
113
+ `;
114
+ }
115
+ function projectInfoExists(workDir) {
116
+ const dir = workDir || getWorkingDirectory(void 0, true);
117
+ const projectPath = join(dir, PROJECT_MD_PATH);
118
+ return existsSync(projectPath);
119
+ }
120
+ async function loadProjectInfo(workDir) {
121
+ const dir = workDir || getWorkingDirectory(void 0, true);
122
+ const projectPath = join(dir, PROJECT_MD_PATH);
123
+ try {
124
+ if (!existsSync(projectPath)) {
125
+ return null;
126
+ }
127
+ return await readFile(projectPath, "utf-8");
128
+ } catch {
129
+ return null;
130
+ }
131
+ }
132
+ async function saveProjectInfo(content, workDir) {
133
+ const dir = workDir || getWorkingDirectory(void 0, true);
134
+ const trieDir = join(dir, ".trie");
135
+ const projectPath = join(dir, PROJECT_MD_PATH);
136
+ await mkdir(trieDir, { recursive: true });
137
+ await writeFile(projectPath, content, "utf-8");
138
+ }
139
+ async function initProjectInfo(workDir) {
140
+ const dir = workDir || getWorkingDirectory(void 0, true);
141
+ const projectPath = join(dir, PROJECT_MD_PATH);
142
+ if (existsSync(projectPath)) {
143
+ return { created: false, path: projectPath };
144
+ }
145
+ await saveProjectInfo(getProjectTemplate(), dir);
146
+ return { created: true, path: projectPath };
147
+ }
148
+ async function getProjectSection(sectionName, workDir) {
149
+ const content = await loadProjectInfo(workDir);
150
+ if (!content) return null;
151
+ const sectionRegex = new RegExp(
152
+ `## ${escapeRegex(sectionName)}\\s*\\n([\\s\\S]*?)(?=\\n## |\\n---\\s*$|$)`,
153
+ "i"
154
+ );
155
+ const match = content.match(sectionRegex);
156
+ if (match?.[1]) {
157
+ return match[1].trim();
158
+ }
159
+ return null;
160
+ }
161
+ async function updateProjectSection(sectionName, newContent, workDir) {
162
+ let content = await loadProjectInfo(workDir);
163
+ if (!content) {
164
+ await initProjectInfo(workDir);
165
+ content = await loadProjectInfo(workDir);
166
+ if (!content) return false;
167
+ }
168
+ const sectionRegex = new RegExp(
169
+ `(## ${escapeRegex(sectionName)}\\s*\\n)([\\s\\S]*?)((?=\\n## )|(?=\\n---\\s*$)|$)`,
170
+ "i"
171
+ );
172
+ if (content.match(sectionRegex)) {
173
+ const updatedContent = content.replace(sectionRegex, `$1
174
+ ${newContent}
175
+
176
+ $3`);
177
+ await saveProjectInfo(updatedContent, workDir);
178
+ return true;
179
+ }
180
+ return false;
181
+ }
182
+ async function appendToSection(sectionName, contentToAdd, workDir) {
183
+ const currentContent = await getProjectSection(sectionName, workDir);
184
+ if (currentContent === null) return false;
185
+ const newContent = currentContent + "\n" + contentToAdd;
186
+ return updateProjectSection(sectionName, newContent, workDir);
187
+ }
188
+ async function getProjectSections(workDir) {
189
+ const content = await loadProjectInfo(workDir);
190
+ if (!content) return [];
191
+ const sectionRegex = /^## (.+)$/gm;
192
+ const sections = [];
193
+ let match;
194
+ while ((match = sectionRegex.exec(content)) !== null) {
195
+ if (match[1]) {
196
+ sections.push(match[1].trim());
197
+ }
198
+ }
199
+ return sections;
200
+ }
201
+ async function getProjectInfoStructured(workDir) {
202
+ const dir = workDir || getWorkingDirectory(void 0, true);
203
+ const projectPath = join(dir, PROJECT_MD_PATH);
204
+ const content = await loadProjectInfo(dir);
205
+ if (!content) {
206
+ return {
207
+ exists: false,
208
+ path: projectPath,
209
+ sections: {},
210
+ raw: null
211
+ };
212
+ }
213
+ const sectionNames = await getProjectSections(dir);
214
+ const sections = {};
215
+ for (const name of sectionNames) {
216
+ const sectionContent = await getProjectSection(name, dir);
217
+ if (sectionContent) {
218
+ sections[name] = sectionContent;
219
+ }
220
+ }
221
+ return {
222
+ exists: true,
223
+ path: projectPath,
224
+ sections,
225
+ raw: content
226
+ };
227
+ }
228
+ function escapeRegex(str) {
229
+ return str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
230
+ }
231
+
232
+ // src/skills/built-in/security.ts
22
233
  var ALWAYS_SKIP_FILES = [
23
234
  /vulnerability-signatures\.[jt]s$/,
24
235
  /vibe-code-signatures\.[jt]s$/,
@@ -75,7 +286,7 @@ var CRITICAL_PATTERNS = [
75
286
  { pattern: /sk_live_[A-Za-z0-9]{24,}/, severity: "critical", issue: "Stripe live API key exposed", fix: "Rotate Stripe key immediately. Use environment variables." },
76
287
  { pattern: /xox[baprs]-[A-Za-z0-9-]{10,}/, severity: "critical", issue: "Slack token exposed", fix: "Revoke Slack token and use environment variables." }
77
288
  ];
78
- var SecurityAgent = class extends BaseAgent {
289
+ var SecuritySkill = class extends BaseSkill {
79
290
  name = "security";
80
291
  description = "AI-powered security analysis: vulnerabilities, injection risks, authentication issues";
81
292
  version = "2.0.0";
@@ -298,7 +509,7 @@ Output STRICT JSON:
298
509
  }
299
510
  };
300
511
 
301
- // src/agents/privacy.ts
512
+ // src/skills/built-in/privacy.ts
302
513
  var PRIVACY_INDICATORS = {
303
514
  high: [
304
515
  { pattern: /email|phone|ssn|social.*security|passport|driver.*license/i, reason: "PII fields" },
@@ -342,7 +553,7 @@ var CRITICAL_PRIVACY_PATTERNS = [
342
553
  regulation: "PCI DSS"
343
554
  }
344
555
  ];
345
- var PrivacyAgent = class extends BaseAgent {
556
+ var PrivacySkill = class extends BaseSkill {
346
557
  name = "privacy";
347
558
  description = "AI-powered privacy analysis: GDPR, CCPA, PCI-DSS compliance";
348
559
  version = "2.0.0";
@@ -593,7 +804,7 @@ Output STRICT JSON:
593
804
  }
594
805
  };
595
806
 
596
- // src/agents/typecheck.ts
807
+ // src/skills/built-in/typecheck.ts
597
808
  import { extname } from "path";
598
809
  var SKIP_FILES = [
599
810
  /node_modules\//,
@@ -604,7 +815,7 @@ var SKIP_FILES = [
604
815
  /\.test\.[jt]sx?$/,
605
816
  /\.spec\.[jt]sx?$/
606
817
  ];
607
- var TypeCheckAgent = class extends BaseAgent {
818
+ var TypeCheckSkill = class extends BaseSkill {
608
819
  name = "typecheck";
609
820
  description = "Catches type errors and ensures type safety";
610
821
  version = "1.0.0";
@@ -679,8 +890,8 @@ var TypeCheckAgent = class extends BaseAgent {
679
890
  }
680
891
  };
681
892
 
682
- // src/agents/comprehension.ts
683
- var ComprehensionAgent = class extends BaseAgent {
893
+ // src/skills/built-in/comprehension.ts
894
+ var ComprehensionSkill = class extends BaseSkill {
684
895
  name = "comprehension";
685
896
  description = "Explains what code does in plain language for non-technical builders";
686
897
  version = "1.0.0";
@@ -897,7 +1108,7 @@ var ComprehensionAgent = class extends BaseAgent {
897
1108
  }
898
1109
  };
899
1110
 
900
- // src/agents/accessibility.ts
1111
+ // src/skills/built-in/accessibility.ts
901
1112
  var WCAG_CRITERIA = {
902
1113
  // Perceivable
903
1114
  "1.1.1": { name: "Non-text Content", level: "A", description: "All non-text content has text alternatives" },
@@ -924,6 +1135,7 @@ var WCAG_CRITERIA = {
924
1135
  // Understandable
925
1136
  "3.2.1": { name: "On Focus", level: "A", description: "Focus does not trigger unexpected context changes" },
926
1137
  "3.2.2": { name: "On Input", level: "A", description: "Input does not trigger unexpected context changes" },
1138
+ "3.2.5": { name: "Change on Request", level: "AAA", description: "Changes of context are initiated only by user request" },
927
1139
  "3.3.1": { name: "Error Identification", level: "A", description: "Errors are identified and described in text" },
928
1140
  "3.3.2": { name: "Labels or Instructions", level: "A", description: "Labels or instructions are provided for user input" },
929
1141
  // Robust
@@ -960,7 +1172,7 @@ var REQUIRED_ARIA_ATTRIBUTES = {
960
1172
  "treegrid": [],
961
1173
  "treeitem": []
962
1174
  };
963
- var AccessibilityAgent = class extends BaseAgent {
1175
+ var AccessibilitySkill = class extends BaseSkill {
964
1176
  name = "accessibility";
965
1177
  description = "WCAG 2.1 AA compliance: screen readers, keyboard nav, color contrast, touch targets, semantic HTML, ARIA patterns";
966
1178
  version = "2.0.0";
@@ -1084,7 +1296,7 @@ var AccessibilityAgent = class extends BaseAgent {
1084
1296
  }
1085
1297
  }
1086
1298
  if (/<svg\s/i.test(line)) {
1087
- const svgContext = this.getMultiLineElement(lines, i, "svg");
1299
+ const svgContext = this.getMultiLineElement(lines, i, "svg") ?? line;
1088
1300
  if (!/aria-label|aria-labelledby|<title>|role=["']img["']/i.test(svgContext) && !/aria-hidden=["']true["']/i.test(svgContext)) {
1089
1301
  issues.push(this.createIssue(
1090
1302
  this.generateIssueId(),
@@ -1112,7 +1324,7 @@ var AccessibilityAgent = class extends BaseAgent {
1112
1324
  const line = lines[i];
1113
1325
  const lineNumber = i + 1;
1114
1326
  if (/<button/i.test(line) || /Button\s/i.test(line)) {
1115
- const buttonContext = this.getMultiLineElement(lines, i, "button") || this.getMultiLineElement(lines, i, "Button");
1327
+ const buttonContext = this.getMultiLineElement(lines, i, "button") ?? this.getMultiLineElement(lines, i, "Button") ?? line;
1116
1328
  const hasIconOnly = />\s*<(Icon|svg|i\s|img)[^>]*>\s*<\/(button|Button)/i.test(buttonContext) || />\s*<[A-Z][a-zA-Z]*Icon[^>]*\s*\/>\s*<\/(button|Button)/i.test(buttonContext) || /<(Icon|svg)[^>]*\/>\s*<\/(button|Button)/i.test(buttonContext);
1117
1329
  const hasAccessibleName = /aria-label|aria-labelledby|title=|sr-only|visually-hidden/i.test(buttonContext);
1118
1330
  if (hasIconOnly && !hasAccessibleName) {
@@ -1163,7 +1375,7 @@ var AccessibilityAgent = class extends BaseAgent {
1163
1375
  }
1164
1376
  }
1165
1377
  if (/<a\s/i.test(line) || /<Link\s/i.test(line)) {
1166
- const linkContext = this.getMultiLineElement(lines, i, "a") || this.getMultiLineElement(lines, i, "Link");
1378
+ const linkContext = this.getMultiLineElement(lines, i, "a") ?? this.getMultiLineElement(lines, i, "Link") ?? line;
1167
1379
  if (!/href=|to=/i.test(linkContext)) {
1168
1380
  issues.push(this.createIssue(
1169
1381
  this.generateIssueId(),
@@ -1937,7 +2149,7 @@ Review code for comprehensive accessibility compliance.
1937
2149
  }
1938
2150
  };
1939
2151
 
1940
- // src/agents/design-engineer.ts
2152
+ // src/skills/built-in/design-engineer.ts
1941
2153
  var DOMAIN_DESIGN_RULES = {
1942
2154
  fitness: {
1943
2155
  defaultMode: "dark",
@@ -2155,7 +2367,7 @@ var PROJECT_CONTEXTS = {
2155
2367
  effects: ["image reveals", "cursor effects", "page transitions", "scroll-linked galleries"]
2156
2368
  }
2157
2369
  };
2158
- var DesignEngineerAgent = class extends BaseAgent {
2370
+ var DesignEngineerSkill = class extends BaseSkill {
2159
2371
  name = "design-engineer";
2160
2372
  description = "Award-winning frontend craft: design systems, motion design, creative CSS, modern color palettes, Awwwards-level polish";
2161
2373
  version = "2.0.0";
@@ -3662,8 +3874,8 @@ Output STRICT JSON:
3662
3874
  }
3663
3875
  };
3664
3876
 
3665
- // src/agents/legal.ts
3666
- var LegalAgent = class extends BaseAgent {
3877
+ // src/skills/built-in/legal.ts
3878
+ var LegalSkill = class extends BaseSkill {
3667
3879
  name = "legal";
3668
3880
  description = "Comprehensive legal compliance for app development: licensing, ToS, accessibility, IP, data protection, e-commerce, and regulatory requirements";
3669
3881
  version = "2.0.0";
@@ -4655,10 +4867,10 @@ var LegalAgent = class extends BaseAgent {
4655
4867
  }
4656
4868
  };
4657
4869
 
4658
- // src/agents/test.ts
4870
+ // src/skills/built-in/test.ts
4659
4871
  import { basename, dirname } from "path";
4660
- import { existsSync } from "fs";
4661
- var TestAgent = class extends BaseAgent {
4872
+ import { existsSync as existsSync2 } from "fs";
4873
+ var TestSkill = class extends BaseSkill {
4662
4874
  name = "test";
4663
4875
  description = "Test coverage analysis, test quality, and testing best practices";
4664
4876
  version = "1.0.0";
@@ -4700,12 +4912,9 @@ var TestAgent = class extends BaseAgent {
4700
4912
  `${fileDir}/__tests__/${fileName}`,
4701
4913
  `${fileDir}/../__tests__/${fileName}`
4702
4914
  ];
4703
- const hasTestFile = testPatterns.some((pattern) => existsSync(pattern));
4915
+ const hasTestFile = testPatterns.some((pattern) => existsSync2(pattern));
4704
4916
  if (!hasTestFile) {
4705
4917
  const severity = this.determineTestSeverity(content);
4706
- if (severity === "low") {
4707
- return issues;
4708
- }
4709
4918
  issues.push(this.createIssue(
4710
4919
  this.generateIssueId(),
4711
4920
  severity,
@@ -4751,8 +4960,8 @@ var TestAgent = class extends BaseAgent {
4751
4960
  }
4752
4961
  };
4753
4962
 
4754
- // src/agents/software-architect.ts
4755
- var SoftwareArchitectAgent = class extends BaseAgent {
4963
+ // src/skills/built-in/software-architect.ts
4964
+ var SoftwareArchitectSkill = class extends BaseSkill {
4756
4965
  name = "software-architect";
4757
4966
  description = "Architecture patterns, code organization, SOLID principles, and scalability";
4758
4967
  version = "1.0.0";
@@ -4981,8 +5190,8 @@ Output STRICT JSON:
4981
5190
  }
4982
5191
  };
4983
5192
 
4984
- // src/agents/devops.ts
4985
- var DevOpsAgent = class extends BaseAgent {
5193
+ // src/skills/built-in/devops.ts
5194
+ var DevOpsSkill = class extends BaseSkill {
4986
5195
  name = "devops";
4987
5196
  description = "Infrastructure, deployment, configuration, and operational concerns";
4988
5197
  version = "1.0.0";
@@ -5187,7 +5396,7 @@ Output STRICT JSON:
5187
5396
  }
5188
5397
  };
5189
5398
 
5190
- // src/agents/bug-finding.ts
5399
+ // src/skills/built-in/bug-finding.ts
5191
5400
  var BUG_INDICATORS = {
5192
5401
  high: [
5193
5402
  { pattern: /async|await|promise/i, reason: "async code" },
@@ -5223,7 +5432,7 @@ var CRITICAL_BUG_PATTERNS = [
5223
5432
  fix: "Use === for comparison instead of ="
5224
5433
  }
5225
5434
  ];
5226
- var BugFindingAgent = class extends BaseAgent {
5435
+ var BugFindingSkill = class extends BaseSkill {
5227
5436
  name = "bug-finding";
5228
5437
  description = "AI-powered bug detection: null safety, edge cases, async issues, runtime errors";
5229
5438
  version = "2.0.0";
@@ -5418,8 +5627,8 @@ Output STRICT JSON:
5418
5627
  }
5419
5628
  };
5420
5629
 
5421
- // src/agents/user-testing.ts
5422
- var UserTestingAgent = class extends BaseAgent {
5630
+ // src/skills/built-in/user-testing.ts
5631
+ var UserTestingSkill = class extends BaseSkill {
5423
5632
  name = "user-testing";
5424
5633
  description = "Simulates user personas (happy path, security tester, confused user) to find vulnerabilities";
5425
5634
  version = "2.0.0";
@@ -5889,8 +6098,8 @@ var UserTestingAgent = class extends BaseAgent {
5889
6098
  }
5890
6099
  };
5891
6100
 
5892
- // src/agents/trie-clean.ts
5893
- var TrieCleanAgent = class extends BaseAgent {
6101
+ // src/skills/built-in/trie-clean.ts
6102
+ var TrieCleanSkill = class extends BaseSkill {
5894
6103
  name = "trie_clean";
5895
6104
  description = "Reviews AI-generated code for common mistakes and best practices (for non-technical users)";
5896
6105
  version = "1.0.0";
@@ -5974,7 +6183,7 @@ var TrieCleanAgent = class extends BaseAgent {
5974
6183
  }
5975
6184
  };
5976
6185
 
5977
- // src/agents/soc2.ts
6186
+ // src/skills/built-in/soc2.ts
5978
6187
  var SOC2_PATTERNS = {
5979
6188
  // CC6 - Logical Access Controls
5980
6189
  hardcodedSecrets: [
@@ -6041,7 +6250,7 @@ var REGULATION_DESCRIPTIONS = {
6041
6250
  "CC7.3": "Incident Detection - Proper error handling and alerting",
6042
6251
  "CC8.1": "Change Management - Controlled changes with proper review"
6043
6252
  };
6044
- var SOC2Agent = class extends BaseAgent {
6253
+ var SOC2Skill = class extends BaseSkill {
6045
6254
  name = "soc2";
6046
6255
  description = "SOC 2 Type II compliance: access controls, encryption, logging, change management";
6047
6256
  version = "1.0.0";
@@ -6189,8 +6398,8 @@ Output STRICT JSON:
6189
6398
  }
6190
6399
  };
6191
6400
 
6192
- // src/agents/super-reviewer.ts
6193
- var SuperReviewerAgent = class extends BaseAgent {
6401
+ // src/skills/built-in/super-reviewer.ts
6402
+ var SuperReviewerSkill = class extends BaseSkill {
6194
6403
  name = "super-reviewer";
6195
6404
  description = "Interactive PR review: walks through changes file-by-file, explains each chunk, waits for cross-examination";
6196
6405
  version = "1.0.0";
@@ -6340,8 +6549,8 @@ var CRITICAL_REVIEW_CHECKLIST = {
6340
6549
  ]
6341
6550
  };
6342
6551
 
6343
- // src/agents/performance.ts
6344
- var PerformanceAgent = class extends BaseAgent {
6552
+ // src/skills/built-in/performance.ts
6553
+ var PerformanceSkill = class extends BaseSkill {
6345
6554
  name = "performance";
6346
6555
  description = "Surfaces performance patterns for human review: memory, renders, bundles, queries";
6347
6556
  version = "1.0.0";
@@ -6640,8 +6849,8 @@ var PerformanceAgent = class extends BaseAgent {
6640
6849
  }
6641
6850
  };
6642
6851
 
6643
- // src/agents/e2e.ts
6644
- var E2EAgent = class extends BaseAgent {
6852
+ // src/skills/built-in/e2e.ts
6853
+ var E2ESkill = class extends BaseSkill {
6645
6854
  name = "e2e";
6646
6855
  description = "Identifies E2E test gaps and flaky test patterns for human review";
6647
6856
  version = "1.0.0";
@@ -6873,8 +7082,8 @@ var E2EAgent = class extends BaseAgent {
6873
7082
  }
6874
7083
  };
6875
7084
 
6876
- // src/agents/visual-qa.ts
6877
- var VisualQAAgent = class extends BaseAgent {
7085
+ // src/skills/built-in/visual-qa.ts
7086
+ var VisualQASkill = class extends BaseSkill {
6878
7087
  name = "visual-qa";
6879
7088
  description = "Surfaces potential visual/layout issues in CSS for human review";
6880
7089
  version = "1.0.0";
@@ -7209,8 +7418,8 @@ var VisualQAAgent = class extends BaseAgent {
7209
7418
  }
7210
7419
  };
7211
7420
 
7212
- // src/agents/data-flow.ts
7213
- var DataFlowAgent = class extends BaseAgent {
7421
+ // src/skills/built-in/data-flow.ts
7422
+ var DataFlowSkill = class extends BaseSkill {
7214
7423
  name = "data-flow";
7215
7424
  description = "Detects schema mismatches, placeholder data, and data integrity issues";
7216
7425
  version = "1.0.0";
@@ -7420,6 +7629,20 @@ var DataFlowAgent = class extends BaseAgent {
7420
7629
  for (let i = 0; i < lines.length; i++) {
7421
7630
  const line = lines[i] || "";
7422
7631
  const lineNumber = i + 1;
7632
+ if (/==\s*null/.test(line) || /==\s*undefined/.test(line)) {
7633
+ issues.push(this.createIssue(
7634
+ this.generateIssueId(),
7635
+ "moderate",
7636
+ "Loose equality check against null/undefined",
7637
+ "Use strict equality (===) to avoid accidental truthiness",
7638
+ file,
7639
+ lineNumber,
7640
+ 0.75,
7641
+ void 0,
7642
+ true,
7643
+ { category: "equality", effort: "trivial" }
7644
+ ));
7645
+ }
7423
7646
  if (/==\s*["']['"]/.test(line) || /==\s*0[^.]/.test(line)) {
7424
7647
  issues.push(this.createIssue(
7425
7648
  this.generateIssueId(),
@@ -7439,7 +7662,7 @@ var DataFlowAgent = class extends BaseAgent {
7439
7662
  }
7440
7663
  };
7441
7664
 
7442
- // src/agents/moneybags.ts
7665
+ // src/skills/built-in/moneybags.ts
7443
7666
  var MONEYBAGS_ASCII = `
7444
7667
  \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557
7445
7668
  \u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u255A\u2588\u2588\u2557 \u2588\u2588\u2554\u255D
@@ -7462,51 +7685,51 @@ var MONEYBAGS_QUOTES = [
7462
7685
  "Floating-point for money? That's going to be an expensive lesson."
7463
7686
  ];
7464
7687
  var BASE_COST_BY_SEVERITY = {
7465
- critical: 500,
7466
- // Critical bugs found in dev - 2-4 hours of focused work
7467
- serious: 200,
7468
- // Serious issues need careful remediation - 1-2 hours
7469
- moderate: 75,
7470
- // Moderate issues are quicker fixes - 30-60 minutes
7471
- low: 25
7472
- // Low severity - mostly cleanup - 15-30 minutes
7688
+ critical: 5e3,
7689
+ // Critical bugs found in dev - high impact, deep fixes
7690
+ serious: 2e3,
7691
+ // Serious issues need careful remediation
7692
+ moderate: 500,
7693
+ // Moderate issues are quicker fixes
7694
+ low: 150
7695
+ // Low severity - mostly cleanup
7473
7696
  };
7474
7697
  var PRODUCTION_MULTIPLIER = {
7475
- critical: 10,
7476
- // Critical bugs can cause outages, breaches (capped from 30x)
7477
- serious: 6,
7478
- // Serious bugs cause significant user impact (capped from 20x)
7479
- moderate: 3,
7480
- // Moderate bugs require hotfixes, user support (capped from 10x)
7698
+ critical: 12,
7699
+ // Critical bugs can cause outages, breaches
7700
+ serious: 8,
7701
+ // Serious bugs cause significant user impact
7702
+ moderate: 4,
7703
+ // Moderate bugs require hotfixes, user support
7481
7704
  low: 2
7482
- // Low bugs accumulate tech debt (capped from 5x)
7705
+ // Low bugs accumulate tech debt
7483
7706
  };
7484
7707
  var CATEGORY_MULTIPLIERS = {
7485
7708
  // Security categories - important but realistic
7486
- "security": { multiplier: 2, reason: "Security vulnerabilities require careful remediation" },
7487
- "authentication": { multiplier: 2.5, reason: "Auth bypass is serious but fixable" },
7488
- "authorization": { multiplier: 2, reason: "Authorization flaws expose sensitive data" },
7489
- "injection": { multiplier: 3, reason: "SQL/Command injection is severe - prioritize fix" },
7490
- "xss": { multiplier: 1.5, reason: "XSS needs fixing but React mitigates most cases" },
7491
- "secrets": { multiplier: 2.5, reason: "Exposed secrets require rotation" },
7492
- "cryptography": { multiplier: 1.5, reason: "Weak crypto should be updated" },
7709
+ "security": { multiplier: 6, reason: "Security vulnerabilities require careful remediation" },
7710
+ "authentication": { multiplier: 8, reason: "Auth bypass is serious but fixable" },
7711
+ "authorization": { multiplier: 6, reason: "Authorization flaws expose sensitive data" },
7712
+ "injection": { multiplier: 12, reason: "SQL/Command injection is severe - prioritize fix" },
7713
+ "xss": { multiplier: 4, reason: "XSS needs fixing but React mitigates most cases" },
7714
+ "secrets": { multiplier: 8, reason: "Exposed secrets require rotation" },
7715
+ "cryptography": { multiplier: 4, reason: "Weak crypto should be updated" },
7493
7716
  // Data integrity categories
7494
- "data-loss": { multiplier: 3, reason: "Data loss is serious - ensure backups exist" },
7495
- "data-corruption": { multiplier: 2.5, reason: "Data corruption requires recovery work" },
7496
- "privacy": { multiplier: 2, reason: "Privacy violations carry compliance risk" },
7717
+ "data-loss": { multiplier: 10, reason: "Data loss is serious - ensure backups exist" },
7718
+ "data-corruption": { multiplier: 6, reason: "Data corruption requires recovery work" },
7719
+ "privacy": { multiplier: 8, reason: "Privacy violations carry compliance risk" },
7497
7720
  // Financial categories
7498
- "payment": { multiplier: 3, reason: "Payment bugs need immediate attention" },
7499
- "billing": { multiplier: 2.5, reason: "Billing errors erode trust" },
7500
- "financial-calculation": { multiplier: 2, reason: "Incorrect calculations compound over time" },
7721
+ "payment": { multiplier: 25, reason: "Payment bugs need immediate attention" },
7722
+ "billing": { multiplier: 8, reason: "Billing errors erode trust" },
7723
+ "financial-calculation": { multiplier: 6, reason: "Incorrect calculations compound over time" },
7501
7724
  // Reliability categories
7502
- "crash": { multiplier: 2, reason: "Crashes hurt user experience" },
7503
- "memory-leak": { multiplier: 1.5, reason: "Memory leaks cause gradual degradation" },
7504
- "deadlock": { multiplier: 2, reason: "Deadlocks require restarts" },
7505
- "race-condition": { multiplier: 2, reason: "Race conditions are hard to debug" },
7725
+ "crash": { multiplier: 4, reason: "Crashes hurt user experience" },
7726
+ "memory-leak": { multiplier: 3, reason: "Memory leaks cause gradual degradation" },
7727
+ "deadlock": { multiplier: 4, reason: "Deadlocks require restarts" },
7728
+ "race-condition": { multiplier: 4, reason: "Race conditions are hard to debug" },
7506
7729
  // User experience
7507
- "accessibility": { multiplier: 1.2, reason: "Accessibility issues should be addressed" },
7508
- "performance": { multiplier: 1.2, reason: "Performance issues hurt conversion rates" },
7509
- "ux": { multiplier: 1, reason: "UX bugs increase support costs" },
7730
+ "accessibility": { multiplier: 1.5, reason: "Accessibility issues should be addressed" },
7731
+ "performance": { multiplier: 2, reason: "Performance issues hurt conversion rates" },
7732
+ "ux": { multiplier: 1.2, reason: "UX bugs increase support costs" },
7510
7733
  // Code quality
7511
7734
  "bug": { multiplier: 1, reason: "General bugs require developer time" },
7512
7735
  "type-error": { multiplier: 0.8, reason: "Type errors caught early save debugging time" },
@@ -7537,13 +7760,13 @@ var USER_COUNT_MULTIPLIERS = [
7537
7760
  { threshold: 50, multiplier: 0.5, label: "MVP (50 users)" },
7538
7761
  { threshold: 250, multiplier: 1, label: "Early stage (250 users)" },
7539
7762
  // Baseline (default)
7540
- { threshold: 1e3, multiplier: 1.5, label: "Growing (1K users)" },
7541
- { threshold: 5e3, multiplier: 2, label: "Traction (5K users)" },
7542
- { threshold: 25e3, multiplier: 2.5, label: "Scale-up (25K users)" },
7543
- { threshold: 1e5, multiplier: 3, label: "Growth (100K users)" },
7544
- { threshold: 5e5, multiplier: 3.5, label: "Large (500K users)" },
7545
- { threshold: 1e6, multiplier: 4, label: "Enterprise (1M+ users)" }
7546
- // Capped at 4x, not 40x
7763
+ { threshold: 1e3, multiplier: 3, label: "Growing (1K users)" },
7764
+ { threshold: 5e3, multiplier: 6, label: "Traction (5K users)" },
7765
+ { threshold: 25e3, multiplier: 10, label: "Scale-up (25K users)" },
7766
+ { threshold: 1e5, multiplier: 15, label: "Growth (100K users)" },
7767
+ { threshold: 5e5, multiplier: 18, label: "Large (500K users)" },
7768
+ { threshold: 1e6, multiplier: 20, label: "Enterprise (1M+ users)" }
7769
+ // Capped to avoid runaway estimates
7547
7770
  ];
7548
7771
  var PER_USER_COSTS = {
7549
7772
  "data-loss": 5,
@@ -7559,7 +7782,7 @@ var PER_USER_COSTS = {
7559
7782
  "accessibility": 0.1
7560
7783
  // $0.10 per user (support costs)
7561
7784
  };
7562
- var MoneybagAgent = class extends BaseAgent {
7785
+ var MoneybagSkill = class extends BaseSkill {
7563
7786
  name = "moneybags";
7564
7787
  description = "Estimates the dollar cost of bugs based on severity, category, and user scale. Uses industry research (IBM, NIST, Ponemon) with configurable user count scaling.";
7565
7788
  version = "1.1.0";
@@ -7712,8 +7935,8 @@ var MoneybagAgent = class extends BaseAgent {
7712
7935
  const fixHours = EFFORT_HOURS[effort] || 8;
7713
7936
  const developerRate = this.config.developerRate ?? DEVELOPER_HOURLY_RATE;
7714
7937
  const fixCost = fixHours * developerRate;
7715
- const BASE_NOW_CAP = 500;
7716
- const BASE_PROD_CAP = 2e3;
7938
+ const BASE_NOW_CAP = 25e3;
7939
+ const BASE_PROD_CAP = 25e4;
7717
7940
  const maxNowCost = BASE_NOW_CAP * userScaleMultiplier;
7718
7941
  const maxProdCost = BASE_PROD_CAP * userScaleMultiplier;
7719
7942
  const rawNowCost = baseCost * categoryMultiplier * contextMultiplier + fixCost;
@@ -8040,7 +8263,7 @@ Default: 250 users. Scale with: trie scan --users 10000
8040
8263
  }
8041
8264
  };
8042
8265
 
8043
- // src/agents/production-ready.ts
8266
+ // src/skills/built-in/production-ready.ts
8044
8267
  var PRODUCTION_READY_ASCII = `
8045
8268
  \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557
8046
8269
  \u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2550\u2588\u2588\u2557\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2557
@@ -8202,7 +8425,7 @@ var PRODUCTION_CONFIG_FILES = [
8202
8425
  /vercel\.json$/,
8203
8426
  /netlify\.toml$/
8204
8427
  ];
8205
- var ProductionReadyAgent = class extends BaseAgent {
8428
+ var ProductionReadySkill = class extends BaseSkill {
8206
8429
  name = "production-ready";
8207
8430
  description = "Production readiness checker: health endpoints, graceful shutdown, connection pooling, security headers, monitoring, and deployment gates";
8208
8431
  version = "1.0.0";
@@ -8466,10 +8689,1376 @@ Output STRICT JSON:
8466
8689
  }
8467
8690
  };
8468
8691
 
8692
+ // src/skills/installer.ts
8693
+ import { mkdir as mkdir2, rm, writeFile as writeFile2, readdir, readFile as readFile3, access, cp } from "fs/promises";
8694
+ import { join as join3 } from "path";
8695
+ import { exec } from "child_process";
8696
+ import { promisify } from "util";
8697
+
8698
+ // src/skills/parser.ts
8699
+ import { readFile as readFile2 } from "fs/promises";
8700
+ import { join as join2 } from "path";
8701
+ async function parseSkillMd(skillPath) {
8702
+ const skillMdPath = join2(skillPath, "SKILL.md");
8703
+ const rawContent = await readFile2(skillMdPath, "utf-8");
8704
+ const frontmatterMatch = rawContent.match(/^---\n([\s\S]*?)\n---/);
8705
+ if (!frontmatterMatch || !frontmatterMatch[1]) {
8706
+ throw new Error("Invalid SKILL.md: missing YAML frontmatter");
8707
+ }
8708
+ const frontmatter = parseYamlFrontmatter(frontmatterMatch[1]);
8709
+ if (!frontmatter.name || !frontmatter.description) {
8710
+ throw new Error("Invalid SKILL.md: missing required name or description in frontmatter");
8711
+ }
8712
+ const content = rawContent.slice(frontmatterMatch[0].length).trim();
8713
+ return {
8714
+ frontmatter,
8715
+ content,
8716
+ rawContent
8717
+ };
8718
+ }
8719
+ function parseYamlFrontmatter(yaml) {
8720
+ const result = {};
8721
+ const lines = yaml.split("\n");
8722
+ for (const line of lines) {
8723
+ const trimmed = line.trim();
8724
+ if (!trimmed || trimmed.startsWith("#")) continue;
8725
+ const colonIndex = trimmed.indexOf(":");
8726
+ if (colonIndex === -1) continue;
8727
+ const key = trimmed.slice(0, colonIndex).trim();
8728
+ let value = trimmed.slice(colonIndex + 1).trim();
8729
+ if (value === "") continue;
8730
+ if (typeof value === "string") {
8731
+ if (value.startsWith('"') && value.endsWith('"') || value.startsWith("'") && value.endsWith("'")) {
8732
+ value = value.slice(1, -1);
8733
+ }
8734
+ if (typeof value === "string" && value.startsWith("[") && value.endsWith("]")) {
8735
+ value = value.slice(1, -1).split(",").map((s) => s.trim().replace(/^["']|["']$/g, ""));
8736
+ }
8737
+ }
8738
+ result[key] = value;
8739
+ }
8740
+ return result;
8741
+ }
8742
+
8743
+ // src/skills/installer.ts
8744
+ var execAsync = promisify(exec);
8745
+ async function installSkill(source, skillName) {
8746
+ const parts = source.split("/");
8747
+ if (parts.length < 2) {
8748
+ return { success: false, name: "unknown", error: "Invalid source format. Use owner/repo or owner/repo/skill-name" };
8749
+ }
8750
+ const owner = parts[0];
8751
+ const repo = parts[1];
8752
+ const specifiedSkill = skillName || parts[2];
8753
+ const skillsDir = join3(getWorkingDirectory(void 0, true), ".trie", "skills");
8754
+ const tempDir = join3(skillsDir, `.temp-${Date.now()}`);
8755
+ try {
8756
+ await mkdir2(skillsDir, { recursive: true });
8757
+ const repoUrl = `https://github.com/${owner}/${repo}.git`;
8758
+ await execAsync(`git clone --depth 1 "${repoUrl}" "${tempDir}"`, { timeout: 6e4 });
8759
+ const sourcePath = await findSkillPath(tempDir, specifiedSkill);
8760
+ if (!sourcePath) {
8761
+ throw new Error(`SKILL.md not found in repository. Searched in: root, skills/, ${specifiedSkill || "subdirectories"}`);
8762
+ }
8763
+ const parsed = await parseSkillMd(sourcePath);
8764
+ const name = parsed.frontmatter.name;
8765
+ const targetPath = join3(skillsDir, name);
8766
+ await rm(targetPath, { recursive: true, force: true });
8767
+ await cp(sourcePath, targetPath, { recursive: true });
8768
+ await writeFile2(join3(targetPath, ".installed.json"), JSON.stringify({
8769
+ installedFrom: source,
8770
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
8771
+ repository: `${owner}/${repo}`
8772
+ }, null, 2));
8773
+ return { success: true, name, path: targetPath };
8774
+ } catch (error) {
8775
+ const message = error instanceof Error ? error.message : String(error);
8776
+ return { success: false, name: skillName || "unknown", error: message };
8777
+ } finally {
8778
+ await rm(tempDir, { recursive: true, force: true }).catch(() => {
8779
+ });
8780
+ }
8781
+ }
8782
+ async function findSkillPath(repoPath, skillName) {
8783
+ const searchPaths = [];
8784
+ if (skillName) {
8785
+ searchPaths.push(
8786
+ join3(repoPath, "skills", skillName),
8787
+ join3(repoPath, skillName)
8788
+ );
8789
+ }
8790
+ searchPaths.push(
8791
+ repoPath,
8792
+ join3(repoPath, "skill")
8793
+ );
8794
+ if (!skillName) {
8795
+ try {
8796
+ const skillsSubdir = join3(repoPath, "skills");
8797
+ await access(skillsSubdir);
8798
+ const entries = await readdir(skillsSubdir, { withFileTypes: true });
8799
+ for (const entry of entries) {
8800
+ if (entry.isDirectory() && !entry.name.startsWith(".")) {
8801
+ searchPaths.push(join3(skillsSubdir, entry.name));
8802
+ }
8803
+ }
8804
+ } catch {
8805
+ }
8806
+ }
8807
+ for (const searchPath of searchPaths) {
8808
+ try {
8809
+ await parseSkillMd(searchPath);
8810
+ return searchPath;
8811
+ } catch {
8812
+ }
8813
+ }
8814
+ return null;
8815
+ }
8816
+ async function listInstalledSkills() {
8817
+ const skillsDir = join3(getWorkingDirectory(void 0, true), ".trie", "skills");
8818
+ const skills = [];
8819
+ try {
8820
+ const entries = await readdir(skillsDir, { withFileTypes: true });
8821
+ for (const entry of entries) {
8822
+ if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
8823
+ const skillPath = join3(skillsDir, entry.name);
8824
+ try {
8825
+ const parsed = await parseSkillMd(skillPath);
8826
+ const metaPath = join3(skillPath, ".installed.json");
8827
+ let meta = { installedFrom: "unknown", installedAt: (/* @__PURE__ */ new Date()).toISOString() };
8828
+ try {
8829
+ meta = JSON.parse(await readFile3(metaPath, "utf-8"));
8830
+ } catch {
8831
+ }
8832
+ skills.push({
8833
+ name: parsed.frontmatter.name,
8834
+ description: parsed.frontmatter.description,
8835
+ path: skillPath,
8836
+ installedFrom: meta.installedFrom,
8837
+ installedAt: meta.installedAt
8838
+ });
8839
+ } catch {
8840
+ }
8841
+ }
8842
+ } catch {
8843
+ }
8844
+ return skills;
8845
+ }
8846
+ async function removeSkill(skillName) {
8847
+ const skillsDir = join3(getWorkingDirectory(void 0, true), ".trie", "skills");
8848
+ const skillPath = join3(skillsDir, skillName);
8849
+ try {
8850
+ await rm(skillPath, { recursive: true });
8851
+ return true;
8852
+ } catch {
8853
+ return false;
8854
+ }
8855
+ }
8856
+
8857
+ // src/utils/context-state.ts
8858
+ import { readFile as readFile7, writeFile as writeFile6, mkdir as mkdir6 } from "fs/promises";
8859
+ import { existsSync as existsSync6 } from "fs";
8860
+ import { join as join7, basename as basename2 } from "path";
8861
+
8862
+ // src/memory/issue-store.ts
8863
+ import { mkdir as mkdir4, writeFile as writeFile4, readFile as readFile5, readdir as readdir2 } from "fs/promises";
8864
+ import { existsSync as existsSync4 } from "fs";
8865
+ import { join as join5 } from "path";
8866
+
8867
+ // src/memory/bm25.ts
8868
+ var BM25Index = class _BM25Index {
8869
+ documents = /* @__PURE__ */ new Map();
8870
+ termFrequencies = /* @__PURE__ */ new Map();
8871
+ documentFrequencies = /* @__PURE__ */ new Map();
8872
+ documentLengths = /* @__PURE__ */ new Map();
8873
+ avgDocLength = 0;
8874
+ k1 = 1.5;
8875
+ b = 0.75;
8876
+ /**
8877
+ * Add a document to the index
8878
+ */
8879
+ addDocument(doc) {
8880
+ const tokens = this.tokenize(doc.text);
8881
+ this.documents.set(doc.id, doc);
8882
+ this.documentLengths.set(doc.id, tokens.length);
8883
+ const termFreq = /* @__PURE__ */ new Map();
8884
+ const seenTerms = /* @__PURE__ */ new Set();
8885
+ for (const token of tokens) {
8886
+ termFreq.set(token, (termFreq.get(token) || 0) + 1);
8887
+ if (!seenTerms.has(token)) {
8888
+ seenTerms.add(token);
8889
+ this.documentFrequencies.set(token, (this.documentFrequencies.get(token) || 0) + 1);
8890
+ }
8891
+ }
8892
+ this.termFrequencies.set(doc.id, termFreq);
8893
+ this.updateAvgDocLength();
8894
+ }
8895
+ /**
8896
+ * Add multiple documents
8897
+ */
8898
+ addDocuments(docs) {
8899
+ for (const doc of docs) {
8900
+ this.addDocument(doc);
8901
+ }
8902
+ }
8903
+ /**
8904
+ * Search the index
8905
+ */
8906
+ search(query, limit = 10) {
8907
+ const queryTokens = this.tokenize(query);
8908
+ const scores = /* @__PURE__ */ new Map();
8909
+ const N = this.documents.size;
8910
+ for (const [docId] of this.documents) {
8911
+ let score = 0;
8912
+ const docLength = this.documentLengths.get(docId) || 0;
8913
+ const termFreqs = this.termFrequencies.get(docId);
8914
+ if (!termFreqs) continue;
8915
+ for (const term of queryTokens) {
8916
+ const tf = termFreqs.get(term) || 0;
8917
+ if (tf === 0) continue;
8918
+ const df = this.documentFrequencies.get(term) || 0;
8919
+ const idf = Math.log((N - df + 0.5) / (df + 0.5) + 1);
8920
+ const numerator = tf * (this.k1 + 1);
8921
+ const denominator = tf + this.k1 * (1 - this.b + this.b * (docLength / this.avgDocLength));
8922
+ score += idf * (numerator / denominator);
8923
+ }
8924
+ if (score > 0) {
8925
+ scores.set(docId, score);
8926
+ }
8927
+ }
8928
+ return Array.from(scores.entries()).sort((a, b) => b[1] - a[1]).slice(0, limit).map(([id, score]) => {
8929
+ const metadata = this.documents.get(id)?.metadata;
8930
+ const result = { id, score };
8931
+ if (metadata !== void 0) {
8932
+ result.metadata = metadata;
8933
+ }
8934
+ return result;
8935
+ });
8936
+ }
8937
+ /**
8938
+ * Get document count
8939
+ */
8940
+ get size() {
8941
+ return this.documents.size;
8942
+ }
8943
+ /**
8944
+ * Clear the index
8945
+ */
8946
+ clear() {
8947
+ this.documents.clear();
8948
+ this.termFrequencies.clear();
8949
+ this.documentFrequencies.clear();
8950
+ this.documentLengths.clear();
8951
+ this.avgDocLength = 0;
8952
+ }
8953
+ /**
8954
+ * Serialize the index to JSON
8955
+ */
8956
+ serialize() {
8957
+ return JSON.stringify({
8958
+ documents: Array.from(this.documents.entries()),
8959
+ termFrequencies: Array.from(this.termFrequencies.entries()).map(([k, v]) => [k, Array.from(v.entries())]),
8960
+ documentFrequencies: Array.from(this.documentFrequencies.entries()),
8961
+ documentLengths: Array.from(this.documentLengths.entries()),
8962
+ avgDocLength: this.avgDocLength
8963
+ });
8964
+ }
8965
+ /**
8966
+ * Load from serialized JSON
8967
+ */
8968
+ static deserialize(json) {
8969
+ const data = JSON.parse(json);
8970
+ const index = new _BM25Index();
8971
+ index.documents = new Map(data.documents);
8972
+ index.termFrequencies = new Map(data.termFrequencies.map(([k, v]) => [k, new Map(v)]));
8973
+ index.documentFrequencies = new Map(data.documentFrequencies);
8974
+ index.documentLengths = new Map(data.documentLengths);
8975
+ index.avgDocLength = data.avgDocLength;
8976
+ return index;
8977
+ }
8978
+ tokenize(text) {
8979
+ return text.toLowerCase().replace(/[^\w\s]/g, " ").split(/\s+/).filter((token) => token.length > 2 && !this.isStopWord(token));
8980
+ }
8981
+ isStopWord(word) {
8982
+ const stopWords = /* @__PURE__ */ new Set([
8983
+ "the",
8984
+ "be",
8985
+ "to",
8986
+ "of",
8987
+ "and",
8988
+ "a",
8989
+ "in",
8990
+ "that",
8991
+ "have",
8992
+ "i",
8993
+ "it",
8994
+ "for",
8995
+ "not",
8996
+ "on",
8997
+ "with",
8998
+ "he",
8999
+ "as",
9000
+ "you",
9001
+ "do",
9002
+ "at",
9003
+ "this",
9004
+ "but",
9005
+ "his",
9006
+ "by",
9007
+ "from",
9008
+ "they",
9009
+ "we",
9010
+ "say",
9011
+ "her",
9012
+ "she",
9013
+ "or",
9014
+ "an",
9015
+ "will",
9016
+ "my",
9017
+ "one",
9018
+ "all",
9019
+ "would",
9020
+ "there",
9021
+ "their",
9022
+ "what",
9023
+ "so",
9024
+ "up",
9025
+ "out",
9026
+ "if",
9027
+ "about",
9028
+ "who",
9029
+ "get",
9030
+ "which",
9031
+ "go",
9032
+ "me",
9033
+ "when",
9034
+ "make",
9035
+ "can",
9036
+ "like",
9037
+ "time",
9038
+ "no",
9039
+ "just",
9040
+ "him",
9041
+ "know",
9042
+ "take",
9043
+ "into",
9044
+ "year",
9045
+ "your",
9046
+ "some",
9047
+ "could",
9048
+ "them",
9049
+ "see",
9050
+ "other",
9051
+ "than",
9052
+ "then",
9053
+ "now",
9054
+ "look",
9055
+ "only",
9056
+ "come",
9057
+ "its",
9058
+ "over",
9059
+ "also",
9060
+ "back",
9061
+ "after",
9062
+ "use",
9063
+ "two",
9064
+ "how",
9065
+ "our",
9066
+ "first",
9067
+ "way",
9068
+ "even",
9069
+ "new",
9070
+ "want",
9071
+ "because",
9072
+ "any",
9073
+ "these",
9074
+ "give",
9075
+ "day",
9076
+ "most",
9077
+ "us",
9078
+ "should",
9079
+ "been",
9080
+ "has",
9081
+ "was",
9082
+ "are"
9083
+ ]);
9084
+ return stopWords.has(word);
9085
+ }
9086
+ updateAvgDocLength() {
9087
+ if (this.documentLengths.size === 0) {
9088
+ this.avgDocLength = 0;
9089
+ return;
9090
+ }
9091
+ const total = Array.from(this.documentLengths.values()).reduce((a, b) => a + b, 0);
9092
+ this.avgDocLength = total / this.documentLengths.size;
9093
+ }
9094
+ };
9095
+
9096
+ // src/memory/compactor.ts
9097
+ import { mkdir as mkdir3, writeFile as writeFile3, readFile as readFile4 } from "fs/promises";
9098
+ import { existsSync as existsSync3 } from "fs";
9099
+ import { join as join4 } from "path";
9100
+ async function compactOldIssues(issues, options = {}) {
9101
+ const keepDays = options.keepDays ?? 30;
9102
+ const minIssues = options.minIssuesToCompact ?? 100;
9103
+ const cutoffDate = /* @__PURE__ */ new Date();
9104
+ cutoffDate.setDate(cutoffDate.getDate() - keepDays);
9105
+ const oldIssues = issues.filter((i) => new Date(i.timestamp) < cutoffDate);
9106
+ const recentIssues = issues.filter((i) => new Date(i.timestamp) >= cutoffDate);
9107
+ if (oldIssues.length < minIssues) {
9108
+ return { summary: null, remaining: issues };
9109
+ }
9110
+ const summary = buildSummary(oldIssues);
9111
+ return { summary, remaining: recentIssues };
9112
+ }
9113
+ function buildSummary(issues) {
9114
+ const sorted = issues.sort(
9115
+ (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
9116
+ );
9117
+ const bySeverity = {};
9118
+ const byAgent = {};
9119
+ const patternMap = /* @__PURE__ */ new Map();
9120
+ const fileCount = /* @__PURE__ */ new Map();
9121
+ for (const issue of issues) {
9122
+ bySeverity[issue.severity] = (bySeverity[issue.severity] || 0) + 1;
9123
+ byAgent[issue.agent] = (byAgent[issue.agent] || 0) + 1;
9124
+ const patternKey = normalizePattern(issue.issue);
9125
+ const existing = patternMap.get(patternKey);
9126
+ if (existing) {
9127
+ existing.count++;
9128
+ } else {
9129
+ patternMap.set(patternKey, { count: 1, issue });
9130
+ }
9131
+ const fileName = issue.file.split("/").pop() || issue.file;
9132
+ fileCount.set(fileName, (fileCount.get(fileName) || 0) + 1);
9133
+ }
9134
+ const topPatterns = Array.from(patternMap.entries()).sort((a, b) => b[1].count - a[1].count).slice(0, 10).map(([pattern, data]) => ({
9135
+ pattern: pattern.slice(0, 100),
9136
+ count: data.count,
9137
+ severity: data.issue.severity,
9138
+ agent: data.issue.agent,
9139
+ exampleFix: data.issue.fix.slice(0, 200)
9140
+ }));
9141
+ const hotFiles = Array.from(fileCount.entries()).sort((a, b) => b[1] - a[1]).slice(0, 10).map(([file, count]) => ({ file, count }));
9142
+ return {
9143
+ period: `${sorted[0]?.timestamp.split("T")[0]} to ${sorted[sorted.length - 1]?.timestamp.split("T")[0]}`,
9144
+ startDate: sorted[0]?.timestamp || "",
9145
+ endDate: sorted[sorted.length - 1]?.timestamp || "",
9146
+ totalIssues: issues.length,
9147
+ resolvedCount: issues.filter((i) => i.resolved).length,
9148
+ bySeverity,
9149
+ byAgent,
9150
+ topPatterns,
9151
+ hotFiles,
9152
+ compactedAt: (/* @__PURE__ */ new Date()).toISOString()
9153
+ };
9154
+ }
9155
+ function normalizePattern(text) {
9156
+ return text.toLowerCase().replace(/`[^`]+`/g, "CODE").replace(/\b\d+\b/g, "N").replace(/["']/g, "").replace(/\s+/g, " ").trim().slice(0, 150);
9157
+ }
9158
+ async function saveCompactedSummary(summary, projectDir) {
9159
+ const memoryDir = join4(projectDir, ".trie", "memory");
9160
+ await mkdir3(memoryDir, { recursive: true });
9161
+ const summaryPath = join4(memoryDir, "compacted-summaries.json");
9162
+ let summaries = [];
9163
+ try {
9164
+ if (existsSync3(summaryPath)) {
9165
+ summaries = JSON.parse(await readFile4(summaryPath, "utf-8"));
9166
+ }
9167
+ } catch {
9168
+ summaries = [];
9169
+ }
9170
+ summaries.push(summary);
9171
+ if (summaries.length > 12) {
9172
+ summaries = summaries.slice(-12);
9173
+ }
9174
+ await writeFile3(summaryPath, JSON.stringify(summaries, null, 2));
9175
+ }
9176
+ async function loadCompactedSummaries(projectDir) {
9177
+ const summaryPath = join4(projectDir, ".trie", "memory", "compacted-summaries.json");
9178
+ try {
9179
+ if (existsSync3(summaryPath)) {
9180
+ return JSON.parse(await readFile4(summaryPath, "utf-8"));
9181
+ }
9182
+ } catch {
9183
+ }
9184
+ return [];
9185
+ }
9186
+ async function getHistoricalInsights(projectDir) {
9187
+ const summaries = await loadCompactedSummaries(projectDir);
9188
+ if (summaries.length === 0) {
9189
+ return {
9190
+ totalHistoricalIssues: 0,
9191
+ recurringPatterns: [],
9192
+ improvementTrend: "unknown"
9193
+ };
9194
+ }
9195
+ const totalHistoricalIssues = summaries.reduce((sum, s) => sum + s.totalIssues, 0);
9196
+ const patternCounts = /* @__PURE__ */ new Map();
9197
+ for (const summary of summaries) {
9198
+ for (const pattern of summary.topPatterns) {
9199
+ const key = pattern.pattern;
9200
+ const existing = patternCounts.get(key);
9201
+ if (existing) {
9202
+ existing.count += pattern.count;
9203
+ existing.appearances++;
9204
+ } else {
9205
+ patternCounts.set(key, { ...pattern, appearances: 1 });
9206
+ }
9207
+ }
9208
+ }
9209
+ const recurringPatterns = Array.from(patternCounts.values()).filter((p) => p.appearances >= 2).sort((a, b) => b.count - a.count).slice(0, 5);
9210
+ let improvementTrend = "unknown";
9211
+ if (summaries.length >= 2) {
9212
+ const recent = summaries.slice(-2);
9213
+ const olderCount = recent[0]?.totalIssues || 0;
9214
+ const newerCount = recent[1]?.totalIssues || 0;
9215
+ if (newerCount < olderCount * 0.8) {
9216
+ improvementTrend = "improving";
9217
+ } else if (newerCount > olderCount * 1.2) {
9218
+ improvementTrend = "declining";
9219
+ } else {
9220
+ improvementTrend = "stable";
9221
+ }
9222
+ }
9223
+ return {
9224
+ totalHistoricalIssues,
9225
+ recurringPatterns,
9226
+ improvementTrend
9227
+ };
9228
+ }
9229
+
9230
+ // src/memory/issue-store.ts
9231
+ async function storeIssues(issues, project, workDir) {
9232
+ const projectDir = workDir || getWorkingDirectory(void 0, true);
9233
+ const memoryDir = join5(projectDir, ".trie", "memory");
9234
+ await mkdir4(memoryDir, { recursive: true });
9235
+ const stored = [];
9236
+ const now = (/* @__PURE__ */ new Date()).toISOString();
9237
+ for (const issue of issues) {
9238
+ const hash = hashIssue(issue);
9239
+ const storedIssue = {
9240
+ id: issue.id,
9241
+ hash,
9242
+ severity: issue.severity,
9243
+ issue: issue.issue,
9244
+ fix: issue.fix,
9245
+ file: issue.file,
9246
+ agent: issue.agent,
9247
+ timestamp: now,
9248
+ project,
9249
+ resolved: false
9250
+ };
9251
+ if (issue.line !== void 0) {
9252
+ storedIssue.line = issue.line;
9253
+ }
9254
+ if (issue.category !== void 0) {
9255
+ storedIssue.category = issue.category;
9256
+ }
9257
+ stored.push(storedIssue);
9258
+ }
9259
+ await appendToDailyLog(stored, projectDir);
9260
+ await updateIssueIndex(stored, projectDir);
9261
+ return stored.length;
9262
+ }
9263
+ async function searchIssues(query, options = {}) {
9264
+ const projectDir = options.workDir || getWorkingDirectory(void 0, true);
9265
+ const limit = options.limit || 10;
9266
+ const allIssues = await loadIssueIndex(projectDir);
9267
+ if (allIssues.length === 0) {
9268
+ return [];
9269
+ }
9270
+ const filteredIssues = allIssues.filter((issue) => {
9271
+ if (options.project && issue.project !== options.project) return false;
9272
+ if (options.severity && !options.severity.includes(issue.severity)) return false;
9273
+ if (options.agent && issue.agent !== options.agent) return false;
9274
+ if (!options.includeResolved && issue.resolved) return false;
9275
+ return true;
9276
+ });
9277
+ if (filteredIssues.length === 0) {
9278
+ return [];
9279
+ }
9280
+ const bm25 = new BM25Index();
9281
+ const issueMap = /* @__PURE__ */ new Map();
9282
+ for (const issue of filteredIssues) {
9283
+ const searchText = `${issue.issue} ${issue.fix} ${issue.file} ${issue.agent} ${issue.category || ""} ${issue.severity}`;
9284
+ bm25.addDocument({
9285
+ id: issue.id,
9286
+ text: searchText
9287
+ });
9288
+ issueMap.set(issue.id, issue);
9289
+ }
9290
+ const bm25Results = bm25.search(query, limit);
9291
+ return bm25Results.map((result) => ({
9292
+ issue: issueMap.get(result.id),
9293
+ score: result.score,
9294
+ matchType: "bm25"
9295
+ }));
9296
+ }
9297
+ async function findSimilarIssues(issue, options = {}) {
9298
+ const query = `${issue.issue} ${issue.fix} ${issue.agent}`;
9299
+ const searchOptions = {
9300
+ limit: (options.limit || 5) + 5,
9301
+ // Get extra to account for filtering
9302
+ includeResolved: true
9303
+ };
9304
+ if (options.workDir !== void 0) {
9305
+ searchOptions.workDir = options.workDir;
9306
+ }
9307
+ const results = await searchIssues(query, searchOptions);
9308
+ let filtered = results.filter((r) => r.issue.id !== issue.id);
9309
+ if (options.excludeSameFile) {
9310
+ filtered = filtered.filter((r) => r.issue.file !== issue.file);
9311
+ }
9312
+ return filtered.slice(0, options.limit || 5);
9313
+ }
9314
+ async function markIssueResolved(issueId, workDir) {
9315
+ const projectDir = workDir || getWorkingDirectory(void 0, true);
9316
+ const index = await loadIssueIndex(projectDir);
9317
+ const issue = index.find((i) => i.id === issueId);
9318
+ if (!issue) return false;
9319
+ issue.resolved = true;
9320
+ issue.resolvedAt = (/* @__PURE__ */ new Date()).toISOString();
9321
+ await saveIssueIndex(index, projectDir);
9322
+ return true;
9323
+ }
9324
+ async function getMemoryStats(workDir) {
9325
+ const projectDir = workDir || getWorkingDirectory(void 0, true);
9326
+ const index = await loadIssueIndex(projectDir);
9327
+ const historical = await getHistoricalInsights(projectDir);
9328
+ const stats = {
9329
+ totalIssues: index.length,
9330
+ issuesByAgent: {},
9331
+ issuesBySeverity: {},
9332
+ resolvedCount: 0,
9333
+ historicalIssues: historical.totalHistoricalIssues,
9334
+ improvementTrend: historical.improvementTrend
9335
+ };
9336
+ for (const issue of index) {
9337
+ stats.issuesByAgent[issue.agent] = (stats.issuesByAgent[issue.agent] || 0) + 1;
9338
+ stats.issuesBySeverity[issue.severity] = (stats.issuesBySeverity[issue.severity] || 0) + 1;
9339
+ if (issue.resolved) stats.resolvedCount++;
9340
+ }
9341
+ if (index.length > 0) {
9342
+ const sorted = [...index].sort(
9343
+ (a, b) => new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
9344
+ );
9345
+ const oldest = sorted[0]?.timestamp;
9346
+ const newest = sorted[sorted.length - 1]?.timestamp;
9347
+ if (oldest !== void 0) {
9348
+ stats.oldestIssue = oldest;
9349
+ }
9350
+ if (newest !== void 0) {
9351
+ stats.newestIssue = newest;
9352
+ }
9353
+ }
9354
+ return stats;
9355
+ }
9356
+ async function getRecentIssues(options = {}) {
9357
+ const projectDir = options.workDir || getWorkingDirectory(void 0, true);
9358
+ const index = await loadIssueIndex(projectDir);
9359
+ const limit = options.limit || 20;
9360
+ const daysBack = options.daysBack || 7;
9361
+ const cutoff = /* @__PURE__ */ new Date();
9362
+ cutoff.setDate(cutoff.getDate() - daysBack);
9363
+ return index.filter((i) => new Date(i.timestamp) >= cutoff).sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()).slice(0, limit);
9364
+ }
9365
+ async function getDailyLogs(workDir) {
9366
+ const projectDir = workDir || getWorkingDirectory(void 0, true);
9367
+ const memoryDir = join5(projectDir, ".trie", "memory");
9368
+ try {
9369
+ if (!existsSync4(memoryDir)) return [];
9370
+ const files = await readdir2(memoryDir);
9371
+ return files.filter((f) => /^\d{4}-\d{2}-\d{2}\.md$/.test(f)).sort().reverse();
9372
+ } catch {
9373
+ return [];
9374
+ }
9375
+ }
9376
+ async function appendToDailyLog(issues, projectDir) {
9377
+ const memoryDir = join5(projectDir, ".trie", "memory");
9378
+ const today = (/* @__PURE__ */ new Date()).toISOString().split("T")[0];
9379
+ const logPath = join5(memoryDir, `${today}.md`);
9380
+ let content = "";
9381
+ try {
9382
+ if (existsSync4(logPath)) {
9383
+ content = await readFile5(logPath, "utf-8");
9384
+ } else {
9385
+ content = `# Issue Log: ${today}
9386
+
9387
+ `;
9388
+ }
9389
+ } catch {
9390
+ content = `# Issue Log: ${today}
9391
+
9392
+ `;
9393
+ }
9394
+ const time = (/* @__PURE__ */ new Date()).toTimeString().split(" ")[0];
9395
+ const newEntries = issues.map(
9396
+ (i) => `## [${time}] ${i.severity.toUpperCase()}: ${i.issue.slice(0, 80)}${i.issue.length > 80 ? "..." : ""}
9397
+ - **File:** \`${i.file}\`${i.line ? `:${i.line}` : ""}
9398
+ - **Agent:** ${i.agent}
9399
+ - **Fix:** ${i.fix.slice(0, 200)}${i.fix.length > 200 ? "..." : ""}
9400
+ `
9401
+ ).join("\n");
9402
+ content += newEntries + "\n";
9403
+ await writeFile4(logPath, content);
9404
+ }
9405
+ async function loadIssueIndex(projectDir) {
9406
+ const indexPath = join5(projectDir, ".trie", "memory", "issues.json");
9407
+ try {
9408
+ if (existsSync4(indexPath)) {
9409
+ const content = await readFile5(indexPath, "utf-8");
9410
+ return JSON.parse(content);
9411
+ }
9412
+ } catch {
9413
+ }
9414
+ return [];
9415
+ }
9416
+ async function updateIssueIndex(newIssues, projectDir) {
9417
+ const memoryDir = join5(projectDir, ".trie", "memory");
9418
+ await mkdir4(memoryDir, { recursive: true });
9419
+ let existing = await loadIssueIndex(projectDir);
9420
+ const hashSet = new Set(existing.map((i) => i.hash));
9421
+ const toAdd = newIssues.filter((i) => !hashSet.has(i.hash));
9422
+ existing = [...existing, ...toAdd];
9423
+ if (existing.length > 500) {
9424
+ const { summary, remaining } = await compactOldIssues(existing, {
9425
+ keepDays: 30,
9426
+ minIssuesToCompact: 100
9427
+ });
9428
+ if (summary) {
9429
+ await saveCompactedSummary(summary, projectDir);
9430
+ existing = remaining;
9431
+ }
9432
+ }
9433
+ if (existing.length > 1e3) {
9434
+ existing = existing.sort((a, b) => new Date(b.timestamp).getTime() - new Date(a.timestamp).getTime()).slice(0, 1e3);
9435
+ }
9436
+ await saveIssueIndex(existing, projectDir);
9437
+ }
9438
+ async function saveIssueIndex(issues, projectDir) {
9439
+ const indexPath = join5(projectDir, ".trie", "memory", "issues.json");
9440
+ await writeFile4(indexPath, JSON.stringify(issues, null, 2));
9441
+ }
9442
+ function hashIssue(issue) {
9443
+ const content = `${issue.issue}|${issue.file}|${issue.severity}|${issue.agent}`;
9444
+ let hash = 0;
9445
+ for (let i = 0; i < content.length; i++) {
9446
+ const char = content.charCodeAt(i);
9447
+ hash = (hash << 5) - hash + char;
9448
+ hash = hash & hash;
9449
+ }
9450
+ return Math.abs(hash).toString(36);
9451
+ }
9452
+
9453
+ // src/memory/global-memory.ts
9454
+ import { mkdir as mkdir5, writeFile as writeFile5, readFile as readFile6, readdir as readdir3 } from "fs/promises";
9455
+ import { existsSync as existsSync5 } from "fs";
9456
+ import { join as join6 } from "path";
9457
+ import { homedir } from "os";
9458
+ var GLOBAL_TRIE_DIR = join6(homedir(), ".trie");
9459
+ var GLOBAL_MEMORY_DIR = join6(GLOBAL_TRIE_DIR, "memory");
9460
+ async function recordToGlobalMemory(issues, projectName, projectPath, healthScore = 0) {
9461
+ await mkdir5(GLOBAL_MEMORY_DIR, { recursive: true });
9462
+ await mkdir5(join6(GLOBAL_MEMORY_DIR, "projects"), { recursive: true });
9463
+ const patterns = await loadGlobalPatterns();
9464
+ const now = (/* @__PURE__ */ new Date()).toISOString();
9465
+ for (const issue of issues) {
9466
+ const patternId = extractPatternId(issue);
9467
+ const existing = patterns.find((p) => p.id === patternId);
9468
+ if (existing) {
9469
+ existing.occurrences++;
9470
+ existing.lastSeen = now;
9471
+ if (!existing.projects.includes(projectName)) {
9472
+ existing.projects.push(projectName);
9473
+ }
9474
+ } else {
9475
+ patterns.push({
9476
+ id: patternId,
9477
+ pattern: issue.issue.slice(0, 200),
9478
+ description: issue.fix.slice(0, 200),
9479
+ severity: issue.severity,
9480
+ agent: issue.agent,
9481
+ occurrences: 1,
9482
+ projects: [projectName],
9483
+ firstSeen: now,
9484
+ lastSeen: now
9485
+ });
9486
+ }
9487
+ }
9488
+ await saveGlobalPatterns(patterns);
9489
+ const summaryPath = join6(GLOBAL_MEMORY_DIR, "projects", `${sanitizeName(projectName)}.json`);
9490
+ const summary = {
9491
+ name: projectName,
9492
+ path: projectPath,
9493
+ lastScan: now,
9494
+ healthScore,
9495
+ totalIssues: issues.length,
9496
+ patterns: [...new Set(issues.map((i) => extractPatternId(i)))]
9497
+ };
9498
+ await writeFile5(summaryPath, JSON.stringify(summary, null, 2));
9499
+ }
9500
+ async function findCrossProjectPatterns(minOccurrences = 2) {
9501
+ const patterns = await loadGlobalPatterns();
9502
+ return patterns.filter((p) => p.projects.length >= minOccurrences).sort((a, b) => b.occurrences - a.occurrences);
9503
+ }
9504
+ async function listTrackedProjects() {
9505
+ const projectsDir = join6(GLOBAL_MEMORY_DIR, "projects");
9506
+ try {
9507
+ if (!existsSync5(projectsDir)) return [];
9508
+ const files = await readdir3(projectsDir);
9509
+ const summaries = [];
9510
+ for (const file of files) {
9511
+ if (!file.endsWith(".json")) continue;
9512
+ try {
9513
+ const content = await readFile6(join6(projectsDir, file), "utf-8");
9514
+ summaries.push(JSON.parse(content));
9515
+ } catch {
9516
+ }
9517
+ }
9518
+ return summaries.sort(
9519
+ (a, b) => new Date(b.lastScan).getTime() - new Date(a.lastScan).getTime()
9520
+ );
9521
+ } catch {
9522
+ return [];
9523
+ }
9524
+ }
9525
+ async function getGlobalMemoryStats() {
9526
+ const patterns = await loadGlobalPatterns();
9527
+ const projects = await listTrackedProjects();
9528
+ const patternsByAgent = {};
9529
+ for (const pattern of patterns) {
9530
+ patternsByAgent[pattern.agent] = (patternsByAgent[pattern.agent] || 0) + 1;
9531
+ }
9532
+ return {
9533
+ totalPatterns: patterns.length,
9534
+ crossProjectPatterns: patterns.filter((p) => p.projects.length >= 2).length,
9535
+ trackedProjects: projects.length,
9536
+ totalOccurrences: patterns.reduce((sum, p) => sum + p.occurrences, 0),
9537
+ fixedPatterns: patterns.filter((p) => p.fixApplied).length,
9538
+ patternsByAgent
9539
+ };
9540
+ }
9541
+ async function updateGlobalMemoryMd() {
9542
+ const patterns = await loadGlobalPatterns();
9543
+ const crossProject = patterns.filter((p) => p.projects.length >= 2);
9544
+ const projects = await listTrackedProjects();
9545
+ const lines = [
9546
+ "# Global Trie Memory",
9547
+ "",
9548
+ "> Auto-generated file tracking patterns across all your projects.",
9549
+ `> Last updated: ${(/* @__PURE__ */ new Date()).toISOString()}`,
9550
+ "",
9551
+ "## Summary",
9552
+ "",
9553
+ `- **Projects tracked:** ${projects.length}`,
9554
+ `- **Total patterns:** ${patterns.length}`,
9555
+ `- **Cross-project patterns:** ${crossProject.length}`,
9556
+ "",
9557
+ "## Cross-Project Patterns",
9558
+ "",
9559
+ "These issues appear in multiple projects:",
9560
+ ""
9561
+ ];
9562
+ for (const p of crossProject.slice(0, 20)) {
9563
+ lines.push(
9564
+ `### ${p.pattern.slice(0, 60)}${p.pattern.length > 60 ? "..." : ""}`,
9565
+ "",
9566
+ `- **Severity:** ${p.severity}`,
9567
+ `- **Agent:** ${p.agent}`,
9568
+ `- **Occurrences:** ${p.occurrences} across ${p.projects.length} projects`,
9569
+ `- **Projects:** ${p.projects.slice(0, 5).join(", ")}${p.projects.length > 5 ? "..." : ""}`
9570
+ );
9571
+ if (p.fixApplied) {
9572
+ lines.push(`- **Fixed in:** ${p.fixApplied.project} on ${p.fixApplied.timestamp.split("T")[0]}`);
9573
+ } else {
9574
+ lines.push("- **Status:** Not fixed");
9575
+ }
9576
+ lines.push("");
9577
+ }
9578
+ lines.push(
9579
+ "## Tracked Projects",
9580
+ "",
9581
+ "| Project | Last Scan | Health | Issues |",
9582
+ "|---------|-----------|--------|--------|"
9583
+ );
9584
+ for (const p of projects.slice(0, 20)) {
9585
+ lines.push(`| ${p.name} | ${p.lastScan.split("T")[0]} | ${p.healthScore}% | ${p.totalIssues} |`);
9586
+ }
9587
+ lines.push("", "---", "", "*This file is auto-generated by Trie. Do not edit manually.*");
9588
+ await mkdir5(GLOBAL_MEMORY_DIR, { recursive: true });
9589
+ await writeFile5(join6(GLOBAL_MEMORY_DIR, "GLOBAL_MEMORY.md"), lines.join("\n"));
9590
+ }
9591
+ async function searchGlobalPatterns(query, options = {}) {
9592
+ const patterns = await loadGlobalPatterns();
9593
+ const limit = options.limit || 10;
9594
+ const queryTerms = query.toLowerCase().split(/\s+/).filter((t) => t.length > 2);
9595
+ const scored = patterns.filter((p) => {
9596
+ if (options.severity && !options.severity.includes(p.severity)) return false;
9597
+ if (options.agent && p.agent !== options.agent) return false;
9598
+ return true;
9599
+ }).map((p) => {
9600
+ const text = `${p.pattern} ${p.description} ${p.agent}`.toLowerCase();
9601
+ let score = 0;
9602
+ for (const term of queryTerms) {
9603
+ if (text.includes(term)) score++;
9604
+ }
9605
+ return { pattern: p, score };
9606
+ }).filter((s) => s.score > 0).sort((a, b) => b.score - a.score).slice(0, limit);
9607
+ return scored.map((s) => s.pattern);
9608
+ }
9609
+ async function loadGlobalPatterns() {
9610
+ const patternsPath = join6(GLOBAL_MEMORY_DIR, "global-patterns.json");
9611
+ try {
9612
+ if (existsSync5(patternsPath)) {
9613
+ const content = await readFile6(patternsPath, "utf-8");
9614
+ return JSON.parse(content);
9615
+ }
9616
+ } catch {
9617
+ }
9618
+ return [];
9619
+ }
9620
+ async function saveGlobalPatterns(patterns) {
9621
+ await mkdir5(GLOBAL_MEMORY_DIR, { recursive: true });
9622
+ const patternsPath = join6(GLOBAL_MEMORY_DIR, "global-patterns.json");
9623
+ const pruned = patterns.sort((a, b) => new Date(b.lastSeen).getTime() - new Date(a.lastSeen).getTime()).slice(0, 500);
9624
+ await writeFile5(patternsPath, JSON.stringify(pruned, null, 2));
9625
+ }
9626
+ function extractPatternId(issue) {
9627
+ const normalized = issue.issue.toLowerCase().replace(/`[^`]+`/g, "CODE").replace(/\b\d+\b/g, "N").replace(/['"]/g, "").slice(0, 100);
9628
+ let hash = 0;
9629
+ for (let i = 0; i < normalized.length; i++) {
9630
+ const char = normalized.charCodeAt(i);
9631
+ hash = (hash << 5) - hash + char;
9632
+ hash = hash & hash;
9633
+ }
9634
+ return `${issue.agent}-${issue.severity}-${Math.abs(hash).toString(36)}`;
9635
+ }
9636
+ function sanitizeName(name) {
9637
+ return name.replace(/[^a-zA-Z0-9-_]/g, "-").toLowerCase();
9638
+ }
9639
+
9640
+ // src/utils/context-state.ts
9641
+ var AGENTS_MD_PATH = ".trie/AGENTS.md";
9642
+ var STATE_JSON_PATH = ".trie/state.json";
9643
+ async function loadContextState() {
9644
+ const workDir = getWorkingDirectory(void 0, true);
9645
+ const statePath = join7(workDir, STATE_JSON_PATH);
9646
+ const defaults = getDefaultState();
9647
+ try {
9648
+ if (existsSync6(statePath)) {
9649
+ const content = await readFile7(statePath, "utf-8");
9650
+ const loaded = JSON.parse(content);
9651
+ return {
9652
+ ...defaults,
9653
+ ...loaded,
9654
+ skills: loaded.skills || defaults.skills
9655
+ };
9656
+ }
9657
+ } catch {
9658
+ }
9659
+ return defaults;
9660
+ }
9661
+ async function saveContextState(state) {
9662
+ const workDir = getWorkingDirectory(void 0, true);
9663
+ const trieDir = join7(workDir, ".trie");
9664
+ const statePath = join7(workDir, STATE_JSON_PATH);
9665
+ await mkdir6(trieDir, { recursive: true });
9666
+ await writeFile6(statePath, JSON.stringify(state, null, 2));
9667
+ }
9668
+ async function updateContextAfterScan(results, filesScanned, contextSignals, duration) {
9669
+ const state = await loadContextState();
9670
+ const workDir = getWorkingDirectory(void 0, true);
9671
+ const now = (/* @__PURE__ */ new Date()).toISOString();
9672
+ const allIssues = results.flatMap((r) => r.issues);
9673
+ const issueCounts = {
9674
+ critical: allIssues.filter((i) => i.severity === "critical").length,
9675
+ serious: allIssues.filter((i) => i.severity === "serious").length,
9676
+ moderate: allIssues.filter((i) => i.severity === "moderate").length,
9677
+ low: allIssues.filter((i) => i.severity === "low").length,
9678
+ total: allIssues.length
9679
+ };
9680
+ const fileIssueMap = /* @__PURE__ */ new Map();
9681
+ for (const issue of allIssues) {
9682
+ const count = fileIssueMap.get(issue.file) || 0;
9683
+ fileIssueMap.set(issue.file, count + 1);
9684
+ }
9685
+ const hotFiles = Array.from(fileIssueMap.entries()).sort((a, b) => b[1] - a[1]).slice(0, 10).map(([file, issueCount]) => ({ file, issueCount }));
9686
+ const scanSummary = {
9687
+ timestamp: now,
9688
+ agents: results.map((r) => r.agent),
9689
+ filesScanned,
9690
+ issues: issueCounts,
9691
+ duration,
9692
+ hotFiles
9693
+ };
9694
+ for (const result of results) {
9695
+ state.agentStatus[result.agent] = {
9696
+ lastRun: now,
9697
+ issuesFound: result.issues.length
9698
+ };
9699
+ }
9700
+ const criticalPenalty = issueCounts.critical * 25;
9701
+ const seriousPenalty = issueCounts.serious * 10;
9702
+ const moderatePenalty = issueCounts.moderate * 3;
9703
+ const lowPenalty = issueCounts.low * 1;
9704
+ const totalPenalty = Math.min(100, criticalPenalty + seriousPenalty + moderatePenalty + lowPenalty);
9705
+ state.healthScore = Math.max(0, 100 - totalPenalty);
9706
+ state.activePriorities = generatePriorities(issueCounts, contextSignals);
9707
+ state.contextSignals = { ...state.contextSignals, ...contextSignals };
9708
+ state.scanHistory = [scanSummary, ...state.scanHistory.slice(0, 19)];
9709
+ state.lastScan = scanSummary;
9710
+ await saveContextState(state);
9711
+ await updateAgentsMd(state);
9712
+ if (allIssues.length > 0) {
9713
+ const projectName = basename2(workDir);
9714
+ try {
9715
+ await storeIssues(allIssues, projectName, workDir);
9716
+ await recordToGlobalMemory(allIssues, projectName, workDir, state.healthScore);
9717
+ await updateGlobalMemoryMd();
9718
+ } catch {
9719
+ }
9720
+ }
9721
+ }
9722
+ async function updateAgentsMd(state) {
9723
+ const workDir = getWorkingDirectory(void 0, true);
9724
+ const mdPath = join7(workDir, AGENTS_MD_PATH);
9725
+ let content;
9726
+ try {
9727
+ content = await readFile7(mdPath, "utf-8");
9728
+ } catch {
9729
+ content = getAgentsMdTemplate();
9730
+ }
9731
+ content = updateSection(content, "Project State", generateProjectStateTable(state));
9732
+ content = updateSection(content, "Active Priorities", generatePrioritiesList(state));
9733
+ content = updateSection(content, "Agent Status", generateAgentStatusTable(state));
9734
+ content = updateSection(content, "Recent Scan History", generateScanHistoryTable(state));
9735
+ content = updateSection(content, "Context Signals Detected", generateContextSignals(state));
9736
+ content = updateSection(content, "Risk Assessment", generateRiskAssessment(state));
9737
+ content = updateSection(content, "Hot Files", generateHotFilesSection(state));
9738
+ content = content.replace(
9739
+ /Last updated:.*$/m,
9740
+ `Last updated: ${(/* @__PURE__ */ new Date()).toISOString()}`
9741
+ );
9742
+ await writeFile6(mdPath, content);
9743
+ }
9744
+ function updateSection(content, sectionName, newContent) {
9745
+ const sectionRegex = new RegExp(
9746
+ `(### ${sectionName}[\\s\\S]*?)(?=###|---|
9747
+ ## |$)`,
9748
+ "g"
9749
+ );
9750
+ const replacement = `### ${sectionName}
9751
+ ${newContent}
9752
+
9753
+ `;
9754
+ if (content.match(sectionRegex)) {
9755
+ return content.replace(sectionRegex, replacement);
9756
+ }
9757
+ return content;
9758
+ }
9759
+ function generateProjectStateTable(state) {
9760
+ const lastScan = state.lastScan;
9761
+ const lastScanDate = lastScan ? new Date(lastScan.timestamp).toLocaleString() : "Never";
9762
+ const criticalCount = lastScan?.issues.critical ?? 0;
9763
+ const totalTasks = lastScan?.issues.total ?? 0;
9764
+ return `| Metric | Value | Updated |
9765
+ |--------|-------|---------|
9766
+ | Last Scan | ${lastScanDate} | ${lastScan ? "Auto" : "-"} |
9767
+ | Critical Issues | ${criticalCount} | ${lastScan ? "Auto" : "-"} |
9768
+ | Open Tasks | ${totalTasks} | ${lastScan ? "Auto" : "-"} |
9769
+ | Health Score | ${state.healthScore}% | ${lastScan ? "Auto" : "-"} |`;
9770
+ }
9771
+ function generatePrioritiesList(state) {
9772
+ if (state.activePriorities.length === 0) {
9773
+ return "_No active priorities. Run a scan to identify issues._";
9774
+ }
9775
+ return state.activePriorities.map((p, i) => `${i + 1}. ${p}`).join("\n");
9776
+ }
9777
+ function generatePriorities(issues, contextSignals) {
9778
+ const priorities = [];
9779
+ if (issues.critical > 0) {
9780
+ priorities.push(`\u{1F6A8} Fix ${issues.critical} critical security issue${issues.critical > 1 ? "s" : ""} immediately`);
9781
+ }
9782
+ if (issues.serious > 0) {
9783
+ priorities.push(`\u26A0\uFE0F Address ${issues.serious} serious issue${issues.serious > 1 ? "s" : ""} before deployment`);
9784
+ }
9785
+ if (contextSignals.touchesAuth && issues.critical === 0) {
9786
+ priorities.push("\u2705 Auth code reviewed - continue monitoring");
9787
+ }
9788
+ if (contextSignals.touchesPayments) {
9789
+ priorities.push("\u{1F4B3} Payment code detected - ensure PCI compliance");
9790
+ }
9791
+ if (contextSignals.touchesUserData) {
9792
+ priorities.push("\u{1F510} User data handling detected - verify privacy compliance");
9793
+ }
9794
+ if (issues.moderate > 5) {
9795
+ priorities.push(`\u{1F4CB} Schedule time to address ${issues.moderate} moderate issues`);
9796
+ }
9797
+ if (priorities.length === 0) {
9798
+ priorities.push("\u2728 No critical issues - focus on feature development");
9799
+ }
9800
+ return priorities.slice(0, 5);
9801
+ }
9802
+ function generateAgentStatusTable(state) {
9803
+ const builtInAgents = [
9804
+ "security",
9805
+ "privacy",
9806
+ "legal",
9807
+ "accessibility",
9808
+ "bugs",
9809
+ "design",
9810
+ "architecture",
9811
+ "performance",
9812
+ "devops",
9813
+ "soc2",
9814
+ "e2e",
9815
+ "typecheck",
9816
+ "visual-qa",
9817
+ "data-flow"
9818
+ ];
9819
+ let table = `| Agent | Status | Last Run | Issues Found |
9820
+ |-------|--------|----------|--------------|`;
9821
+ for (const agent of builtInAgents) {
9822
+ const status = state.agentStatus[agent];
9823
+ const lastRun = status?.lastRun ? new Date(status.lastRun).toLocaleDateString() : "Never";
9824
+ const issues = status?.issuesFound ?? "-";
9825
+ const statusEmoji = status ? "\u2705" : "\u23F8\uFE0F";
9826
+ table += `
9827
+ | ${agent} | ${statusEmoji} Ready | ${lastRun} | ${issues} |`;
9828
+ }
9829
+ return table;
9830
+ }
9831
+ function generateScanHistoryTable(state) {
9832
+ if (state.scanHistory.length === 0) {
9833
+ return `| Date | Agents | Files | Issues | Duration |
9834
+ |------|--------|-------|--------|----------|
9835
+ | - | - | - | - | - |`;
9836
+ }
9837
+ let table = `| Date | Agents | Files | Issues | Duration |
9838
+ |------|--------|-------|--------|----------|`;
9839
+ for (const scan of state.scanHistory.slice(0, 10)) {
9840
+ const date = new Date(scan.timestamp).toLocaleDateString();
9841
+ const agents = scan.agents.slice(0, 3).join(", ") + (scan.agents.length > 3 ? "..." : "");
9842
+ const duration = `${(scan.duration / 1e3).toFixed(1)}s`;
9843
+ table += `
9844
+ | ${date} | ${agents} | ${scan.filesScanned} | ${scan.issues.total} | ${duration} |`;
9845
+ }
9846
+ return table;
9847
+ }
9848
+ function generateContextSignals(state) {
9849
+ const signals = [
9850
+ "touchesAuth",
9851
+ "touchesPayments",
9852
+ "touchesUserData",
9853
+ "touchesAPI",
9854
+ "touchesDatabase",
9855
+ "touchesCrypto"
9856
+ ];
9857
+ return signals.map((s) => {
9858
+ const value = state.contextSignals[s];
9859
+ const emoji = value === true ? "\u2705" : value === false ? "\u274C" : "\u2753";
9860
+ return `- \`${s}\`: ${emoji} ${value === void 0 ? "Unknown" : value ? "Yes" : "No"}`;
9861
+ }).join("\n");
9862
+ }
9863
+ function generateRiskAssessment(state) {
9864
+ const score = state.healthScore;
9865
+ let riskLevel;
9866
+ let confidence;
9867
+ if (state.lastScan === null) {
9868
+ return `- Overall Risk: Unknown
9869
+ - Confidence: 0%`;
9870
+ }
9871
+ if (score >= 90) {
9872
+ riskLevel = "\u{1F7E2} Low";
9873
+ confidence = 95;
9874
+ } else if (score >= 70) {
9875
+ riskLevel = "\u{1F7E1} Medium";
9876
+ confidence = 85;
9877
+ } else if (score >= 50) {
9878
+ riskLevel = "\u{1F7E0} High";
9879
+ confidence = 80;
9880
+ } else {
9881
+ riskLevel = "\u{1F534} Critical";
9882
+ confidence = 90;
9883
+ }
9884
+ return `- Overall Risk: ${riskLevel}
9885
+ - Health Score: ${score}%
9886
+ - Confidence: ${confidence}%`;
9887
+ }
9888
+ function generateHotFilesSection(state) {
9889
+ if (!state.lastScan || state.lastScan.hotFiles.length === 0) {
9890
+ return "_Run a scan to identify hot files._";
9891
+ }
9892
+ return state.lastScan.hotFiles.map((f) => `- \`${f.file}\` - ${f.issueCount} issue${f.issueCount > 1 ? "s" : ""}`).join("\n");
9893
+ }
9894
+ function getDefaultState() {
9895
+ return {
9896
+ lastScan: null,
9897
+ healthScore: 0,
9898
+ activePriorities: [
9899
+ "Initial setup required - run first scan with `trie scan`",
9900
+ "Configure agents in `.trie/config.json`",
9901
+ "Set up CI/CD integration"
9902
+ ],
9903
+ contextSignals: {},
9904
+ agentStatus: {},
9905
+ scanHistory: [],
9906
+ customAgents: [],
9907
+ skills: {},
9908
+ environment: detectEnvironment()
9909
+ };
9910
+ }
9911
+ function detectEnvironment() {
9912
+ if (process.env.GITHUB_ACTIONS) return "github-actions";
9913
+ if (process.env.GITLAB_CI) return "gitlab-ci";
9914
+ if (process.env.CI) return "ci";
9915
+ const parent = process.env._ || "";
9916
+ if (parent.includes("cursor")) return "cursor";
9917
+ if (parent.includes("claude")) return "claude-code";
9918
+ return "cli";
9919
+ }
9920
+ async function recordSkillInstalled(params) {
9921
+ const state = await loadContextState();
9922
+ state.skills[params.name] = {
9923
+ source: params.source,
9924
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
9925
+ timesApplied: 0,
9926
+ appliedBy: []
9927
+ };
9928
+ await saveContextState(state);
9929
+ }
9930
+ async function recordSkillUsage(params) {
9931
+ const state = await loadContextState();
9932
+ const now = (/* @__PURE__ */ new Date()).toISOString();
9933
+ for (const skillName of params.skillNames) {
9934
+ const skillRecord = state.skills[skillName];
9935
+ if (skillRecord) {
9936
+ skillRecord.timesApplied++;
9937
+ skillRecord.lastApplied = now;
9938
+ if (!skillRecord.appliedBy.includes(params.agentName)) {
9939
+ skillRecord.appliedBy.push(params.agentName);
9940
+ }
9941
+ }
9942
+ }
9943
+ const agentStatus = state.agentStatus[params.agentName];
9944
+ if (agentStatus) {
9945
+ agentStatus.skillsApplied = params.skillNames;
9946
+ }
9947
+ await saveContextState(state);
9948
+ }
9949
+ function getAgentsMdTemplate() {
9950
+ return `# Trie Agent Context
9951
+
9952
+ > **Auto-generated file** - Updated automatically when agents run.
9953
+ > Last updated: Never (initial state)
9954
+
9955
+ This file provides prioritized context for all AI coding assistants working with this codebase.
9956
+ Agents should read this file first and update it after completing scans.
9957
+
9958
+ ---
9959
+
9960
+ ## Quick Context (Read First)
9961
+
9962
+ ### Project State
9963
+ | Metric | Value | Updated |
9964
+ |--------|-------|---------|
9965
+ | Last Scan | Never | - |
9966
+ | Critical Issues | 0 | - |
9967
+ | Open Tasks | 0 | - |
9968
+ | Health Score | Unknown | - |
9969
+
9970
+ ### Active Priorities
9971
+ 1. Initial setup required - run first scan with \`trie scan\`
9972
+ 2. Configure agents in \`.trie/config.json\`
9973
+ 3. Set up CI/CD integration
9974
+
9975
+ ### Hot Files
9976
+ _Run a scan to identify hot files._
9977
+
9978
+ ---
9979
+
9980
+ ## Agent Status
9981
+
9982
+ ### Agent Status
9983
+ | Agent | Status | Last Run | Issues Found |
9984
+ |-------|--------|----------|--------------|
9985
+ | security | Ready | Never | - |
9986
+ | privacy | Ready | Never | - |
9987
+ | bugs | Ready | Never | - |
9988
+
9989
+ ### Recent Scan History
9990
+ | Date | Agents | Files | Issues | Duration |
9991
+ |------|--------|-------|--------|----------|
9992
+ | - | - | - | - | - |
9993
+
9994
+ ---
9995
+
9996
+ ## Context Analysis
9997
+
9998
+ ### Context Signals Detected
9999
+ - \`touchesAuth\`: Unknown
10000
+ - \`touchesPayments\`: Unknown
10001
+ - \`touchesUserData\`: Unknown
10002
+ - \`touchesAPI\`: Unknown
10003
+ - \`touchesDatabase\`: Unknown
10004
+ - \`touchesCrypto\`: Unknown
10005
+
10006
+ ### Risk Assessment
10007
+ - Overall Risk: Unknown
10008
+ - Confidence: 0%
10009
+
10010
+ ---
10011
+
10012
+ *This file is maintained by Trie agents. Manual edits will be preserved in non-auto sections.*
10013
+ `;
10014
+ }
10015
+ async function getContextForAI() {
10016
+ const state = await loadContextState();
10017
+ const workDir = getWorkingDirectory(void 0, true);
10018
+ const lines = [];
10019
+ if (projectInfoExists(workDir)) {
10020
+ const projectInfo = await loadProjectInfo(workDir);
10021
+ if (projectInfo) {
10022
+ lines.push(projectInfo);
10023
+ lines.push("");
10024
+ lines.push("---");
10025
+ lines.push("");
10026
+ }
10027
+ }
10028
+ lines.push(
10029
+ "## Trie Scan Context",
10030
+ "",
10031
+ `**Health Score:** ${state.healthScore}%`,
10032
+ `**Last Scan:** ${state.lastScan ? new Date(state.lastScan.timestamp).toLocaleString() : "Never"}`,
10033
+ "",
10034
+ "**Active Priorities:**",
10035
+ ...state.activePriorities.map((p) => `- ${p}`),
10036
+ ""
10037
+ );
10038
+ if (state.lastScan) {
10039
+ lines.push(
10040
+ "**Recent Issues:**",
10041
+ `- Critical: ${state.lastScan.issues.critical}`,
10042
+ `- Serious: ${state.lastScan.issues.serious}`,
10043
+ `- Moderate: ${state.lastScan.issues.moderate}`,
10044
+ `- Low: ${state.lastScan.issues.low}`,
10045
+ ""
10046
+ );
10047
+ if (state.lastScan.hotFiles.length > 0) {
10048
+ lines.push(
10049
+ "**Hot Files (most issues):**",
10050
+ ...state.lastScan.hotFiles.slice(0, 5).map((f) => `- ${f.file}: ${f.issueCount} issues`),
10051
+ ""
10052
+ );
10053
+ }
10054
+ }
10055
+ return lines.join("\n");
10056
+ }
10057
+
8469
10058
  // src/skills/gating.ts
8470
- import { existsSync as existsSync2 } from "fs";
8471
- import { readFile } from "fs/promises";
8472
- import { join } from "path";
10059
+ import { existsSync as existsSync7 } from "fs";
10060
+ import { readFile as readFile8 } from "fs/promises";
10061
+ import { join as join8 } from "path";
8473
10062
  import { execSync } from "child_process";
8474
10063
  async function checkSkillRequirements(frontmatter, projectDir) {
8475
10064
  const result = { allowed: true };
@@ -8526,7 +10115,7 @@ async function checkSkillRequirements(frontmatter, projectDir) {
8526
10115
  }
8527
10116
  }
8528
10117
  if (reqs.configFiles && reqs.configFiles.length > 0) {
8529
- const missing = reqs.configFiles.filter((file) => !existsSync2(join(projectDir, file)));
10118
+ const missing = reqs.configFiles.filter((file) => !existsSync7(join8(projectDir, file)));
8530
10119
  if (missing.length > 0) {
8531
10120
  result.allowed = false;
8532
10121
  result.missingConfigs = missing;
@@ -8538,11 +10127,11 @@ async function checkSkillRequirements(frontmatter, projectDir) {
8538
10127
  }
8539
10128
  async function getProjectDependencies(projectDir) {
8540
10129
  try {
8541
- const pkgPath = join(projectDir, "package.json");
8542
- if (!existsSync2(pkgPath)) {
10130
+ const pkgPath = join8(projectDir, "package.json");
10131
+ if (!existsSync7(pkgPath)) {
8543
10132
  return /* @__PURE__ */ new Set();
8544
10133
  }
8545
- const pkg = JSON.parse(await readFile(pkgPath, "utf-8"));
10134
+ const pkg = JSON.parse(await readFile8(pkgPath, "utf-8"));
8546
10135
  return /* @__PURE__ */ new Set([
8547
10136
  ...Object.keys(pkg.dependencies || {}),
8548
10137
  ...Object.keys(pkg.devDependencies || {})
@@ -8578,8 +10167,8 @@ function formatGatingReason(result) {
8578
10167
  return `Missing: ${parts.join("; ")}`;
8579
10168
  }
8580
10169
 
8581
- // src/agents/skill-review.ts
8582
- var SkillReviewAgent = class extends BaseAgent {
10170
+ // src/skills/built-in/skill-review.ts
10171
+ var SkillReviewSkill = class extends BaseSkill {
8583
10172
  name = "skill-review";
8584
10173
  description = "Applies installed skills from GitHub repositories to code review";
8585
10174
  version = "1.0.0";
@@ -8786,13 +10375,13 @@ ${parsed.rawContent}`);
8786
10375
  }
8787
10376
  };
8788
10377
 
8789
- // src/agents/custom-skill.ts
8790
- var CustomSkill = class extends BaseAgent {
10378
+ // src/skills/built-in/custom-skill.ts
10379
+ var CustomSkill = class extends BaseSkill {
8791
10380
  name;
8792
10381
  description;
8793
10382
  version;
8794
- author;
8795
- authorUrl;
10383
+ author = void 0;
10384
+ authorUrl = void 0;
8796
10385
  config;
8797
10386
  constructor(config) {
8798
10387
  super();
@@ -8800,8 +10389,14 @@ var CustomSkill = class extends BaseAgent {
8800
10389
  this.name = config.name;
8801
10390
  this.description = config.description;
8802
10391
  this.version = config.version;
8803
- this.author = config.author;
8804
- this.authorUrl = config.authorUrl;
10392
+ const authorAttr = config.author;
10393
+ if (authorAttr !== void 0) {
10394
+ this.author = authorAttr;
10395
+ }
10396
+ const authorUrlAttr = config.authorUrl;
10397
+ if (authorUrlAttr !== void 0) {
10398
+ this.authorUrl = authorUrlAttr;
10399
+ }
8805
10400
  }
8806
10401
  get priority() {
8807
10402
  return {
@@ -8997,75 +10592,75 @@ var CustomSkill = class extends BaseAgent {
8997
10592
  }
8998
10593
  };
8999
10594
 
9000
- // src/agents/registry.ts
9001
- import { readdir, readFile as readFile2 } from "fs/promises";
9002
- import { join as join2 } from "path";
9003
- var AgentRegistryImpl = class {
9004
- agents = /* @__PURE__ */ new Map();
9005
- customAgentsLoaded = false;
10595
+ // src/skills/built-in/registry.ts
10596
+ import { readdir as readdir4, readFile as readFile9 } from "fs/promises";
10597
+ import { join as join9 } from "path";
10598
+ var SkillRegistryImpl = class {
10599
+ skills = /* @__PURE__ */ new Map();
10600
+ customSkillsLoaded = false;
9006
10601
  initialized = false;
9007
10602
  constructor() {
9008
- this.registerBuiltinAgents();
10603
+ this.registerBuiltinSkills();
9009
10604
  }
9010
- registerBuiltinAgents() {
10605
+ registerBuiltinSkills() {
9011
10606
  if (this.initialized) return;
9012
10607
  this.initialized = true;
9013
- const builtinAgents = [
9014
- // Core agents (always available)
9015
- new SecurityAgent(),
9016
- new PrivacyAgent(),
9017
- new TypeCheckAgent(),
9018
- new ComprehensionAgent(),
9019
- // Specialized agents
9020
- new AccessibilityAgent(),
9021
- new DesignEngineerAgent(),
9022
- new LegalAgent(),
9023
- new TestAgent(),
9024
- new SoftwareArchitectAgent(),
9025
- new DevOpsAgent(),
9026
- new BugFindingAgent(),
9027
- new UserTestingAgent(),
9028
- new TrieCleanAgent(),
9029
- new SOC2Agent(),
9030
- new SuperReviewerAgent(),
9031
- new AgentSmithAgent(),
9032
- // New agents (inspired by Turkey Build)
9033
- new PerformanceAgent(),
9034
- new E2EAgent(),
9035
- new VisualQAAgent(),
9036
- new DataFlowAgent(),
9037
- // Cost analysis agent
9038
- new MoneybagAgent(),
10608
+ const builtinSkills = [
10609
+ // Core skills (always available)
10610
+ new SecuritySkill(),
10611
+ new PrivacySkill(),
10612
+ new TypeCheckSkill(),
10613
+ new ComprehensionSkill(),
10614
+ // Specialized skills
10615
+ new AccessibilitySkill(),
10616
+ new DesignEngineerSkill(),
10617
+ new LegalSkill(),
10618
+ new TestSkill(),
10619
+ new SoftwareArchitectSkill(),
10620
+ new DevOpsSkill(),
10621
+ new BugFindingSkill(),
10622
+ new UserTestingSkill(),
10623
+ new TrieCleanSkill(),
10624
+ new SOC2Skill(),
10625
+ new SuperReviewerSkill(),
10626
+ new AgentSmithSkill(),
10627
+ // New skills (inspired by Turkey Build)
10628
+ new PerformanceSkill(),
10629
+ new E2ESkill(),
10630
+ new VisualQASkill(),
10631
+ new DataFlowSkill(),
10632
+ // Cost analysis skill
10633
+ new MoneybagSkill(),
9039
10634
  // Production readiness gate
9040
- new ProductionReadyAgent(),
9041
- // Skill review agent (applies external skills)
9042
- new SkillReviewAgent()
10635
+ new ProductionReadySkill(),
10636
+ // Skill review skill (applies external skills)
10637
+ new SkillReviewSkill()
9043
10638
  ];
9044
10639
  const isWorker = typeof process !== "undefined" && (process.env.TRIE_WORKER === "true" || process.env.NODE_ENV === "test");
9045
10640
  if (!isWorker && !process.env.TRIE_QUIET) {
9046
- console.error(`Loaded config for ${builtinAgents.length} built-in agents`);
10641
+ console.error(`Loaded config for ${builtinSkills.length} built-in skills`);
9047
10642
  }
9048
- for (const agent of builtinAgents) {
9049
- this.agents.set(agent.name, agent);
10643
+ for (const skill of builtinSkills) {
10644
+ this.skills.set(skill.name, skill);
9050
10645
  }
9051
10646
  }
9052
10647
  /**
9053
10648
  * Load custom skills from .trie/agents/ directory
9054
10649
  */
9055
10650
  async loadCustomSkills() {
9056
- if (this.customAgentsLoaded) return;
10651
+ if (this.customSkillsLoaded) return;
9057
10652
  try {
9058
- const skillsDir = join2(getWorkingDirectory(void 0, true), ".trie", "agents");
9059
- const files = await readdir(skillsDir);
10653
+ const skillsDir = join9(getWorkingDirectory(void 0, true), ".trie", "agents");
10654
+ const files = await readdir4(skillsDir);
9060
10655
  const jsonFiles = files.filter((f) => f.endsWith(".json"));
9061
10656
  let loadedCount = 0;
9062
10657
  for (const file of jsonFiles) {
9063
10658
  try {
9064
- const configPath = join2(skillsDir, file);
9065
- const content = await readFile2(configPath, "utf-8");
10659
+ const configPath = join9(skillsDir, file);
10660
+ const content = await readFile9(configPath, "utf-8");
9066
10661
  const config = JSON.parse(content);
9067
10662
  const skill = new CustomSkill(config);
9068
- this.agents.set(skill.name, skill);
10663
+ this.skills.set(skill.name, skill);
9069
10664
  loadedCount++;
9070
10665
  } catch (error) {
9071
10666
  console.error(`Failed to load custom skill from ${file}:`, error);
@@ -9074,22 +10669,22 @@ var AgentRegistryImpl = class {
9074
10669
  if (loadedCount > 0) {
9075
10670
  console.error(`Loaded ${loadedCount} custom skill(s) from .trie/agents/`);
9076
10671
  }
9077
- this.customAgentsLoaded = true;
10672
+ this.customSkillsLoaded = true;
9078
10673
  } catch (error) {
9079
- this.customAgentsLoaded = true;
10674
+ this.customSkillsLoaded = true;
9080
10675
  }
9081
- await this.loadSkillsForAgent();
10676
+ await this.loadSkillsForSkill();
9082
10677
  }
9083
10678
  // Backward compatibility alias
9084
10679
  async loadCustomAgents() {
9085
10680
  return this.loadCustomSkills();
9086
10681
  }
9087
10682
  /**
9088
- * Load installed skills for the SkillReviewAgent
10683
+ * Load installed skills for the SkillReviewSkill
9089
10684
  */
9090
- async loadSkillsForAgent() {
9091
- const skillReviewAgent = this.agents.get("skill-review");
9092
- if (skillReviewAgent && skillReviewAgent instanceof SkillReviewAgent) {
10685
+ async loadSkillsForSkill() {
10686
+ const skillReviewAgent = this.skills.get("skill-review");
10687
+ if (skillReviewAgent && skillReviewAgent instanceof SkillReviewSkill) {
9093
10688
  await skillReviewAgent.loadSkills();
9094
10689
  if (skillReviewAgent.hasSkills()) {
9095
10690
  console.error(`Loaded ${skillReviewAgent.getAppliedSkillNames().length} skill(s) for skill-review agent`);
@@ -9100,40 +10695,56 @@ var AgentRegistryImpl = class {
9100
10695
  * Reload custom skills (useful after creating new ones)
9101
10696
  */
9102
10697
  async reloadCustomSkills() {
9103
- for (const [name, agent] of this.agents.entries()) {
10698
+ for (const [name, agent] of this.skills.entries()) {
9104
10699
  if (agent instanceof CustomSkill) {
9105
- this.agents.delete(name);
10700
+ this.skills.delete(name);
9106
10701
  }
9107
10702
  }
9108
- this.customAgentsLoaded = false;
10703
+ this.customSkillsLoaded = false;
9109
10704
  await this.loadCustomSkills();
9110
10705
  }
9111
10706
  // Backward compatibility alias
9112
10707
  async reloadCustomAgents() {
9113
10708
  return this.reloadCustomSkills();
9114
10709
  }
10710
+ getSkill(name) {
10711
+ return this.skills.get(name);
10712
+ }
10713
+ // Backward compatibility alias
9115
10714
  getAgent(name) {
9116
- return this.agents.get(name);
10715
+ return this.getSkill(name);
10716
+ }
10717
+ getSkillsByNames(names) {
10718
+ return names.map((name) => this.getSkill(name)).filter((skill) => skill !== void 0);
9117
10719
  }
10720
+ // Backward compatibility alias
9118
10721
  getAgentsByNames(names) {
9119
- return names.map((name) => this.getAgent(name)).filter((agent) => agent !== void 0);
10722
+ return this.getSkillsByNames(names);
9120
10723
  }
10724
+ getAllSkills() {
10725
+ return Array.from(this.skills.values());
10726
+ }
10727
+ // Backward compatibility alias
9121
10728
  getAllAgents() {
9122
- return Array.from(this.agents.values());
10729
+ return this.getAllSkills();
9123
10730
  }
9124
10731
  /**
9125
- * Get only built-in agents
10732
+ * Get only built-in skills
9126
10733
  */
9127
- getBuiltinAgents() {
9128
- return Array.from(this.agents.values()).filter(
9129
- (agent) => !(agent instanceof CustomSkill)
10734
+ getBuiltinSkills() {
10735
+ return Array.from(this.skills.values()).filter(
10736
+ (skill) => !(skill instanceof CustomSkill)
9130
10737
  );
9131
10738
  }
10739
+ // Backward compatibility alias
10740
+ getBuiltinAgents() {
10741
+ return this.getBuiltinSkills();
10742
+ }
9132
10743
  /**
9133
10744
  * Get only custom skills
9134
10745
  */
9135
10746
  getCustomSkills() {
9136
- return Array.from(this.agents.values()).filter(
10747
+ return Array.from(this.skills.values()).filter(
9137
10748
  (agent) => agent instanceof CustomSkill
9138
10749
  );
9139
10750
  }
@@ -9141,32 +10752,40 @@ var AgentRegistryImpl = class {
9141
10752
  getCustomAgents() {
9142
10753
  return this.getCustomSkills();
9143
10754
  }
9144
- registerAgent(agent) {
9145
- this.agents.set(agent.name, agent);
9146
- console.error(`Registered custom skill: ${agent.name}`);
10755
+ registerSkill(skill) {
10756
+ this.skills.set(skill.name, skill);
10757
+ console.error(`Registered custom skill: ${skill.name}`);
10758
+ }
10759
+ // Backward compatibility alias
10760
+ registerAgent(skill) {
10761
+ this.registerSkill(skill);
9147
10762
  }
9148
10763
  /**
9149
- * Unregister an agent by name
10764
+ * Unregister a skill by name
9150
10765
  */
10766
+ unregisterSkill(name) {
10767
+ return this.skills.delete(name);
10768
+ }
10769
+ // Backward compatibility alias
9151
10770
  unregisterAgent(name) {
9152
- return this.agents.delete(name);
10771
+ return this.unregisterSkill(name);
9153
10772
  }
9154
- getAgentNames() {
9155
- return Array.from(this.agents.keys());
10773
+ getSkillNames() {
10774
+ return Array.from(this.skills.keys());
9156
10775
  }
9157
- getAgentDescriptions() {
9158
- return Array.from(this.agents.values()).map((agent) => ({
9159
- name: agent.name,
9160
- description: agent.description,
9161
- isCustom: agent instanceof CustomSkill
10776
+ getSkillDescriptions() {
10777
+ return Array.from(this.skills.values()).map((skill) => ({
10778
+ name: skill.name,
10779
+ description: skill.description,
10780
+ isCustom: skill instanceof CustomSkill
9162
10781
  }));
9163
10782
  }
9164
10783
  /**
9165
- * Check if an agent is a custom skill
10784
+ * Check if a skill is custom
9166
10785
  */
9167
10786
  isCustomSkill(name) {
9168
- const agent = this.agents.get(name);
9169
- return agent instanceof CustomSkill;
10787
+ const skill = this.skills.get(name);
10788
+ return skill instanceof CustomSkill;
9170
10789
  }
9171
10790
  // Backward compatibility alias
9172
10791
  isCustomAgent(name) {
@@ -9176,9 +10795,9 @@ var AgentRegistryImpl = class {
9176
10795
  * Get custom skill metadata
9177
10796
  */
9178
10797
  getCustomSkillMetadata(name) {
9179
- const agent = this.agents.get(name);
9180
- if (agent instanceof CustomSkill) {
9181
- return agent.getMetadata();
10798
+ const skill = this.skills.get(name);
10799
+ if (skill instanceof CustomSkill) {
10800
+ return skill.getMetadata();
9182
10801
  }
9183
10802
  return null;
9184
10803
  }
@@ -9187,19 +10806,49 @@ var AgentRegistryImpl = class {
9187
10806
  return this.getCustomSkillMetadata(name);
9188
10807
  }
9189
10808
  };
9190
- var SINGLETON_KEY = "__TRIE_AGENT_REGISTRY__";
9191
- function getAgentRegistry() {
10809
+ var SINGLETON_KEY = "__TRIE_SKILL_REGISTRY__";
10810
+ var LEGACY_SINGLETON_KEY = "__TRIE_AGENT_REGISTRY__";
10811
+ function getSkillRegistry() {
9192
10812
  const global = globalThis;
9193
10813
  if (!global[SINGLETON_KEY]) {
9194
- global[SINGLETON_KEY] = new AgentRegistryImpl();
10814
+ const existing = global[LEGACY_SINGLETON_KEY];
10815
+ global[SINGLETON_KEY] = existing ?? new SkillRegistryImpl();
10816
+ global[LEGACY_SINGLETON_KEY] = global[SINGLETON_KEY];
9195
10817
  }
9196
10818
  return global[SINGLETON_KEY];
9197
10819
  }
9198
10820
 
9199
10821
  export {
9200
- SuperReviewerAgent,
10822
+ SuperReviewerSkill,
9201
10823
  CRITICAL_REVIEW_CHECKLIST,
10824
+ installSkill,
10825
+ listInstalledSkills,
10826
+ removeSkill,
10827
+ projectInfoExists,
10828
+ loadProjectInfo,
10829
+ initProjectInfo,
10830
+ getProjectSection,
10831
+ updateProjectSection,
10832
+ appendToSection,
10833
+ getProjectSections,
10834
+ getProjectInfoStructured,
10835
+ getHistoricalInsights,
10836
+ searchIssues,
10837
+ findSimilarIssues,
10838
+ markIssueResolved,
10839
+ getMemoryStats,
10840
+ getRecentIssues,
10841
+ getDailyLogs,
10842
+ findCrossProjectPatterns,
10843
+ listTrackedProjects,
10844
+ getGlobalMemoryStats,
10845
+ updateGlobalMemoryMd,
10846
+ searchGlobalPatterns,
10847
+ loadContextState,
10848
+ updateContextAfterScan,
10849
+ recordSkillInstalled,
10850
+ getContextForAI,
9202
10851
  CustomSkill,
9203
- getAgentRegistry
10852
+ getSkillRegistry
9204
10853
  };
9205
- //# sourceMappingURL=chunk-37U65YW7.js.map
10854
+ //# sourceMappingURL=chunk-TOE75CFZ.js.map