@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.
- package/dist/{agent-smith-5QOZXLMV.js → agent-smith-RVXIMAL6.js} +2 -2
- package/dist/{agent-smith-runner-ZTDCJJQG.js → agent-smith-runner-3AWGEOZC.js} +2 -2
- package/dist/{chunk-VZYCZXEQ.js → chunk-37U65YW7.js} +244 -250
- package/dist/chunk-37U65YW7.js.map +1 -0
- package/dist/{chunk-KQOMSIVR.js → chunk-3SQK2RKF.js} +5 -1
- package/dist/chunk-3SQK2RKF.js.map +1 -0
- package/dist/{chunk-JDICQHNT.js → chunk-GERAB55E.js} +101 -10
- package/dist/chunk-GERAB55E.js.map +1 -0
- package/dist/cli/main.js +22 -3
- package/dist/cli/main.js.map +1 -1
- package/dist/cli/yolo-daemon.js +30 -18
- package/dist/cli/yolo-daemon.js.map +1 -1
- package/dist/index.js +36 -5
- package/dist/index.js.map +1 -1
- package/dist/workers/agent-worker.js +3 -2
- package/dist/workers/agent-worker.js.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-JDICQHNT.js.map +0 -1
- package/dist/chunk-KQOMSIVR.js.map +0 -1
- package/dist/chunk-VZYCZXEQ.js.map +0 -1
- /package/dist/{agent-smith-5QOZXLMV.js.map → agent-smith-RVXIMAL6.js.map} +0 -0
- /package/dist/{agent-smith-runner-ZTDCJJQG.js.map → agent-smith-runner-3AWGEOZC.js.map} +0 -0
|
@@ -13,7 +13,7 @@ import {
|
|
|
13
13
|
BaseAgent,
|
|
14
14
|
isAIAvailable,
|
|
15
15
|
runAIAnalysis
|
|
16
|
-
} from "./chunk-
|
|
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
|
-
|
|
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.
|
|
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
|
-
|
|
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.
|
|
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
|
-
"
|
|
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.
|
|
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
|
-
"
|
|
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.
|
|
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
|
-
"
|
|
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.
|
|
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
|
-
|
|
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
|
-
"
|
|
4357
|
-
|
|
4358
|
-
"
|
|
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.
|
|
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.
|
|
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)
|
|
4795
|
-
|
|
4796
|
-
|
|
4797
|
-
|
|
4798
|
-
|
|
4799
|
-
|
|
4800
|
-
|
|
4801
|
-
|
|
4802
|
-
|
|
4803
|
-
|
|
4804
|
-
|
|
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
|
|
4856
|
-
const hasDB = /prisma|mongoose|query
|
|
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 >=
|
|
4852
|
+
if (concernCount >= 3) {
|
|
4859
4853
|
issues.push(this.createIssue(
|
|
4860
4854
|
this.generateIssueId(),
|
|
4861
|
-
"
|
|
4855
|
+
"low",
|
|
4856
|
+
// Downgraded - this is more of a suggestion
|
|
4862
4857
|
"Multiple concerns mixed in single file",
|
|
4863
|
-
"
|
|
4858
|
+
"Consider separating UI, API, and data access layers",
|
|
4864
4859
|
file,
|
|
4865
4860
|
void 0,
|
|
4866
|
-
0.
|
|
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: /["']
|
|
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[-_]
|
|
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
|
-
"
|
|
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.
|
|
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 (
|
|
7468
|
-
|
|
7469
|
-
|
|
7470
|
-
|
|
7471
|
-
|
|
7472
|
-
|
|
7473
|
-
|
|
7474
|
-
|
|
7475
|
-
|
|
7476
|
-
|
|
7477
|
-
|
|
7478
|
-
|
|
7479
|
-
|
|
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:
|
|
7529
|
-
// Critical bugs found in dev -
|
|
7530
|
-
serious:
|
|
7531
|
-
// Serious issues need careful remediation
|
|
7532
|
-
moderate:
|
|
7533
|
-
// Moderate issues are quicker fixes
|
|
7534
|
-
low:
|
|
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:
|
|
7539
|
-
// Critical bugs can cause outages, breaches
|
|
7540
|
-
serious:
|
|
7541
|
-
// Serious bugs cause significant user impact
|
|
7542
|
-
moderate:
|
|
7543
|
-
// Moderate bugs require hotfixes, user support
|
|
7544
|
-
low:
|
|
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 -
|
|
7549
|
-
"security": { multiplier:
|
|
7550
|
-
"authentication": { multiplier:
|
|
7551
|
-
"authorization": { multiplier:
|
|
7552
|
-
"injection": { multiplier:
|
|
7553
|
-
"xss": { multiplier: 5, reason: "XSS
|
|
7554
|
-
"secrets": { multiplier:
|
|
7555
|
-
"cryptography": { multiplier:
|
|
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:
|
|
7558
|
-
"data-corruption": { multiplier:
|
|
7559
|
-
"privacy": { multiplier:
|
|
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:
|
|
7562
|
-
"billing": { multiplier:
|
|
7563
|
-
"financial-calculation": { multiplier:
|
|
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:
|
|
7566
|
-
"memory-leak": { multiplier: 5, reason: "Memory leaks cause gradual degradation
|
|
7567
|
-
"deadlock": { multiplier:
|
|
7568
|
-
"race-condition": { multiplier:
|
|
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:
|
|
7571
|
-
"performance": { multiplier: 2, reason: "Performance issues hurt conversion rates
|
|
7572
|
-
"ux": { multiplier: 1
|
|
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:
|
|
7575
|
-
"type-error": { multiplier:
|
|
7576
|
-
"logic-error": { multiplier:
|
|
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:
|
|
7515
|
+
"default": { multiplier: 1, reason: "General code issues" }
|
|
7579
7516
|
};
|
|
7580
7517
|
var CONTEXT_MULTIPLIERS = {
|
|
7581
|
-
touchesPayments: { multiplier:
|
|
7582
|
-
touchesAuth: { multiplier:
|
|
7583
|
-
touchesUserData: { multiplier:
|
|
7584
|
-
touchesHealthData: { multiplier:
|
|
7585
|
-
touchesDatabase: { multiplier:
|
|
7586
|
-
touchesAPI: { multiplier:
|
|
7587
|
-
touchesCrypto: { multiplier:
|
|
7588
|
-
touchesFileSystem: { multiplier:
|
|
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.
|
|
7600
|
-
{ threshold: 50, multiplier: 0.
|
|
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:
|
|
7604
|
-
{ threshold: 5e3, multiplier:
|
|
7605
|
-
{ threshold: 25e3, multiplier:
|
|
7606
|
-
{ threshold: 1e5, multiplier:
|
|
7607
|
-
{ threshold: 5e5, multiplier:
|
|
7608
|
-
{ threshold: 1e6, multiplier:
|
|
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,
|
|
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
|
|
7777
|
-
|
|
7778
|
-
|
|
7779
|
-
const
|
|
7780
|
-
|
|
7781
|
-
|
|
7782
|
-
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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: "
|
|
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.
|
|
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
|
-
|
|
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-
|
|
9205
|
+
//# sourceMappingURL=chunk-37U65YW7.js.map
|