@triedotdev/mcp 1.0.37 → 1.0.39

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  CustomAgent,
3
3
  getAgentRegistry
4
- } from "./chunk-QFTSX2BX.js";
4
+ } from "./chunk-B3MBKB2U.js";
5
5
  import {
6
6
  ProgressReporter
7
7
  } from "./chunk-OB45V2QC.js";
@@ -21,9 +21,9 @@ import {
21
21
  } from "./chunk-DGUM43GV.js";
22
22
 
23
23
  // src/tools/scan.ts
24
- import { readFile as readFile8, readdir as readdir2, writeFile as writeFile3 } from "fs/promises";
25
- import { existsSync as existsSync5 } from "fs";
26
- import { basename as basename6, isAbsolute, resolve as resolve2, join as join6, extname as extname3 } from "path";
24
+ import { readFile as readFile9, readdir as readdir2, writeFile as writeFile4 } from "fs/promises";
25
+ import { existsSync as existsSync6 } from "fs";
26
+ import { basename as basename6, isAbsolute, resolve as resolve2, join as join7, extname as extname3 } from "path";
27
27
 
28
28
  // src/orchestrator/context-analyzer.ts
29
29
  import { readFile } from "fs/promises";
@@ -650,11 +650,366 @@ var RiskAssessor = class {
650
650
  }
651
651
  };
652
652
 
