aiknowsys 0.6.0 → 0.7.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.
@@ -1,6 +1,8 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
+ import ora from 'ora';
3
4
  import { createLogger } from '../logger.js';
5
+ import { ErrorTemplates } from '../error-helpers.js';
4
6
 
5
7
  /**
6
8
  * Audit command - Finds common issues and pattern violations
@@ -26,42 +28,86 @@ export async function audit(options) {
26
28
 
27
29
  // Check if knowledge system exists
28
30
  if (!fs.existsSync(essentialsPath) && !fs.existsSync(agentsPath)) {
29
- log.error('No knowledge system found in this directory');
30
- log.dim(' Run: npx aiknowsys init');
31
- log.blank();
32
- throw new Error('No knowledge system found');
31
+ throw ErrorTemplates.noKnowledgeSystem();
32
+ }
33
+
34
+ // Edge case: Check file sizes before reading
35
+ const filesToCheck = [
36
+ { path: essentialsPath, name: 'CODEBASE_ESSENTIALS.md' },
37
+ { path: agentsPath, name: 'AGENTS.md' },
38
+ { path: changelogPath, name: 'CODEBASE_CHANGELOG.md' }
39
+ ];
40
+
41
+ for (const file of filesToCheck) {
42
+ if (fs.existsSync(file.path)) {
43
+ const stats = fs.statSync(file.path);
44
+ const fileSize = stats.size;
45
+ const fiftyMB = 50 * 1024 * 1024;
46
+
47
+ // Edge case: File is empty
48
+ if (fileSize === 0) {
49
+ throw ErrorTemplates.emptyFile(file.name);
50
+ }
51
+
52
+ // Edge case: File too large
53
+ if (fileSize > fiftyMB) {
54
+ throw ErrorTemplates.fileTooLarge(file.name, fileSize / 1024 / 1024);
55
+ }
56
+ }
33
57
  }
34
58
 
59
+ // Create spinner for progress (only if not silent)
60
+ const spinner = silent ? null : ora('Starting audit...').start();
61
+
35
62
  // Audit 1: Check for duplicated validation matrix
36
- log.white('🔍 Checking for duplication issues...');
63
+ if (spinner) {
64
+ spinner.text = 'Check 1/5: Checking for duplication issues...';
65
+ } else {
66
+ log.white('🔍 Checking for duplication issues...');
67
+ }
37
68
 
38
69
  if (fs.existsSync(essentialsPath) && fs.existsSync(agentsPath)) {
39
- const essentialsContent = fs.readFileSync(essentialsPath, 'utf-8');
40
- const agentsContent = fs.readFileSync(agentsPath, 'utf-8');
41
-
42
- // Look for validation matrix table in both files
43
- const matrixTablePattern = /\|\s*Command\s*\|.*\|[\s\S]*?\|.*test.*\|/i;
44
- const hasEssentialsMatrix = matrixTablePattern.test(essentialsContent);
45
- const hasAgentsMatrix = matrixTablePattern.test(agentsContent);
46
-
47
- if (hasEssentialsMatrix && hasAgentsMatrix) {
48
- log.warn('Validation matrix duplicated in both files');
70
+ try {
71
+ const essentialsContent = fs.readFileSync(essentialsPath, 'utf-8');
72
+ const agentsContent = fs.readFileSync(agentsPath, 'utf-8');
73
+
74
+ // Look for validation matrix table in both files
75
+ const matrixTablePattern = /\|\s*Command\s*\|.*\|[\s\S]*?\|.*test.*\|/i;
76
+ const hasEssentialsMatrix = matrixTablePattern.test(essentialsContent);
77
+ const hasAgentsMatrix = matrixTablePattern.test(agentsContent);
78
+
79
+ if (hasEssentialsMatrix && hasAgentsMatrix) {
80
+ log.warn('Validation matrix duplicated in both files');
81
+ issues.push({
82
+ type: 'warning',
83
+ category: 'DRY Violation',
84
+ message: 'Validation matrix appears in both ESSENTIALS and AGENTS',
85
+ fix: 'Run: npx aiknowsys sync'
86
+ });
87
+ warnings++;
88
+ } else if (hasEssentialsMatrix) {
89
+ log.log(' ✓ Validation matrix in ESSENTIALS only (correct)');
90
+ }
91
+ } catch (error) {
92
+ // Handle malformed or corrupted files gracefully
93
+ info++;
49
94
  issues.push({
50
- type: 'warning',
51
- category: 'DRY Violation',
52
- message: 'Validation matrix appears in both ESSENTIALS and AGENTS',
53
- fix: 'Run: npx aiknowsys sync'
95
+ type: 'info',
96
+ category: 'File Processing',
97
+ message: `Could not fully parse files: ${error.message}`,
98
+ fix: 'Check file encoding and markdown structure'
54
99
  });
55
- warnings++;
56
- } else if (hasEssentialsMatrix) {
57
- log.log(' ✓ Validation matrix in ESSENTIALS only (correct)');
58
100
  }
59
101
  }
60
102
 
61
103
  log.blank();
62
104
 
63
105
  // Audit 2: Check for generic placeholder values
64
- log.white('📝 Checking for placeholder quality...');
106
+ if (spinner) {
107
+ spinner.text = 'Check 2/5: Checking placeholder quality...';
108
+ } else {
109
+ log.white('📝 Checking for placeholder quality...');
110
+ }
65
111
 
66
112
  if (fs.existsSync(essentialsPath)) {
67
113
  const content = fs.readFileSync(essentialsPath, 'utf-8');
@@ -125,7 +171,11 @@ export async function audit(options) {
125
171
  log.blank();
126
172
 
127
173
  // Audit 3: Check validation matrix quality
128
- log.white('✅ Checking validation matrix quality...');
174
+ if (spinner) {
175
+ spinner.text = 'Check 3/5: Checking validation matrix quality...';
176
+ } else {
177
+ log.white('✅ Checking validation matrix quality...');
178
+ }
129
179
 
130
180
  if (fs.existsSync(essentialsPath)) {
131
181
  const content = fs.readFileSync(essentialsPath, 'utf-8');
@@ -172,7 +222,11 @@ export async function audit(options) {
172
222
  log.blank();
173
223
 
174
224
  // Audit 4: Check changelog usage
175
- log.white('📚 Checking changelog...');
225
+ if (spinner) {
226
+ spinner.text = 'Check 4/5: Checking changelog...';
227
+ } else {
228
+ log.white('📚 Checking changelog...');
229
+ }
176
230
 
177
231
  if (fs.existsSync(changelogPath)) {
178
232
  const content = fs.readFileSync(changelogPath, 'utf-8');
@@ -192,7 +246,11 @@ export async function audit(options) {
192
246
  log.blank();
193
247
 
194
248
  // Audit 5: Check .aiknowsys/ gitignore configuration
195
- log.white('🔒 Checking .aiknowsys/ gitignore...');
249
+ if (spinner) {
250
+ spinner.text = 'Check 5/5: Checking .aiknowsys/ gitignore...';
251
+ } else {
252
+ log.white('🔒 Checking .aiknowsys/ gitignore...');
253
+ }
196
254
 
197
255
  const gitignorePath = path.join(targetDir, '.gitignore');
198
256
  const aiknowsysDir = path.join(targetDir, '.aiknowsys');
@@ -266,6 +324,9 @@ export async function audit(options) {
266
324
 
267
325
  log.blank();
268
326
 
327
+ // Stop spinner before summary
328
+ if (spinner) spinner.succeed('Audit complete');
329
+
269
330
  // Summary
270
331
  log.section('Audit Summary', '📊');
271
332
 
@@ -1,6 +1,7 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import { createLogger } from '../logger.js';
4
+ import { ErrorTemplates } from '../error-helpers.js';
4
5
 
5
6
  /**
6
7
  * Check command - Validates knowledge system setup
@@ -28,9 +29,36 @@ export async function check(options) {
28
29
  ];
29
30
 
30
31
  log.white('📁 Checking required files...');
32
+ const warnings = [];
33
+
31
34
  for (const file of requiredFiles) {
32
35
  const filePath = path.join(targetDir, file.path);
33
36
  if (fs.existsSync(filePath)) {
37
+ // Check file size and content
38
+ const stats = fs.statSync(filePath);
39
+ const fileSize = stats.size;
40
+
41
+ // Edge case: Empty file
42
+ if (fileSize === 0) {
43
+ log.log(` ✗ ${file.name} - Empty file`);
44
+ checks.push({ name: file.name, status: 'fail', error: 'File is empty' });
45
+ failed++;
46
+ throw ErrorTemplates.emptyFile(file.path);
47
+ }
48
+
49
+ // Edge case: Huge file (>5MB warning, >50MB error)
50
+ const fiveMB = 5 * 1024 * 1024;
51
+ const fiftyMB = 50 * 1024 * 1024;
52
+
53
+ if (fileSize > fiftyMB) {
54
+ log.log(` ✗ ${file.name} - File too large (${(fileSize / 1024 / 1024).toFixed(1)}MB)`);
55
+ checks.push({ name: file.name, status: 'fail', error: 'File size exceeds 50MB limit' });
56
+ failed++;
57
+ throw ErrorTemplates.fileTooLarge(file.path, fileSize / 1024 / 1024);
58
+ } else if (fileSize > fiveMB) {
59
+ warnings.push(`${file.name} is large (${(fileSize / 1024 / 1024).toFixed(1)}MB). Consider splitting content into multiple files.`);
60
+ }
61
+
34
62
  log.log(` ✓ ${file.name}`);
35
63
  checks.push({ name: file.name, status: 'pass' });
36
64
  passed++;
@@ -177,9 +205,10 @@ export async function check(options) {
177
205
  if (failed > 0) {
178
206
  log.log(` ✗ Failed: ${failed}`);
179
207
  }
180
- const warnings = checks.filter(c => c.status === 'warn').length;
181
- if (warnings > 0) {
182
- log.log(` ⚠ Warnings: ${warnings}`);
208
+ const warningCount = checks.filter(c => c.status === 'warn').length;
209
+ if (warningCount > 0 || warnings.length > 0) {
210
+ log.log(` ⚠ Warnings: ${warningCount + warnings.length}`);
211
+ warnings.forEach(w => log.warn(` • ${w}`));
183
212
  }
184
213
 
185
214
  log.blank();
@@ -209,10 +238,13 @@ export async function check(options) {
209
238
  // Exit with appropriate code
210
239
  if (failed > 0) {
211
240
  log.error('Health check failed');
212
- throw new Error(`Health check failed: ${failed} check(s) failed`);
213
- } else if (warnings > 0) {
241
+ const failedList = checks.filter(c => c.status === 'fail').map(c => c.name);
242
+ throw ErrorTemplates.validationFailed(failed, failedList);
243
+ } else if (warningCount > 0 || warnings.length > 0) {
214
244
  log.warn('Health check passed with warnings');
245
+ return { checks, passed, failed, warnings }; // Return for programmatic use
215
246
  } else {
216
247
  log.success('Health check passed');
248
+ return { checks, passed, failed, warnings }; // Return for programmatic use
217
249
  }
218
250
  }
@@ -4,7 +4,6 @@
4
4
  import fs from 'fs';
5
5
  import path from 'path';
6
6
  import ora from 'ora';
7
- import { createLogger } from '../../logger.js';
8
7
  import { getPackageDir, copyTemplate } from '../../utils.js';
9
8
  import { getProjectTypeName, getLanguageName, getFrameworkName, buildValidationMatrix, TEMPLATE_PATHS } from './index.js';
10
9
 
@@ -1,16 +1,18 @@
1
1
  import fs from 'fs';
2
2
  import path from 'path';
3
3
  import inquirer from 'inquirer';
4
+ import ora from 'ora';
4
5
  import { createLogger } from '../logger.js';
5
6
  import { scan } from './scan.js';
6
7
  import { installAgents } from './install-agents.js';
7
8
  import { installSkills } from './install-skills.js';
8
- import { getPackageDir, copyTemplate, displayAIPrompt } from '../utils.js';
9
+ import { getPackageDir, copyTemplate, displayAIPrompt, FileTracker } from '../utils.js';
9
10
 
10
11
  export async function migrate(options) {
11
12
  const targetDir = path.resolve(options.dir);
12
13
  const essentialsFile = options.essentials || 'CODEBASE_ESSENTIALS.md';
13
14
  const log = createLogger(false);
15
+ const tracker = new FileTracker();
14
16
 
15
17
  log.blank();
16
18
  log.header('Knowledge System Migration (Existing Project)', '🚀');
@@ -35,13 +37,23 @@ export async function migrate(options) {
35
37
  return;
36
38
  }
37
39
 
40
+ try {
41
+
38
42
  // Step 1: Scan codebase
39
43
  log.blank();
40
44
  log.cyan('══════════════════════════════════════════');
41
45
  log.header('Step 1/5: Scanning codebase', '');
42
46
  log.cyan('══════════════════════════════════════════');
43
47
 
48
+ // Create single spinner for entire migration workflow (Steps 1-5)
49
+ // Reused across automated phases (skipped for Step 2's interactive prompts)
50
+ const spinner = ora('Scanning codebase...').start();
44
51
  const _findings = await scan({ dir: targetDir, output: 'CODEBASE_ESSENTIALS.draft.md' });
52
+ spinner.succeed('Codebase scan complete');
53
+
54
+ // Track draft file for rollback if migration fails
55
+ const draftPath = path.join(targetDir, 'CODEBASE_ESSENTIALS.draft.md');
56
+ tracker.trackFile(draftPath);
45
57
 
46
58
  // Step 2: Review draft
47
59
  log.blank();
@@ -68,18 +80,18 @@ export async function migrate(options) {
68
80
  }]);
69
81
 
70
82
  const essentialsPath = path.join(targetDir, essentialsFile);
71
- const draftPath = path.join(targetDir, 'CODEBASE_ESSENTIALS.draft.md');
72
83
 
73
84
  if (!reviewed && !fs.existsSync(essentialsPath)) {
74
85
  const { action } = await inquirer.prompt([{
75
- type: 'list',
86
+ type: 'rawlist',
76
87
  name: 'action',
77
88
  message: `${essentialsFile} not found. What would you like to do?`,
78
89
  choices: [
79
90
  { name: 'Rename draft file now and continue', value: 'rename' },
80
91
  { name: 'Continue anyway (not recommended)', value: 'continue' },
81
92
  { name: 'Exit and complete the file first', value: 'exit' }
82
- ]
93
+ ],
94
+ default: 1
83
95
  }]);
84
96
 
85
97
  if (action === 'exit') {
@@ -87,8 +99,9 @@ export async function migrate(options) {
87
99
  return;
88
100
  }
89
101
 
90
- if (action === 'rename' && fs.existsSync(draftPath)) {
91
- fs.renameSync(draftPath, essentialsPath);
102
+ const draftFilePath = path.join(targetDir, 'CODEBASE_ESSENTIALS.draft.md');
103
+ if (action === 'rename' && fs.existsSync(draftFilePath)) {
104
+ fs.renameSync(draftFilePath, essentialsPath);
92
105
  log.success('✅ Renamed to CODEBASE_ESSENTIALS.md');
93
106
  }
94
107
  }
@@ -99,6 +112,7 @@ export async function migrate(options) {
99
112
  log.header('Step 3/5: Creating AGENTS.md', '');
100
113
  log.cyan('══════════════════════════════════════════');
101
114
 
115
+ spinner.start('Creating AGENTS.md...');
102
116
  const agentsPath = path.join(targetDir, 'AGENTS.md');
103
117
  if (!fs.existsSync(agentsPath)) {
104
118
  const packageDir = getPackageDir();
@@ -106,8 +120,11 @@ export async function migrate(options) {
106
120
  path.join(packageDir, 'templates', 'AGENTS.template.md'),
107
121
  agentsPath
108
122
  );
123
+ tracker.trackFile(agentsPath);
124
+ spinner.succeed('AGENTS.md created');
109
125
  log.success('✅ AGENTS.md created (customize validation matrix as needed)');
110
126
  } else {
127
+ spinner.info('AGENTS.md already exists');
111
128
  log.dim('⏭️ AGENTS.md already exists, skipping');
112
129
  }
113
130
 
@@ -117,7 +134,9 @@ export async function migrate(options) {
117
134
  log.header('Step 4/5: Installing custom agents', '');
118
135
  log.cyan('══════════════════════════════════════════');
119
136
 
137
+ spinner.start('Installing custom agents...');
120
138
  await installAgents({ dir: targetDir, essentials: essentialsFile });
139
+ spinner.succeed('Custom agents installed');
121
140
 
122
141
  // Step 5: Install skills
123
142
  log.blank();
@@ -125,7 +144,9 @@ export async function migrate(options) {
125
144
  log.header('Step 5/5: Installing universal skills', '');
126
145
  log.cyan('══════════════════════════════════════════');
127
146
 
147
+ spinner.start('Installing universal skills...');
128
148
  await installSkills({ dir: targetDir });
149
+ spinner.succeed('Universal skills installed');
129
150
 
130
151
  // Initialize changelog
131
152
  const changelogPath = path.join(targetDir, 'CODEBASE_CHANGELOG.md');
@@ -140,6 +161,7 @@ export async function migrate(options) {
140
161
  '{{DATE}}': new Date().toLocaleDateString('en-US', { year: 'numeric', month: 'long', day: 'numeric' })
141
162
  }
142
163
  );
164
+ tracker.trackFile(changelogPath);
143
165
  log.success('✅ CODEBASE_CHANGELOG.md initialized');
144
166
  }
145
167
 
@@ -172,4 +194,9 @@ export async function migrate(options) {
172
194
  '5. Explaining architecture decisions',
173
195
  'Make it project-specific, not a template!"'
174
196
  ]);
197
+ } catch (error) {
198
+ log.error(`Migration failed: ${error.message}`);
199
+ await tracker.rollback(log);
200
+ throw error;
201
+ }
175
202
  }
@@ -225,10 +225,11 @@ export async function scan(options) {
225
225
 
226
226
  // Scan for common pattern directories
227
227
  const commonDirs = ['src', 'lib', 'server', 'backend', 'api', 'app'];
228
+ let filesScanned = 0;
228
229
  for (const dir of commonDirs) {
229
230
  const dirPath = path.join(targetDir, dir);
230
231
  if (fs.existsSync(dirPath)) {
231
- scanForPatterns(dirPath, findings);
232
+ filesScanned = scanForPatterns(dirPath, findings, spinner, filesScanned);
232
233
  }
233
234
  }
234
235
 
@@ -270,7 +271,7 @@ export async function scan(options) {
270
271
  log.log('\x1b[33m\x1b[1m📝 Next Steps:\x1b[0m');
271
272
  log.white(` 1. Review and complete TODO sections in ${outputFile}`);
272
273
  log.white(' 2. Rename to CODEBASE_ESSENTIALS.md when ready');
273
- log.white(` 3. Run: `);
274
+ log.white(' 3. Run: ');
274
275
  log.cyan(' npx aiknowsys install-agents');
275
276
  log.blank();
276
277
 
@@ -294,9 +295,9 @@ export async function scan(options) {
294
295
  }
295
296
  }
296
297
 
297
- function scanForPatterns(dir, findings, depth = 0) {
298
+ function scanForPatterns(dir, findings, spinner = null, filesScanned = 0, depth = 0) {
298
299
  // Limit recursion depth to avoid performance issues
299
- if (depth > 2) return;
300
+ if (depth > 2) return filesScanned;
300
301
 
301
302
  try {
302
303
  const entries = fs.readdirSync(dir, { withFileTypes: true });
@@ -316,8 +317,15 @@ function scanForPatterns(dir, findings, depth = 0) {
316
317
  if (entry.name === 'middleware' || entry.name === 'auth') findings.patterns.hasAuthMiddleware = true;
317
318
 
318
319
  // Recurse into subdirectories
319
- scanForPatterns(fullPath, findings, depth + 1);
320
+ filesScanned = scanForPatterns(fullPath, findings, spinner, filesScanned, depth + 1);
320
321
  } else if (entry.isFile() && (entry.name.endsWith('.js') || entry.name.endsWith('.ts'))) {
322
+ filesScanned++;
323
+
324
+ // Update spinner text every 50 files for better performance
325
+ if (spinner && filesScanned % 50 === 0) {
326
+ spinner.text = `Analyzing codebase... (${filesScanned} files scanned)`;
327
+ }
328
+
321
329
  // Quick scan of file content for patterns
322
330
  try {
323
331
  const content = fs.readFileSync(fullPath, 'utf-8');
@@ -343,6 +351,8 @@ function scanForPatterns(dir, findings, depth = 0) {
343
351
  } catch (_e) {
344
352
  // Skip directories we can't read
345
353
  }
354
+
355
+ return filesScanned;
346
356
  }
347
357
 
348
358
  function generateEssentialsDraft(findings) {
@@ -2,6 +2,7 @@ import fs from 'fs';
2
2
  import path from 'path';
3
3
  import ora from 'ora';
4
4
  import { createLogger } from '../logger.js';
5
+ import { ErrorTemplates } from '../error-helpers.js';
5
6
 
6
7
  /**
7
8
  * Sync command - Syncs AGENTS.md validation reference with CODEBASE_ESSENTIALS.md
@@ -22,15 +23,11 @@ export async function sync(options) {
22
23
 
23
24
  // Check files exist
24
25
  if (!fs.existsSync(essentialsPath)) {
25
- log.error(`${essentialsFile} not found`);
26
- log.dim(' Run: npx aiknowsys init');
27
- throw new Error(`${essentialsFile} not found`);
26
+ throw ErrorTemplates.fileNotFound(essentialsFile, ['npx aiknowsys init']);
28
27
  }
29
28
 
30
29
  if (!fs.existsSync(agentsPath)) {
31
- log.error('AGENTS.md not found');
32
- log.dim(' Run: npx aiknowsys init');
33
- throw new Error('AGENTS.md not found');
30
+ throw ErrorTemplates.fileNotFound('AGENTS.md', ['npx aiknowsys init']);
34
31
  }
35
32
 
36
33
  const spinner = silent ? null : ora('Checking validation matrix...').start();
@@ -42,9 +39,7 @@ export async function sync(options) {
42
39
 
43
40
  if (!hasValidationMatrix) {
44
41
  if (spinner) spinner.fail('Validation matrix not found in CODEBASE_ESSENTIALS.md');
45
- log.blank();
46
- log.info('Add a Validation Matrix section to CODEBASE_ESSENTIALS.md');
47
- throw new Error('Validation matrix not found in CODEBASE_ESSENTIALS.md');
42
+ throw ErrorTemplates.missingSection('Validation Matrix', essentialsFile);
48
43
  }
49
44
 
50
45
  if (spinner) spinner.text = 'Reading AGENTS.md...';
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Error handling utilities for AIKnowSys
3
+ * Provides structured errors with helpful suggestions and documentation links
4
+ */
5
+
6
+ /**
7
+ * AIKnowSys structured error with helpful suggestions
8
+ *
9
+ * @example
10
+ * throw new AIKnowSysError(
11
+ * 'CODEBASE_ESSENTIALS.md not found',
12
+ * 'Create it by running:\n aiknowsys scan (from existing code)\n aiknowsys init (from scratch)',
13
+ * 'https://github.com/arpa73/AIKnowSys#getting-started'
14
+ * );
15
+ */
16
+ export class AIKnowSysError extends Error {
17
+ /**
18
+ * @param {string} message - What went wrong
19
+ * @param {string} suggestion - How to fix it
20
+ * @param {string} learnMore - URL to documentation (optional)
21
+ */
22
+ constructor(message, suggestion, learnMore = null) {
23
+ super(message);
24
+ this.suggestion = suggestion;
25
+ this.learnMore = learnMore;
26
+ this.name = 'AIKnowSysError';
27
+
28
+ // Maintain proper stack trace (V8 engine)
29
+ if (Error.captureStackTrace) {
30
+ Error.captureStackTrace(this, AIKnowSysError);
31
+ }
32
+ }
33
+
34
+ /**
35
+ * Format error with logger for consistent display
36
+ * @param {object} log - Logger instance with error(), info() methods
37
+ */
38
+ format(log) {
39
+ log.error(this.message);
40
+ log.blank();
41
+
42
+ if (this.suggestion) {
43
+ log.info('💡 How to fix:');
44
+ // Split multi-line suggestions and indent them
45
+ const lines = this.suggestion.split('\n');
46
+ lines.forEach(line => {
47
+ if (line.trim()) {
48
+ log.white(` ${line}`);
49
+ } else {
50
+ log.blank();
51
+ }
52
+ });
53
+ log.blank();
54
+ }
55
+
56
+ if (this.learnMore) {
57
+ log.cyan(`📚 Learn more: ${this.learnMore}`);
58
+ log.blank();
59
+ }
60
+ }
61
+
62
+ /**
63
+ * Get plain text version (for silent mode or testing)
64
+ * @returns {string} Formatted error message
65
+ */
66
+ toPlainText() {
67
+ let text = `✗ ${this.message}\n`;
68
+
69
+ if (this.suggestion) {
70
+ text += `\n💡 How to fix:\n${this.suggestion}\n`;
71
+ }
72
+
73
+ if (this.learnMore) {
74
+ text += `\n📚 Learn more: ${this.learnMore}\n`;
75
+ }
76
+
77
+ return text;
78
+ }
79
+ }
80
+
81
+ /**
82
+ * Common error templates for consistency
83
+ */
84
+ export const ErrorTemplates = {
85
+ /**
86
+ * File not found error
87
+ * @param {string} filename - Name of missing file
88
+ * @param {string[]} suggestions - Array of command suggestions
89
+ * @returns {AIKnowSysError}
90
+ */
91
+ fileNotFound(filename, suggestions = []) {
92
+ const defaultSuggestions = [
93
+ 'aiknowsys scan # Generate from existing codebase',
94
+ 'aiknowsys init # Start from scratch',
95
+ ];
96
+
97
+ const suggestionText = (suggestions.length > 0 ? suggestions : defaultSuggestions)
98
+ .map((s, i) => `${i + 1}. ${s}`)
99
+ .join('\n');
100
+
101
+ return new AIKnowSysError(
102
+ `${filename} not found`,
103
+ `This file is required for AIKnowSys to work. Create it by running:\n\n${suggestionText}`,
104
+ 'https://github.com/arpa73/AIKnowSys#getting-started'
105
+ );
106
+ },
107
+
108
+ /**
109
+ * Empty file error
110
+ * @param {string} filename - Name of empty file
111
+ * @returns {AIKnowSysError}
112
+ */
113
+ emptyFile(filename) {
114
+ return new AIKnowSysError(
115
+ `${filename} is empty or has no content`,
116
+ 'Generate content by running:\n\n1. aiknowsys scan # Analyze existing codebase\n2. Fill in manually # Copy template and customize',
117
+ 'https://github.com/arpa73/AIKnowSys#scanning-existing-projects'
118
+ );
119
+ },
120
+
121
+ /**
122
+ * File too large error
123
+ * @param {string} filename - Name of large file
124
+ * @param {number} sizeMB - File size in megabytes
125
+ * @returns {AIKnowSysError}
126
+ */
127
+ fileTooLarge(filename, sizeMB) {
128
+ return new AIKnowSysError(
129
+ `${filename} is too large (${sizeMB.toFixed(1)}MB)`,
130
+ 'Files larger than 50MB can cause performance issues.\n\nConsider:\n1. Split content into multiple files\n2. Move detailed examples to separate docs\n3. Use references/links instead of inline content',
131
+ 'https://github.com/arpa73/AIKnowSys/wiki/Best-Practices#keeping-files-lean'
132
+ );
133
+ },
134
+
135
+ /**
136
+ * Missing section error
137
+ * @param {string} section - Name of missing section
138
+ * @param {string} filename - File that should contain the section
139
+ * @returns {AIKnowSysError}
140
+ */
141
+ missingSection(section, filename) {
142
+ return new AIKnowSysError(
143
+ `Required section "${section}" not found in ${filename}`,
144
+ `Add this section to your ${filename}:\n\n1. Copy from template:\n cp node_modules/aiknowsys/templates/${filename.replace('.md', '.template.md')} ./${filename}\n\n2. Or update to latest:\n aiknowsys update --templates`,
145
+ 'https://github.com/arpa73/AIKnowSys#codebase-essentials-structure'
146
+ );
147
+ },
148
+
149
+ /**
150
+ * Validation failed error
151
+ * @param {number} failedCount - Number of failed checks
152
+ * @param {string[]} failures - Array of failure descriptions
153
+ * @returns {AIKnowSysError}
154
+ */
155
+ validationFailed(failedCount, failures = []) {
156
+ const failureList = failures.length > 0
157
+ ? failures.map((f, i) => `${i + 1}. ${f}`).join('\n')
158
+ : 'See details above';
159
+
160
+ return new AIKnowSysError(
161
+ `Health check failed: ${failedCount} check(s) failed`,
162
+ `Fix the following issues:\n\n${failureList}\n\nThen run:\n aiknowsys check # Verify fixes`,
163
+ 'https://github.com/arpa73/AIKnowSys#health-checks'
164
+ );
165
+ },
166
+
167
+ /**
168
+ * No knowledge system found error
169
+ * @returns {AIKnowSysError}
170
+ */
171
+ noKnowledgeSystem() {
172
+ return new AIKnowSysError(
173
+ 'No knowledge system found in this directory',
174
+ 'Initialize AIKnowSys by running:\n\n1. aiknowsys init # Interactive setup\n2. aiknowsys init --yes # Quick setup with defaults\n3. aiknowsys migrate # Migrate existing project',
175
+ 'https://github.com/arpa73/AIKnowSys#quick-start'
176
+ );
177
+ }
178
+ };
package/lib/sanitize.js CHANGED
@@ -38,6 +38,22 @@ export function sanitizeProjectName(name) {
38
38
  errors.push('Project name can only contain letters, numbers, hyphens, underscores, and dots');
39
39
  }
