@codebakers/cli 3.5.1 → 3.6.0

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.
@@ -3416,6 +3416,8 @@ Just describe what you want to build! I'll automatically:
3416
3416
  let testsPass = false;
3417
3417
  let typescriptPass = false;
3418
3418
  const testsWritten = [];
3419
+ // v6.1: Code analysis for compliance scoring
3420
+ const codeAnalysis = {};
3419
3421
  // Step 1: Get session token (from memory or state file)
3420
3422
  let sessionToken = this.currentSessionToken;
3421
3423
  if (!sessionToken) {
@@ -3464,6 +3466,74 @@ Just describe what you want to build! I'll automatically:
3464
3466
  catch {
3465
3467
  // Ignore errors
3466
3468
  }
3469
+ // Step 2.5: v6.1 - Analyze code for compliance scoring
3470
+ try {
3471
+ let totalLines = 0;
3472
+ let hasErrorHandling = false;
3473
+ let hasLoadingStates = false;
3474
+ let hasConsoleLog = false;
3475
+ let hasAnyType = false;
3476
+ // Analyze provided files
3477
+ const filesToAnalyze = files.length > 0 ? files : [];
3478
+ // Also scan for recently modified .ts/.tsx files if no files provided
3479
+ if (filesToAnalyze.length === 0) {
3480
+ const srcDir = path.join(cwd, 'src');
3481
+ if (fs.existsSync(srcDir)) {
3482
+ const recentFiles = fs.readdirSync(srcDir, { recursive: true })
3483
+ .filter((f) => {
3484
+ const name = String(f);
3485
+ return (name.endsWith('.ts') || name.endsWith('.tsx')) &&
3486
+ !name.includes('.test.') && !name.includes('.spec.');
3487
+ })
3488
+ .slice(0, 20) // Limit to 20 files for performance
3489
+ .map(f => path.join('src', String(f)));
3490
+ filesToAnalyze.push(...recentFiles);
3491
+ }
3492
+ }
3493
+ for (const file of filesToAnalyze) {
3494
+ try {
3495
+ const filePath = path.isAbsolute(file) ? file : path.join(cwd, file);
3496
+ if (!fs.existsSync(filePath))
3497
+ continue;
3498
+ const content = fs.readFileSync(filePath, 'utf-8');
3499
+ const lines = content.split('\n').length;
3500
+ totalLines += lines;
3501
+ // Check for error handling patterns
3502
+ if (content.includes('try {') || content.includes('catch (') ||
3503
+ content.includes('.catch(') || content.includes('onError') ||
3504
+ content.includes('error:') || content.includes('handleError')) {
3505
+ hasErrorHandling = true;
3506
+ }
3507
+ // Check for loading states
3508
+ if (content.includes('isLoading') || content.includes('loading:') ||
3509
+ content.includes('isPending') || content.includes('Skeleton') ||
3510
+ content.includes('Spinner') || content.includes('Loading')) {
3511
+ hasLoadingStates = true;
3512
+ }
3513
+ // Check for console.log (bad in production)
3514
+ if (content.includes('console.log') || content.includes('console.warn') ||
3515
+ content.includes('console.error')) {
3516
+ hasConsoleLog = true;
3517
+ }
3518
+ // Check for any type (should be avoided)
3519
+ if (content.includes(': any') || content.includes(':any') ||
3520
+ content.includes('as any') || content.includes('<any>')) {
3521
+ hasAnyType = true;
3522
+ }
3523
+ }
3524
+ catch {
3525
+ // Skip files that can't be read
3526
+ }
3527
+ }
3528
+ codeAnalysis.linesOfCode = totalLines;
3529
+ codeAnalysis.hasErrorHandling = hasErrorHandling;
3530
+ codeAnalysis.hasLoadingStates = hasLoadingStates;
3531
+ codeAnalysis.hasConsoleLog = hasConsoleLog;
3532
+ codeAnalysis.hasAnyType = hasAnyType;
3533
+ }
3534
+ catch {
3535
+ // Ignore code analysis errors
3536
+ }
3467
3537
  // Step 3: Run tests locally
3468
3538
  if (testsExist) {
3469
3539
  try {
@@ -3522,6 +3592,7 @@ Just describe what you want to build! I'll automatically:
3522
3592
  testsRun: testsExist,
3523
3593
  testsPassed: testsPass,
3524
3594
  typescriptPassed: typescriptPass,
3595
+ codeAnalysis, // v6.1: Send code analysis for compliance scoring
3525
3596
  }),
3526
3597
  });
