@codebakers/cli 3.9.40 → 3.9.41

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.
@@ -893,6 +893,27 @@ async function validateCode() {
893
893
  log(CYAN, 'Fix these issues and try again.');
894
894
  log(YELLOW, 'To bypass (not recommended): git commit --no-verify\\n');
895
895
 
896
+ // Write violations to file for AI to read
897
+ const cbDir = path.join(cwd, '.codebakers');
898
+ if (!fs.existsSync(cbDir)) {
899
+ fs.mkdirSync(cbDir, { recursive: true });
900
+ }
901
+ fs.writeFileSync(
902
+ path.join(cbDir, 'violations.json'),
903
+ JSON.stringify({
904
+ timestamp: new Date().toISOString(),
905
+ count: violations.length,
906
+ violations: violations.map(v => ({
907
+ file: v.file,
908
+ check: v.check,
909
+ category: v.category,
910
+ message: v.message
911
+ }))
912
+ }, null, 2)
913
+ );
914
+ log(DIM, '📝 Violations saved to .codebakers/violations.json');
915
+ log(DIM, '💡 Ask AI to run heal_violations() to auto-fix\\n');
916
+
896
917
  return { valid: false, violations };
897
918
  }
898
919
 
@@ -921,6 +942,12 @@ async function validateCode() {
921
942
  log(GREEN, '✅ All pre-commit checks passed!');
922
943
  log(GREEN, '================================\\n');
923
944
 
945
+ // Clear violations file on success
946
+ const violationsPath = path.join(cwd, '.codebakers', 'violations.json');
947
+ if (fs.existsSync(violationsPath)) {
948
+ fs.unlinkSync(violationsPath);
949
+ }
950
+
924
951
  return { valid: true };
925
952
  }
926
953
 
@@ -62,6 +62,28 @@ class CodeBakersServer {
62
62
  lastUpdateCheck = 0;
63
63
  updateCheckInterval = 60 * 60 * 1000; // Check every hour
64
64
  currentSessionToken = null; // v6.19: Server-side enforcement session
65
+ // Check for pre-commit violations
66
+ checkForViolations() {
67
+ const cwd = process.cwd();
68
+ const violationsPath = path.join(cwd, '.codebakers', 'violations.json');
69
+ if (!fs.existsSync(violationsPath)) {
70
+ return { hasViolations: false, violations: null, message: null };
71
+ }
72
+ try {
73
+ const data = JSON.parse(fs.readFileSync(violationsPath, 'utf-8'));
74
+ if (data.violations && data.violations.length > 0) {
75
+ return {
76
+ hasViolations: true,
77
+ violations: data.violations,
78
+ message: `⚠️ ${data.count} pre-commit violation(s) found! Call heal_violations() to auto-fix.`
79
+ };
80
+ }
81
+ }
82
+ catch {
83
+ // Ignore parse errors
84
+ }
85
+ return { hasViolations: false, violations: null, message: null };
86
+ }
65
87
  constructor() {
66
88
  this.apiKey = (0, config_js_1.getApiKey)();
67
89
  this.apiUrl = (0, config_js_1.getApiUrl)();
@@ -1527,6 +1549,20 @@ class CodeBakersServer {
1527
1549
  },
1528
1550
  },
1529
1551
  },
1552
+ // Pre-commit violation healing tool
1553
+ {
1554
+ name: 'heal_violations',
1555
+ description: 'Auto-fix pre-commit hook violations. Call this when you see a violation warning in tool responses. Reads .codebakers/violations.json and provides fixes using CodeBakers patterns. After fixing, clears the violations file.',
1556
+ inputSchema: {
1557
+ type: 'object',
1558
+ properties: {
1559
+ autoFix: {
1560
+ type: 'boolean',
1561
+ description: 'Automatically apply fixes (default: true). Set to false to just see the issues.',
1562
+ },
1563
+ },
1564
+ },
1565
+ },
1530
1566
  // Engineering workflow tools
1531
1567
  ...engineering_tools_js_1.ENGINEERING_TOOLS,
1532
1568
  ],