40
40
 
41
+ // Check for emoji and special Unicode characters
42
+ // Emoji range: U+1F300 to U+1F9FF (and others)
43
+ if (/[\u{1F300}-\u{1F9FF}\u{2600}-\u{26FF}\u{2700}-\u{27BF}]/u.test(trimmed)) {
44
+ errors.push('Project name cannot contain emoji or special Unicode characters');
45
+ }
46
+
47
+ // Check for npm reserved names
48
+ const reservedNames = [
49
+ 'node_modules', 'favicon.ico', 'node', 'npm', 'package', 'readme',
50
+ 'license', 'changelog', 'test', 'tests', 'example', 'examples'
51
+ ];
52
+ const lowercaseName = trimmed.toLowerCase().replace(/^@[^/]+\//, ''); // Remove scope
53
+ if (reservedNames.includes(lowercaseName)) {
54
+ errors.push(`Project name '${lowercaseName}' is reserved by npm`);
55
+ }
56
+
41
57
  // Check for leading/trailing special characters
42
58
  if (/^[._-]/.test(trimmed)) {
43
59
  errors.push('Project name cannot start with a dot, hyphen, or underscore');
@@ -198,7 +214,7 @@ export function validatePathTraversal(basePath, userPath) {
198
214
  }
199
215
 
200
216
  // Normalize paths to prevent traversal
201
- const normalizedBase = basePath.replace(/\\/g, '/').replace(/\/+$/, '');
217
+ const _normalizedBase = basePath.replace(/\\/g, '/').replace(/\/+$/, '');
202
218
  const normalizedUser = userPath.replace(/\\/g, '/');
203
219
 
204
220
  // Check for absolute paths (should be relative to base)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiknowsys",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "AI-Powered Development Workflow for Consistent, High-Quality Code",
5
5
  "keywords": [
6
6
  "ai",
@@ -258,36 +258,7 @@ Follow patterns from CODEBASE_ESSENTIALS.md and the skill you read.
258
258
  2. Use skill format with clear trigger words
259
259
  3. Document the pattern for future reuse
260
260
 
261
- **Example:**
262
- ```markdown
263
- # Learned Skill: Django Query Optimization Pattern
264
-
265
- **Pattern Type:** project_specific
266
- **Created:** {{DATE}}
267
- **Trigger Words:** "slow query", "n+1 problem", "django performance"
268
-
269
- ## When to Use
270
- Use when encountering slow Django queries with related objects.
271
-
272
- ## Pattern
273
- Always use select_related() for foreign keys and prefetch_related() for many-to-many.
274
-
275
- \```python
276
- # ❌ N+1 query problem
277
- users = User.objects.all()
278
- for user in users:
279
- print(user.profile.bio) # Query per user!
280
-
281
- # ✅ Optimized with select_related
282
- users = User.objects.select_related('profile').all()
283
- for user in users:
284
- print(user.profile.bio) # Single query!
285
- \```
286
-
287
- ## Related
288
- - Django ORM documentation
289
- - Performance monitoring with django-debug-toolbar
290
- ```
261
+ **See `.github/skills/skill-creator/SKILL.md` for detailed format and examples.**
291
262
 
292
263
  **Pattern Types:**
293
264
  - `error_resolution` - How specific errors were fixed
@@ -360,100 +331,6 @@ This project uses Developer + Architect agents for automated code review.
360
331
 
361
332
  ---
362
333
 
363
- ## ✅ Pre-Commit Validation Checklist
364
-
365
- **Run this checklist BEFORE every commit. Copy-paste into terminal:**
366
-
367
- ### Quick Check (1 minute)
368
- ```bash
369
- # 1. Validation Matrix commands
370
- {{VALIDATION_CMD_1}} # e.g., npm test
371
- {{VALIDATION_CMD_2}} # e.g., npm run lint
372
-
373
- # 2. No debug code
374
- grep -r "console.log\|debugger\|TODO:" src/ || echo "✓ No debug code"
375
-
376
- # 3. No secrets
377
- grep -r "password\|api_key\|secret" . --exclude-dir={node_modules,.git} || echo "✓ No secrets"
378
- ```
379
-
380
- ### Full Check (5 minutes)
381
- ```bash
382
- # Run all validation commands from matrix
383
- {{ALL_VALIDATION_COMMANDS}}
384
-
385
- # Additional checks
386
- git status # No untracked files
387
- git diff # Review changes
388
- grep "{{" {{TEMPLATE_FILES}} # No unfilled placeholders
389
- ```
390
-
391
- ### Before Push
392
- ```bash
393
- # Final validation
394
- {{VALIDATION_CMD_1}}
395
-
396
- # Check commits
397
- git log origin/main..HEAD # Review commits
398
-
399
- # Push
400
- git push
401
- ```
402
-
403
- ---
404
-
405
- ## 🔍 Troubleshooting Validation Failures
406
-
407
- ### Tests Failing
408
- 1. Read error message carefully
409
- 2. Check CODEBASE_ESSENTIALS.md for test patterns
410
- 3. Review "Common Gotchas" section
411
- 4. Run single failing test: `{{SINGLE_TEST_CMD}}`
412
- 5. Check if pattern violated (Critical Invariants)
413
-
414
- ### Linting Errors
415
- 1. Auto-fix if possible: `{{AUTO_FIX_CMD}}`
416
- 2. Review Core Patterns for style rules
417
- 3. Don't disable rules - fix the code
418
- 4. If rule is wrong, update ESSENTIALS first
419
-
420
- ### Build Errors
421
- 1. Check dependency versions (Technology Stack section)
422
- 2. Clear cache: `{{CLEAR_CACHE_CMD}}`
423
- 3. Rebuild from scratch: `{{CLEAN_BUILD_CMD}}`
424
- 4. Check environment variables
425
-
426
- ---
427
-
428
- ## 📝 Customization Instructions
429
-
430
- **This is a template file. To customize:**
431
-
432
- 1. **{{SKILL_MAPPING}}** - Add your project's skill trigger words
433
- ```markdown
434
- | "refactor", "clean up" | code-refactoring | Test-driven refactoring |
435
- | "update deps" | dependency-updates | Safe dependency updates |
436
- | "write tests", "TDD", "test first" | tdd-workflow | Test-driven development |
437
- ```
438
-
439
- 2. **Validation Checklist Placeholders:**
440
- - `{{VALIDATION_CMD_1}}` → Your primary test command (e.g., `npm test`)
441
- - `{{VALIDATION_CMD_2}}` → Your lint command (e.g., `npm run lint`)
442
- - `{{ALL_VALIDATION_COMMANDS}}` → All commands from validation matrix in ESSENTIALS
443
- - `{{TEMPLATE_FILES}}` → Files to check for placeholders
444
- - `{{SINGLE_TEST_CMD}}` → How to run one test (e.g., `npm test -- file.test.js`)
445
- - `{{AUTO_FIX_CMD}}` → Auto-fix linting (e.g., `npm run lint:fix`)
446
- - `{{CLEAR_CACHE_CMD}}` → Clear build cache
447
- - `{{CLEAN_BUILD_CMD}}` → Clean rebuild command
448
-
449
- 3. **Add project-specific sections** as needed
450
-
451
- 4. **Remove placeholder text** and instructions
452
-
453
- **Note:** Validation Matrix is in CODEBASE_ESSENTIALS.md - no need to duplicate it here.
454
-
455
- ---
456
-
457
334
  *This file helps AI agents follow a consistent workflow: Read → Plan → Implement → Validate → Document → Confirm*
458
335
 
459
336
  *Part of aiknowsys. See [README](README.md) and [SETUP_GUIDE.md](SETUP_GUIDE.md) for full documentation.*
@@ -110,6 +110,44 @@ To ensure your review feedback is preserved and actionable:
110
110
  - Developer deletes PENDING_REVIEW.md after addressing issues
111
111
  - Session file gets brief completion status (not full review text)
112
112
 
113
+ ### Documentation Location Guidance (Read Before Reviewing!):
114
+
115
+ When recommending where to document patterns during your review, use this decision framework:
116
+
117
+ **Document in {{ESSENTIALS_FILE}} when:**
118
+ - ✅ **Critical Invariants**: Cannot be violated (ES modules only, no globals, etc.)
119
+ - ✅ **Core Patterns**: Used in EVERY file of that type (Logger, FileTracker, etc.)
120
+ - ✅ **Architecture Decisions**: Technology choices (Node 20+, framework selections, etc.)
121
+ - ✅ **Universal Rules**: Applies project-wide (KISS, DRY, test structure, etc.)
122
+ - ⚠️ **Size check**: ESSENTIALS getting large (>350 lines)? Consider moving to learned/
123
+
124
+ **Document in `.aiknowsys/learned/` when:**
125
+ - ✅ **Project-Specific Patterns**: Emerged from practice (not planned upfront)
126
+ - ✅ **Problem-Solution Pairs**: Recurring error with consistent fix
127
+ - ✅ **Workarounds**: Library/framework-specific solutions
128
+ - ✅ **Advanced Techniques**: Optional patterns that improve quality but aren't mandatory
129
+ - ✅ **Domain Knowledge**: Business logic patterns, API conventions, etc.
130
+
131
+ **Reasoning:**
132
+ - ESSENTIALS = "What AI MUST know before any change" (single source of truth)
133
+ - Learned = "What AI SHOULD know for this specific context" (discoverable via triggers)
134
+ - Keep ESSENTIALS lean (<350 lines ideal) so AI reads it every session
135
+ - Learned skills can be detailed without bloating core docs
136
+
137
+ **How to recommend:**
138
+ ```markdown
139
+ **Recommendation:** Document this as a learned skill.
140
+
141
+ **Reasoning:**
142
+ - Pattern emerged from [context] implementation (not core architecture)
143
+ - [X] distinct patterns discovered through practice
144
+ - Optional technique that improves [aspect] but not mandatory
145
+ - {{ESSENTIALS_FILE}} already at [X] lines (over ideal 350)
146
+ - Fits Pattern Extraction Protocol in AGENTS.md
147
+
148
+ **Action:** Create `.aiknowsys/learned/pattern-name.md` using skill format.
149
+ ```
150
+
113
151
  ### Additional Reminders to Developer:
114
152
  After completing your review, remind the developer to:
115
153
  - **Read PENDING_REVIEW.md:** "Detailed review written to `.aiknowsys/PENDING_REVIEW.md`"
@@ -0,0 +1,486 @@
1
+ ---
2
+ name: validation-troubleshooting
3
+ description: Universal troubleshooting guide for validation failures (tests, linting, builds). Use when tests fail, validation commands error, or build breaks. Framework-agnostic debugging strategies for common development workflow issues.
4
+ ---
5
+
6
+ # Validation Troubleshooting Skill
7
+
8
+ Step-by-step debugging guide for when validation commands fail.
9
+
10
+ ## When to Use This Skill
11
+
12
+ Use when:
13
+ - Tests fail after making changes
14
+ - Validation commands from matrix error
15
+ - Build/compilation fails
16
+ - Linting errors appear
17
+ - Type checking fails
18
+ - User mentions: "tests failing", "validation error", "build broken", "lint error"
19
+
20
+ **Trigger words:** "test fail", "validation fail", "build error", "lint error", "type error", "won't compile"
21
+
22
+ ---
23
+
24
+ ## 1. Test Failures
25
+
26
+ ### Step 1: Read the Error Message Carefully
27
+
28
+ **DON'T:**
29
+ - ❌ Immediately modify code
30
+ - ❌ Delete failing tests
31
+ - ❌ Disable test runner
32
+
33
+ **DO:**
34
+ - ✅ Read full error output
35
+ - ✅ Note exact line number and file
36
+ - ✅ Identify what was expected vs actual
37
+
38
+ ### Step 2: Isolate the Failure
39
+
40
+ Run only the failing test:
41
+
42
+ ```bash
43
+ # Node.js
44
+ npm test -- path/to/test.test.js
45
+
46
+ # Python
47
+ pytest path/to/test.py::test_name -v
48
+
49
+ # Jest
50
+ npm test -- --testNamePattern="test name"
51
+
52
+ # Vitest
53
+ npx vitest path/to/test.test.ts
54
+
55
+ # Go
56
+ go test -run TestName ./...
57
+
58
+ # Rust
59
+ cargo test test_name
60
+ ```
61
+
62
+ ### Step 3: Check Test Expectations
63
+
64
+ **Common issues:**
65
+ - Test expects old behavior (need to update test)
66
+ - Implementation is wrong (fix code)
67
+ - Test setup/mocking is incorrect
68
+ - Environment/config mismatch
69
+
70
+ **Questions to ask:**
71
+ 1. Is the test expectation still valid?
72
+ 2. Did I change behavior the test depends on?
73
+ 3. Are mocks/fixtures up to date?
74
+ 4. Does the test match CODEBASE_ESSENTIALS.md patterns?
75
+
76
+ ### Step 4: Debug the Test
77
+
78
+ **Add logging:**
79
+ ```javascript
80
+ // JavaScript/TypeScript
81
+ console.log('Actual value:', result);
82
+ console.log('Expected:', expected);
83
+
84
+ // Python
85
+ print(f"Actual: {result}, Expected: {expected}")
86
+
87
+ // Rust
88
+ println!("Actual: {:?}, Expected: {:?}", result, expected);
89
+ ```
90
+
91
+ **Run in debug mode:**
92
+ ```bash
93
+ # Node.js
94
+ node --inspect-brk node_modules/.bin/jest --runInBand
95
+
96
+ # Python
97
+ python -m pdb -m pytest path/to/test.py
98
+
99
+ # Rust
100
+ rust-gdb target/debug/test_binary
101
+ ```
102
+
103
+ ### Step 5: Fix and Validate
104
+
105
+ 1. Fix the issue (code or test)
106
+ 2. Run the single test again - should pass
107
+ 3. Run full test suite - all should pass
108
+ 4. Commit with clear message explaining the fix
109
+
110
+ **Never claim done without running full test suite!**
111
+
112
+ ---
113
+
114
+ ## 2. Linting Errors
115
+
116
+ ### Step 1: Identify Error Type
117
+
118
+ **Syntax errors:**
119
+ ```
120
+ Parsing error: Unexpected token
121
+ Missing semicolon
122
+ Unexpected identifier
123
+ ```
124
+ → **Fix:** Correct syntax immediately
125
+
126
+ **Style violations:**
127
+ ```
128
+ 'variable' is assigned but never used
129
+ Missing trailing comma
130
+ Prefer const over let
131
+ ```
132
+ → **Fix:** Address or justify
133
+
134
+ **Security issues:**
135
+ ```
136
+ Detected eval usage
137
+ Unsafe regex
138
+ XSS vulnerability
139
+ ```
140
+ → **Fix:** MUST fix, don't disable
141
+
142
+ ### Step 2: Auto-Fix When Possible
143
+
144
+ ```bash
145
+ # ESLint
146
+ npm run lint:fix
147
+
148
+ # Prettier
149
+ npm run format
150
+
151
+ # Black (Python)
152
+ black .
153
+
154
+ # Rustfmt
155
+ cargo fmt
156
+
157
+ # Go
158
+ go fmt ./...
159
+ ```
160
+
161
+ ### Step 3: Manual Fixes
162
+
163
+ **Read CODEBASE_ESSENTIALS.md for style rules:**
164
+ - Check "Code Patterns" section
165
+ - Verify naming conventions
166
+ - Review import ordering
167
+
168
+ **DON'T disable rules without justification:**
169
+ ```javascript
170
+ // ❌ BAD - Disabling without reason
171
+ // eslint-disable-next-line no-console
172
+ console.log(data);
173
+
174
+ // ✅ GOOD - Justified exception
175
+ // eslint-disable-next-line no-console -- Debugging production issue #123
176
+ console.log(data);
177
+ ```
178
+
179
+ ### Step 4: Update Rules If Wrong
180
+
181
+ If rule conflicts with project patterns:
182
+ 1. Discuss with team/review ESSENTIALS
183
+ 2. Update linting config
184
+ 3. Document change in CODEBASE_CHANGELOG.md
185
+ 4. Update CODEBASE_ESSENTIALS.md if pattern changed
186
+
187
+ ---
188
+
189
+ ## 3. Build/Compilation Errors
190
+
191
+ ### Step 1: Check Error Category
192
+
193
+ **Dependency errors:**
194
+ ```
195
+ Cannot find module 'package-name'
196
+ Module not found
197
+ Package not installed
198
+ ```
199
+ → **Fix:** Install dependencies
200
+
201
+ **Type errors:**
202
+ ```
203
+ Type 'string' is not assignable to type 'number'
204
+ Property 'x' does not exist on type 'Y'
205
+ ```
206
+ → **Fix:** Correct types or update type definitions
207
+
208
+ **Configuration errors:**
209
+ ```
210
+ Invalid configuration object
211
+ Missing environment variable
212
+ Unknown compiler option
213
+ ```
214
+ → **Fix:** Check config files
215
+
216
+ ### Step 2: Clean Build
217
+
218
+ ```bash
219
+ # JavaScript/TypeScript
220
+ rm -rf node_modules dist .cache
221
+ npm install
222
+ npm run build
223
+
224
+ # Python
225
+ rm -rf __pycache__ .pytest_cache dist
226
+ pip install -r requirements.txt
227
+
228
+ # Rust
229
+ cargo clean
230
+ cargo build
231
+
232
+ # Go
233
+ go clean -cache
234
+ go build
235
+ ```
236
+
237
+ ### Step 3: Check Environment
238
+
239
+ **Verify versions match CODEBASE_ESSENTIALS.md:**
240
+ ```bash
241
+ # Check Node.js version
242
+ node --version
243
+
244
+ # Check Python version
245
+ python --version
246
+
247
+ # Check Rust version
248
+ rustc --version
249
+
250
+ # Check Go version
251
+ go version
252
+ ```
253
+
254
+ **Check environment variables:**
255
+ ```bash
256
+ # List all env vars
257
+ printenv
258
+
259
+ # Check specific required vars
260
+ echo $NODE_ENV
261
+ echo $DATABASE_URL
262
+ ```
263
+
264
+ ### Step 4: Incremental Debugging
265
+
266
+ 1. Comment out recent changes
267
+ 2. Build incrementally
268
+ 3. Identify breaking change
269
+ 4. Fix root cause
270
+ 5. Uncomment and rebuild
271
+
272
+ ---
273
+
274
+ ## 4. Type Checking Errors
275
+
276
+ ### Common TypeScript Issues
277
+
278
+ **Missing type definitions:**
279
+ ```bash
280
+ npm install --save-dev @types/package-name
281
+ ```
282
+
283
+ **Type mismatch:**
284
+ ```typescript
285
+ // ❌ Wrong
286
+ const id: number = "123";
287
+
288
+ // ✅ Fix - convert type
289
+ const id: number = parseInt("123", 10);
290
+
291
+ // ✅ Or - fix type annotation
292
+ const id: string = "123";
293
+ ```
294
+
295
+ **Null/undefined issues:**
296
+ ```typescript
297
+ // ❌ Unsafe
298
+ const name = user.name;
299
+
300
+ // ✅ Safe - optional chaining
301
+ const name = user?.name;
302
+
303
+ // ✅ Safe - nullish coalescing
304
+ const name = user?.name ?? 'Unknown';
305
+ ```
306
+
307
+ ### Common Python Type Issues
308
+
309
+ **mypy errors:**
310
+ ```bash
311
+ # Run mypy
312
+ mypy src/
313
+
314
+ # Ignore specific line (rarely)
315
+ result = something() # type: ignore[attr-defined]
316
+ ```
317
+
318
+ ---
319
+
320
+ ## 5. Validation Matrix Command Failures
321
+
322
+ ### Strategy: Work Through Matrix Systematically
323
+
324
+ **From CODEBASE_ESSENTIALS.md validation matrix:**
325
+
326
+ ```markdown
327
+ | Command | Purpose | Expected |
328
+ |---------|---------|----------|
329
+ | npm test | Run tests | All pass |
330
+ | npm run lint | Check style | No errors |
331
+ | npm run build | Compile | No errors |
332
+ ```
333
+
334
+ **Run each command:**
335
+ 1. If passes → ✅ Move to next
336
+ 2. If fails → 🔴 Debug using sections above
337
+ 3. Don't move forward until current command passes
338
+
339
+ ### Example Debugging Session
340
+
341
+ ```bash
342
+ # 1. Run tests
343
+ npm test
344
+ # ❌ FAIL - 2 tests failing
345
+
346
+ # 2. Isolate failure
347
+ npm test -- auth.test.js
348
+ # Read error, fix issue
349
+
350
+ # 3. Verify fix
351
+ npm test
352
+ # ✅ PASS - All tests green
353
+
354
+ # 4. Continue to next validation
355
+ npm run lint
356
+ # ✅ PASS - No issues
357
+
358
+ # 5. Final check
359
+ npm run build
360
+ # ✅ PASS - Build successful
361
+ ```
362
+
363
+ **Rule: Fix failures in order, don't skip ahead!**
364
+
365
+ ---
366
+
367
+ ## 6. Common Patterns and Solutions
368
+
369
+ ### Pattern: "Works on my machine"
370
+
371
+ **Cause:** Environment differences
372
+
373
+ **Solutions:**
374
+ 1. Check Node.js/Python/Rust version matches team
375
+ 2. Verify environment variables set correctly
376
+ 3. Clear caches and reinstall dependencies
377
+ 4. Check for OS-specific issues (Windows vs Unix paths)
378
+ 5. Use Docker/containers for consistency
379
+
380
+ ### Pattern: "Test passes locally, fails in CI"
381
+
382
+ **Cause:** CI environment differences
383
+
384
+ **Solutions:**
385
+ 1. Check CI logs carefully
386
+ 2. Verify CI environment variables
387
+ 3. Check for timing issues (add proper waits)
388
+ 4. Ensure deterministic test data
389
+ 5. Check for missing CI dependencies
390
+
391
+ ### Pattern: "Intermittent test failures"
392
+
393
+ **Cause:** Non-deterministic tests
394
+
395
+ **Solutions:**
396
+ 1. Remove time-dependent logic
397
+ 2. Fix race conditions
398
+ 3. Mock random/date functions
399
+ 4. Ensure proper cleanup between tests
400
+ 5. Avoid shared state
401
+
402
+ ### Pattern: "Everything broke after dependency update"
403
+
404
+ **Cause:** Breaking changes in dependency
405
+
406
+ **Solutions:**
407
+ 1. Check dependency changelog
408
+ 2. Revert to previous version temporarily
409
+ 3. Read migration guide
410
+ 4. Update code to new API
411
+ 5. Consider alternative package
412
+
413
+ ---
414
+
415
+ ## Workflow Checklist
416
+
417
+ When validation fails:
418
+
419
+ - [ ] **Read error message** - Don't guess
420
+ - [ ] **Check CODEBASE_ESSENTIALS.md** - Verify patterns
421
+ - [ ] **Isolate the issue** - Run single test/command
422
+ - [ ] **Debug systematically** - Use tools, not trial-and-error
423
+ - [ ] **Fix root cause** - Not just symptoms
424
+ - [ ] **Verify fix** - Run full validation matrix
425
+ - [ ] **Document if needed** - Update docs if pattern unclear
426
+ - [ ] **Commit with context** - Explain what broke and why
427
+
428
+ ---
429
+
430
+ ## Never Do These
431
+
432
+ ❌ **Delete tests to make them pass**
433
+ - Tests found a real issue
434
+ - Fix the code, not the test
435
+
436
+ ❌ **Disable linting rules without justification**
437
+ - Rules exist for a reason
438
+ - Discuss with team first
439
+
440
+ ❌ **Skip validation steps**
441
+ - "It probably works" is not good enough
442
+ - Run full matrix before claiming done
443
+
444
+ ❌ **Commit broken code "to fix later"**
445
+ - Breaks team workflow
446
+ - Creates technical debt
447
+
448
+ ❌ **Change multiple things at once**
449
+ - Can't identify root cause
450
+ - Fix one thing, validate, then next
451
+
452
+ ---
453
+
454
+ ## Quick Reference
455
+
456
+ ### Emergency Triage
457
+
458
+ ```bash
459
+ # 1. What broke?
460
+ git diff # Review recent changes
461
+
462
+ # 2. When did it break?
463
+ git log --oneline -10 # Recent commits
464
+
465
+ # 3. Revert if needed
466
+ git revert HEAD # Undo last commit safely
467
+
468
+ # 4. Isolate and fix
469
+ # Use sections above based on error type
470
+
471
+ # 5. Validate before moving on
472
+ npm test && npm run lint && npm run build
473
+ ```
474
+
475
+ ### Getting Unstuck
476
+
477
+ If stuck for >15 minutes:
478
+ 1. Read error message again (slowly)
479
+ 2. Check CODEBASE_ESSENTIALS.md for relevant pattern
480
+ 3. Search project for similar code that works
481
+ 4. Check dependency documentation
482
+ 5. Ask for help (provide full error message)
483
+
484
+ ---
485
+
486
+ *Framework-agnostic troubleshooting - adapt commands to your project's tech stack.*