3527
3598
  const result = await response.json();
@@ -3558,6 +3629,52 @@ Just describe what you want to build! I'll automatically:
3558
3629
  let responseText = `# ✅ Feature Validation: ${feature}\n\n`;
3559
3630
  responseText += `## Server Validation Result\n\n`;
3560
3631
  responseText += `**Status:** ${result.passed ? '✅ PASSED' : '❌ FAILED'}\n\n`;
3632
+ // v6.1: Show compliance score
3633
+ if (result.compliance) {
3634
+ const score = result.compliance.score || 0;
3635
+ const scoreEmoji = score >= 90 ? '🏆' : score >= 70 ? '👍' : score >= 50 ? '⚠️' : '❌';
3636
+ responseText += `## ${scoreEmoji} Compliance Score: ${score}/100\n\n`;
3637
+ if (result.compliance.patternScores) {
3638
+ responseText += `### Pattern Scores:\n`;
3639
+ responseText += `| Pattern | Score |\n|---------|-------|\n`;
3640
+ for (const [pattern, patternScore] of Object.entries(result.compliance.patternScores)) {
3641
+ const emoji = patternScore >= 80 ? '✅' : patternScore >= 50 ? '⚠️' : '❌';
3642
+ responseText += `| ${pattern} | ${emoji} ${patternScore}/100 |\n`;
3643
+ }
3644
+ responseText += `\n`;
3645
+ }
3646
+ if (result.compliance.deductions && result.compliance.deductions.length > 0) {
3647
+ responseText += `### Deductions:\n`;
3648
+ for (const deduction of result.compliance.deductions) {
3649
+ responseText += `- ❌ **${deduction.rule}**: ${deduction.issue} (-${deduction.points} pts)\n`;
3650
+ }
3651
+ responseText += `\n`;
3652
+ }
3653
+ }
3654
+ // v6.1: Show test quality metrics
3655
+ if (result.testQuality) {
3656
+ const tq = result.testQuality;
3657
+ responseText += `## 🧪 Test Quality Score: ${tq.overallScore}/100\n\n`;
3658
+ responseText += `| Metric | Status |\n|--------|--------|\n`;
3659
+ responseText += `| Coverage | ${tq.coverage || 0}% |\n`;
3660
+ responseText += `| Happy Path Tests | ${tq.hasHappyPath ? '✅' : '❌'} |\n`;
3661
+ responseText += `| Error Case Tests | ${tq.hasErrorCases ? '✅' : '❌'} |\n`;
3662
+ responseText += `| Boundary Cases | ${tq.hasBoundaryCases ? '✅' : '❌'} |\n\n`;
3663
+ if (tq.missingTests && tq.missingTests.length > 0) {
3664
+ responseText += `### Missing Tests:\n`;
3665
+ for (const missing of tq.missingTests) {
3666
+ responseText += `- ⚠️ ${missing}\n`;
3667
+ }
3668
+ responseText += `\n`;
3669
+ }
3670
+ if (tq.recommendations && tq.recommendations.length > 0) {
3671
+ responseText += `### Recommendations:\n`;
3672
+ for (const rec of tq.recommendations) {
3673
+ responseText += `- 💡 ${rec}\n`;
3674
+ }
3675
+ responseText += `\n`;
3676
+ }
3677
+ }
3561
3678
  if (result.issues && result.issues.length > 0) {
3562
3679
  responseText += `### Issues:\n\n`;
3563
3680
  for (const issue of result.issues) {
@@ -3572,7 +3689,10 @@ Just describe what you want to build! I'll automatically:
3572
3689
  responseText += `| TypeScript compiles | ${typescriptPass ? '✅ PASS' : '❌ FAIL'} |\n\n`;
3573
3690
  if (result.passed) {
3574
3691
  responseText += `## ✅ Feature is COMPLETE\n\n`;
3575
- responseText += `Server has recorded this completion. You may now mark this feature as done.\n`;
3692
+ const completionMsg = result.compliance && result.compliance.score >= 90
3693
+ ? 'Excellent work! High compliance score achieved.'
3694
+ : 'Server has recorded this completion. You may now mark this feature as done.';
3695
+ responseText += `${completionMsg}\n`;
3576
3696
  }
3577
3697
  else {
3578
3698
  responseText += `## ❌ Feature is NOT COMPLETE\n\n`;
@@ -3640,11 +3760,92 @@ Just describe what you want to build! I'll automatically:
3640
3760
  // Generate project hash for context
3641
3761
  let projectHash;
3642
3762
  let projectName;
3763
+ let detectedStack = {};
3643
3764
  try {
3644
3765
  const pkgPath = path.join(cwd, 'package.json');
3645
3766
  if (fs.existsSync(pkgPath)) {
3646
3767
  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
3647
3768
  projectName = pkg.name || path.basename(cwd);
3769
+ // v6.1: Extract detected stack from dependencies for conflict detection
3770
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
3771
+ const depNames = Object.keys(allDeps);
3772
+ // Detect framework
3773
+ if (depNames.includes('next'))
3774
+ detectedStack.framework = 'nextjs';
3775
+ else if (depNames.includes('remix'))
3776
+ detectedStack.framework = 'remix';
3777
+ else if (depNames.includes('gatsby'))
3778
+ detectedStack.framework = 'gatsby';
3779
+ else if (depNames.includes('react'))
3780
+ detectedStack.framework = 'react';
3781
+ else if (depNames.includes('vue'))
3782
+ detectedStack.framework = 'vue';
3783
+ // Detect ORM/database
3784
+ const orms = [];
3785
+ if (depNames.includes('drizzle-orm'))
3786
+ orms.push('drizzle');
3787
+ if (depNames.includes('prisma') || depNames.includes('@prisma/client'))
3788
+ orms.push('prisma');
3789
+ if (depNames.includes('typeorm'))
3790
+ orms.push('typeorm');
3791
+ if (depNames.includes('mongoose'))
3792
+ orms.push('mongoose');
3793
+ if (depNames.includes('sequelize'))
3794
+ orms.push('sequelize');
3795
+ if (orms.length > 0)
3796
+ detectedStack.orm = orms.length === 1 ? orms[0] : orms;
3797
+ // Detect state management
3798
+ const stateLibs = [];
3799
+ if (depNames.includes('@reduxjs/toolkit') || depNames.includes('redux'))
3800
+ stateLibs.push('redux');
3801
+ if (depNames.includes('zustand'))
3802
+ stateLibs.push('zustand');
3803
+ if (depNames.includes('jotai'))
3804
+ stateLibs.push('jotai');
3805
+ if (depNames.includes('recoil'))
3806
+ stateLibs.push('recoil');
3807
+ if (depNames.includes('mobx'))
3808
+ stateLibs.push('mobx');
3809
+ if (stateLibs.length > 0)
3810
+ detectedStack.stateManagement = stateLibs.length === 1 ? stateLibs[0] : stateLibs;
3811
+ // Detect styling
3812
+ const styleLibs = [];
3813
+ if (depNames.includes('tailwindcss'))
3814
+ styleLibs.push('tailwind');
3815
+ if (depNames.includes('@emotion/react') || depNames.includes('@emotion/styled'))
3816
+ styleLibs.push('emotion');
3817
+ if (depNames.includes('styled-components'))
3818
+ styleLibs.push('styled-components');
3819
+ if (depNames.includes('@mui/material'))
3820
+ styleLibs.push('mui');
3821
+ if (depNames.includes('@chakra-ui/react'))
3822
+ styleLibs.push('chakra');
3823
+ if (styleLibs.length > 0)
3824
+ detectedStack.styling = styleLibs.length === 1 ? styleLibs[0] : styleLibs;
3825
+ // Detect form libraries
3826
+ const formLibs = [];
3827
+ if (depNames.includes('react-hook-form'))
3828
+ formLibs.push('react-hook-form');
3829
+ if (depNames.includes('formik'))
3830
+ formLibs.push('formik');
3831
+ if (depNames.includes('react-final-form'))
3832
+ formLibs.push('react-final-form');
3833
+ if (formLibs.length > 0)
3834
+ detectedStack.forms = formLibs.length === 1 ? formLibs[0] : formLibs;
3835
+ // Detect auth
3836
+ if (depNames.includes('@supabase/supabase-js'))
3837
+ detectedStack.auth = 'supabase';
3838
+ else if (depNames.includes('next-auth') || depNames.includes('@auth/core'))
3839
+ detectedStack.auth = 'next-auth';
3840
+ else if (depNames.includes('@clerk/nextjs'))
3841
+ detectedStack.auth = 'clerk';
3842
+ else if (depNames.includes('firebase'))
3843
+ detectedStack.auth = 'firebase';
3844
+ // Detect payments
3845
+ if (depNames.includes('stripe'))
3846
+ detectedStack.payments = 'stripe';
3847
+ else if (depNames.includes('@paypal/react-paypal-js'))
3848
+ detectedStack.payments = 'paypal';
3648
3849
  }
3649
3850
  else {
3650
3851
  projectName = path.basename(cwd);
@@ -3669,6 +3870,7 @@ Just describe what you want to build! I'll automatically:
3669
3870
  keywords,
3670
3871
  projectHash,
3671
3872
  projectName,
3873
+ detectedStack, // v6.1: Send stack for conflict detection
3672
3874
  }),
3673
3875
  });
3674
3876
  if (!response.ok) {
@@ -3701,6 +3903,63 @@ Just describe what you want to build! I'll automatically:
3701
3903
  let responseText = `# 🔍 Pattern Discovery: ${task}\n\n`;
3702
3904
  responseText += `## ⛔ SERVER-ENFORCED SESSION ACTIVE\n\n`;
3703
3905
  responseText += `**Session Token:** \`${result.sessionToken}\`\n\n`;
3906
+ // v6.1: Show detected conflicts (high priority warning)
3907
+ if (result.detectedConflicts && result.detectedConflicts.length > 0) {
3908
+ responseText += `---\n\n`;
3909
+ responseText += `## ⚠️ ARCHITECTURE CONFLICTS DETECTED\n\n`;
3910
+ responseText += `The following conflicts were found in your project:\n\n`;
3911
+ for (const conflict of result.detectedConflicts) {
3912
+ responseText += `### ${conflict.type}\n`;
3913
+ responseText += `**Conflicting:** ${conflict.items.join(' + ')}\n`;
3914
+ responseText += `**Recommendation:** ${conflict.recommendation}\n`;
3915
+ responseText += `**Reason:** ${conflict.reason}\n\n`;
3916
+ }
3917
+ responseText += `**Please resolve these conflicts before proceeding.**\n\n`;
3918
+ }
3919
+ // v6.1: Show team profile settings if configured
3920
+ if (result.teamProfile) {
3921
+ responseText += `---\n\n`;
3922
+ responseText += `## 🏢 TEAM PROFILE\n\n`;
3923
+ responseText += `| Setting | Value |\n|---------|-------|\n`;
3924
+ responseText += `| Industry | ${result.teamProfile.industryProfile || 'general'} |\n`;
3925
+ responseText += `| Strictness | ${result.teamProfile.strictnessLevel || 'standard'} |\n`;
3926
+ if (result.teamProfile.requireHipaa)
3927
+ responseText += `| HIPAA | ✅ Required |\n`;
3928
+ if (result.teamProfile.requirePci)
3929
+ responseText += `| PCI-DSS | ✅ Required |\n`;
3930
+ if (result.teamProfile.requireSoc2)
3931
+ responseText += `| SOC2 | ✅ Required |\n`;
3932
+ if (result.teamProfile.requireGdpr)
3933
+ responseText += `| GDPR | ✅ Required |\n`;
3934
+ responseText += `\n`;
3935
+ }
3936
+ // v6.1: Show project memory if available
3937
+ if (result.projectMemory) {
3938
+ responseText += `---\n\n`;
3939
+ responseText += `## 🧠 PROJECT MEMORY\n\n`;
3940
+ responseText += `Server has remembered your project's architectural decisions:\n\n`;
3941
+ const memory = result.projectMemory;
3942
+ if (memory.stackDecisions) {
3943
+ const stack = typeof memory.stackDecisions === 'string'
3944
+ ? JSON.parse(memory.stackDecisions)
3945
+ : memory.stackDecisions;
3946
+ if (Object.keys(stack).length > 0) {
3947
+ responseText += `### Stack Decisions\n`;
3948
+ responseText += `| Category | Choice |\n|----------|--------|\n`;
3949
+ for (const [key, value] of Object.entries(stack)) {
3950
+ responseText += `| ${key} | ${value} |\n`;
3951
+ }
3952
+ responseText += `\n`;
3953
+ }
3954
+ }
3955
+ if (memory.namingConventions) {
3956
+ responseText += `### Naming Conventions\n\`\`\`\n${memory.namingConventions}\n\`\`\`\n\n`;
3957
+ }
3958
+ if (memory.projectRules) {
3959
+ responseText += `### Project Rules\n${memory.projectRules}\n\n`;
3960
+ }
3961
+ responseText += `**Follow these established patterns for consistency.**\n\n`;
3962
+ }
3704
3963
  responseText += `---\n\n`;
3705
3964
  // Section 1: Patterns from server
3706
3965
  if (result.patterns && result.patterns.length > 0) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebakers/cli",
3
- "version": "3.5.1",
3
+ "version": "3.6.0",
4
4
  "description": "CodeBakers CLI - Production patterns for AI-assisted development",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
package/src/mcp/server.ts CHANGED
@@ -3853,6 +3853,16 @@ Just describe what you want to build! I'll automatically:
3853
3853
  let typescriptPass = false;
3854
3854
  const testsWritten: string[] = [];
3855
3855
 
3856
+ // v6.1: Code analysis for compliance scoring
3857
+ const codeAnalysis: {
3858
+ hasErrorHandling?: boolean;
3859
+ hasLoadingStates?: boolean;
3860
+ hasTypeAnnotations?: boolean;
3861
+ hasConsoleLog?: boolean;
3862
+ hasAnyType?: boolean;
3863
+ linesOfCode?: number;
3864
+ } = {};
3865
+
3856
3866
  // Step 1: Get session token (from memory or state file)
3857
3867
  let sessionToken = this.currentSessionToken;
3858
3868
  if (!sessionToken) {
@@ -3903,6 +3913,81 @@ Just describe what you want to build! I'll automatically:
3903
3913
  // Ignore errors
3904
3914
  }
3905
3915
 
3916
+ // Step 2.5: v6.1 - Analyze code for compliance scoring
3917
+ try {
3918
+ let totalLines = 0;
3919
+ let hasErrorHandling = false;
3920
+ let hasLoadingStates = false;
3921
+ let hasConsoleLog = false;
3922
+ let hasAnyType = false;
3923
+
3924
+ // Analyze provided files
3925
+ const filesToAnalyze = files.length > 0 ? files : [];
3926
+
3927
+ // Also scan for recently modified .ts/.tsx files if no files provided
3928
+ if (filesToAnalyze.length === 0) {
3929
+ const srcDir = path.join(cwd, 'src');
3930
+ if (fs.existsSync(srcDir)) {
3931
+ const recentFiles = fs.readdirSync(srcDir, { recursive: true })
3932
+ .filter((f: string | Buffer) => {
3933
+ const name = String(f);
3934
+ return (name.endsWith('.ts') || name.endsWith('.tsx')) &&
3935
+ !name.includes('.test.') && !name.includes('.spec.');
3936
+ })
3937
+ .slice(0, 20) // Limit to 20 files for performance
3938
+ .map(f => path.join('src', String(f)));
3939
+ filesToAnalyze.push(...recentFiles);
3940
+ }
3941
+ }
3942
+
3943
+ for (const file of filesToAnalyze) {
3944
+ try {
3945
+ const filePath = path.isAbsolute(file) ? file : path.join(cwd, file);
3946
+ if (!fs.existsSync(filePath)) continue;
3947
+
3948
+ const content = fs.readFileSync(filePath, 'utf-8');
3949
+ const lines = content.split('\n').length;
3950
+ totalLines += lines;
3951
+
3952
+ // Check for error handling patterns
3953
+ if (content.includes('try {') || content.includes('catch (') ||
3954
+ content.includes('.catch(') || content.includes('onError') ||
3955
+ content.includes('error:') || content.includes('handleError')) {
3956
+ hasErrorHandling = true;
3957
+ }
3958
+
3959
+ // Check for loading states
3960
+ if (content.includes('isLoading') || content.includes('loading:') ||
3961
+ content.includes('isPending') || content.includes('Skeleton') ||
3962
+ content.includes('Spinner') || content.includes('Loading')) {
3963
+ hasLoadingStates = true;
3964
+ }
3965
+
3966
+ // Check for console.log (bad in production)
3967
+ if (content.includes('console.log') || content.includes('console.warn') ||
3968
+ content.includes('console.error')) {
3969
+ hasConsoleLog = true;
3970
+ }
3971
+
3972
+ // Check for any type (should be avoided)
3973
+ if (content.includes(': any') || content.includes(':any') ||
3974
+ content.includes('as any') || content.includes('<any>')) {
3975
+ hasAnyType = true;
3976
+ }
3977
+ } catch {
3978
+ // Skip files that can't be read
3979
+ }
3980
+ }
3981
+
3982
+ codeAnalysis.linesOfCode = totalLines;
3983
+ codeAnalysis.hasErrorHandling = hasErrorHandling;
3984
+ codeAnalysis.hasLoadingStates = hasLoadingStates;
3985
+ codeAnalysis.hasConsoleLog = hasConsoleLog;
3986
+ codeAnalysis.hasAnyType = hasAnyType;
3987
+ } catch {
3988
+ // Ignore code analysis errors
3989
+ }
3990
+
3906
3991
  // Step 3: Run tests locally
3907
3992
  if (testsExist) {
3908
3993
  try {
@@ -3959,6 +4044,7 @@ Just describe what you want to build! I'll automatically:
3959
4044
  testsRun: testsExist,
3960
4045
  testsPassed: testsPass,
3961
4046
  typescriptPassed: typescriptPass,
4047
+ codeAnalysis, // v6.1: Send code analysis for compliance scoring
3962
4048
  }),
3963
4049
  });