653
+ // src/utils/context-state.ts
654
+ import { readFile as readFile2, writeFile, mkdir } from "fs/promises";
655
+ import { existsSync as existsSync2 } from "fs";
656
+ import { join } from "path";
657
+ var AGENTS_MD_PATH = ".trie/AGENTS.md";
658
+ var STATE_JSON_PATH = ".trie/state.json";
659
+ async function loadContextState() {
660
+ const workDir = getWorkingDirectory(void 0, true);
661
+ const statePath = join(workDir, STATE_JSON_PATH);
662
+ try {
663
+ if (existsSync2(statePath)) {
664
+ const content = await readFile2(statePath, "utf-8");
665
+ return JSON.parse(content);
666
+ }
667
+ } catch {
668
+ }
669
+ return getDefaultState();
670
+ }
671
+ async function saveContextState(state) {
672
+ const workDir = getWorkingDirectory(void 0, true);
673
+ const trieDir = join(workDir, ".trie");
674
+ const statePath = join(workDir, STATE_JSON_PATH);
675
+ await mkdir(trieDir, { recursive: true });
676
+ await writeFile(statePath, JSON.stringify(state, null, 2));
677
+ }
678
+ async function updateContextAfterScan(results, filesScanned, contextSignals, duration) {
679
+ const state = await loadContextState();
680
+ const now = (/* @__PURE__ */ new Date()).toISOString();
681
+ const allIssues = results.flatMap((r) => r.issues);
682
+ const issueCounts = {
683
+ critical: allIssues.filter((i) => i.severity === "critical").length,
684
+ serious: allIssues.filter((i) => i.severity === "serious").length,
685
+ moderate: allIssues.filter((i) => i.severity === "moderate").length,
686
+ low: allIssues.filter((i) => i.severity === "low").length,
687
+ total: allIssues.length
688
+ };
689
+ const fileIssueMap = /* @__PURE__ */ new Map();
690
+ for (const issue of allIssues) {
691
+ const count = fileIssueMap.get(issue.file) || 0;
692
+ fileIssueMap.set(issue.file, count + 1);
693
+ }
694
+ const hotFiles = Array.from(fileIssueMap.entries()).sort((a, b) => b[1] - a[1]).slice(0, 10).map(([file, issueCount]) => ({ file, issueCount }));
695
+ const scanSummary = {
696
+ timestamp: now,
697
+ agents: results.map((r) => r.agent),
698
+ filesScanned,
699
+ issues: issueCounts,
700
+ duration,
701
+ hotFiles
702
+ };
703
+ for (const result of results) {
704
+ state.agentStatus[result.agent] = {
705
+ lastRun: now,
706
+ issuesFound: result.issues.length
707
+ };
708
+ }
709
+ const criticalPenalty = issueCounts.critical * 25;
710
+ const seriousPenalty = issueCounts.serious * 10;
711
+ const moderatePenalty = issueCounts.moderate * 3;
712
+ const lowPenalty = issueCounts.low * 1;
713
+ const totalPenalty = Math.min(100, criticalPenalty + seriousPenalty + moderatePenalty + lowPenalty);
714
+ state.healthScore = Math.max(0, 100 - totalPenalty);
715
+ state.activePriorities = generatePriorities(issueCounts, contextSignals);
716
+ state.contextSignals = { ...state.contextSignals, ...contextSignals };
717
+ state.scanHistory = [scanSummary, ...state.scanHistory.slice(0, 19)];
718
+ state.lastScan = scanSummary;
719
+ await saveContextState(state);
720
+ await updateAgentsMd(state);
721
+ }
722
+ async function updateAgentsMd(state) {
723
+ const workDir = getWorkingDirectory(void 0, true);
724
+ const mdPath = join(workDir, AGENTS_MD_PATH);
725
+ let content;
726
+ try {
727
+ content = await readFile2(mdPath, "utf-8");
728
+ } catch {
729
+ content = getAgentsMdTemplate();
730
+ }
731
+ content = updateSection(content, "Project State", generateProjectStateTable(state));
732
+ content = updateSection(content, "Active Priorities", generatePrioritiesList(state));
733
+ content = updateSection(content, "Agent Status", generateAgentStatusTable(state));
734
+ content = updateSection(content, "Recent Scan History", generateScanHistoryTable(state));
735
+ content = updateSection(content, "Context Signals Detected", generateContextSignals(state));
736
+ content = updateSection(content, "Risk Assessment", generateRiskAssessment(state));
737
+ content = updateSection(content, "Hot Files", generateHotFilesSection(state));
738
+ content = content.replace(
739
+ /Last updated:.*$/m,
740
+ `Last updated: ${(/* @__PURE__ */ new Date()).toISOString()}`
741
+ );
742
+ await writeFile(mdPath, content);
743
+ }
744
+ function updateSection(content, sectionName, newContent) {
745
+ const sectionRegex = new RegExp(
746
+ `(### ${sectionName}[\\s\\S]*?)(?=###|---|
747
+ ## |$)`,
748
+ "g"
749
+ );
750
+ const replacement = `### ${sectionName}
751
+ ${newContent}
752
+
753
+ `;
754
+ if (content.match(sectionRegex)) {
755
+ return content.replace(sectionRegex, replacement);
756
+ }
757
+ return content;
758
+ }
759
+ function generateProjectStateTable(state) {
760
+ const lastScan = state.lastScan;
761
+ const lastScanDate = lastScan ? new Date(lastScan.timestamp).toLocaleString() : "Never";
762
+ const criticalCount = lastScan?.issues.critical ?? 0;
763
+ const totalTasks = lastScan?.issues.total ?? 0;
764
+ return `| Metric | Value | Updated |
765
+ |--------|-------|---------|
766
+ | Last Scan | ${lastScanDate} | ${lastScan ? "Auto" : "-"} |
767
+ | Critical Issues | ${criticalCount} | ${lastScan ? "Auto" : "-"} |
768
+ | Open Tasks | ${totalTasks} | ${lastScan ? "Auto" : "-"} |
769
+ | Health Score | ${state.healthScore}% | ${lastScan ? "Auto" : "-"} |`;
770
+ }
771
+ function generatePrioritiesList(state) {
772
+ if (state.activePriorities.length === 0) {
773
+ return "_No active priorities. Run a scan to identify issues._";
774
+ }
775
+ return state.activePriorities.map((p, i) => `${i + 1}. ${p}`).join("\n");
776
+ }
777
+ function generatePriorities(issues, contextSignals) {
778
+ const priorities = [];
779
+ if (issues.critical > 0) {
780
+ priorities.push(`\u{1F6A8} Fix ${issues.critical} critical security issue${issues.critical > 1 ? "s" : ""} immediately`);
781
+ }
782
+ if (issues.serious > 0) {
783
+ priorities.push(`\u26A0\uFE0F Address ${issues.serious} serious issue${issues.serious > 1 ? "s" : ""} before deployment`);
784
+ }
785
+ if (contextSignals.touchesAuth && issues.critical === 0) {
786
+ priorities.push("\u2705 Auth code reviewed - continue monitoring");
787
+ }
788
+ if (contextSignals.touchesPayments) {
789
+ priorities.push("\u{1F4B3} Payment code detected - ensure PCI compliance");
790
+ }
791
+ if (contextSignals.touchesUserData) {
792
+ priorities.push("\u{1F510} User data handling detected - verify privacy compliance");
793
+ }
794
+ if (issues.moderate > 5) {
795
+ priorities.push(`\u{1F4CB} Schedule time to address ${issues.moderate} moderate issues`);
796
+ }
797
+ if (priorities.length === 0) {
798
+ priorities.push("\u2728 No critical issues - focus on feature development");
799
+ }
800
+ return priorities.slice(0, 5);
801
+ }
802
+ function generateAgentStatusTable(state) {
803
+ const builtInAgents = [
804
+ "security",
805
+ "privacy",
806
+ "legal",
807
+ "accessibility",
808
+ "bugs",
809
+ "design",
810
+ "architecture",
811
+ "performance",
812
+ "devops",
813
+ "soc2",
814
+ "e2e",
815
+ "typecheck",
816
+ "visual-qa",
817
+ "data-flow"
818
+ ];
819
+ let table = `| Agent | Status | Last Run | Issues Found |
820
+ |-------|--------|----------|--------------|`;
821
+ for (const agent of builtInAgents) {
822
+ const status = state.agentStatus[agent];
823
+ const lastRun = status?.lastRun ? new Date(status.lastRun).toLocaleDateString() : "Never";
824
+ const issues = status?.issuesFound ?? "-";
825
+ const statusEmoji = status ? "\u2705" : "\u23F8\uFE0F";
826
+ table += `
827
+ | ${agent} | ${statusEmoji} Ready | ${lastRun} | ${issues} |`;
828
+ }
829
+ return table;
830
+ }
831
+ function generateScanHistoryTable(state) {
832
+ if (state.scanHistory.length === 0) {
833
+ return `| Date | Agents | Files | Issues | Duration |
834
+ |------|--------|-------|--------|----------|
835
+ | - | - | - | - | - |`;
836
+ }
837
+ let table = `| Date | Agents | Files | Issues | Duration |
838
+ |------|--------|-------|--------|----------|`;
839
+ for (const scan of state.scanHistory.slice(0, 10)) {
840
+ const date = new Date(scan.timestamp).toLocaleDateString();
841
+ const agents = scan.agents.slice(0, 3).join(", ") + (scan.agents.length > 3 ? "..." : "");
842
+ const duration = `${(scan.duration / 1e3).toFixed(1)}s`;
843
+ table += `
844
+ | ${date} | ${agents} | ${scan.filesScanned} | ${scan.issues.total} | ${duration} |`;
845
+ }
846
+ return table;
847
+ }
848
+ function generateContextSignals(state) {
849
+ const signals = [
850
+ "touchesAuth",
851
+ "touchesPayments",
852
+ "touchesUserData",
853
+ "touchesAPI",
854
+ "touchesDatabase",
855
+ "touchesCrypto"
856
+ ];
857
+ return signals.map((s) => {
858
+ const value = state.contextSignals[s];
859
+ const emoji = value === true ? "\u2705" : value === false ? "\u274C" : "\u2753";
860
+ return `- \`${s}\`: ${emoji} ${value === void 0 ? "Unknown" : value ? "Yes" : "No"}`;
861
+ }).join("\n");
862
+ }
863
+ function generateRiskAssessment(state) {
864
+ const score = state.healthScore;
865
+ let riskLevel;
866
+ let confidence;
867
+ if (state.lastScan === null) {
868
+ return `- Overall Risk: Unknown
869
+ - Confidence: 0%`;
870
+ }
871
+ if (score >= 90) {
872
+ riskLevel = "\u{1F7E2} Low";
873
+ confidence = 95;
874
+ } else if (score >= 70) {
875
+ riskLevel = "\u{1F7E1} Medium";
876
+ confidence = 85;
877
+ } else if (score >= 50) {
878
+ riskLevel = "\u{1F7E0} High";
879
+ confidence = 80;
880
+ } else {
881
+ riskLevel = "\u{1F534} Critical";
882
+ confidence = 90;
883
+ }
884
+ return `- Overall Risk: ${riskLevel}
885
+ - Health Score: ${score}%
886
+ - Confidence: ${confidence}%`;
887
+ }
888
+ function generateHotFilesSection(state) {
889
+ if (!state.lastScan || state.lastScan.hotFiles.length === 0) {
890
+ return "_Run a scan to identify hot files._";
891
+ }
892
+ return state.lastScan.hotFiles.map((f) => `- \`${f.file}\` - ${f.issueCount} issue${f.issueCount > 1 ? "s" : ""}`).join("\n");
893
+ }
894
+ function getDefaultState() {
895
+ return {
896
+ lastScan: null,
897
+ healthScore: 0,
898
+ activePriorities: [
899
+ "Initial setup required - run first scan with `trie scan`",
900
+ "Configure agents in `.trie/config.json`",
901
+ "Set up CI/CD integration"
902
+ ],
903
+ contextSignals: {},
904
+ agentStatus: {},
905
+ scanHistory: [],
906
+ customAgents: []
907
+ };
908
+ }
909
+ function getAgentsMdTemplate() {
910
+ return `# Trie Agent Context
911
+
912
+ > **Auto-generated file** - Updated automatically when agents run.
913
+ > Last updated: Never (initial state)
914
+
915
+ This file provides prioritized context for all AI coding assistants working with this codebase.
916
+ Agents should read this file first and update it after completing scans.
917
+
918
+ ---
919
+
920
+ ## Quick Context (Read First)
921
+
922
+ ### Project State
923
+ | Metric | Value | Updated |
924
+ |--------|-------|---------|
925
+ | Last Scan | Never | - |
926
+ | Critical Issues | 0 | - |
927
+ | Open Tasks | 0 | - |
928
+ | Health Score | Unknown | - |
929
+
930
+ ### Active Priorities
931
+ 1. Initial setup required - run first scan with \`trie scan\`
932
+ 2. Configure agents in \`.trie/config.json\`
933
+ 3. Set up CI/CD integration
934
+
935
+ ### Hot Files
936
+ _Run a scan to identify hot files._
937
+
938
+ ---
939
+
940
+ ## Agent Status
941
+
942
+ ### Agent Status
943
+ | Agent | Status | Last Run | Issues Found |
944
+ |-------|--------|----------|--------------|
945
+ | security | Ready | Never | - |
946
+ | privacy | Ready | Never | - |
947
+ | bugs | Ready | Never | - |
948
+
949
+ ### Recent Scan History
950
+ | Date | Agents | Files | Issues | Duration |
951
+ |------|--------|-------|--------|----------|
952
+ | - | - | - | - | - |
953
+
954
+ ---
955
+
956
+ ## Context Analysis
957
+
958
+ ### Context Signals Detected
959
+ - \`touchesAuth\`: Unknown
960
+ - \`touchesPayments\`: Unknown
961
+ - \`touchesUserData\`: Unknown
962
+ - \`touchesAPI\`: Unknown
963
+ - \`touchesDatabase\`: Unknown
964
+ - \`touchesCrypto\`: Unknown
965
+
966
+ ### Risk Assessment
967
+ - Overall Risk: Unknown
968
+ - Confidence: 0%
969
+
970
+ ---
971
+
972
+ *This file is maintained by Trie agents. Manual edits will be preserved in non-auto sections.*
973
+ `;
974
+ }
975
+ async function getContextForAI() {
976
+ const state = await loadContextState();
977
+ const lines = [
978
+ "## Trie Context Summary",
979
+ "",
980
+ `**Health Score:** ${state.healthScore}%`,
981
+ `**Last Scan:** ${state.lastScan ? new Date(state.lastScan.timestamp).toLocaleString() : "Never"}`,
982
+ "",
983
+ "**Active Priorities:**",
984
+ ...state.activePriorities.map((p) => `- ${p}`),
985
+ ""
986
+ ];
987
+ if (state.lastScan) {
988
+ lines.push(
989
+ "**Recent Issues:**",
990
+ `- Critical: ${state.lastScan.issues.critical}`,
991
+ `- Serious: ${state.lastScan.issues.serious}`,
992
+ `- Moderate: ${state.lastScan.issues.moderate}`,
993
+ `- Low: ${state.lastScan.issues.low}`,
994
+ ""
995
+ );
996
+ if (state.lastScan.hotFiles.length > 0) {
997
+ lines.push(
998
+ "**Hot Files (most issues):**",
999
+ ...state.lastScan.hotFiles.slice(0, 5).map((f) => `- ${f.file}: ${f.issueCount} issues`),
1000
+ ""
1001
+ );
1002
+ }
1003
+ }
1004
+ return lines.join("\n");
1005
+ }
1006
+
653
1007
  // src/orchestrator/triager.ts
