@triedotdev/mcp 1.0.47 → 1.0.50

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.
@@ -13,7 +13,7 @@ import {
13
13
  BaseAgent,
14
14
  isAIAvailable,
15
15
  runAIAnalysis
16
- } from "./chunk-OB45V2QC.js";
16
+ } from "./chunk-3SQK2RKF.js";
17
17
  import {
18
18
  getWorkingDirectory
19
19
  } from "./chunk-IMFD4SJC.js";
@@ -79,6 +79,7 @@ var SecurityAgent = class extends BaseAgent {
79
79
  name = "security";
80
80
  description = "AI-powered security analysis: vulnerabilities, injection risks, authentication issues";
81
81
  version = "2.0.0";
82
+ author = "Trie Agent";
82
83
  shouldActivate(context) {
83
84
  return context.touchesAuth || context.touchesDatabase || context.touchesAPI || context.touchesUserData || context.touchesPayments || context.touchesSecurityConfig;
84
85
  }
@@ -345,6 +346,7 @@ var PrivacyAgent = class extends BaseAgent {
345
346
  name = "privacy";
346
347
  description = "AI-powered privacy analysis: GDPR, CCPA, PCI-DSS compliance";
347
348
  version = "2.0.0";
349
+ author = "Trie Agent";
348
350
  shouldActivate(context) {
349
351
  const hasUserDataSignals = context.touchesUserData && (context.touchesDatabase || context.touchesAuth || context.patterns?.hasFormHandling || context.patterns?.hasEmailHandling || context.touchesThirdPartyAPI);
350
352
  const fileNameSignals = context.filePatterns.some(
@@ -606,6 +608,7 @@ var TypeCheckAgent = class extends BaseAgent {
606
608
  name = "typecheck";
607
609
  description = "Catches type errors and ensures type safety";
608
610
  version = "1.0.0";
611
+ author = "Trie Agent";
609
612
  shouldActivate(_context) {
610
613
  return true;
611
614
  }
@@ -681,6 +684,7 @@ var ComprehensionAgent = class extends BaseAgent {
681
684
  name = "comprehension";
682
685
  description = "Explains what code does in plain language for non-technical builders";
683
686
  version = "1.0.0";
687
+ author = "Trie Agent";
684
688
  shouldActivate(_context) {
685
689
  return true;
686
690
  }
@@ -960,6 +964,7 @@ var AccessibilityAgent = class extends BaseAgent {
960
964
  name = "accessibility";
961
965
  description = "WCAG 2.1 AA compliance: screen readers, keyboard nav, color contrast, touch targets, semantic HTML, ARIA patterns";
962
966
  version = "2.0.0";
967
+ author = "Trie Agent";
963
968
  shouldActivate(context) {
964
969
  return context.touchesUI;
965
970
  }
@@ -990,12 +995,13 @@ var AccessibilityAgent = class extends BaseAgent {
990
995
  const score = this.calculateAccessibilityScore(issues);
991
996
  issues.push(this.createIssue(
992
997
  this.generateIssueId(),
993
- criticalCount > 0 ? "critical" : "serious",
998
+ "low",
999
+ // Summary is informational, not a blocker
994
1000
  `Accessibility Score: ${score}/100 \u2014 ${criticalCount} critical, ${seriousCount} serious issues`,
995
1001
  `Review and fix accessibility issues starting with critical problems. Use axe-core or Lighthouse for additional validation.`,
996
1002
  files[0] || "project",
997
1003
  void 0,
998
- 0.95,
1004
+ 0.6,
999
1005
  void 0,
1000
1006
  false
1001
1007
  ));
@@ -2153,6 +2159,7 @@ var DesignEngineerAgent = class extends BaseAgent {
2153
2159
  name = "design-engineer";
2154
2160
  description = "Award-winning frontend craft: design systems, motion design, creative CSS, modern color palettes, Awwwards-level polish";
2155
2161
  version = "2.0.0";
2162
+ author = "Trie Agent";
2156
2163
  shouldActivate(context) {
2157
2164
  return context.touchesUI;
2158
2165
  }
@@ -2187,12 +2194,14 @@ var DesignEngineerAgent = class extends BaseAgent {
2187
2194
  const domainRecommendation = this.getDomainRecommendations(designContext);
2188
2195
  issues.push(this.createIssue(
2189
2196
  this.generateIssueId(),
2190
- healthScore.score < 50 ? "serious" : "moderate",
2197
+ "low",
2198
+ // Design scores are informational, not blockers
2191
2199
  `Design Health Score: ${healthScore.score}/100 | Slop Score: ${healthScore.slopScore}/100`,
2192
2200
  `Breakdown: Token adoption ${healthScore.breakdown.tokenAdoption}%, Contrast ${healthScore.breakdown.contrastCompliance}%, Spacing ${healthScore.breakdown.spacingConsistency}%, Typography ${healthScore.breakdown.typographySystem}%, Surface hierarchy ${healthScore.breakdown.surfaceHierarchy}%. ${domainRecommendation}`,
2193
2201
  files[0] || "project",
2194
2202
  void 0,
2195
- 0.95,
2203
+ 0.6,
2204
+ // Lower confidence for aggregate scores
2196
2205
  void 0,
2197
2206
  false
2198
2207
  ));
@@ -2921,12 +2930,13 @@ var DesignEngineerAgent = class extends BaseAgent {
2921
2930
  const suggestedFix = this.suggestLighterSurface(bgColors[0], 10);
2922
2931
  issues.push(this.createIssue(
2923
2932
  this.generateIssueId(),
2924
- "critical",
2933
+ "moderate",
2934
+ // Design issues should not be critical - reserved for security/data loss
2925
2935
  `AI SLOP: Surfaces too similar (${minDelta.toFixed(1)}% lightness delta). Min 8% required.`,
2926
2936
  `Change surface color to create visible hierarchy. Suggestion: use ${suggestedFix} for elevated surfaces. Reference: zinc scale at tailwindcss.com/docs/customizing-colors`,
2927
2937
  file,
2928
2938
  void 0,
2929
- 0.95,
2939
+ 0.75,
2930
2940
  void 0,
2931
2941
  true
2932
2942
  ));
@@ -2937,12 +2947,13 @@ var DesignEngineerAgent = class extends BaseAgent {
2937
2947
  if (accentHues.length > AI_SLOP_BLOCKERS.accents.maxAccentHues + 1) {
2938
2948
  issues.push(this.createIssue(
2939
2949
  this.generateIssueId(),
2940
- "serious",
2950
+ "low",
2951
+ // Design preference, not a real issue
2941
2952
  `AI SLOP: ${accentHues.length} accent color families detected. Use ONE primary accent.`,
2942
2953
  `Standardize on a single accent hue family. Semantic colors (success/warning/error) are exempt. Reference: radix-ui.com/colors for cohesive scales`,
2943
2954
  file,
2944
2955
  void 0,
2945
- 0.9,
2956
+ 0.65,
2946
2957
  void 0,
2947
2958
  true
2948
2959
  ));
@@ -2972,12 +2983,14 @@ var DesignEngineerAgent = class extends BaseAgent {
2972
2983
  const desaturated = this.desaturateColor(color, 60);
2973
2984
  issues.push(this.createIssue(
2974
2985
  this.generateIssueId(),
2975
- "serious",
2986
+ "low",
2987
+ // Design suggestions should be low severity, not serious
2976
2988
  `AI SLOP: Neon color detected (${color}, ${saturation.toFixed(0)}% saturation)`,
2977
2989
  `Desaturate to ${desaturated}. Max recommended saturation: 75%. Source colors from radix-ui.com/colors for contrast-safe alternatives.`,
2978
2990
  file,
2979
2991
  void 0,
2980
- 0.9,
2992
+ 0.7,
2993
+ // Lower confidence for design opinions
2981
2994
  void 0,
2982
2995
  true
2983
2996
  ));
@@ -3654,8 +3667,9 @@ var LegalAgent = class extends BaseAgent {
3654
3667
  name = "legal";
3655
3668
  description = "Comprehensive legal compliance for app development: licensing, ToS, accessibility, IP, data protection, e-commerce, and regulatory requirements";
3656
3669
  version = "2.0.0";
3670
+ author = "Trie Agent";
3657
3671
  shouldActivate(context) {
3658
- return context.touchesUserData || context.touchesPayments || context.touchesAuth || context.touchesUI || context.touchesAPI || context.touchesThirdPartyAPI;
3672
+ return context.touchesUserData || context.touchesPayments || context.touchesAuth || context.touchesUI || context.touchesAPI || context.touchesThirdPartyAPI || context.touchesHealthData;
3659
3673
  }
3660
3674
  async analyzeFiles(files, _context) {
3661
3675
  const issues = [];
@@ -4347,18 +4361,23 @@ var LegalAgent = class extends BaseAgent {
4347
4361
  checkAgeRestrictions(content, file) {
4348
4362
  const issues = [];
4349
4363
  const lines = content.split("\n");
4364
+ const isReactChildrenUsage = /children\s*[:\?})]|React\.ReactNode|PropsWithChildren|\.children/i.test(content);
4350
4365
  for (let i = 0; i < lines.length; i++) {
4351
4366
  const line = lines[i];
4352
- if (/kids|children|child|minor|under.*13|age.*13/i.test(line)) {
4367
+ const childPattern = /\b(kids|minor|under.*13|age.*13)\b/i;
4368
+ const childrenPropPattern = /children\s*[:\?})\]=]|\.children|ReactNode/i;
4369
+ if (childPattern.test(line) && !childrenPropPattern.test(line) && !isReactChildrenUsage) {
4353
4370
  if (!/coppa|parentalConsent|verifiableConsent/i.test(content)) {
4354
4371
  issues.push(this.createIssue(
4355
4372
  this.generateIssueId(),
4356
- "critical",
4357
- "Child-directed content without COPPA compliance",
4358
- "COPPA requires verifiable parental consent before collecting data from children under 13",
4373
+ "serious",
4374
+ // Downgraded from critical - needs human review
4375
+ "Potential child-directed content without COPPA compliance",
4376
+ "COPPA requires verifiable parental consent before collecting data from children under 13. Review if this applies to your app.",
4359
4377
  file,
4360
4378
  i + 1,
4361
- 0.95,
4379
+ 0.7,
4380
+ // Lower confidence - needs human verification
4362
4381
  "COPPA - Children's Online Privacy Protection Act",
4363
4382
  false
4364
4383
  ));
@@ -4643,6 +4662,7 @@ var TestAgent = class extends BaseAgent {
4643
4662
  name = "test";
4644
4663
  description = "Test coverage analysis, test quality, and testing best practices";
4645
4664
  version = "1.0.0";
4665
+ author = "Trie Agent";
4646
4666
  shouldActivate(context) {
4647
4667
  return context.isNewFeature || context.touchesAuth || context.touchesPayments || context.touchesAPI;
4648
4668
  }
@@ -4666,6 +4686,14 @@ var TestAgent = class extends BaseAgent {
4666
4686
  const issues = [];
4667
4687
  const fileName = basename(file);
4668
4688
  const fileDir = dirname(file);
4689
+ if (/index\.[jt]sx?$|types?\.[jt]s$|constants?\.[jt]s$|config\.[jt]s$/.test(fileName)) {
4690
+ return issues;
4691
+ }
4692
+ if (/\.(tsx|jsx)$/.test(fileName) && !/\.test\.|\.spec\./.test(fileName)) {
4693
+ if (!/auth|login|payment|checkout|form/i.test(content)) {
4694
+ return issues;
4695
+ }
4696
+ }
4669
4697
  const testPatterns = [
4670
4698
  file.replace(/\.(ts|js|tsx|jsx)$/, ".test.$1"),
4671
4699
  file.replace(/\.(ts|js|tsx|jsx)$/, ".spec.$1"),
@@ -4675,6 +4703,9 @@ var TestAgent = class extends BaseAgent {
4675
4703
  const hasTestFile = testPatterns.some((pattern) => existsSync(pattern));
4676
4704
  if (!hasTestFile) {
4677
4705
  const severity = this.determineTestSeverity(content);
4706
+ if (severity === "low") {
4707
+ return issues;
4708
+ }
4678
4709
  issues.push(this.createIssue(
4679
4710
  this.generateIssueId(),
4680
4711
  severity,
@@ -4682,7 +4713,8 @@ var TestAgent = class extends BaseAgent {
4682
4713
  `Create test file: ${fileName.replace(/\.(ts|js|tsx|jsx)$/, ".test.$1")}`,
4683
4714
  file,
4684
4715
  void 0,
4685
- 0.85,
4716
+ 0.7,
4717
+ // Lower confidence - we can't know if tests exist elsewhere
4686
4718
  void 0,
4687
4719
  false
4688
4720
  ));
@@ -4700,52 +4732,8 @@ var TestAgent = class extends BaseAgent {
4700
4732
  }
4701
4733
  checkTestablePatterns(content, file) {
4702
4734
  const issues = [];
4703
- const lines = content.split("\n");
4704
4735
  const exports = content.match(/export\s+(function|class|const|async function)/g);
4705
4736
  const exportCount = exports?.length || 0;
4706
- for (let i = 0; i < lines.length; i++) {
4707
- const line = lines[i];
4708
- const lineNumber = i + 1;
4709
- if ((line.match(/if|else|switch|\?.*:/g) || []).length >= 3) {
4710
- issues.push(this.createIssue(
4711
- this.generateIssueId(),
4712
- "low",
4713
- "Complex conditional logic should have unit tests",
4714
- "Write tests covering different branches of this logic",
4715
- file,
4716
- lineNumber,
4717
- 0.7,
4718
- void 0,
4719
- false
4720
- ));
4721
- }
4722
- if (/catch\s*\(|\.catch\(/.test(line)) {
4723
- issues.push(this.createIssue(
4724
- this.generateIssueId(),
4725
- "low",
4726
- "Error handling path should be tested",
4727
- "Write tests that trigger and verify error handling behavior",
4728
- file,
4729
- lineNumber,
4730
- 0.65,
4731
- void 0,
4732
- false
4733
- ));
4734
- }
4735
- if (/async\s+function|await\s+/.test(line) && /fetch|axios|database|query/i.test(line)) {
4736
- issues.push(this.createIssue(
4737
- this.generateIssueId(),
4738
- "moderate",
4739
- "Async operation should have integration tests",
4740
- "Mock external dependencies and test async behavior",
4741
- file,
4742
- lineNumber,
4743
- 0.75,
4744
- void 0,
4745
- false
4746
- ));
4747
- }
4748
- }
4749
4737
  if (exportCount > 5) {
4750
4738
  issues.push(this.createIssue(
4751
4739
  this.generateIssueId(),
@@ -4768,6 +4756,7 @@ var SoftwareArchitectAgent = class extends BaseAgent {
4768
4756
  name = "software-architect";
4769
4757
  description = "Architecture patterns, code organization, SOLID principles, and scalability";
4770
4758
  version = "1.0.0";
4759
+ author = "Trie Agent";
4771
4760
  shouldActivate(context) {
4772
4761
  return context.isNewFeature || context.touchesDatabase || context.touchesAPI || context.linesChanged > 200;
4773
4762
  }
@@ -4791,18 +4780,23 @@ var SoftwareArchitectAgent = class extends BaseAgent {
4791
4780
  for (let i = 0; i < lines.length; i++) {
4792
4781
  const line = lines[i];
4793
4782
  const lineNumber = i + 1;
4794
- if (/\.(tsx|jsx)$/.test(file) && /prisma|mongoose|sequelize|typeorm|query|SELECT/i.test(line)) {
4795
- issues.push(this.createIssue(
4796
- this.generateIssueId(),
4797
- "serious",
4798
- "Direct database access in UI component",
4799
- "Move database logic to API layer or server action",
4800
- file,
4801
- lineNumber,
4802
- 0.9,
4803
- void 0,
4804
- false
4805
- ));
4783
+ if (/\.(tsx|jsx)$/.test(file)) {
4784
+ const hasOrmImport = /from\s+['"]prisma|from\s+['"]mongoose|from\s+['"]sequelize|from\s+['"]typeorm|from\s+['"]@prisma/i.test(line);
4785
+ const hasDirectQuery = /\.query\s*\(|\.execute\s*\(|\.raw\s*\(/.test(line);
4786
+ if (hasOrmImport || hasDirectQuery) {
4787
+ issues.push(this.createIssue(
4788
+ this.generateIssueId(),
4789
+ "moderate",
4790
+ // Downgraded - sometimes this is intentional (Next.js server components)
4791
+ "Direct database access in UI component",
4792
+ "Move database logic to API layer or server action",
4793
+ file,
4794
+ lineNumber,
4795
+ 0.75,
4796
+ void 0,
4797
+ false
4798
+ ));
4799
+ }
4806
4800
  }
4807
4801
  if (/controller|handler|route/i.test(file) && lines.slice(i, i + 20).join("\n").split("if").length > 5) {
4808
4802
  issues.push(this.createIssue(
@@ -4852,18 +4846,19 @@ var SoftwareArchitectAgent = class extends BaseAgent {
4852
4846
  checkCodeOrganization(content, file) {
4853
4847
  const issues = [];
4854
4848
  const hasUI = /jsx|tsx|render|component|React|useState/i.test(content);
4855
- const hasAPI = /fetch|axios|api|endpoint|route/i.test(content);
4856
- const hasDB = /prisma|mongoose|query|INSERT|SELECT/i.test(content);
4849
+ const hasAPI = /fetch\(|axios\.|api\/|endpoint|route/i.test(content);
4850
+ const hasDB = /from\s+['"]prisma|from\s+['"]mongoose|from\s+['"]sequelize|\.query\s*\(/i.test(content);
4857
4851
  const concernCount = [hasUI, hasAPI, hasDB].filter(Boolean).length;
4858
- if (concernCount >= 2) {
4852
+ if (concernCount >= 3) {
4859
4853
  issues.push(this.createIssue(
4860
4854
  this.generateIssueId(),
4861
- "moderate",
4855
+ "low",
4856
+ // Downgraded - this is more of a suggestion
4862
4857
  "Multiple concerns mixed in single file",
4863
- "Separate UI, API, and data access layers",
4858
+ "Consider separating UI, API, and data access layers",
4864
4859
  file,
4865
4860
  void 0,
4866
- 0.75,
4861
+ 0.6,
4867
4862
  void 0,
4868
4863
  false
4869
4864
  ));
@@ -4991,6 +4986,7 @@ var DevOpsAgent = class extends BaseAgent {
4991
4986
  name = "devops";
4992
4987
  description = "Infrastructure, deployment, configuration, and operational concerns";
4993
4988
  version = "1.0.0";
4989
+ author = "Trie Agent";
4994
4990
  shouldActivate(context) {
4995
4991
  return context.touchesSecurityConfig || context.touchesDatabase || context.touchesPayments || context.touchesHealthData;
4996
4992
  }
@@ -5231,6 +5227,7 @@ var BugFindingAgent = class extends BaseAgent {
5231
5227
  name = "bug-finding";
5232
5228
  description = "AI-powered bug detection: null safety, edge cases, async issues, runtime errors";
5233
5229
  version = "2.0.0";
5230
+ author = "Trie Agent";
5234
5231
  shouldActivate(context) {
5235
5232
  return context.touchesPayments || context.isNewFeature || context.touchesDatabase || context.touchesAPI;
5236
5233
  }
@@ -5426,6 +5423,7 @@ var UserTestingAgent = class extends BaseAgent {
5426
5423
  name = "user-testing";
5427
5424
  description = "Simulates user personas (happy path, security tester, confused user) to find vulnerabilities";
5428
5425
  version = "2.0.0";
5426
+ author = "Trie Agent";
5429
5427
  get priority() {
5430
5428
  return {
5431
5429
  name: this.name,
@@ -5896,6 +5894,7 @@ var TrieCleanAgent = class extends BaseAgent {
5896
5894
  name = "trie_clean";
5897
5895
  description = "Reviews AI-generated code for common mistakes and best practices (for non-technical users)";
5898
5896
  version = "1.0.0";
5897
+ author = "Trie Agent";
5899
5898
  get priority() {
5900
5899
  return {
5901
5900
  name: this.name,
@@ -6046,6 +6045,7 @@ var SOC2Agent = class extends BaseAgent {
6046
6045
  name = "soc2";
6047
6046
  description = "SOC 2 Type II compliance: access controls, encryption, logging, change management";
6048
6047
  version = "1.0.0";
6048
+ author = "Trie Agent";
6049
6049
  shouldActivate(context) {
6050
6050
  return context.touchesAuth || context.touchesAPI || context.touchesDatabase || context.touchesUserData || context.touchesSecurityConfig || context.touchesLogging;
6051
6051
  }
@@ -6194,8 +6194,9 @@ var SuperReviewerAgent = class extends BaseAgent {
6194
6194
  name = "super-reviewer";
6195
6195
  description = "Interactive PR review: walks through changes file-by-file, explains each chunk, waits for cross-examination";
6196
6196
  version = "1.0.0";
6197
- shouldActivate(context) {
6198
- return context.linesChanged > 50 || context.isNewFeature || context.touchesAuth || context.touchesPayments || context.touchesDatabase || context.touchesAPI;
6197
+ author = "Trie Agent";
6198
+ shouldActivate(_context) {
6199
+ return false;
6199
6200
  }
6200
6201
  /**
6201
6202
  * The Super Reviewer doesn't do static pattern matching like other agents.
@@ -6344,6 +6345,7 @@ var PerformanceAgent = class extends BaseAgent {
6344
6345
  name = "performance";
6345
6346
  description = "Surfaces performance patterns for human review: memory, renders, bundles, queries";
6346
6347
  version = "1.0.0";
6348
+ author = "Trie Agent";
6347
6349
  shouldActivate(context) {
6348
6350
  return context.touchesUI || context.touchesDatabase || context.touchesAPI || context.patterns.hasAsyncCode || context.linesChanged > 100;
6349
6351
  }
@@ -6643,6 +6645,7 @@ var E2EAgent = class extends BaseAgent {
6643
6645
  name = "e2e";
6644
6646
  description = "Identifies E2E test gaps and flaky test patterns for human review";
6645
6647
  version = "1.0.0";
6648
+ author = "Trie Agent";
6646
6649
  shouldActivate(context) {
6647
6650
  return context.touchesUI || context.isNewFeature || context.patterns.hasFormHandling;
6648
6651
  }
@@ -6875,6 +6878,7 @@ var VisualQAAgent = class extends BaseAgent {
6875
6878
  name = "visual-qa";
6876
6879
  description = "Surfaces potential visual/layout issues in CSS for human review";
6877
6880
  version = "1.0.0";
6881
+ author = "Trie Agent";
6878
6882
  shouldActivate(context) {
6879
6883
  return context.touchesUI || context.filePatterns.some((f) => /\.(css|scss|sass|less|styled)/.test(f));
6880
6884
  }
@@ -7210,6 +7214,7 @@ var DataFlowAgent = class extends BaseAgent {
7210
7214
  name = "data-flow";
7211
7215
  description = "Detects schema mismatches, placeholder data, and data integrity issues";
7212
7216
  version = "1.0.0";
7217
+ author = "Trie Agent";
7213
7218
  shouldActivate(context) {
7214
7219
  return context.touchesAPI || context.touchesDatabase || context.isNewFeature || context.patterns.hasFormHandling;
7215
7220
  }
@@ -7240,13 +7245,9 @@ var DataFlowAgent = class extends BaseAgent {
7240
7245
  const placeholderPatterns = [
7241
7246
  { pattern: /["']lorem ipsum/i, desc: "Lorem ipsum placeholder text" },
7242
7247
  { pattern: /["']test@(test|example)\.com["']/i, desc: "Test email address" },
7243
- { pattern: /["']TODO["']|["']FIXME["']|["']PLACEHOLDER["']/i, desc: "TODO/PLACEHOLDER string value" },
7244
- { pattern: /["']xxx["']|["']yyy["']|["']zzz["']/i, desc: "Placeholder string (xxx/yyy/zzz)" },
7245
- { pattern: /["']foo["']|["']bar["']|["']baz["']/, desc: "Common placeholder names" },
7246
- { pattern: /["']asdf["']|["']qwerty["']/i, desc: "Keyboard mash placeholder" },
7248
+ { pattern: /["']PLACEHOLDER["']/i, desc: "PLACEHOLDER string value" },
7247
7249
  { pattern: /["']changeme["']|["']replace[-_]?me["']/i, desc: "Replace-me placeholder" },
7248
- { pattern: /["']your[-_]?.*[-_]?here["']/i, desc: "Your-X-here placeholder" },
7249
- { pattern: /price:\s*0[,\s]|amount:\s*0[,\s]|total:\s*0[,\s]/i, desc: "Zero price/amount (placeholder?)" }
7250
+ { pattern: /["']your[-_]?(api[-_]?key|token|password)[-_]?here["']/i, desc: "Your-X-here placeholder" }
7250
7251
  ];
7251
7252
  for (let i = 0; i < lines.length; i++) {
7252
7253
  const line = lines[i] || "";
@@ -7351,45 +7352,17 @@ var DataFlowAgent = class extends BaseAgent {
7351
7352
  for (let i = 0; i < lines.length; i++) {
7352
7353
  const line = lines[i] || "";
7353
7354
  const lineNumber = i + 1;
7354
- const optionalChainCount = (line.match(/\?\./g) || []).length;
7355
- if (optionalChainCount >= 3) {
7356
- issues.push(this.createIssue(
7357
- this.generateIssueId(),
7358
- "low",
7359
- "Heavy optional chaining may indicate schema uncertainty",
7360
- "Review: if data structure is well-defined, some ?. may be unnecessary",
7361
- file,
7362
- lineNumber,
7363
- 0.5,
7364
- void 0,
7365
- false,
7366
- { category: "schema", effort: "medium" }
7367
- ));
7368
- }
7369
- if (/as\s+\w+(\[\])?[,;\s)]/.test(line) && !/as\s+const/.test(line)) {
7370
- issues.push(this.createIssue(
7371
- this.generateIssueId(),
7372
- "low",
7373
- "Type assertion may hide actual type mismatch",
7374
- "Prefer type guards or validation for runtime safety",
7375
- file,
7376
- lineNumber,
7377
- 0.45,
7378
- void 0,
7379
- false,
7380
- { category: "type-assertion", effort: "medium" }
7381
- ));
7382
- }
7383
7355
  if (/response\.(data|body)\.(\w+)\.(\w+)\.(\w+)/.test(line)) {
7384
7356
  if (!/\?\./.test(line)) {
7385
7357
  issues.push(this.createIssue(
7386
7358
  this.generateIssueId(),
7387
- "moderate",
7359
+ "low",
7360
+ // Downgraded - optional chaining is good but not critical
7388
7361
  "Deep property access on API response without null checks",
7389
7362
  "Add optional chaining or validate response structure",
7390
7363
  file,
7391
7364
  lineNumber,
7392
- 0.75,
7365
+ 0.6,
7393
7366
  void 0,
7394
7367
  false,
7395
7368
  { category: "null-access", effort: "easy" }
@@ -7438,23 +7411,6 @@ var DataFlowAgent = class extends BaseAgent {
7438
7411
  ));
7439
7412
  }
7440
7413
  }
7441
- if (/Number\(|parseFloat\(|\+\s*\w+/.test(line)) {
7442
- const context = lines.slice(i, Math.min(i + 3, lines.length)).join("\n");
7443
- if (!/isNaN|Number\.isFinite|isFinite|\|\|\s*0/.test(context)) {
7444
- issues.push(this.createIssue(
7445
- this.generateIssueId(),
7446
- "low",
7447
- "Number conversion without NaN check",
7448
- "Check for NaN: isNaN(result) or provide fallback: value || 0",
7449
- file,
7450
- lineNumber,
7451
- 0.55,
7452
- void 0,
7453
- false,
7454
- { category: "nan", effort: "easy" }
7455
- ));
7456
- }
7457
- }
7458
7414
  }
7459
7415
  return issues;
7460
7416
  }
@@ -7464,38 +7420,19 @@ var DataFlowAgent = class extends BaseAgent {
7464
7420
  for (let i = 0; i < lines.length; i++) {
7465
7421
  const line = lines[i] || "";
7466
7422
  const lineNumber = i + 1;
7467
- if (/[^!=]==[^=]/.test(line) && !/===/.test(line)) {
7468
- if (/null|undefined|""|\d+|true|false/.test(line)) {
7469
- issues.push(this.createIssue(
7470
- this.generateIssueId(),
7471
- "moderate",
7472
- "Loose equality (==) may cause unexpected type coercion",
7473
- "Use strict equality (===) for predictable comparisons",
7474
- file,
7475
- lineNumber,
7476
- 0.8,
7477
- void 0,
7478
- true,
7479
- { category: "equality", effort: "trivial" }
7480
- ));
7481
- }
7482
- }
7483
- if (/if\s*\(\s*\w+\s*\)/.test(line)) {
7484
- const varName = line.match(/if\s*\(\s*(\w+)\s*\)/)?.[1];
7485
- if (varName && /count|total|length|index|num|amount|price/i.test(varName)) {
7486
- issues.push(this.createIssue(
7487
- this.generateIssueId(),
7488
- "low",
7489
- "Truthy check on number variable - 0 is falsy but might be valid",
7490
- "Consider explicit: if (count !== undefined) or if (count > 0)",
7491
- file,
7492
- lineNumber,
7493
- 0.6,
7494
- void 0,
7495
- false,
7496
- { category: "falsy", effort: "easy" }
7497
- ));
7498
- }
7423
+ if (/==\s*["']['"]/.test(line) || /==\s*0[^.]/.test(line)) {
7424
+ issues.push(this.createIssue(
7425
+ this.generateIssueId(),
7426
+ "low",
7427
+ "Loose equality with empty string or zero - type coercion risk",
7428
+ "Use strict equality (===) to avoid unexpected behavior",
7429
+ file,
7430
+ lineNumber,
7431
+ 0.65,
7432
+ void 0,
7433
+ true,
7434
+ { category: "equality", effort: "trivial" }
7435
+ ));
7499
7436
  }
7500
7437
  }
7501
7438
  return issues;
@@ -7519,79 +7456,73 @@ var MONEYBAGS_ASCII = `
7519
7456
  \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D
7520
7457
  `;
7521
7458
  var MONEYBAGS_QUOTES = [
7522
- `"Every bug has a price tag. I'm here to show you the receipt."`,
7523
- `"That 'temporary fix' will cost you $50k when it hits production."`,
7524
- `"Show me the bug, I'll show you the money you're about to lose."`,
7525
- '"A penny saved in development is $30 saved in production."',
7526
- `"Your CFO doesn't care about code quality. They care about THIS."`,
7527
- `"Floating-point for money? That's going to be an expensive lesson."`,
7528
- '"The best time to fix a bug was yesterday. The second best time is before production."',
7529
- '"I see dead... budget allocations for emergency fixes."',
7530
- '"You can pay me now, or pay production support later. Your choice."',
7531
- '"That empty catch block? $5,600 per minute when it fails silently."'
7459
+ "Every bug has a price tag. I'm here to show you the receipt.",
7460
+ "That temporary fix will cost you $50k when it hits production.",
7461
+ "A penny saved in development is $30 saved in production.",
7462
+ "Floating-point for money? That's going to be an expensive lesson."
7532
7463
  ];
7533
7464
  var BASE_COST_BY_SEVERITY = {
7534
- critical: 5e3,
7535
- // Critical bugs found in dev - still expensive to fix properly
7536
- serious: 2e3,
7537
- // Serious issues need careful remediation
7538
- moderate: 500,
7539
- // Moderate issues are quicker fixes
7540
- low: 100
7541
- // Low severity - mostly cleanup
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
7542
7473
  };
7543
7474
  var PRODUCTION_MULTIPLIER = {
7544
- critical: 30,
7545
- // Critical bugs can cause outages, breaches
7546
- serious: 20,
7547
- // Serious bugs cause significant user impact
7548
- moderate: 10,
7549
- // Moderate bugs require hotfixes, user support
7550
- low: 5
7551
- // Low bugs accumulate tech debt
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)
7481
+ low: 2
7482
+ // Low bugs accumulate tech debt (capped from 5x)
7552
7483
  };
7553
7484
  var CATEGORY_MULTIPLIERS = {
7554
- // Security categories - based on breach cost data
7555
- "security": { multiplier: 8, reason: "Security vulnerabilities can lead to data breaches (avg $4.45M)" },
7556
- "authentication": { multiplier: 10, reason: "Auth bypass leads to complete system compromise" },
7557
- "authorization": { multiplier: 8, reason: "Authorization flaws expose sensitive data" },
7558
- "injection": { multiplier: 12, reason: "SQL/Command injection enables full system takeover" },
7559
- "xss": { multiplier: 5, reason: "XSS enables session hijacking and data theft" },
7560
- "secrets": { multiplier: 15, reason: "Exposed secrets require immediate rotation and audit" },
7561
- "cryptography": { multiplier: 6, reason: "Weak crypto undermines entire security model" },
7485
+ // 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" },
7562
7493
  // Data integrity categories
7563
- "data-loss": { multiplier: 20, reason: "Data loss can be irrecoverable and legally actionable" },
7564
- "data-corruption": { multiplier: 15, reason: "Data corruption requires manual recovery and validation" },
7565
- "privacy": { multiplier: 10, reason: "Privacy violations carry regulatory fines (GDPR: 4% revenue)" },
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" },
7566
7497
  // Financial categories
7567
- "payment": { multiplier: 25, reason: "Payment bugs can cause direct financial loss or fraud" },
7568
- "billing": { multiplier: 20, reason: "Billing errors require refunds and erode trust" },
7569
- "financial-calculation": { multiplier: 15, reason: "Incorrect calculations compound over time" },
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" },
7570
7501
  // Reliability categories
7571
- "crash": { multiplier: 8, reason: "Crashes cause downtime (avg $5,600/minute)" },
7572
- "memory-leak": { multiplier: 5, reason: "Memory leaks cause gradual degradation and outages" },
7573
- "deadlock": { multiplier: 10, reason: "Deadlocks require restarts and cause data inconsistency" },
7574
- "race-condition": { multiplier: 8, reason: "Race conditions cause intermittent, hard-to-debug failures" },
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" },
7575
7506
  // User experience
7576
- "accessibility": { multiplier: 3, reason: "Accessibility issues can lead to lawsuits (ADA compliance)" },
7577
- "performance": { multiplier: 2, reason: "Performance issues hurt conversion rates (~7% per 1s delay)" },
7578
- "ux": { multiplier: 1.5, reason: "UX bugs increase support costs and churn" },
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" },
7579
7510
  // Code quality
7580
- "bug": { multiplier: 2, reason: "General bugs require developer time and QA cycles" },
7581
- "type-error": { multiplier: 1.5, reason: "Type errors caught early save debugging time" },
7582
- "logic-error": { multiplier: 3, reason: "Logic errors produce incorrect business outcomes" },
7511
+ "bug": { multiplier: 1, reason: "General bugs require developer time" },
7512
+ "type-error": { multiplier: 0.8, reason: "Type errors caught early save debugging time" },
7513
+ "logic-error": { multiplier: 1.5, reason: "Logic errors produce incorrect outcomes" },
7583
7514
  // Default
7584
- "default": { multiplier: 2, reason: "General code issues" }
7515
+ "default": { multiplier: 1, reason: "General code issues" }
7585
7516
  };
7586
7517
  var CONTEXT_MULTIPLIERS = {
7587
- touchesPayments: { multiplier: 5, description: "Payment processing code" },
7588
- touchesAuth: { multiplier: 4, description: "Authentication/authorization code" },
7589
- touchesUserData: { multiplier: 3, description: "User PII handling" },
7590
- touchesHealthData: { multiplier: 6, description: "Health data (HIPAA liability)" },
7591
- touchesDatabase: { multiplier: 2.5, description: "Database operations" },
7592
- touchesAPI: { multiplier: 2, description: "External API integrations" },
7593
- touchesCrypto: { multiplier: 3, description: "Cryptographic operations" },
7594
- touchesFileSystem: { multiplier: 2, description: "File system operations" }
7518
+ touchesPayments: { multiplier: 1.3, description: "Payment processing code" },
7519
+ touchesAuth: { multiplier: 1.2, description: "Authentication/authorization code" },
7520
+ touchesUserData: { multiplier: 1.15, description: "User PII handling" },
7521
+ touchesHealthData: { multiplier: 1.3, description: "Health data (HIPAA liability)" },
7522
+ touchesDatabase: { multiplier: 1.1, description: "Database operations" },
7523
+ touchesAPI: { multiplier: 1.1, description: "External API integrations" },
7524
+ touchesCrypto: { multiplier: 1.15, description: "Cryptographic operations" },
7525
+ touchesFileSystem: { multiplier: 1.05, description: "File system operations" }
7595
7526
  };
7596
7527
  var EFFORT_HOURS = {
7597
7528
  trivial: 0.5,
@@ -7602,16 +7533,17 @@ var EFFORT_HOURS = {
7602
7533
  var DEVELOPER_HOURLY_RATE = 150;
7603
7534
  var DEFAULT_USER_COUNT = 250;
7604
7535
  var USER_COUNT_MULTIPLIERS = [
7605
- { threshold: 0, multiplier: 0.1, label: "Pre-launch (0 users)" },
7606
- { threshold: 50, multiplier: 0.3, label: "MVP (50 users)" },
7536
+ { threshold: 0, multiplier: 0.2, label: "Pre-launch (0 users)" },
7537
+ { threshold: 50, multiplier: 0.5, label: "MVP (50 users)" },
7607
7538
  { threshold: 250, multiplier: 1, label: "Early stage (250 users)" },
7608
7539
  // Baseline (default)
7609
- { threshold: 1e3, multiplier: 2, label: "Growing (1K users)" },
7610
- { threshold: 5e3, multiplier: 4, label: "Traction (5K users)" },
7611
- { threshold: 25e3, multiplier: 8, label: "Scale-up (25K users)" },
7612
- { threshold: 1e5, multiplier: 15, label: "Growth (100K users)" },
7613
- { threshold: 5e5, multiplier: 25, label: "Large (500K users)" },
7614
- { threshold: 1e6, multiplier: 40, label: "Enterprise (1M+ users)" }
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
7615
7547
  ];
7616
7548
  var PER_USER_COSTS = {
7617
7549
  "data-loss": 5,
@@ -7631,6 +7563,7 @@ var MoneybagAgent = class extends BaseAgent {
7631
7563
  name = "moneybags";
7632
7564
  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.";
7633
7565
  version = "1.1.0";
7566
+ author = "Trie Agent";
7634
7567
  bannerShown = false;
7635
7568
  config = {
7636
7569
  userCount: DEFAULT_USER_COUNT,
@@ -7669,12 +7602,12 @@ var MoneybagAgent = class extends BaseAgent {
7669
7602
  if (this.bannerShown) return;
7670
7603
  this.bannerShown = true;
7671
7604
  const quote = MONEYBAGS_QUOTES[Math.floor(Math.random() * MONEYBAGS_QUOTES.length)];
7672
- console.error("\n" + "\u2550".repeat(60));
7605
+ console.error("\n" + "=".repeat(60));
7673
7606
  console.error(MONEYBAGS_ASCII);
7674
- console.error(" \u{1F4B0} Bug Cost Estimator v" + this.version + " \u{1F4B0}");
7607
+ console.error(" Bug Cost Estimator v" + this.version);
7675
7608
  console.error("");
7676
7609
  console.error(" " + quote);
7677
- console.error("\u2550".repeat(60) + "\n");
7610
+ console.error("=".repeat(60) + "\n");
7678
7611
  }
7679
7612
  // Run after other agents so we can analyze their findings
7680
7613
  get priority() {
@@ -7757,7 +7690,7 @@ var MoneybagAgent = class extends BaseAgent {
7757
7690
  contextFactors.push(data.description);
7758
7691
  }
7759
7692
  }
7760
- contextMultiplier = Math.min(contextMultiplier, 10);
7693
+ contextMultiplier = Math.min(contextMultiplier, 2);
7761
7694
  const userScale = this.getUserScaleMultiplier();
7762
7695
  const userScaleMultiplier = userScale.multiplier;
7763
7696
  const userScaleLabel = userScale.label;
@@ -7779,14 +7712,15 @@ var MoneybagAgent = class extends BaseAgent {
7779
7712
  const fixHours = EFFORT_HOURS[effort] || 8;
7780
7713
  const developerRate = this.config.developerRate ?? DEVELOPER_HOURLY_RATE;
7781
7714
  const fixCost = fixHours * developerRate;
7782
- const totalNowCost = Math.round(
7783
- baseCost * categoryMultiplier * contextMultiplier * userScaleMultiplier + fixCost
7784
- );
7785
- const totalProductionCost = Math.round(
7786
- baseCost * productionMultiplier * categoryMultiplier * contextMultiplier * userScaleMultiplier + perUserCost + // Add per-user costs for production impact
7787
- fixCost * 3
7788
- // Production fixes take 3x longer (debugging, deployment, rollback, post-mortem)
7789
- );
7715
+ const BASE_NOW_CAP = 500;
7716
+ const BASE_PROD_CAP = 2e3;
7717
+ const maxNowCost = BASE_NOW_CAP * userScaleMultiplier;
7718
+ const maxProdCost = BASE_PROD_CAP * userScaleMultiplier;
7719
+ const rawNowCost = baseCost * categoryMultiplier * contextMultiplier + fixCost;
7720
+ const totalNowCost = Math.round(Math.min(rawNowCost, maxNowCost));
7721
+ const rawProductionCost = baseCost * productionMultiplier * categoryMultiplier * contextMultiplier + perUserCost + // Add per-user costs for production impact
7722
+ fixCost * 2;
7723
+ const totalProductionCost = Math.round(Math.min(rawProductionCost, maxProdCost));
7790
7724
  const savings = totalProductionCost - totalNowCost;
7791
7725
  const summary = this.generateCostSummary(
7792
7726
  issue,
@@ -7849,7 +7783,7 @@ var MoneybagAgent = class extends BaseAgent {
7849
7783
  generateCostSummary(_issue, nowCost, productionCost, savings, contextFactors, userCount) {
7850
7784
  const formatCurrency = (n) => n >= 1e3 ? `$${(n / 1e3).toFixed(1)}k` : `$${n}`;
7851
7785
  const formatUsers = (n) => n >= 1e6 ? `${(n / 1e6).toFixed(1)}M` : n >= 1e3 ? `${(n / 1e3).toFixed(0)}K` : `${n}`;
7852
- let summary = `\u{1F4B0} Fix now: ${formatCurrency(nowCost)} | If production: ${formatCurrency(productionCost)} | Save: ${formatCurrency(savings)}`;
7786
+ let summary = `Fix now: ${formatCurrency(nowCost)} | If production: ${formatCurrency(productionCost)} | Save: ${formatCurrency(savings)}`;
7853
7787
  summary += ` (${formatUsers(userCount)} users)`;
7854
7788
  if (contextFactors.length > 0) {
7855
7789
  summary += ` | Risk factors: ${contextFactors.join(", ")}`;
@@ -7857,9 +7791,9 @@ var MoneybagAgent = class extends BaseAgent {
7857
7791
  const scaledHighThreshold = 5e4 * (userCount / 1e3);
7858
7792
  const scaledMediumThreshold = 1e4 * (userCount / 1e3);
7859
7793
  if (productionCost > scaledHighThreshold) {
7860
- summary = `\u{1F525} HIGH COST RISK - ${summary}`;
7794
+ summary = `[HIGH COST RISK] ${summary}`;
7861
7795
  } else if (productionCost > scaledMediumThreshold) {
7862
- summary = `\u26A0\uFE0F SIGNIFICANT COST - ${summary}`;
7796
+ summary = `[SIGNIFICANT COST] ${summary}`;
7863
7797
  }
7864
7798
  return summary;
7865
7799
  }
@@ -8065,33 +7999,33 @@ Output STRICT JSON:
8065
7999
  const formatCurrency = (n) => n >= 1e6 ? `$${(n / 1e6).toFixed(2)}M` : n >= 1e3 ? `$${(n / 1e3).toFixed(1)}k` : `$${n}`;
8066
8000
  const formatUsers = (n) => n >= 1e6 ? `${(n / 1e6).toFixed(1)}M` : n >= 1e3 ? `${Math.round(n / 1e3)}K` : `${n}`;
8067
8001
  const summary = `
8068
- \u{1F4B0} COST ANALYSIS REPORT
8069
- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
8070
- \u{1F465} User Scale: ${formatUsers(userCount)} users (${userScale.label})
8071
- \u2514\u2500 Costs scaled ${userScale.multiplier}x from 1K baseline
8072
-
8073
- \u{1F4CA} Total Issues: ${issues.length}
8074
- \u251C\u2500 Critical: ${breakdown.find((b) => b.severity === "critical")?.count || 0}
8075
- \u251C\u2500 Serious: ${breakdown.find((b) => b.severity === "serious")?.count || 0}
8076
- \u251C\u2500 Moderate: ${breakdown.find((b) => b.severity === "moderate")?.count || 0}
8077
- \u2514\u2500 Low: ${breakdown.find((b) => b.severity === "low")?.count || 0}
8078
-
8079
- \u{1F4B5} COST IMPACT
8080
- \u251C\u2500 Fix now: ${formatCurrency(totalNowCost)}
8081
- \u251C\u2500 If production: ${formatCurrency(totalProductionCost)}
8082
- \u2514\u2500 Savings by fixing now: ${formatCurrency(totalSavings)} \u26A1
8083
-
8084
- \u{1F3AF} RISK LEVEL: ${riskLevel.toUpperCase()}
8085
- ${riskLevel === "critical" ? " \u26A0\uFE0F URGENT: High-value bugs require immediate attention" : ""}
8086
- ${riskLevel === "high" ? " \u26A0\uFE0F ATTENTION: Significant financial risk detected" : ""}
8087
-
8088
- \u{1F4C8} Based on industry research:
8089
- \u2022 IBM: Production bugs cost 30x more to fix
8090
- \u2022 Ponemon: Average data breach costs $4.45M
8091
- \u2022 Gartner: Downtime averages $5,600/minute
8092
-
8093
- \u{1F4A1} Default: 250 users. Scale with: trie scan --users 10000
8094
- \u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550
8002
+ COST ANALYSIS REPORT
8003
+ =======================================
8004
+ User Scale: ${formatUsers(userCount)} users (${userScale.label})
8005
+ Costs scaled ${userScale.multiplier}x from 1K baseline
8006
+
8007
+ Total Issues: ${issues.length}
8008
+ Critical: ${breakdown.find((b) => b.severity === "critical")?.count || 0}
8009
+ Serious: ${breakdown.find((b) => b.severity === "serious")?.count || 0}
8010
+ Moderate: ${breakdown.find((b) => b.severity === "moderate")?.count || 0}
8011
+ Low: ${breakdown.find((b) => b.severity === "low")?.count || 0}
8012
+
8013
+ COST IMPACT
8014
+ Fix now: ${formatCurrency(totalNowCost)}
8015
+ If production: ${formatCurrency(totalProductionCost)}
8016
+ Savings by fixing now: ${formatCurrency(totalSavings)}
8017
+
8018
+ RISK LEVEL: ${riskLevel.toUpperCase()}
8019
+ ${riskLevel === "critical" ? " URGENT: High-value bugs require immediate attention" : ""}
8020
+ ${riskLevel === "high" ? " ATTENTION: Significant financial risk detected" : ""}
8021
+
8022
+ Based on industry research:
8023
+ - IBM: Production bugs cost 30x more to fix
8024
+ - Ponemon: Average data breach costs $4.45M
8025
+ - Gartner: Downtime averages $5,600/minute
8026
+
8027
+ Default: 250 users. Scale with: trie scan --users 10000
8028
+ =======================================
8095
8029
  `.trim();
8096
8030
  return {
8097
8031
  totalNowCost,
@@ -8123,76 +8057,82 @@ var PRODUCTION_READY_ASCII = `
8123
8057
  \u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u255D\u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D
8124
8058
  `;
8125
8059
  var PRODUCTION_QUOTES = [
8126
- '"Ship it? Not until I say so."',
8060
+ "Ship it? Not until I say so.",
8127
8061
  '"Works on my machine" is not a deployment strategy.',
8128
- '"The last mile is where dreams become revenue\u2014or nightmares."',
8129
- '"Production is where your code meets reality. Is yours ready?"',
8130
- '"One missing health check = 3am pager duty."',
8131
- `"You wouldn't deploy without tests. Why deploy without production checks?"`,
8132
- '"Fortune favors the prepared. So does uptime."',
8133
- `"Your users don't care about your sprint velocity. They care if it works."`
8062
+ "The last mile is where dreams become revenue -- or nightmares.",
8063
+ "Production is where your code meets reality. Is yours ready?"
8134
8064
  ];
8135
8065
  var PRODUCTION_PATTERNS = {
8136
- // Health & Reliability
8066
+ // Health & Reliability - BACKEND ONLY
8137
8067
  healthEndpoint: {
8138
8068
  pattern: /\/health|healthcheck|health-check|readiness|liveness/i,
8139
8069
  category: "reliability",
8140
8070
  requirement: "Health check endpoint",
8141
- severity: "serious"
8071
+ severity: "moderate",
8072
+ // Downgraded - not critical for all apps
8073
+ backendOnly: true
8142
8074
  },
8143
8075
  gracefulShutdown: {
8144
8076
  pattern: /SIGTERM|SIGINT|process\.on\s*\(\s*['"]SIG/i,
8145
8077
  category: "reliability",
8146
8078
  requirement: "Graceful shutdown handling",
8147
- severity: "moderate"
8079
+ severity: "low",
8080
+ backendOnly: true
8148
8081
  },
8149
- // Scalability
8082
+ // Scalability - BACKEND ONLY
8150
8083
  connectionPooling: {
8151
8084
  pattern: /connectionLimit|pool|poolSize|max_connections|maxConnections/i,
8152
8085
  category: "scalability",
8153
8086
  requirement: "Database connection pooling",
8154
- severity: "serious"
8087
+ severity: "moderate",
8088
+ backendOnly: true
8155
8089
  },
8156
8090
  inMemorySession: {
8157
8091
  pattern: /express-session.*(?!redis|memcached|mongo)|session\s*=\s*\{\}/i,
8158
8092
  category: "scalability",
8159
8093
  requirement: "External session store (not in-memory)",
8160
- severity: "serious"
8094
+ severity: "moderate",
8095
+ backendOnly: true
8161
8096
  },
8162
- // Error Handling
8097
+ // Error Handling - BACKEND ONLY
8163
8098
  globalErrorHandler: {
8164
8099
  pattern: /app\.use\s*\(\s*\(?err|errorHandler|process\.on\s*\(\s*['"]uncaughtException/i,
8165
8100
  category: "reliability",
8166
8101
  requirement: "Global error handler",
8167
- severity: "serious"
8102
+ severity: "moderate",
8103
+ backendOnly: true
8168
8104
  },
8169
- // Security Headers
8105
+ // Security Headers - BACKEND ONLY (frontend relies on hosting platform)
8170
8106
  securityHeaders: {
8171
8107
  pattern: /helmet|contentSecurityPolicy|X-Frame-Options|X-Content-Type|Strict-Transport/i,
8172
8108
  category: "security",
8173
8109
  requirement: "Security headers (CSP, HSTS, etc.)",
8174
- severity: "serious"
8110
+ severity: "moderate",
8111
+ backendOnly: true
8175
8112
  },
8176
- // Rate Limiting
8113
+ // Rate Limiting - BACKEND ONLY
8177
8114
  rateLimiting: {
8178
8115
  pattern: /rateLimit|rate-limit|throttle|express-rate-limit|slowDown/i,
8179
8116
  category: "security",
8180
8117
  requirement: "API rate limiting",
8181
- severity: "moderate"
8118
+ severity: "low",
8119
+ backendOnly: true
8182
8120
  },
8183
- // Logging
8121
+ // Logging - applies to both but less critical for frontend
8184
8122
  structuredLogging: {
8185
8123
  pattern: /pino|winston|bunyan|structured.*log|log.*json/i,
8186
8124
  category: "observability",
8187
8125
  requirement: "Structured logging",
8188
- severity: "moderate"
8126
+ severity: "low",
8127
+ backendOnly: false
8189
8128
  },
8190
- // Monitoring
8129
+ // Monitoring - applies to both
8191
8130
  monitoring: {
8192
8131
  pattern: /prometheus|datadog|newrelic|sentry|bugsnag|opentelemetry|@sentry/i,
8193
8132
  category: "observability",
8194
8133
  requirement: "Error/performance monitoring",
8195
- severity: "moderate"
8134
+ severity: "low",
8135
+ backendOnly: false
8196
8136
  }
8197
8137
  };
8198
8138
  var PRODUCTION_ANTIPATTERNS = [
@@ -8266,6 +8206,7 @@ var ProductionReadyAgent = class extends BaseAgent {
8266
8206
  name = "production-ready";
8267
8207
  description = "Production readiness checker: health endpoints, graceful shutdown, connection pooling, security headers, monitoring, and deployment gates";
8268
8208
  version = "1.0.0";
8209
+ author = "Trie Agent";
8269
8210
  bannerShown = false;
8270
8211
  foundRequirements = /* @__PURE__ */ new Set();
8271
8212
  get priority() {
@@ -8293,12 +8234,12 @@ var ProductionReadyAgent = class extends BaseAgent {
8293
8234
  if (this.bannerShown) return;
8294
8235
  this.bannerShown = true;
8295
8236
  const quote = PRODUCTION_QUOTES[Math.floor(Math.random() * PRODUCTION_QUOTES.length)];
8296
- console.error("\n" + "\u2550".repeat(60));
8237
+ console.error("\n" + "=".repeat(60));
8297
8238
  console.error(PRODUCTION_READY_ASCII);
8298
- console.error(" \u{1F680} Production Readiness Gate v" + this.version + " \u{1F680}");
8239
+ console.error(" Production Readiness Gate v" + this.version);
8299
8240
  console.error("");
8300
8241
  console.error(" " + quote);
8301
- console.error("\u2550".repeat(60) + "\n");
8242
+ console.error("=".repeat(60) + "\n");
8302
8243
  }
8303
8244
  checkFileRelevance(file, content) {
8304
8245
  if (/node_modules|\.d\.ts$|\.min\.|dist\/|build\/|\.lock$/.test(file)) {
@@ -8357,7 +8298,7 @@ var ProductionReadyAgent = class extends BaseAgent {
8357
8298
  issues.push(this.createIssue(
8358
8299
  this.generateIssueId(),
8359
8300
  antiPattern.severity,
8360
- `\u{1F680} [NOT PROD READY] ${antiPattern.issue}`,
8301
+ `[NOT PROD READY] ${antiPattern.issue}`,
8361
8302
  antiPattern.fix,
8362
8303
  file,
8363
8304
  i + 1,
@@ -8373,18 +8314,24 @@ var ProductionReadyAgent = class extends BaseAgent {
8373
8314
  }
8374
8315
  }
8375
8316
  const combinedContent = allContent.join("\n");
8317
+ const isFrontendOnly = this.detectFrontendOnlyApp(combinedContent, files);
8376
8318
  for (const [key, config] of Object.entries(PRODUCTION_PATTERNS)) {
8319
+ const patternConfig = config;
8320
+ if (isFrontendOnly && patternConfig.backendOnly) {
8321
+ continue;
8322
+ }
8377
8323
  if (!this.foundRequirements.has(key)) {
8378
8324
  if (!config.pattern.test(combinedContent)) {
8379
8325
  this.progress?.found(config.severity, `Missing: ${config.requirement}`);
8380
8326
  issues.push(this.createIssue(
8381
8327
  this.generateIssueId(),
8382
8328
  config.severity,
8383
- `\u{1F680} [MISSING] ${config.requirement}`,
8329
+ `[MISSING] ${config.requirement}`,
8384
8330
  this.getRequirementFix(key),
8385
8331
  "project",
8386
8332
  void 0,
8387
- 0.8,
8333
+ 0.6,
8334
+ // Lower confidence for missing checks
8388
8335
  void 0,
8389
8336
  false,
8390
8337
  { category: config.category }
@@ -8395,6 +8342,35 @@ var ProductionReadyAgent = class extends BaseAgent {
8395
8342
  this.logReadinessSummary(issues);
8396
8343
  return issues;
8397
8344
  }
8345
+ /**
8346
+ * Detect if this is a frontend-only app (React, Vue, Svelte, etc.) without a backend
8347
+ * Frontend apps don't need health endpoints, database pooling, session stores, etc.
8348
+ */
8349
+ detectFrontendOnlyApp(content, files) {
8350
+ const frontendContentPatterns = [
8351
+ /vite\.config|next\.config|nuxt\.config|svelte\.config/i,
8352
+ /from ['"]react['"]|from ['"]vue['"]|from ['"]svelte['"]/i,
8353
+ /createRoot|ReactDOM|createApp/i
8354
+ ];
8355
+ const frontendFilePatterns = [
8356
+ /\.tsx$/,
8357
+ /\.jsx$/,
8358
+ /\.vue$/,
8359
+ /\.svelte$/
8360
+ ];
8361
+ const backendIndicators = [
8362
+ /express|fastify|koa|hapi|nest|@nestjs/i,
8363
+ /createServer|http\.Server|https\.Server/i,
8364
+ /app\.listen\s*\(|server\.listen\s*\(/i,
8365
+ /middleware|router\.get|router\.post|app\.get\s*\(/i,
8366
+ /prisma|sequelize|mongoose|knex|typeorm/i
8367
+ ];
8368
+ const hasFrontendContent = frontendContentPatterns.some((p) => p.test(content));
8369
+ const hasFrontendFiles = files.some((f) => frontendFilePatterns.some((p) => p.test(f)));
8370
+ const hasFrontendSignals = hasFrontendContent || hasFrontendFiles;
8371
+ const hasBackendSignals = backendIndicators.some((p) => p.test(content));
8372
+ return hasFrontendSignals && !hasBackendSignals;
8373
+ }
8398
8374
  getRequirementFix(key) {
8399
8375
  const fixes = {
8400
8376
  healthEndpoint: 'Add health check endpoint: app.get("/health", (req, res) => res.json({ status: "ok" }))',
@@ -8412,23 +8388,22 @@ var ProductionReadyAgent = class extends BaseAgent {
8412
8388
  logReadinessSummary(issues) {
8413
8389
  const totalRequirements = Object.keys(PRODUCTION_PATTERNS).length;
8414
8390
  const metRequirements = this.foundRequirements.size;
8415
- const missingRequirements = totalRequirements - metRequirements;
8416
8391
  const criticalIssues = issues.filter((i) => i.severity === "critical").length;
8417
8392
  const seriousIssues = issues.filter((i) => i.severity === "serious").length;
8418
8393
  const readinessScore = Math.max(0, Math.round(
8419
8394
  metRequirements / totalRequirements * 50 + (50 - criticalIssues * 20 - seriousIssues * 10)
8420
8395
  ));
8421
- const status = criticalIssues > 0 || seriousIssues > 2 ? "\u274C NOT READY TO SHIP" : seriousIssues > 0 ? "\u26A0\uFE0F SHIP WITH CAUTION" : "\u2705 READY TO SHIP";
8422
- console.error("\n" + "\u2500".repeat(50));
8423
- console.error("\u{1F4CA} PRODUCTION READINESS REPORT");
8424
- console.error("\u2500".repeat(50));
8396
+ const status = criticalIssues > 0 || seriousIssues > 2 ? "[FAIL] NOT READY TO SHIP" : seriousIssues > 0 ? "[WARN] SHIP WITH CAUTION" : "[OK] READY TO SHIP";
8397
+ console.error("\n" + "-".repeat(50));
8398
+ console.error("PRODUCTION READINESS REPORT");
8399
+ console.error("-".repeat(50));
8425
8400
  console.error(` Score: ${readinessScore}/100`);
8426
8401
  console.error(` Requirements: ${metRequirements}/${totalRequirements} met`);
8427
8402
  console.error(` Critical issues: ${criticalIssues}`);
8428
8403
  console.error(` Serious issues: ${seriousIssues}`);
8429
8404
  console.error("");
8430
8405
  console.error(` ${status}`);
8431
- console.error("\u2500".repeat(50) + "\n");
8406
+ console.error("-".repeat(50) + "\n");
8432
8407
  }
8433
8408
  getAIEnhancementSystemPrompt() {
8434
8409
  return `You are a production readiness engineer reviewing code for deployment.
@@ -8608,6 +8583,7 @@ var SkillReviewAgent = class extends BaseAgent {
8608
8583
  name = "skill-review";
8609
8584
  description = "Applies installed skills from GitHub repositories to code review";
8610
8585
  version = "1.0.0";
8586
+ author = "Trie Agent";
8611
8587
  skills = [];
8612
8588
  loadedSkillContent = /* @__PURE__ */ new Map();
8613
8589
  filteredSkills = /* @__PURE__ */ new Map();
@@ -8815,6 +8791,8 @@ var CustomSkill = class extends BaseAgent {
8815
8791
  name;
8816
8792
  description;
8817
8793
  version;
8794
+ author;
8795
+ authorUrl;
8818
8796
  config;
8819
8797
  constructor(config) {
8820
8798
  super();
@@ -8822,6 +8800,8 @@ var CustomSkill = class extends BaseAgent {
8822
8800
  this.name = config.name;
8823
8801
  this.description = config.description;
8824
8802
  this.version = config.version;
8803
+ this.author = config.author;
8804
+ this.authorUrl = config.authorUrl;
8825
8805
  }
8826
8806
  get priority() {
8827
8807
  return {
@@ -9061,7 +9041,10 @@ var AgentRegistryImpl = class {
9061
9041
  // Skill review agent (applies external skills)
9062
9042
  new SkillReviewAgent()
9063
9043
  ];
9064
- console.error(`Loaded config for ${builtinAgents.length} built-in agents`);
9044
+ const isWorker = typeof process !== "undefined" && (process.env.TRIE_WORKER === "true" || process.env.NODE_ENV === "test");
9045
+ if (!isWorker && !process.env.TRIE_QUIET) {
9046
+ console.error(`Loaded config for ${builtinAgents.length} built-in agents`);
9047
+ }
9065
9048
  for (const agent of builtinAgents) {
9066
9049
  this.agents.set(agent.name, agent);
9067
9050
  }
@@ -9219,4 +9202,4 @@ export {
9219
9202
  CustomSkill,
9220
9203
  getAgentRegistry
9221
9204
  };
9222
- //# sourceMappingURL=chunk-R5HWHP5N.js.map
9205
+ //# sourceMappingURL=chunk-37U65YW7.js.map