@@ -1665,6 +1701,8 @@ class CodeBakersServer {
1665
1701
  return this.handleResumeSession(args);
1666
1702
  case 'setup_services':
1667
1703
  return this.handleSetupServices(args);
1704
+ case 'heal_violations':
1705
+ return this.handleHealViolations(args);
1668
1706
  // Engineering workflow tools
1669
1707
  case 'engineering_start':
1670
1708
  case 'engineering_scope':
@@ -3914,6 +3952,106 @@ If you want AI features and prefer Claude over GPT (or want both as fallback).`,
3914
3952
  }],
3915
3953
  };
3916
3954
  }
3955
+ handleHealViolations(args) {
3956
+ const { autoFix = true } = args;
3957
+ const cwd = process.cwd();
3958
+ const violationsPath = path.join(cwd, '.codebakers', 'violations.json');
3959
+ // Check if violations file exists
3960
+ if (!fs.existsSync(violationsPath)) {
3961
+ return {
3962
+ content: [{
3963
+ type: 'text',
3964
+ text: `✅ **No violations found!**\n\nThe \`.codebakers/violations.json\` file doesn't exist, which means:\n- No pre-commit violations have been detected\n- Or they were already fixed\n\nYou're good to commit!`,
3965
+ }],
3966
+ };
3967
+ }
3968
+ // Read violations
3969
+ let data;
3970
+ try {
3971
+ data = JSON.parse(fs.readFileSync(violationsPath, 'utf-8'));
3972
+ }
3973
+ catch {
3974
+ return {
3975
+ content: [{
3976
+ type: 'text',
3977
+ text: `⚠️ **Could not parse violations file**\n\nThe violations.json file exists but couldn't be read. Try running \`git commit\` again to regenerate it.`,
3978
+ }],
3979
+ };
3980
+ }
3981
+ if (!data.violations || data.violations.length === 0) {
3982
+ // Clean up empty violations file
3983
+ fs.unlinkSync(violationsPath);
3984
+ return {
3985
+ content: [{
3986
+ type: 'text',
3987
+ text: `✅ **No violations to fix!**\n\nThe violations file was empty. Cleaned it up for you.`,
3988
+ }],
3989
+ };
3990
+ }
3991
+ // Group violations by file
3992
+ const byFile = {};
3993
+ for (const v of data.violations) {
3994
+ if (!byFile[v.file])
3995
+ byFile[v.file] = [];
3996
+ byFile[v.file].push(v);
3997
+ }
3998
+ // Build response with fix instructions
3999
+ let response = `# 🔧 Pre-Commit Violations Found\n\n`;
4000
+ response += `**${data.count} violation(s)** detected at ${data.timestamp}\n\n`;
4001
+ // Category fixes mapping
4002
+ const categoryFixes = {
4003
+ security: 'Use parameterized queries, escape user input, avoid eval()',
4004
+ errors: 'Add try/catch blocks, handle Promise rejections, use Result types',
4005
+ validation: 'Add Zod schemas at API boundaries, validate inputs before use',
4006
+ quality: 'Remove console.log, add explicit types, avoid any',
4007
+ typescript: 'Add proper type annotations, avoid type assertions',
4008
+ react: 'Add key props, wrap handlers in useCallback, handle loading states',
4009
+ accessibility: 'Add alt text, aria-labels, ensure keyboard navigation',
4010
+ performance: 'Use proper React hooks dependencies, memoize expensive operations',
4011
+ api: 'Use NextResponse for API routes, add rate limiting',
4012
+ imports: 'Fix import order, remove unused imports',
4013
+ };
4014
+ for (const [file, violations] of Object.entries(byFile)) {
4015
+ response += `## 📄 ${file}\n\n`;
4016
+ for (const v of violations) {
4017
+ response += `### ❌ ${v.check}\n`;
4018
+ response += `- **Category:** ${v.category}\n`;
4019
+ response += `- **Issue:** ${v.message}\n`;
4020
+ if (v.line)
4021
+ response += `- **Line:** ${v.line}\n`;
4022
+ if (v.code)
4023
+ response += `- **Code:** \`${v.code.substring(0, 100)}${v.code.length > 100 ? '...' : ''}\`\n`;
4024
+ // Add fix suggestion
4025
+ const fix = categoryFixes[v.category] || 'Review the code and apply best practices';
4026
+ response += `- **Fix:** ${fix}\n\n`;
4027
+ }
4028
+ }
4029
+ if (autoFix) {
4030
+ response += `---\n\n`;
4031
+ response += `## 🛠️ Auto-Fix Instructions\n\n`;
4032
+ response += `I'll now fix these violations. For each file:\n\n`;
4033
+ for (const [file, violations] of Object.entries(byFile)) {
4034
+ response += `**${file}:**\n`;
4035
+ for (const v of violations) {
4036
+ response += `- Fix: ${v.check} (${v.category})\n`;
4037
+ }
4038
+ response += `\n`;
4039
+ }
4040
+ response += `After fixing, run \`git add .\` and \`git commit\` again.\n\n`;
4041
+ response += `---\n\n`;
4042
+ response += `**⚠️ IMPORTANT:** Read each file and apply the fixes according to CodeBakers patterns. Load the relevant pattern module for each category (e.g., \`00-core.md\` for types, \`02-auth.md\` for security, \`03-api.md\` for API routes).\n`;
4043
+ }
4044
+ else {
4045
+ response += `---\n\n`;
4046
+ response += `Run \`heal_violations({ autoFix: true })\` to get fix instructions, or fix manually and commit again.\n`;
4047
+ }
4048
+ return {
4049
+ content: [{
4050
+ type: 'text',
4051
+ text: response,
4052
+ }],
4053
+ };
4054
+ }
3917
4055
  handleRunTests(args) {
3918
4056
  const { filter, watch = false } = args;
3919
4057
  const cwd = process.cwd();
@@ -4549,6 +4687,14 @@ If you want AI features and prefer Claude over GPT (or want both as fallback).`,
4549
4687
  responseText += `## ❌ Feature is NOT COMPLETE\n\n`;
4550
4688
  responseText += `**${result.nextSteps || 'Fix the issues above and try again.'}**\n`;
4551
4689
  }