3964
4050
 
@@ -4001,6 +4087,58 @@ Just describe what you want to build! I'll automatically:
4001
4087
  responseText += `## Server Validation Result\n\n`;
4002
4088
  responseText += `**Status:** ${result.passed ? '✅ PASSED' : '❌ FAILED'}\n\n`;
4003
4089
 
4090
+ // v6.1: Show compliance score
4091
+ if (result.compliance) {
4092
+ const score = result.compliance.score || 0;
4093
+ const scoreEmoji = score >= 90 ? '🏆' : score >= 70 ? '👍' : score >= 50 ? '⚠️' : '❌';
4094
+ responseText += `## ${scoreEmoji} Compliance Score: ${score}/100\n\n`;
4095
+
4096
+ if (result.compliance.patternScores) {
4097
+ responseText += `### Pattern Scores:\n`;
4098
+ responseText += `| Pattern | Score |\n|---------|-------|\n`;
4099
+ for (const [pattern, patternScore] of Object.entries(result.compliance.patternScores)) {
4100
+ const emoji = (patternScore as number) >= 80 ? '✅' : (patternScore as number) >= 50 ? '⚠️' : '❌';
4101
+ responseText += `| ${pattern} | ${emoji} ${patternScore}/100 |\n`;
4102
+ }
4103
+ responseText += `\n`;
4104
+ }
4105
+
4106
+ if (result.compliance.deductions && result.compliance.deductions.length > 0) {
4107
+ responseText += `### Deductions:\n`;
4108
+ for (const deduction of result.compliance.deductions) {
4109
+ responseText += `- ❌ **${deduction.rule}**: ${deduction.issue} (-${deduction.points} pts)\n`;
4110
+ }
4111
+ responseText += `\n`;
4112
+ }
4113
+ }
4114
+
4115
+ // v6.1: Show test quality metrics
4116
+ if (result.testQuality) {
4117
+ const tq = result.testQuality;
4118
+ responseText += `## 🧪 Test Quality Score: ${tq.overallScore}/100\n\n`;
4119
+ responseText += `| Metric | Status |\n|--------|--------|\n`;
4120
+ responseText += `| Coverage | ${tq.coverage || 0}% |\n`;
4121
+ responseText += `| Happy Path Tests | ${tq.hasHappyPath ? '✅' : '❌'} |\n`;
4122
+ responseText += `| Error Case Tests | ${tq.hasErrorCases ? '✅' : '❌'} |\n`;
4123
+ responseText += `| Boundary Cases | ${tq.hasBoundaryCases ? '✅' : '❌'} |\n\n`;
4124
+
4125
+ if (tq.missingTests && tq.missingTests.length > 0) {
4126
+ responseText += `### Missing Tests:\n`;
4127
+ for (const missing of tq.missingTests) {
4128
+ responseText += `- ⚠️ ${missing}\n`;
4129
+ }
4130
+ responseText += `\n`;
4131
+ }
4132
+
4133
+ if (tq.recommendations && tq.recommendations.length > 0) {
4134
+ responseText += `### Recommendations:\n`;
4135
+ for (const rec of tq.recommendations) {
4136
+ responseText += `- 💡 ${rec}\n`;
4137
+ }
4138
+ responseText += `\n`;
4139
+ }
4140
+ }
4141
+
4004
4142
  if (result.issues && result.issues.length > 0) {
4005
4143
  responseText += `### Issues:\n\n`;
4006
4144
  for (const issue of result.issues) {
@@ -4017,7 +4155,10 @@ Just describe what you want to build! I'll automatically:
4017
4155
 
4018
4156
  if (result.passed) {
4019
4157
  responseText += `## ✅ Feature is COMPLETE\n\n`;
4020
- responseText += `Server has recorded this completion. You may now mark this feature as done.\n`;
4158
+ const completionMsg = result.compliance && result.compliance.score >= 90
4159
+ ? 'Excellent work! High compliance score achieved.'
4160
+ : 'Server has recorded this completion. You may now mark this feature as done.';
4161
+ responseText += `${completionMsg}\n`;
4021
4162
  } else {
4022
4163
  responseText += `## ❌ Feature is NOT COMPLETE\n\n`;
4023
4164
  responseText += `**${result.nextSteps || 'Fix the issues above and try again.'}**\n`;
@@ -4088,11 +4229,68 @@ Just describe what you want to build! I'll automatically:
4088
4229
  // Generate project hash for context
4089
4230
  let projectHash: string | undefined;
4090
4231
  let projectName: string | undefined;
4232
+ let detectedStack: Record<string, string | string[]> = {};
4233
+
4091
4234
  try {
4092
4235
  const pkgPath = path.join(cwd, 'package.json');
4093
4236
  if (fs.existsSync(pkgPath)) {
4094
4237
  const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
4095
4238
  projectName = pkg.name || path.basename(cwd);
4239
+
4240
+ // v6.1: Extract detected stack from dependencies for conflict detection
4241
+ const allDeps = { ...pkg.dependencies, ...pkg.devDependencies };
4242
+ const depNames = Object.keys(allDeps);
4243
+
4244
+ // Detect framework
4245
+ if (depNames.includes('next')) detectedStack.framework = 'nextjs';
4246
+ else if (depNames.includes('remix')) detectedStack.framework = 'remix';
4247
+ else if (depNames.includes('gatsby')) detectedStack.framework = 'gatsby';
4248
+ else if (depNames.includes('react')) detectedStack.framework = 'react';
4249
+ else if (depNames.includes('vue')) detectedStack.framework = 'vue';
4250
+
4251
+ // Detect ORM/database
4252
+ const orms: string[] = [];
4253
+ if (depNames.includes('drizzle-orm')) orms.push('drizzle');
4254
+ if (depNames.includes('prisma') || depNames.includes('@prisma/client')) orms.push('prisma');
4255
+ if (depNames.includes('typeorm')) orms.push('typeorm');
4256
+ if (depNames.includes('mongoose')) orms.push('mongoose');
4257
+ if (depNames.includes('sequelize')) orms.push('sequelize');
4258
+ if (orms.length > 0) detectedStack.orm = orms.length === 1 ? orms[0] : orms;
4259
+
4260
+ // Detect state management
4261
+ const stateLibs: string[] = [];
4262
+ if (depNames.includes('@reduxjs/toolkit') || depNames.includes('redux')) stateLibs.push('redux');
4263
+ if (depNames.includes('zustand')) stateLibs.push('zustand');
4264
+ if (depNames.includes('jotai')) stateLibs.push('jotai');
4265
+ if (depNames.includes('recoil')) stateLibs.push('recoil');
4266
+ if (depNames.includes('mobx')) stateLibs.push('mobx');
4267
+ if (stateLibs.length > 0) detectedStack.stateManagement = stateLibs.length === 1 ? stateLibs[0] : stateLibs;
4268
+
4269
+ // Detect styling
4270
+ const styleLibs: string[] = [];
4271
+ if (depNames.includes('tailwindcss')) styleLibs.push('tailwind');
4272
+ if (depNames.includes('@emotion/react') || depNames.includes('@emotion/styled')) styleLibs.push('emotion');
4273
+ if (depNames.includes('styled-components')) styleLibs.push('styled-components');
4274
+ if (depNames.includes('@mui/material')) styleLibs.push('mui');
4275
+ if (depNames.includes('@chakra-ui/react')) styleLibs.push('chakra');
4276
+ if (styleLibs.length > 0) detectedStack.styling = styleLibs.length === 1 ? styleLibs[0] : styleLibs;
4277
+
4278
+ // Detect form libraries
4279
+ const formLibs: string[] = [];
4280
+ if (depNames.includes('react-hook-form')) formLibs.push('react-hook-form');
4281
+ if (depNames.includes('formik')) formLibs.push('formik');
4282
+ if (depNames.includes('react-final-form')) formLibs.push('react-final-form');
4283
+ if (formLibs.length > 0) detectedStack.forms = formLibs.length === 1 ? formLibs[0] : formLibs;
4284
+
4285
+ // Detect auth
4286
+ if (depNames.includes('@supabase/supabase-js')) detectedStack.auth = 'supabase';
4287
+ else if (depNames.includes('next-auth') || depNames.includes('@auth/core')) detectedStack.auth = 'next-auth';
4288
+ else if (depNames.includes('@clerk/nextjs')) detectedStack.auth = 'clerk';
4289
+ else if (depNames.includes('firebase')) detectedStack.auth = 'firebase';
4290
+
4291
+ // Detect payments
4292
+ if (depNames.includes('stripe')) detectedStack.payments = 'stripe';
4293
+ else if (depNames.includes('@paypal/react-paypal-js')) detectedStack.payments = 'paypal';
4096
4294
  } else {
4097
4295
  projectName = path.basename(cwd);
4098
4296
  }
@@ -4116,6 +4314,7 @@ Just describe what you want to build! I'll automatically:
4116
4314
  keywords,
4117
4315
  projectHash,
4118
4316
  projectName,
4317
+ detectedStack, // v6.1: Send stack for conflict detection
4119
4318
  }),
4120
4319
  });