654
1008
  var Triager = class {
655
1009
  agentRegistry = getAgentRegistry();
656
1010
  config;
657
1011
  customAgentsLoaded = false;
1012
+ contextState = null;
658
1013
  constructor(config) {
659
1014
  this.config = {
660
1015
  minConfidence: 0.15,
@@ -665,6 +1020,18 @@ var Triager = class {
665
1020
  ...config
666
1021
  };
667
1022
  }
1023
+ /**
1024
+ * Load previous context state for smart triaging
1025
+ */
1026
+ async loadPreviousContext() {
1027
+ if (this.contextState === null) {
1028
+ try {
1029
+ this.contextState = await loadContextState();
1030
+ } catch {
1031
+ this.contextState = null;
1032
+ }
1033
+ }
1034
+ }
668
1035
  /**
669
1036
  * Ensure custom agents are loaded before triaging
670
1037
  */
@@ -676,11 +1043,20 @@ var Triager = class {
676
1043
  }
677
1044
  async selectAgents(context, riskLevel) {
678
1045
  await this.ensureCustomAgentsLoaded();
679
- if (riskLevel === "critical" || riskLevel === "high") {
680
- console.error(` \u26A0\uFE0F ${riskLevel.toUpperCase()} risk - activating all agents for comprehensive review`);
1046
+ await this.loadPreviousContext();
1047
+ let effectiveRiskLevel = riskLevel;
1048
+ if (this.contextState?.healthScore !== void 0 && this.contextState.healthScore < 50) {
1049
+ if (riskLevel === "low" || riskLevel === "medium") {
1050
+ effectiveRiskLevel = "high";
1051
+ console.error(` \u{1F4CA} Health score ${this.contextState.healthScore}% - escalating to ${effectiveRiskLevel.toUpperCase()} risk`);
1052
+ }
1053
+ }
1054
+ if (effectiveRiskLevel === "critical" || effectiveRiskLevel === "high") {
1055
+ console.error(` \u26A0\uFE0F ${effectiveRiskLevel.toUpperCase()} risk - activating all agents for comprehensive review`);
681
1056
  return this.getAllAgents();
682
1057
  }
683
- const scores = this.scoreAgents(context, riskLevel);
1058
+ const scores = this.scoreAgents(context, effectiveRiskLevel);
1059
+ this.boostAgentsWithHistory(scores);
684
1060
  this.logAgentScoring(scores);
685
1061
  const qualified = scores.filter((s) => s.confidence >= this.config.minConfidence);
686
1062
  qualified.sort((a, b) => {
@@ -692,6 +1068,20 @@ var Triager = class {
692
1068
  }
693
1069
  return qualified.map((s) => s.agent);
694
1070
  }
1071
+ /**
1072
+ * Boost confidence for agents that found issues in previous scans
1073
+ */
1074
+ boostAgentsWithHistory(scores) {
1075
+ if (!this.contextState?.agentStatus) return;
1076
+ for (const score of scores) {
1077
+ const previousRun = this.contextState.agentStatus[score.agent.name];
1078
+ if (previousRun?.issuesFound && previousRun.issuesFound > 0) {
1079
+ const boost = Math.min(0.3, previousRun.issuesFound * 0.05);
1080
+ score.confidence = Math.min(1, score.confidence + boost);
1081
+ score.reasons.push(`found ${previousRun.issuesFound} issues in last scan`);
1082
+ }
1083
+ }
1084
+ }
695
1085
  scoreAgents(context, riskLevel) {
696
1086
  const allAgents = this.getAllAgents();
697
1087
  const scores = [];
@@ -998,6 +1388,64 @@ var Triager = class {
998
1388
  reasons.push("data access");
999
1389
  }
1000
1390
  }
1391
+ if (agent.name === "moneybags") {
1392
+ tier = 3;
1393
+ if (context.touchesPayments) {
1394
+ confidence += 0.6;
1395
+ reasons.push("payment code = high cost risk");
1396
+ }
1397
+ if (context.touchesAuth) {
1398
+ confidence += 0.4;
1399
+ reasons.push("auth bugs are expensive");
1400
+ }
1401
+ if (context.touchesHealthData) {
1402
+ confidence += 0.5;
1403
+ reasons.push("HIPAA violations");
1404
+ }
1405
+ if (context.touchesUserData) {
1406
+ confidence += 0.3;
1407
+ reasons.push("PII exposure costs");
1408
+ }
1409
+ if (context.touchesDatabase) {
1410
+ confidence += 0.25;
1411
+ reasons.push("data loss risk");
1412
+ }
1413
+ if (context.isNewFeature) {
1414
+ confidence += 0.2;
1415
+ reasons.push("new code risk");
1416
+ }
1417
+ if (riskLevel === "high" || riskLevel === "critical") {
1418
+ confidence *= 1.3;
1419
+ reasons.push("high-stakes context");
1420
+ }
1421
+ }
1422
+ if (agent.name === "production-ready") {
1423
+ tier = 3;
1424
+ if (context.touchesAPI) {
1425
+ confidence += 0.4;
1426
+ reasons.push("API deployment");
1427
+ }
1428
+ if (context.touchesDatabase) {
1429
+ confidence += 0.35;
1430
+ reasons.push("database operations");
1431
+ }
1432
+ if (context.touchesAuth) {
1433
+ confidence += 0.35;
1434
+ reasons.push("auth system");
1435
+ }
1436
+ if (context.touchesPayments) {
1437
+ confidence += 0.5;
1438
+ reasons.push("payment processing");
1439
+ }
1440
+ if (context.linesChanged > 200) {
1441
+ confidence += 0.3;
1442
+ reasons.push("significant changes");
1443
+ }
1444
+ if (riskLevel === "high" || riskLevel === "critical") {
1445
+ confidence += 0.4;
1446
+ reasons.push("production gate check");
1447
+ }
1448
+ }
1001
1449
  confidence = Math.min(1, confidence);
1002
1450
  return { agent, confidence, reasons, tier, isCustom: false };
1003
1451
  }
@@ -1373,8 +1821,8 @@ function calculateOptimalConcurrency() {
1373
1821
  }
1374
1822
 
1375
1823
  // src/utils/cache-manager.ts
1376
- import { readFile as readFile2, writeFile, mkdir, stat } from "fs/promises";
1377
- import { join } from "path";
1824
+ import { readFile as readFile3, writeFile as writeFile2, mkdir as mkdir2, stat } from "fs/promises";
1825
+ import { join as join2 } from "path";
1378
1826
  import { createHash } from "crypto";
1379
1827
  var CacheManager = class {
1380
1828
  cacheDir;
@@ -1384,8 +1832,8 @@ var CacheManager = class {
1384
1832
  // 24 hours
1385
1833
  MAX_ENTRIES = 1e3;
1386
1834
  constructor(baseDir) {
1387
- this.cacheDir = join(baseDir, ".trie", "cache");
1388
- this.indexPath = join(this.cacheDir, "index.json");
1835
+ this.cacheDir = join2(baseDir, ".trie", "cache");
1836
+ this.indexPath = join2(this.cacheDir, "index.json");
1389
1837
  }
1390
1838
  /**
1391
1839
  * Generate cache key for a file and agent combination
@@ -1399,7 +1847,7 @@ var CacheManager = class {
1399
1847
  */
1400
1848
  async getFileHash(filePath) {
1401
1849
  try {
1402
- const content = await readFile2(filePath, "utf-8");
1850
+ const content = await readFile3(filePath, "utf-8");
1403
1851
  const stats = await stat(filePath);
1404
1852
  const hash = createHash("sha256").update(content).digest("hex").slice(0, 16);
1405
1853
  return {
@@ -1416,7 +1864,7 @@ var CacheManager = class {
1416
1864
  */
1417
1865
  async loadIndex() {
1418
1866
  try {
1419
- const content = await readFile2(this.indexPath, "utf-8");
1867
+ const content = await readFile3(this.indexPath, "utf-8");
1420
1868
  return JSON.parse(content);
1421
1869
  } catch {
1422
1870
  return {
@@ -1431,8 +1879,8 @@ var CacheManager = class {
1431
1879
  */
1432
1880
  async saveIndex(index) {
1433
1881
  try {
1434
- await mkdir(this.cacheDir, { recursive: true });
1435
- await writeFile(this.indexPath, JSON.stringify(index, null, 2));
1882
+ await mkdir2(this.cacheDir, { recursive: true });
1883
+ await writeFile2(this.indexPath, JSON.stringify(index, null, 2));
1436
1884
  } catch (error) {
1437
1885
  console.warn("Failed to save cache index:", error);
1438
1886
  }
@@ -1639,8 +2087,8 @@ var Executor = class {
1639
2087
  };
1640
2088
 
1641
2089
  // src/analysis/cross-file.ts
1642
- import { readFile as readFile3, readdir } from "fs/promises";
1643
- import { join as join2, extname as extname2, relative, dirname, basename as basename2 } from "path";
2090
+ import { readFile as readFile4, readdir } from "fs/promises";
2091
+ import { join as join3, extname as extname2, relative, dirname, basename as basename2 } from "path";
1644
2092
  async function buildDependencyGraph(rootDir, maxFiles = 200) {
1645
2093
  const files = /* @__PURE__ */ new Map();
1646
2094
  const issues = [];
@@ -1670,7 +2118,7 @@ async function buildDependencyGraph(rootDir, maxFiles = 200) {
1670
2118
  }
1671
2119
  async function parseFile(filePath, rootDir) {
1672
2120
  try {
1673
- const content = await readFile3(filePath, "utf-8");
2121
+ const content = await readFile4(filePath, "utf-8");
1674
2122
  const relativePath = relative(rootDir, filePath);
1675
2123
  const lines = content.split("\n");
1676
2124
  const imports = [];
@@ -1759,7 +2207,7 @@ function resolveImport(source, fromPath, files) {
1759
2207
  return null;
1760
2208
  }
1761
2209
  const fromDir = dirname(fromPath);
1762
- let resolvedPath = join2(fromDir, source);
2210
+ let resolvedPath = join3(fromDir, source);
1763
2211
  const extensions = ["", ".ts", ".tsx", ".js", ".jsx", "/index.ts", "/index.tsx", "/index.js"];
1764
2212
  for (const ext of extensions) {
1765
2213
  const tryPath = resolvedPath + ext;
@@ -1873,7 +2321,7 @@ async function discoverFiles(dir, maxFiles) {
1873
2321
  const entries = await readdir(currentDir, { withFileTypes: true });
1874
2322
  for (const entry of entries) {
1875
2323
  if (files.length >= maxFiles) break;
1876
- const fullPath = join2(currentDir, entry.name);
2324
+ const fullPath = join3(currentDir, entry.name);
1877
2325
  if (entry.isDirectory()) {
1878
2326
  if (!skipDirs.has(entry.name) && !entry.name.startsWith(".")) {
1879
2327
  await walk(fullPath);
@@ -1980,7 +2428,7 @@ ${"\u2501".repeat(60)}
1980
2428
  }
1981
2429
 
1982
2430
  // src/analysis/semantic-analyzer.ts
1983
- import { readFile as readFile4 } from "fs/promises";
2431
+ import { readFile as readFile5 } from "fs/promises";
1984
2432
  import { basename as basename3, relative as relative2 } from "path";
1985
2433
  var SemanticAnalyzer = class {
1986
2434
  functions = [];
@@ -1993,7 +2441,7 @@ var SemanticAnalyzer = class {
1993
2441
  async analyze(files, rootDir) {
1994
2442
  for (const file of files) {
1995
2443
  try {
1996
- const content = await readFile4(file, "utf-8");
2444
+ const content = await readFile5(file, "utf-8");
1997
2445
  const relPath = relative2(rootDir, file);
1998
2446
  this.detectFramework(content);
1999
2447
  this.parseFunctions(content, relPath);
@@ -2554,7 +3002,7 @@ function formatPrioritizedResults(result) {
2554
3002
  }
2555
3003
 
2556
3004
  // src/analysis/attack-surface.ts
2557
- import { readFile as readFile5 } from "fs/promises";
3005
+ import { readFile as readFile6 } from "fs/promises";
2558
3006
  import { basename as basename5, relative as relative3 } from "path";
2559
3007
  var AttackSurfaceAnalyzer = class {
2560
3008
  endpoints = [];
@@ -2564,7 +3012,7 @@ var AttackSurfaceAnalyzer = class {
2564
3012
  async analyze(files, rootDir) {
2565
3013
  for (const file of files) {
2566
3014
  try {
2567
- const content = await readFile5(file, "utf-8");
3015
+ const content = await readFile6(file, "utf-8");
2568
3016
  const relPath = relative3(rootDir, file);
2569
3017
  this.findEndpoints(content, relPath);
2570
3018
  this.findDataFlows(content, relPath);
@@ -3309,9 +3757,9 @@ function getSymbolIndex() {
3309
3757
 
3310
3758
  // src/trie/incremental-scanner.ts
3311
3759
  import { createHash as createHash2 } from "crypto";
3312
- import { readFile as readFile6, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
3313
- import { existsSync as existsSync2 } from "fs";
3314
- import { join as join3 } from "path";
3760
+ import { readFile as readFile7, writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
3761
+ import { existsSync as existsSync3 } from "fs";
3762
+ import { join as join4 } from "path";
3315
3763
  var CACHE_VERSION = "1.0.0";
3316
3764
  var CACHE_FILE = ".trie-cache.json";
3317
3765
  var IncrementalScanner = class {
@@ -3320,7 +3768,7 @@ var IncrementalScanner = class {
3320
3768
  cacheDir;
3321
3769
  dirty = false;
3322
3770
  constructor(projectRoot) {
3323
- this.cacheDir = join3(projectRoot, ".trie");
3771
+ this.cacheDir = join4(projectRoot, ".trie");
3324
3772
  this.symbolIndex = getSymbolIndex();
3325
3773
  this.cache = {
3326
3774
  version: CACHE_VERSION,
@@ -3333,12 +3781,12 @@ var IncrementalScanner = class {
3333
3781
  * Load cache from disk
3334
3782
  */
3335
3783
  async loadCache() {
3336
- const cachePath = join3(this.cacheDir, CACHE_FILE);
3337
- if (!existsSync2(cachePath)) {
3784
+ const cachePath = join4(this.cacheDir, CACHE_FILE);
3785
+ if (!existsSync3(cachePath)) {
3338
3786
  return false;
3339
3787
  }
3340
3788
  try {
3341
- const data = await readFile6(cachePath, "utf-8");
3789
+ const data = await readFile7(cachePath, "utf-8");
3342
3790
  const parsed = JSON.parse(data);
3343
3791
  if (parsed.version !== CACHE_VERSION) {
3344
3792
  console.error(" \u26A0\uFE0F Cache version mismatch, rebuilding...");
@@ -3358,10 +3806,10 @@ var IncrementalScanner = class {
3358
3806
  async saveCache() {
3359
3807
  if (!this.dirty) return;
3360
3808
  try {
3361
- await mkdir2(this.cacheDir, { recursive: true });
3362
- const cachePath = join3(this.cacheDir, CACHE_FILE);
3809
+ await mkdir3(this.cacheDir, { recursive: true });
3810
+ const cachePath = join4(this.cacheDir, CACHE_FILE);
3363
3811
  this.cache.lastUpdated = Date.now();
3364
- await writeFile2(cachePath, JSON.stringify(this.cache, null, 2));
3812
+ await writeFile3(cachePath, JSON.stringify(this.cache, null, 2));
3365
3813
  this.dirty = false;
3366
3814
  } catch (error) {
3367
3815
  console.error(" \u26A0\uFE0F Failed to save cache");
@@ -3383,7 +3831,7 @@ var IncrementalScanner = class {
3383
3831
  if (!cached) return true;
3384
3832
  if (!content) {
3385
3833
  try {
3386
- content = await readFile6(filePath, "utf-8");
3834
+ content = await readFile7(filePath, "utf-8");
3387
3835
  } catch {
3388
3836
  return true;
3389
3837
  }
@@ -3398,7 +3846,7 @@ var IncrementalScanner = class {
3398
3846
  async scanFile(filePath, forceRescan = false) {
3399
3847
  let content;
3400
3848
  try {
3401
- content = await readFile6(filePath, "utf-8");
3849
+ content = await readFile7(filePath, "utf-8");
3402
3850
  } catch {
3403
3851
  return { vulnerabilities: [], fromCache: false, symbolCount: 0 };
3404
3852
  }
@@ -4581,14 +5029,14 @@ var InteractiveDashboard = class {
4581
5029
  };
4582
5030
 
4583
5031
  // src/config/loader.ts
4584
- import { readFile as readFile7 } from "fs/promises";
4585
- import { existsSync as existsSync4 } from "fs";
4586
- import { join as join5 } from "path";
5032
+ import { readFile as readFile8 } from "fs/promises";
5033
+ import { existsSync as existsSync5 } from "fs";
5034
+ import { join as join6 } from "path";
4587
5035
 
4588
5036
  // src/config/validation.ts
4589
5037
  import { z } from "zod";
4590
- import { existsSync as existsSync3, readFileSync } from "fs";
4591
- import { resolve, join as join4 } from "path";
5038
+ import { existsSync as existsSync4, readFileSync } from "fs";
5039
+ import { resolve, join as join5 } from "path";
4592
5040
  var API_KEY_PATTERNS = {
4593
5041
  anthropic: /^sk-ant-api\d{2}-[\w-]{95}$/,
4594
5042
  openai: /^sk-[\w]{48}$/,
@@ -4701,8 +5149,8 @@ var ConfigValidator = class {
4701
5149
  let anthropicKey = process.env.ANTHROPIC_API_KEY;
4702
5150
  if (!anthropicKey) {
4703
5151
  try {
4704
- const configPath = join4(getWorkingDirectory(void 0, true), ".trie", "config.json");
4705
- if (existsSync3(configPath)) {
5152
+ const configPath = join5(getWorkingDirectory(void 0, true), ".trie", "config.json");
5153
+ if (existsSync4(configPath)) {
4706
5154
  const config = JSON.parse(readFileSync(configPath, "utf-8"));
4707
5155
  anthropicKey = config.apiKeys?.anthropic;
4708
5156
  }
@@ -4732,14 +5180,14 @@ var ConfigValidator = class {
4732
5180
  if (paths?.include) {
4733
5181
  for (const path of paths.include) {
4734
5182
  const resolvedPath = resolve(path);
4735
- if (!existsSync3(resolvedPath)) {
5183
+ if (!existsSync4(resolvedPath)) {
4736
5184
  errors.push(`Include path does not exist: ${path}`);
4737
5185
  }
4738
5186
  }
4739
5187
  }
4740
5188
  if (paths?.configDir) {
4741
5189
  const configPath = resolve(paths.configDir);
4742
- if (!existsSync3(configPath)) {
5190
+ if (!existsSync4(configPath)) {
4743
5191
  try {
4744
5192
  __require("fs").mkdirSync(configPath, { recursive: true });
4745
5193
  } catch {
@@ -4859,8 +5307,8 @@ var ConfigValidator = class {
4859
5307
  const workDir = getWorkingDirectory(void 0, true);
4860
5308
  const envFiles = [".env", ".env.local", ".env.production"];
4861
5309
  for (const envFile of envFiles) {
4862
- const envPath = join4(workDir, envFile);
4863
- if (existsSync3(envPath)) {
5310
+ const envPath = join5(workDir, envFile);
5311
+ if (existsSync4(envPath)) {
4864
5312
  const envContent = readFileSync(envPath, "utf-8");
4865
5313
  if (envContent.includes("ANTHROPIC_API_KEY=")) {
4866
5314
  hasApiKey = true;
@@ -4937,12 +5385,12 @@ var DEFAULT_CONFIG = {
4937
5385
  // src/config/loader.ts
4938
5386
  async function loadConfig() {
4939
5387
  const validator = new ConfigValidator();
4940
- const configPath = join5(getWorkingDirectory(void 0, true), ".trie", "config.json");
5388
+ const configPath = join6(getWorkingDirectory(void 0, true), ".trie", "config.json");
4941
5389
  try {
4942
- if (!existsSync4(configPath)) {
5390
+ if (!existsSync5(configPath)) {
4943
5391
  return DEFAULT_CONFIG;
4944
5392
  }
4945
- const configFile = await readFile7(configPath, "utf-8");
5393
+ const configFile = await readFile8(configPath, "utf-8");
4946
5394
  const userConfig = JSON.parse(configFile);
4947
5395
  const merged = mergeConfig(DEFAULT_CONFIG, userConfig);
4948
5396
  const result = validator.validateConfig(merged);
@@ -5801,7 +6249,7 @@ var TrieScanTool = class {
5801
6249
  return resolve2(workDir, f);
5802
6250
  });
5803
6251
  const validFiles = resolvedFiles.filter((f) => {
5804
- if (!existsSync5(f)) {
6252
+ if (!existsSync6(f)) {
5805
6253
  this.progress.warn("File not found", f);
5806
6254
  return false;
5807
6255
  }
@@ -5863,6 +6311,14 @@ var TrieScanTool = class {
5863
6311
  const allAgentNames = this.agentRegistry.getAgentNames();
5864
6312
  this.logTriaging(selectedAgents.map((a) => a.name), allAgentNames, context, riskLevel);
5865
6313
  this.progress.update(`${selectedAgents.length} agents selected for ${riskLevel} risk code`);
6314
+ const userCount = args?.userCount;
6315
+ if (userCount) {
6316
+ const moneybags = selectedAgents.find((a) => a.name === "moneybags");
6317
+ if (moneybags && "configure" in moneybags && typeof moneybags.configure === "function") {
6318
+ moneybags.configure({ userCount });
6319
+ console.error(` \u{1F4B0} Cost estimates scaled for ${userCount.toLocaleString()} users`);
6320
+ }
6321
+ }
5866
6322
  this.progress.startPhase("ai-review", "Running AI analysis...");
5867
6323
  this.progress.ai("Starting agent analysis", `${selectedAgents.length} agents`);
5868
6324
  const agentResults = await this.executor.executeAgents(
@@ -6021,7 +6477,24 @@ var TrieScanTool = class {
6021
6477
  prioritization: prioritized,
6022
6478
  grouping: priorityReport
6023
6479
  };
6024
- await writeFile3(args.output, JSON.stringify(report, null, 2));
6480
+ await writeFile4(args.output, JSON.stringify(report, null, 2));
6481
+ }
6482
+ try {
6483
+ const contextSignals = {
6484
+ touchesAuth: context.touchesAuth ?? false,
6485
+ touchesPayments: context.touchesPayments ?? false,
6486
+ touchesUserData: context.touchesUserData ?? false,
6487
+ touchesAPI: context.touchesAPI ?? false,
6488
+ touchesDatabase: context.touchesDatabase ?? false,
6489
+ touchesCrypto: context.touchesCrypto ?? false
6490
+ };
6491
+ await updateContextAfterScan(
6492
+ agentResults,
6493
+ validFiles.length,
6494
+ contextSignals,
6495
+ Date.now() - startTime
6496
+ );
6497
+ } catch {
6025
6498
  }
6026
6499
  return {
6027
6500
  content: [
@@ -6120,8 +6593,8 @@ var TrieScanTool = class {
6120
6593
  const enriched = [];
6121
6594
  for (const issue of issues) {
6122
6595
  try {
6123
- if (issue.line && existsSync5(issue.file)) {
6124
- const content = await readFile8(issue.file, "utf-8");
6596
+ if (issue.line && existsSync6(issue.file)) {
6597
+ const content = await readFile9(issue.file, "utf-8");
6125
6598
  const lines = content.split("\n");
6126
6599
  const startLine = Math.max(0, issue.line - 3);
6127
6600
  const endLine = Math.min(lines.length, issue.line + 2);
@@ -6360,9 +6833,9 @@ ${issue.fix}
6360
6833
  * Get a code snippet around a specific line
6361
6834
  */
6362
6835
  async getCodeSnippet(filePath, line) {
6363
- if (!line || !existsSync5(filePath)) return null;
6836
+ if (!line || !existsSync6(filePath)) return null;
6364
6837
  try {
6365
- const content = await readFile8(filePath, "utf-8");
6838
+ const content = await readFile9(filePath, "utf-8");
6366
6839
  const lines = content.split("\n");
6367
6840
  const start = Math.max(0, line - 3);
6368
6841
  const end = Math.min(lines.length, line + 2);
@@ -6386,7 +6859,7 @@ ${issue.fix}
6386
6859
  const entries = await readdir2(currentDir, { withFileTypes: true });
6387
6860
  for (const entry of entries) {
6388
6861
  if (files.length >= maxFiles) break;
6389
- const fullPath = join6(currentDir, entry.name);
6862
+ const fullPath = join7(currentDir, entry.name);
6390
6863
  if (entry.isDirectory()) {
6391
6864
  if (!SKIP_DIRS.has(entry.name) && !entry.name.startsWith(".")) {
6392
6865
  await walk(fullPath);
@@ -6411,12 +6884,12 @@ ${issue.fix}
6411
6884
  return files;
6412
6885
  }
6413
6886
  async loadTeamMembers(workDir) {
6414
- const teamConfigPath = join6(workDir, ".trie", "team.json");
6415
- if (!existsSync5(teamConfigPath)) {
6887
+ const teamConfigPath = join7(workDir, ".trie", "team.json");
6888
+ if (!existsSync6(teamConfigPath)) {
6416
6889
  return [];
6417
6890
  }
6418
6891
  try {
6419
- const content = await readFile8(teamConfigPath, "utf-8");
6892
+ const content = await readFile9(teamConfigPath, "utf-8");
6420
6893
  const data = JSON.parse(content);
6421
6894
  return Array.isArray(data.members) ? data.members : [];
6422
6895
  } catch {
@@ -6435,6 +6908,8 @@ ${issue.fix}
6435
6908
 
6436
6909
  export {
6437
6910
  loadConfig,
6911
+ loadContextState,
6912
+ getContextForAI,
6438
6913
  TrieScanTool
6439
6914
  };
6440
- //# sourceMappingURL=chunk-VSCPOIWS.js.map
6915
+ //# sourceMappingURL=chunk-HG5AWUH7.js.map