4690
+ // Check for pre-commit violations
4691
+ const violations = this.checkForViolations();
4692
+ if (violations.hasViolations) {
4693
+ responseText += `\n---\n\n`;
4694
+ responseText += `## 🚨 PRE-COMMIT VIOLATIONS DETECTED\n\n`;
4695
+ responseText += violations.message + `\n\n`;
4696
+ responseText += `**IMPORTANT:** These violations will block your commit. Call \`heal_violations()\` to fix them.\n`;
4697
+ }
4552
4698
  return {
4553
4699
  content: [{
4554
4700
  type: 'text',
@@ -4890,6 +5036,14 @@ If you want AI features and prefer Claude over GPT (or want both as fallback).`,
4890
5036
  responseText += `4. TypeScript must compile - validation fails on errors\n`;
4891
5037
  responseText += `5. Pre-commit hook blocks commits without passed validation\n\n`;
4892
5038
  responseText += `**Server is tracking this session. Compliance is enforced.**`;
5039
+ // Check for pre-commit violations
5040
+ const violations = this.checkForViolations();
5041
+ if (violations.hasViolations) {
5042
+ responseText += `\n\n---\n\n`;
5043
+ responseText += `## 🚨 PRE-COMMIT VIOLATIONS DETECTED\n\n`;
5044
+ responseText += violations.message + `\n\n`;
5045
+ responseText += `**Fix these violations BEFORE writing new code.** Call \`heal_violations()\` to see details and fixes.\n`;
5046
+ }
4893
5047
  return {
4894
5048
  content: [{
4895
5049
  type: 'text',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebakers/cli",
3
- "version": "3.9.40",
3
+ "version": "3.9.41",
4
4
  "description": "CodeBakers CLI - Production patterns for AI-assisted development",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -889,6 +889,27 @@ async function validateCode() {
889
889
  log(CYAN, 'Fix these issues and try again.');
890
890
  log(YELLOW, 'To bypass (not recommended): git commit --no-verify\\n');
891
891
 
892
+ // Write violations to file for AI to read
893
+ const cbDir = path.join(cwd, '.codebakers');
894
+ if (!fs.existsSync(cbDir)) {
895
+ fs.mkdirSync(cbDir, { recursive: true });
896
+ }
897
+ fs.writeFileSync(
898
+ path.join(cbDir, 'violations.json'),
899
+ JSON.stringify({
900
+ timestamp: new Date().toISOString(),
901
+ count: violations.length,
902
+ violations: violations.map(v => ({
903
+ file: v.file,
904
+ check: v.check,
905
+ category: v.category,
906
+ message: v.message
907
+ }))
908
+ }, null, 2)
909
+ );
910
+ log(DIM, '📝 Violations saved to .codebakers/violations.json');
911
+ log(DIM, '💡 Ask AI to run heal_violations() to auto-fix\\n');
912
+
892
913
  return { valid: false, violations };
893
914
  }
894
915
 
@@ -917,6 +938,12 @@ async function validateCode() {
917
938
  log(GREEN, '✅ All pre-commit checks passed!');
918
939
  log(GREEN, '================================\\n');
919
940
 
941
+ // Clear violations file on success
942
+ const violationsPath = path.join(cwd, '.codebakers', 'violations.json');
943
+ if (fs.existsSync(violationsPath)) {
944
+ fs.unlinkSync(violationsPath);
945
+ }
946
+
920
947
  return { valid: true };
921
948
  }
922
949
 
package/src/mcp/server.ts CHANGED
@@ -71,6 +71,31 @@ class CodeBakersServer {
71
71
  private updateCheckInterval = 60 * 60 * 1000; // Check every hour
72
72
  private currentSessionToken: string | null = null; // v6.19: Server-side enforcement session
73
73
 
74
+ // Check for pre-commit violations
75
+ private checkForViolations(): { hasViolations: boolean; violations: any[] | null; message: string | null } {
76
+ const cwd = process.cwd();
77
+ const violationsPath = path.join(cwd, '.codebakers', 'violations.json');
78
+
79
+ if (!fs.existsSync(violationsPath)) {
80
+ return { hasViolations: false, violations: null, message: null };
81
+ }
82
+
83
+ try {
84
+ const data = JSON.parse(fs.readFileSync(violationsPath, 'utf-8'));
85
+ if (data.violations && data.violations.length > 0) {
86
+ return {
87
+ hasViolations: true,
88
+ violations: data.violations,
89
+ message: `⚠️ ${data.count} pre-commit violation(s) found! Call heal_violations() to auto-fix.`
90
+ };
91
+ }
92
+ } catch {
93
+ // Ignore parse errors
94
+ }
95
+
96
+ return { hasViolations: false, violations: null, message: null };
97
+ }
98
+
74
99
  constructor() {
75
100
  this.apiKey = getApiKey();
76
101
  this.apiUrl = getApiUrl();
@@ -1643,6 +1668,21 @@ class CodeBakersServer {
1643
1668
  },
1644
1669
  },
1645
1670
  },
1671
+ // Pre-commit violation healing tool
1672
+ {
1673
+ name: 'heal_violations',
1674
+ description:
1675
+ 'Auto-fix pre-commit hook violations. Call this when you see a violation warning in tool responses. Reads .codebakers/violations.json and provides fixes using CodeBakers patterns. After fixing, clears the violations file.',
1676
+ inputSchema: {
1677
+ type: 'object' as const,
1678
+ properties: {
1679
+ autoFix: {
1680
+ type: 'boolean',
1681
+ description: 'Automatically apply fixes (default: true). Set to false to just see the issues.',
1682
+ },
1683
+ },
1684
+ },
1685
+ },
1646
1686
  // Engineering workflow tools
1647
1687
  ...ENGINEERING_TOOLS,
1648
1688
  ],
@@ -1900,6 +1940,9 @@ class CodeBakersServer {
1900
1940
  case 'setup_services':
1901
1941
  return this.handleSetupServices(args as { services?: string[]; checkOnly?: boolean });
1902
1942
 
1943
+ case 'heal_violations':
1944
+ return this.handleHealViolations(args as { autoFix?: boolean });
1945
+
1903
1946
  // Engineering workflow tools
1904
1947
  case 'engineering_start':
1905
1948
  case 'engineering_scope':
@@ -4394,6 +4437,115 @@ If you want AI features and prefer Claude over GPT (or want both as fallback).`,
4394
4437
  };
4395
4438
  }
4396
4439
 
4440
+ private handleHealViolations(args: { autoFix?: boolean }) {
4441
+ const { autoFix = true } = args;
4442
+ const cwd = process.cwd();
4443
+ const violationsPath = path.join(cwd, '.codebakers', 'violations.json');
4444
+
4445
+ // Check if violations file exists
4446
+ if (!fs.existsSync(violationsPath)) {
4447
+ return {
4448
+ content: [{
4449
+ type: 'text' as const,
4450
+ text: `✅ **No violations found!**\n\nThe \`.codebakers/violations.json\` file doesn't exist, which means:\n- No pre-commit violations have been detected\n- Or they were already fixed\n\nYou're good to commit!`,
4451
+ }],
4452
+ };
4453
+ }
4454
+
4455
+ // Read violations
4456
+ let data: { timestamp: string; count: number; violations: Array<{ file: string; check: string; category: string; message: string; line?: number; code?: string }> };
4457
+ try {
4458
+ data = JSON.parse(fs.readFileSync(violationsPath, 'utf-8'));
4459
+ } catch {
4460
+ return {
4461
+ content: [{
4462
+ type: 'text' as const,
4463
+ text: `⚠️ **Could not parse violations file**\n\nThe violations.json file exists but couldn't be read. Try running \`git commit\` again to regenerate it.`,
4464
+ }],
4465
+ };
4466
+ }
4467
+
4468
+ if (!data.violations || data.violations.length === 0) {
4469
+ // Clean up empty violations file
4470
+ fs.unlinkSync(violationsPath);
4471
+ return {
4472
+ content: [{
4473
+ type: 'text' as const,
4474
+ text: `✅ **No violations to fix!**\n\nThe violations file was empty. Cleaned it up for you.`,
4475
+ }],
4476
+ };
4477
+ }
4478
+
4479
+ // Group violations by file
4480
+ const byFile: Record<string, typeof data.violations> = {};
4481
+ for (const v of data.violations) {
4482
+ if (!byFile[v.file]) byFile[v.file] = [];
4483
+ byFile[v.file].push(v);
4484
+ }
4485
+
4486
+ // Build response with fix instructions
4487
+ let response = `# 🔧 Pre-Commit Violations Found\n\n`;
4488
+ response += `**${data.count} violation(s)** detected at ${data.timestamp}\n\n`;
4489
+
4490
+ // Category fixes mapping
4491
+ const categoryFixes: Record<string, string> = {
4492
+ security: 'Use parameterized queries, escape user input, avoid eval()',
4493
+ errors: 'Add try/catch blocks, handle Promise rejections, use Result types',
4494
+ validation: 'Add Zod schemas at API boundaries, validate inputs before use',
4495
+ quality: 'Remove console.log, add explicit types, avoid any',
4496
+ typescript: 'Add proper type annotations, avoid type assertions',
4497
+ react: 'Add key props, wrap handlers in useCallback, handle loading states',
4498
+ accessibility: 'Add alt text, aria-labels, ensure keyboard navigation',
4499
+ performance: 'Use proper React hooks dependencies, memoize expensive operations',
4500
+ api: 'Use NextResponse for API routes, add rate limiting',
4501
+ imports: 'Fix import order, remove unused imports',
4502
+ };
4503
+
4504
+ for (const [file, violations] of Object.entries(byFile)) {
4505
+ response += `## 📄 ${file}\n\n`;
4506
+
4507
+ for (const v of violations) {
4508
+ response += `### ❌ ${v.check}\n`;
4509
+ response += `- **Category:** ${v.category}\n`;
4510
+ response += `- **Issue:** ${v.message}\n`;
4511
+ if (v.line) response += `- **Line:** ${v.line}\n`;
4512
+ if (v.code) response += `- **Code:** \`${v.code.substring(0, 100)}${v.code.length > 100 ? '...' : ''}\`\n`;
4513
+
4514
+ // Add fix suggestion
4515
+ const fix = categoryFixes[v.category] || 'Review the code and apply best practices';
4516
+ response += `- **Fix:** ${fix}\n\n`;
4517
+ }
4518
+ }
4519
+
4520
+ if (autoFix) {
4521
+ response += `---\n\n`;
4522
+ response += `## 🛠️ Auto-Fix Instructions\n\n`;
4523
+ response += `I'll now fix these violations. For each file:\n\n`;
4524
+
4525
+ for (const [file, violations] of Object.entries(byFile)) {
4526
+ response += `**${file}:**\n`;
4527
+ for (const v of violations) {
4528
+ response += `- Fix: ${v.check} (${v.category})\n`;
4529
+ }
4530
+ response += `\n`;
4531
+ }
4532
+
4533
+ response += `After fixing, run \`git add .\` and \`git commit\` again.\n\n`;
4534
+ response += `---\n\n`;
4535
+ response += `**⚠️ IMPORTANT:** Read each file and apply the fixes according to CodeBakers patterns. Load the relevant pattern module for each category (e.g., \`00-core.md\` for types, \`02-auth.md\` for security, \`03-api.md\` for API routes).\n`;
4536
+ } else {
4537
+ response += `---\n\n`;
4538
+ response += `Run \`heal_violations({ autoFix: true })\` to get fix instructions, or fix manually and commit again.\n`;
4539
+ }
4540
+
4541
+ return {
4542
+ content: [{
4543
+ type: 'text' as const,
4544
+ text: response,
4545
+ }],
4546
+ };
4547
+ }
4548
+
4397
4549
  private handleRunTests(args: { filter?: string; watch?: boolean }) {
4398
4550
  const { filter, watch = false } = args;
4399
4551
  const cwd = process.cwd();
@@ -5080,6 +5232,15 @@ If you want AI features and prefer Claude over GPT (or want both as fallback).`,
5080
5232
  responseText += `**${result.nextSteps || 'Fix the issues above and try again.'}**\n`;
5081
5233
  }
5082
5234
 
5235
+ // Check for pre-commit violations
5236
+ const violations = this.checkForViolations();
5237
+ if (violations.hasViolations) {
5238
+ responseText += `\n---\n\n`;
5239
+ responseText += `## 🚨 PRE-COMMIT VIOLATIONS DETECTED\n\n`;
5240
+ responseText += violations.message + `\n\n`;
5241
+ responseText += `**IMPORTANT:** These violations will block your commit. Call \`heal_violations()\` to fix them.\n`;
5242
+ }
5243
+
5083
5244
  return {
5084
5245
  content: [{
5085
5246
  type: 'text' as const,
@@ -5417,6 +5578,15 @@ If you want AI features and prefer Claude over GPT (or want both as fallback).`,
5417
5578
  responseText += `5. Pre-commit hook blocks commits without passed validation\n\n`;
5418
5579
  responseText += `**Server is tracking this session. Compliance is enforced.**`;
5419
5580
 
5581
+ // Check for pre-commit violations
5582
+ const violations = this.checkForViolations();
5583
+ if (violations.hasViolations) {
5584
+ responseText += `\n\n---\n\n`;
5585
+ responseText += `## 🚨 PRE-COMMIT VIOLATIONS DETECTED\n\n`;
5586
+ responseText += violations.message + `\n\n`;
5587
+ responseText += `**Fix these violations BEFORE writing new code.** Call \`heal_violations()\` to see details and fixes.\n`;
5588
+ }
5589
+
5420
5590
  return {
5421
5591
  content: [{
5422
5592
  type: 'text' as const,