4121
4320
 
@@ -4152,6 +4351,67 @@ Just describe what you want to build! I'll automatically:
4152
4351
  let responseText = `# 🔍 Pattern Discovery: ${task}\n\n`;
4153
4352
  responseText += `## ⛔ SERVER-ENFORCED SESSION ACTIVE\n\n`;
4154
4353
  responseText += `**Session Token:** \`${result.sessionToken}\`\n\n`;
4354
+
4355
+ // v6.1: Show detected conflicts (high priority warning)
4356
+ if (result.detectedConflicts && result.detectedConflicts.length > 0) {
4357
+ responseText += `---\n\n`;
4358
+ responseText += `## ⚠️ ARCHITECTURE CONFLICTS DETECTED\n\n`;
4359
+ responseText += `The following conflicts were found in your project:\n\n`;
4360
+ for (const conflict of result.detectedConflicts) {
4361
+ responseText += `### ${conflict.type}\n`;
4362
+ responseText += `**Conflicting:** ${conflict.items.join(' + ')}\n`;
4363
+ responseText += `**Recommendation:** ${conflict.recommendation}\n`;
4364
+ responseText += `**Reason:** ${conflict.reason}\n\n`;
4365
+ }
4366
+ responseText += `**Please resolve these conflicts before proceeding.**\n\n`;
4367
+ }
4368
+
4369
+ // v6.1: Show team profile settings if configured
4370
+ if (result.teamProfile) {
4371
+ responseText += `---\n\n`;
4372
+ responseText += `## 🏢 TEAM PROFILE\n\n`;
4373
+ responseText += `| Setting | Value |\n|---------|-------|\n`;
4374
+ responseText += `| Industry | ${result.teamProfile.industryProfile || 'general'} |\n`;
4375
+ responseText += `| Strictness | ${result.teamProfile.strictnessLevel || 'standard'} |\n`;
4376
+ if (result.teamProfile.requireHipaa) responseText += `| HIPAA | ✅ Required |\n`;
4377
+ if (result.teamProfile.requirePci) responseText += `| PCI-DSS | ✅ Required |\n`;
4378
+ if (result.teamProfile.requireSoc2) responseText += `| SOC2 | ✅ Required |\n`;
4379
+ if (result.teamProfile.requireGdpr) responseText += `| GDPR | ✅ Required |\n`;
4380
+ responseText += `\n`;
4381
+ }
4382
+
4383
+ // v6.1: Show project memory if available
4384
+ if (result.projectMemory) {
4385
+ responseText += `---\n\n`;
4386
+ responseText += `## 🧠 PROJECT MEMORY\n\n`;
4387
+ responseText += `Server has remembered your project's architectural decisions:\n\n`;
4388
+
4389
+ const memory = result.projectMemory;
4390
+ if (memory.stackDecisions) {
4391
+ const stack = typeof memory.stackDecisions === 'string'
4392
+ ? JSON.parse(memory.stackDecisions)
4393
+ : memory.stackDecisions;
4394
+ if (Object.keys(stack).length > 0) {
4395
+ responseText += `### Stack Decisions\n`;
4396
+ responseText += `| Category | Choice |\n|----------|--------|\n`;
4397
+ for (const [key, value] of Object.entries(stack)) {
4398
+ responseText += `| ${key} | ${value} |\n`;
4399
+ }
4400
+ responseText += `\n`;
4401
+ }
4402
+ }
4403
+
4404
+ if (memory.namingConventions) {
4405
+ responseText += `### Naming Conventions\n\`\`\`\n${memory.namingConventions}\n\`\`\`\n\n`;
4406
+ }
4407
+
4408
+ if (memory.projectRules) {
4409
+ responseText += `### Project Rules\n${memory.projectRules}\n\n`;
4410
+ }
4411
+
4412
+ responseText += `**Follow these established patterns for consistency.**\n\n`;
4413
+ }
4414
+
4155
4415
  responseText += `---\n\n`;
4156
4416
 
4157
4417
  // Section 1: Patterns from server