@triedotdev/mcp 1.0.49 → 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-KQOMSIVR.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,6 +3667,7 @@ 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
3672
  return context.touchesUserData || context.touchesPayments || context.touchesAuth || context.touchesUI || context.touchesAPI || context.touchesThirdPartyAPI || context.touchesHealthData;
3659
3673
  }
@@ -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,6 +6194,7 @@ 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
+ author = "Trie Agent";
6197
6198
  shouldActivate(_context) {
6198
6199
  return false;
6199
6200
  }
@@ -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;
@@ -7525,67 +7462,67 @@ var MONEYBAGS_QUOTES = [
7525
7462
  "Floating-point for money? That's going to be an expensive lesson."
7526
7463
  ];
7527
7464
  var BASE_COST_BY_SEVERITY = {
7528
- critical: 5e3,
7529
- // Critical bugs found in dev - still expensive to fix properly
7530
- serious: 2e3,
7531
- // Serious issues need careful remediation
7532
- moderate: 500,
7533
- // Moderate issues are quicker fixes
7534
- low: 100
7535
- // 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
7536
7473
  };
7537
7474
  var PRODUCTION_MULTIPLIER = {
7538
- critical: 30,
7539
- // Critical bugs can cause outages, breaches
7540
- serious: 20,
7541
- // Serious bugs cause significant user impact
7542
- moderate: 10,
7543
- // Moderate bugs require hotfixes, user support
7544
- low: 5
7545
- // 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)
7546
7483
  };
7547
7484
  var CATEGORY_MULTIPLIERS = {
7548
- // Security categories - based on breach cost data
7549
- "security": { multiplier: 8, reason: "Security vulnerabilities can lead to data breaches (avg $4.45M)" },
7550
- "authentication": { multiplier: 10, reason: "Auth bypass leads to complete system compromise" },
7551
- "authorization": { multiplier: 8, reason: "Authorization flaws expose sensitive data" },
7552
- "injection": { multiplier: 12, reason: "SQL/Command injection enables full system takeover" },
7553
- "xss": { multiplier: 5, reason: "XSS enables session hijacking and data theft" },
7554
- "secrets": { multiplier: 15, reason: "Exposed secrets require immediate rotation and audit" },
7555
- "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" },
7556
7493
  // Data integrity categories
7557
- "data-loss": { multiplier: 20, reason: "Data loss can be irrecoverable and legally actionable" },
7558
- "data-corruption": { multiplier: 15, reason: "Data corruption requires manual recovery and validation" },
7559
- "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" },
7560
7497
  // Financial categories
7561
- "payment": { multiplier: 25, reason: "Payment bugs can cause direct financial loss or fraud" },
7562
- "billing": { multiplier: 20, reason: "Billing errors require refunds and erode trust" },
7563
- "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" },
7564
7501
  // Reliability categories
7565
- "crash": { multiplier: 8, reason: "Crashes cause downtime (avg $5,600/minute)" },
7566
- "memory-leak": { multiplier: 5, reason: "Memory leaks cause gradual degradation and outages" },
7567
- "deadlock": { multiplier: 10, reason: "Deadlocks require restarts and cause data inconsistency" },
7568
- "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" },
7569
7506
  // User experience
7570
- "accessibility": { multiplier: 3, reason: "Accessibility issues can lead to lawsuits (ADA compliance)" },
7571
- "performance": { multiplier: 2, reason: "Performance issues hurt conversion rates (~7% per 1s delay)" },
7572
- "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" },
7573
7510
  // Code quality
7574
- "bug": { multiplier: 2, reason: "General bugs require developer time and QA cycles" },
7575
- "type-error": { multiplier: 1.5, reason: "Type errors caught early save debugging time" },
7576
- "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" },
7577
7514
  // Default
7578
- "default": { multiplier: 2, reason: "General code issues" }
7515
+ "default": { multiplier: 1, reason: "General code issues" }
7579
7516
  };
7580
7517
  var CONTEXT_MULTIPLIERS = {
7581
- touchesPayments: { multiplier: 5, description: "Payment processing code" },
7582
- touchesAuth: { multiplier: 4, description: "Authentication/authorization code" },
7583
- touchesUserData: { multiplier: 3, description: "User PII handling" },
7584
- touchesHealthData: { multiplier: 6, description: "Health data (HIPAA liability)" },
7585
- touchesDatabase: { multiplier: 2.5, description: "Database operations" },
7586
- touchesAPI: { multiplier: 2, description: "External API integrations" },
7587
- touchesCrypto: { multiplier: 3, description: "Cryptographic operations" },
7588
- 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" }
7589
7526
  };
7590
7527
  var EFFORT_HOURS = {
7591
7528
  trivial: 0.5,
@@ -7596,16 +7533,17 @@ var EFFORT_HOURS = {
7596
7533
  var DEVELOPER_HOURLY_RATE = 150;
7597
7534
  var DEFAULT_USER_COUNT = 250;
7598
7535
  var USER_COUNT_MULTIPLIERS = [
7599
- { threshold: 0, multiplier: 0.1, label: "Pre-launch (0 users)" },
7600
- { 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)" },
7601
7538
  { threshold: 250, multiplier: 1, label: "Early stage (250 users)" },
7602
7539
  // Baseline (default)
7603
- { threshold: 1e3, multiplier: 2, label: "Growing (1K users)" },
7604
- { threshold: 5e3, multiplier: 4, label: "Traction (5K users)" },
7605
- { threshold: 25e3, multiplier: 8, label: "Scale-up (25K users)" },
7606
- { threshold: 1e5, multiplier: 15, label: "Growth (100K users)" },
7607
- { threshold: 5e5, multiplier: 25, label: "Large (500K users)" },
7608
- { 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
7609
7547
  ];
7610
7548
  var PER_USER_COSTS = {
7611
7549
  "data-loss": 5,
@@ -7625,6 +7563,7 @@ var MoneybagAgent = class extends BaseAgent {
7625
7563
  name = "moneybags";
7626
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.";
7627
7565
  version = "1.1.0";
7566
+ author = "Trie Agent";
7628
7567
  bannerShown = false;
7629
7568
  config = {
7630
7569
  userCount: DEFAULT_USER_COUNT,
@@ -7751,7 +7690,7 @@ var MoneybagAgent = class extends BaseAgent {
7751
7690
  contextFactors.push(data.description);
7752
7691
  }
7753
7692
  }
7754
- contextMultiplier = Math.min(contextMultiplier, 10);
7693
+ contextMultiplier = Math.min(contextMultiplier, 2);
7755
7694
  const userScale = this.getUserScaleMultiplier();
7756
7695
  const userScaleMultiplier = userScale.multiplier;
7757
7696
  const userScaleLabel = userScale.label;
@@ -7773,14 +7712,15 @@ var MoneybagAgent = class extends BaseAgent {
7773
7712
  const fixHours = EFFORT_HOURS[effort] || 8;
7774
7713
  const developerRate = this.config.developerRate ?? DEVELOPER_HOURLY_RATE;
7775
7714
  const fixCost = fixHours * developerRate;
7776
- const totalNowCost = Math.round(
7777
- baseCost * categoryMultiplier * contextMultiplier * userScaleMultiplier + fixCost
7778
- );
7779
- const totalProductionCost = Math.round(
7780
- baseCost * productionMultiplier * categoryMultiplier * contextMultiplier * userScaleMultiplier + perUserCost + // Add per-user costs for production impact
7781
- fixCost * 3
7782
- // Production fixes take 3x longer (debugging, deployment, rollback, post-mortem)
7783
- );
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));
7784
7724
  const savings = totalProductionCost - totalNowCost;
7785
7725
  const summary = this.generateCostSummary(
7786
7726
  issue,
@@ -8123,66 +8063,76 @@ var PRODUCTION_QUOTES = [
8123
8063
  "Production is where your code meets reality. Is yours ready?"
8124
8064
  ];
8125
8065
  var PRODUCTION_PATTERNS = {
8126
- // Health & Reliability
8066
+ // Health & Reliability - BACKEND ONLY
8127
8067
  healthEndpoint: {
8128
8068
  pattern: /\/health|healthcheck|health-check|readiness|liveness/i,
8129
8069
  category: "reliability",
8130
8070
  requirement: "Health check endpoint",
8131
- severity: "serious"
8071
+ severity: "moderate",
8072
+ // Downgraded - not critical for all apps
8073
+ backendOnly: true
8132
8074
  },
8133
8075
  gracefulShutdown: {
8134
8076
  pattern: /SIGTERM|SIGINT|process\.on\s*\(\s*['"]SIG/i,
8135
8077
  category: "reliability",
8136
8078
  requirement: "Graceful shutdown handling",
8137
- severity: "moderate"
8079
+ severity: "low",
8080
+ backendOnly: true
8138
8081
  },
8139
- // Scalability
8082
+ // Scalability - BACKEND ONLY
8140
8083
  connectionPooling: {
8141
8084
  pattern: /connectionLimit|pool|poolSize|max_connections|maxConnections/i,
8142
8085
  category: "scalability",
8143
8086
  requirement: "Database connection pooling",
8144
- severity: "serious"
8087
+ severity: "moderate",
8088
+ backendOnly: true
8145
8089
  },
8146
8090
  inMemorySession: {
8147
8091
  pattern: /express-session.*(?!redis|memcached|mongo)|session\s*=\s*\{\}/i,
8148
8092
  category: "scalability",
8149
8093
  requirement: "External session store (not in-memory)",
8150
- severity: "serious"
8094
+ severity: "moderate",
8095
+ backendOnly: true
8151
8096
  },
8152
- // Error Handling
8097
+ // Error Handling - BACKEND ONLY
8153
8098
  globalErrorHandler: {
8154
8099
  pattern: /app\.use\s*\(\s*\(?err|errorHandler|process\.on\s*\(\s*['"]uncaughtException/i,
8155
8100
  category: "reliability",
8156
8101
  requirement: "Global error handler",
8157
- severity: "serious"
8102
+ severity: "moderate",
8103
+ backendOnly: true
8158
8104
  },
8159
- // Security Headers
8105
+ // Security Headers - BACKEND ONLY (frontend relies on hosting platform)
8160
8106
  securityHeaders: {
8161
8107
  pattern: /helmet|contentSecurityPolicy|X-Frame-Options|X-Content-Type|Strict-Transport/i,
8162
8108
  category: "security",
8163
8109
  requirement: "Security headers (CSP, HSTS, etc.)",
8164
- severity: "serious"
8110
+ severity: "moderate",
8111
+ backendOnly: true
8165
8112
  },
8166
- // Rate Limiting
8113
+ // Rate Limiting - BACKEND ONLY
8167
8114
  rateLimiting: {
8168
8115
  pattern: /rateLimit|rate-limit|throttle|express-rate-limit|slowDown/i,
8169
8116
  category: "security",
8170
8117
  requirement: "API rate limiting",
8171
- severity: "moderate"
8118
+ severity: "low",
8119
+ backendOnly: true
8172
8120
  },
8173
- // Logging
8121
+ // Logging - applies to both but less critical for frontend
8174
8122
  structuredLogging: {
8175
8123
  pattern: /pino|winston|bunyan|structured.*log|log.*json/i,
8176
8124
  category: "observability",
8177
8125
  requirement: "Structured logging",
8178
- severity: "moderate"
8126
+ severity: "low",
8127
+ backendOnly: false
8179
8128
  },
8180
- // Monitoring
8129
+ // Monitoring - applies to both
8181
8130
  monitoring: {
8182
8131
  pattern: /prometheus|datadog|newrelic|sentry|bugsnag|opentelemetry|@sentry/i,
8183
8132
  category: "observability",
8184
8133
  requirement: "Error/performance monitoring",
8185
- severity: "moderate"
8134
+ severity: "low",
8135
+ backendOnly: false
8186
8136
  }
8187
8137
  };
8188
8138
  var PRODUCTION_ANTIPATTERNS = [
@@ -8256,6 +8206,7 @@ var ProductionReadyAgent = class extends BaseAgent {
8256
8206
  name = "production-ready";
8257
8207
  description = "Production readiness checker: health endpoints, graceful shutdown, connection pooling, security headers, monitoring, and deployment gates";
8258
8208
  version = "1.0.0";
8209
+ author = "Trie Agent";
8259
8210
  bannerShown = false;
8260
8211
  foundRequirements = /* @__PURE__ */ new Set();
8261
8212
  get priority() {
@@ -8363,7 +8314,12 @@ var ProductionReadyAgent = class extends BaseAgent {
8363
8314
  }
8364
8315
  }
8365
8316
  const combinedContent = allContent.join("\n");
8317
+ const isFrontendOnly = this.detectFrontendOnlyApp(combinedContent, files);
8366
8318
  for (const [key, config] of Object.entries(PRODUCTION_PATTERNS)) {
8319
+ const patternConfig = config;
8320
+ if (isFrontendOnly && patternConfig.backendOnly) {
8321
+ continue;
8322
+ }
8367
8323
  if (!this.foundRequirements.has(key)) {
8368
8324
  if (!config.pattern.test(combinedContent)) {
8369
8325
  this.progress?.found(config.severity, `Missing: ${config.requirement}`);
@@ -8374,7 +8330,8 @@ var ProductionReadyAgent = class extends BaseAgent {
8374
8330
  this.getRequirementFix(key),
8375
8331
  "project",
8376
8332
  void 0,
8377
- 0.8,
8333
+ 0.6,
8334
+ // Lower confidence for missing checks
8378
8335
  void 0,
8379
8336
  false,
8380
8337
  { category: config.category }
@@ -8385,6 +8342,35 @@ var ProductionReadyAgent = class extends BaseAgent {
8385
8342
  this.logReadinessSummary(issues);
8386
8343
  return issues;
8387
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
+ }
8388
8374
  getRequirementFix(key) {
8389
8375
  const fixes = {
8390
8376
  healthEndpoint: 'Add health check endpoint: app.get("/health", (req, res) => res.json({ status: "ok" }))',
@@ -8597,6 +8583,7 @@ var SkillReviewAgent = class extends BaseAgent {
8597
8583
  name = "skill-review";
8598
8584
  description = "Applies installed skills from GitHub repositories to code review";
8599
8585
  version = "1.0.0";
8586
+ author = "Trie Agent";
8600
8587
  skills = [];
8601
8588
  loadedSkillContent = /* @__PURE__ */ new Map();
8602
8589
  filteredSkills = /* @__PURE__ */ new Map();
@@ -8804,6 +8791,8 @@ var CustomSkill = class extends BaseAgent {
8804
8791
  name;
8805
8792
  description;
8806
8793
  version;
8794
+ author;
8795
+ authorUrl;
8807
8796
  config;
8808
8797
  constructor(config) {
8809
8798
  super();
@@ -8811,6 +8800,8 @@ var CustomSkill = class extends BaseAgent {
8811
8800
  this.name = config.name;
8812
8801
  this.description = config.description;
8813
8802
  this.version = config.version;
8803
+ this.author = config.author;
8804
+ this.authorUrl = config.authorUrl;
8814
8805
  }
8815
8806
  get priority() {
8816
8807
  return {
@@ -9050,7 +9041,10 @@ var AgentRegistryImpl = class {
9050
9041
  // Skill review agent (applies external skills)
9051
9042
  new SkillReviewAgent()
9052
9043
  ];
9053
- 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
+ }
9054
9048
  for (const agent of builtinAgents) {
9055
9049
  this.agents.set(agent.name, agent);
9056
9050
  }
@@ -9208,4 +9202,4 @@ export {
9208
9202
  CustomSkill,
9209
9203
  getAgentRegistry
9210
9204
  };
9211
- //# sourceMappingURL=chunk-VZYCZXEQ.js.map
9205
+ //# sourceMappingURL=chunk-37U65YW7.js.map