@paths.design/caws-cli 7.0.2 → 7.0.3

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.
Files changed (117) hide show
  1. package/dist/budget-derivation.js +5 -4
  2. package/dist/commands/diagnose.js +24 -19
  3. package/dist/commands/init.js +51 -4
  4. package/dist/commands/specs.js +40 -1
  5. package/dist/commands/status.js +2 -2
  6. package/dist/commands/tool.js +2 -3
  7. package/dist/config/index.js +17 -8
  8. package/dist/generators/working-spec.js +19 -6
  9. package/dist/scaffold/git-hooks.js +127 -29
  10. package/dist/scaffold/index.js +53 -7
  11. package/dist/templates/.caws/tools/README.md +20 -0
  12. package/dist/templates/.cursor/README.md +311 -0
  13. package/dist/templates/.cursor/hooks/audit.sh +55 -0
  14. package/dist/templates/.cursor/hooks/block-dangerous.sh +83 -0
  15. package/dist/templates/.cursor/hooks/caws-quality-check.sh +52 -0
  16. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +130 -0
  17. package/dist/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
  18. package/dist/templates/.cursor/hooks/format.sh +38 -0
  19. package/dist/templates/.cursor/hooks/naming-check.sh +64 -0
  20. package/dist/templates/.cursor/hooks/scan-secrets.sh +46 -0
  21. package/dist/templates/.cursor/hooks/scope-guard.sh +52 -0
  22. package/dist/templates/.cursor/hooks/validate-spec.sh +83 -0
  23. package/dist/templates/.cursor/hooks.json +59 -0
  24. package/dist/templates/.cursor/rules/00-claims-verification.mdc +144 -0
  25. package/dist/templates/.cursor/rules/01-working-style.mdc +50 -0
  26. package/dist/templates/.cursor/rules/02-quality-gates.mdc +370 -0
  27. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
  28. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
  29. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
  30. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
  31. package/dist/templates/.cursor/rules/07-process-ops.mdc +20 -0
  32. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
  33. package/dist/templates/.cursor/rules/09-docstrings.mdc +89 -0
  34. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +390 -0
  35. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +385 -0
  36. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +516 -0
  37. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +588 -0
  38. package/dist/templates/.cursor/rules/README.md +148 -0
  39. package/dist/templates/.github/copilot/instructions.md +311 -0
  40. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
  41. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
  42. package/dist/templates/.vscode/launch.json +56 -0
  43. package/dist/templates/.vscode/settings.json +93 -0
  44. package/dist/templates/.windsurf/workflows/caws-guided-development.md +92 -0
  45. package/dist/templates/COMMIT_CONVENTIONS.md +86 -0
  46. package/dist/templates/OIDC_SETUP.md +300 -0
  47. package/dist/templates/agents.md +1047 -0
  48. package/dist/templates/codemod/README.md +1 -0
  49. package/dist/templates/codemod/test.js +93 -0
  50. package/dist/templates/docs/README.md +150 -0
  51. package/dist/templates/scripts/quality-gates/check-god-objects.js +146 -0
  52. package/dist/templates/scripts/quality-gates/run-quality-gates.js +50 -0
  53. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +1997 -0
  54. package/dist/tool-loader.js +6 -1
  55. package/dist/tool-validator.js +8 -2
  56. package/dist/utils/detection.js +4 -3
  57. package/dist/utils/git-lock.js +118 -0
  58. package/dist/utils/gitignore-updater.js +148 -0
  59. package/dist/utils/quality-gates.js +47 -7
  60. package/dist/utils/spec-resolver.js +23 -3
  61. package/dist/utils/yaml-validation.js +155 -0
  62. package/dist/validation/spec-validation.js +81 -2
  63. package/package.json +2 -2
  64. package/templates/.caws/schemas/waivers.schema.json +30 -0
  65. package/templates/.caws/schemas/working-spec.schema.json +133 -0
  66. package/templates/.caws/templates/working-spec.template.yml +74 -0
  67. package/templates/.caws/tools/README.md +20 -0
  68. package/templates/.caws/tools/scope-guard.js +208 -0
  69. package/templates/.caws/tools-allow.json +331 -0
  70. package/templates/.caws/waivers.yml +19 -0
  71. package/templates/.cursor/hooks/scope-guard.sh +2 -2
  72. package/templates/.cursor/hooks/validate-spec.sh +42 -7
  73. package/templates/apps/tools/caws/COMPLETION_REPORT.md +0 -331
  74. package/templates/apps/tools/caws/MIGRATION_SUMMARY.md +0 -360
  75. package/templates/apps/tools/caws/README.md +0 -463
  76. package/templates/apps/tools/caws/TEST_STATUS.md +0 -365
  77. package/templates/apps/tools/caws/attest.js +0 -357
  78. package/templates/apps/tools/caws/ci-optimizer.js +0 -642
  79. package/templates/apps/tools/caws/config.ts +0 -245
  80. package/templates/apps/tools/caws/cross-functional.js +0 -876
  81. package/templates/apps/tools/caws/dashboard.js +0 -1112
  82. package/templates/apps/tools/caws/flake-detector.ts +0 -362
  83. package/templates/apps/tools/caws/gates.js +0 -198
  84. package/templates/apps/tools/caws/gates.ts +0 -271
  85. package/templates/apps/tools/caws/language-adapters.ts +0 -381
  86. package/templates/apps/tools/caws/language-support.d.ts +0 -367
  87. package/templates/apps/tools/caws/language-support.d.ts.map +0 -1
  88. package/templates/apps/tools/caws/language-support.js +0 -585
  89. package/templates/apps/tools/caws/legacy-assessment.ts +0 -408
  90. package/templates/apps/tools/caws/legacy-assessor.js +0 -764
  91. package/templates/apps/tools/caws/mutant-analyzer.js +0 -734
  92. package/templates/apps/tools/caws/perf-budgets.ts +0 -349
  93. package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
  94. package/templates/apps/tools/caws/property-testing.js +0 -707
  95. package/templates/apps/tools/caws/provenance.d.ts +0 -14
  96. package/templates/apps/tools/caws/provenance.d.ts.map +0 -1
  97. package/templates/apps/tools/caws/provenance.js +0 -132
  98. package/templates/apps/tools/caws/provenance.js.backup +0 -73
  99. package/templates/apps/tools/caws/provenance.ts +0 -211
  100. package/templates/apps/tools/caws/security-provenance.ts +0 -483
  101. package/templates/apps/tools/caws/shared/base-tool.ts +0 -281
  102. package/templates/apps/tools/caws/shared/config-manager.ts +0 -366
  103. package/templates/apps/tools/caws/shared/gate-checker.ts +0 -849
  104. package/templates/apps/tools/caws/shared/types.ts +0 -444
  105. package/templates/apps/tools/caws/shared/validator.ts +0 -305
  106. package/templates/apps/tools/caws/shared/waivers-manager.ts +0 -174
  107. package/templates/apps/tools/caws/spec-test-mapper.ts +0 -391
  108. package/templates/apps/tools/caws/test-quality.js +0 -578
  109. package/templates/apps/tools/caws/validate.js +0 -76
  110. package/templates/apps/tools/caws/validate.ts +0 -228
  111. package/templates/apps/tools/caws/waivers.js +0 -344
  112. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/waivers.schema.json +0 -0
  113. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/working-spec.schema.json +0 -0
  114. /package/{templates/apps/tools/caws → dist/templates/.caws}/templates/working-spec.template.yml +0 -0
  115. /package/{templates/apps/tools/caws → dist/templates/.caws/tools}/scope-guard.js +0 -0
  116. /package/{templates/apps/tools/caws → dist/templates/.caws}/tools-allow.json +0 -0
  117. /package/{templates/apps/tools/caws → dist/templates/.caws}/waivers.yml +0 -0
@@ -196,10 +196,11 @@ async function deriveBudget(spec, projectRoot = process.cwd(), options = {}) {
196
196
  ' This may be a path resolution or caching issue\n'
197
197
  );
198
198
  } else {
199
- console.warn(
200
- '⚠️ Policy file not found: .caws/policy.yaml\n' +
201
- ' Using default policy. Run "caws init" to create policy.yaml'
202
- );
199
+ // Policy.yaml is optional - defaults work fine, so don't warn unnecessarily
200
+ // Only show info message if user explicitly wants to see it
201
+ if (options.showPolicyInfo !== false) {
202
+ // Silent by default - policy.yaml is optional
203
+ }
203
204
  }
204
205
  }
205
206
 
@@ -240,41 +240,44 @@ async function checkTestFiles() {
240
240
  * @returns {Promise<Object>} Check result
241
241
  */
242
242
  async function checkCAWSTools() {
243
- const toolsPath = 'apps/tools/caws';
243
+ // Check new location first, then legacy location for backward compatibility
244
+ const toolsPath = '.caws/tools';
245
+ const legacyToolsPath = 'apps/tools/caws';
244
246
 
245
- if (!(await fs.pathExists(toolsPath))) {
247
+ if (!(await fs.pathExists(toolsPath)) && !(await fs.pathExists(legacyToolsPath))) {
246
248
  return {
247
- passed: false,
248
- severity: 'low',
249
- message: 'CAWS tools directory not found',
250
- fix: 'Scaffold tools: caws scaffold',
249
+ passed: true,
250
+ severity: 'info',
251
+ message: 'CAWS tools directory not found (optional - use CLI commands instead)',
252
+ fix: 'Core functionality available via: caws validate, caws quality-gates, caws provenance',
251
253
  autoFixable: false,
252
254
  };
253
255
  }
254
256
 
255
- // Check for essential tools
256
- const essentialTools = ['validate.js', 'gates.js', 'provenance.js'];
257
- let missingTools = [];
257
+ // Tools directory exists - check for specialized tools (not core CLI duplicates)
258
+ const specializedTools = ['flake-detector.ts', 'spec-test-mapper.ts', 'perf-budgets.ts'];
259
+ const foundTools = [];
258
260
 
259
- for (const tool of essentialTools) {
260
- if (!(await fs.pathExists(path.join(toolsPath, tool)))) {
261
- missingTools.push(tool);
261
+ for (const tool of specializedTools) {
262
+ if (await fs.pathExists(path.join(toolsPath, tool))) {
263
+ foundTools.push(tool);
262
264
  }
263
265
  }
264
266
 
265
- if (missingTools.length > 0) {
267
+ if (foundTools.length === 0) {
266
268
  return {
267
- passed: false,
268
- severity: 'medium',
269
- message: `Missing ${missingTools.length} essential tools`,
270
- fix: 'Re-scaffold tools: caws scaffold --force',
269
+ passed: true,
270
+ severity: 'info',
271
+ message: 'No specialized tools found (optional - use CLI commands for core functionality)',
272
+ fix: 'Core functionality available via: caws validate, caws quality-gates, caws provenance',
271
273
  autoFixable: false,
272
274
  };
273
275
  }
274
276
 
275
277
  return {
276
278
  passed: true,
277
- message: 'All essential CAWS tools present',
279
+ message: `Found ${foundTools.length} specialized tool(s): ${foundTools.join(', ')}`,
280
+ note: 'Core functionality (validate, quality-gates, provenance) available via CLI commands',
278
281
  };
279
282
  }
280
283
 
@@ -484,7 +487,9 @@ async function diagnoseCommand(options = {}) {
484
487
  console.log(chalk.blue(' • Run: caws status --visual to view project health'));
485
488
  console.log(chalk.blue(' • Run: caws validate to check working spec'));
486
489
  console.log(chalk.blue(' • Optional: Create .caws/policy.yaml for custom budgets'));
487
- console.log(chalk.blue(' • Start implementing: caws iterate --current-state "Ready to begin"'));
490
+ console.log(
491
+ chalk.blue(' • Start implementing: caws iterate --current-state "Ready to begin"')
492
+ );
488
493
  }
489
494
  } catch (error) {
490
495
  console.error(chalk.red('\n❌ Error running diagnosis:'), error.message);
@@ -17,6 +17,7 @@ const { generateWorkingSpec } = require('../generators/working-spec');
17
17
  const { finalizeProject } = require('../utils/finalization');
18
18
  const { scaffoldCursorHooks } = require('../scaffold/cursor-hooks');
19
19
  const { scaffoldIDEIntegrations } = require('../scaffold/index');
20
+ const { updateGitignore } = require('../utils/gitignore-updater');
20
21
 
21
22
  /**
22
23
  * Initialize a new project with CAWS
@@ -361,6 +362,18 @@ async function initProject(projectName, options) {
361
362
  await fs.writeFile(path.join('.caws', 'working-spec.yaml'), specContent);
362
363
  console.log(chalk.green('✅ Created .caws/working-spec.yaml'));
363
364
 
365
+ // Optionally create policy.yaml (optional - defaults work fine)
366
+ const policyPath = path.join('.caws', 'policy.yaml');
367
+ if (!fs.existsSync(policyPath)) {
368
+ const { PolicyManager } = require('../policy/PolicyManager');
369
+ const policyManager = new PolicyManager();
370
+ const defaultPolicy = policyManager.getDefaultPolicy();
371
+ const yaml = require('js-yaml');
372
+ const policyContent = yaml.dump(defaultPolicy, { indent: 2 });
373
+ await fs.writeFile(policyPath, policyContent);
374
+ console.log(chalk.green('✅ Created .caws/policy.yaml (optional - defaults work fine)'));
375
+ }
376
+
364
377
  // Generate additional files if requested
365
378
  if (answers.generateExamples) {
366
379
  console.log(chalk.blue('📝 Generating example files...'));
@@ -409,6 +422,17 @@ Happy coding! 🎯
409
422
  console.log(chalk.blue('🎨 Setting up IDE integrations...'));
410
423
  await scaffoldIDEIntegrations(process.cwd(), { force: false });
411
424
 
425
+ // Update .gitignore to exclude CAWS local runtime files
426
+ console.log(chalk.blue('📝 Updating .gitignore...'));
427
+ const gitignoreUpdated = await updateGitignore(process.cwd());
428
+ if (gitignoreUpdated) {
429
+ console.log(chalk.green('✅ Updated .gitignore to exclude CAWS local runtime files'));
430
+ console.log(
431
+ chalk.gray(' Tracked: Specs, policy, waivers, provenance, plans (shared with team)')
432
+ );
433
+ console.log(chalk.gray(' Ignored: Agent runtime, temp files, logs (local-only)'));
434
+ }
435
+
412
436
  // Finalize project
413
437
  await finalizeProject(projectName, options, answers);
414
438
  } else {
@@ -456,7 +480,7 @@ Happy coding! 🎯
456
480
  experimentalSandbox: '',
457
481
  aiConfidence: 0.8,
458
482
  uncertaintyAreas: '',
459
- complexityFactors: ''
483
+ complexityFactors: '',
460
484
  };
461
485
 
462
486
  const specContent = generateWorkingSpec(defaultAnswers);
@@ -464,6 +488,18 @@ Happy coding! 🎯
464
488
  await fs.writeFile(path.join('.caws', 'working-spec.yaml'), specContent);
465
489
  console.log(chalk.green('✅ Created .caws/working-spec.yaml'));
466
490
 
491
+ // Optionally create policy.yaml (optional - defaults work fine)
492
+ const policyPath = path.join('.caws', 'policy.yaml');
493
+ if (!fs.existsSync(policyPath)) {
494
+ const { PolicyManager } = require('../policy/PolicyManager');
495
+ const policyManager = new PolicyManager();
496
+ const defaultPolicy = policyManager.getDefaultPolicy();
497
+ const yaml = require('js-yaml');
498
+ const policyContent = yaml.dump(defaultPolicy, { indent: 2 });
499
+ await fs.writeFile(policyPath, policyContent);
500
+ console.log(chalk.green('✅ Created .caws/policy.yaml (optional - defaults work fine)'));
501
+ }
502
+
467
503
  // Setup Cursor hooks by default in non-interactive mode
468
504
  console.log(chalk.blue('🎯 Setting up Cursor hooks...'));
469
505
  await scaffoldCursorHooks(process.cwd());
@@ -472,6 +508,17 @@ Happy coding! 🎯
472
508
  console.log(chalk.blue('🎨 Setting up IDE integrations...'));
473
509
  await scaffoldIDEIntegrations(process.cwd(), { force: false });
474
510
 
511
+ // Update .gitignore to exclude CAWS local runtime files
512
+ console.log(chalk.blue('📝 Updating .gitignore...'));
513
+ const gitignoreUpdated = await updateGitignore(process.cwd());
514
+ if (gitignoreUpdated) {
515
+ console.log(chalk.green('✅ Updated .gitignore to exclude CAWS local runtime files'));
516
+ console.log(
517
+ chalk.gray(' Tracked: Specs, policy, waivers, provenance, plans (shared with team)')
518
+ );
519
+ console.log(chalk.gray(' Ignored: Agent runtime, temp files, logs (local-only)'));
520
+ }
521
+
475
522
  // Finalize project
476
523
  await finalizeProject(projectName, options, defaultAnswers);
477
524
  }
@@ -481,7 +528,7 @@ Happy coding! 🎯
481
528
  console.log(chalk.blue('\nNext steps:'));
482
529
  console.log('1. Review .caws/working-spec.yaml');
483
530
  console.log('2. Customize the specification for your needs');
484
-
531
+
485
532
  // Show contract requirements if Tier 1 or 2
486
533
  // Use answers if available (interactive mode), otherwise default to 2
487
534
  const riskTier = answers?.riskTier || 2;
@@ -495,7 +542,7 @@ Happy coding! 🎯
495
542
  console.log(chalk.gray(' description: "Project-level CAWS configuration"'));
496
543
  console.log(' Or use "chore" mode for maintenance work (mode: chore)');
497
544
  }
498
-
545
+
499
546
  console.log('\n📋 Recommended Setup Workflow:');
500
547
  console.log(' 1. Review .caws/working-spec.yaml');
501
548
  console.log(' 2. Run: caws scaffold (adds tools and templates)');
@@ -511,7 +558,7 @@ Happy coding! 🎯
511
558
  if (error.stack) {
512
559
  console.error(chalk.gray(error.stack));
513
560
  }
514
-
561
+
515
562
  // Cleanup on error (only for new directory creation)
516
563
  if (projectName && projectName !== '.' && fs.existsSync(projectName)) {
517
564
  try {
@@ -202,7 +202,46 @@ async function createSpec(id, options = {}) {
202
202
  const filePath = path.join(SPECS_DIR, fileName);
203
203
 
204
204
  // Write spec file
205
- await fs.writeFile(filePath, yaml.dump(specContent, { indent: 2 }));
205
+ const yamlContent = yaml.dump(specContent, { indent: 2 });
206
+ await fs.writeFile(filePath, yamlContent);
207
+
208
+ // Validate written file (YAML syntax and structure)
209
+ try {
210
+ const writtenContent = await fs.readFile(filePath, 'utf8');
211
+ const parsed = yaml.load(writtenContent);
212
+
213
+ // Validate YAML syntax was preserved
214
+ if (!parsed || typeof parsed !== 'object') {
215
+ await fs.remove(filePath);
216
+ throw new Error('Failed to parse written spec file - invalid YAML structure');
217
+ }
218
+
219
+ // Validate spec structure using CAWS validation
220
+ const { validateWorkingSpec } = require('../validation/spec-validation');
221
+ const validation = validateWorkingSpec(parsed);
222
+
223
+ if (!validation.valid) {
224
+ await fs.remove(filePath);
225
+ const errorMessages = validation.errors
226
+ .map((e) => `${e.instancePath}: ${e.message}`)
227
+ .join('; ');
228
+ throw new Error(`Spec validation failed: ${errorMessages}`);
229
+ }
230
+ } catch (error) {
231
+ // Clean up invalid file if it exists
232
+ if (await fs.pathExists(filePath)) {
233
+ await fs.remove(filePath);
234
+ }
235
+
236
+ // Re-throw with helpful message
237
+ if (error.message.includes('YAMLException') || error.message.includes('yaml')) {
238
+ throw new Error(
239
+ `Failed to create valid spec: YAML syntax error. ${error.message}\n` +
240
+ '💡 Consider using the interactive mode: caws specs create <id> --interactive'
241
+ );
242
+ }
243
+ throw error;
244
+ }
206
245
 
207
246
  // Update registry
208
247
  const registry = await loadSpecsRegistry();
@@ -182,10 +182,10 @@ async function loadWaiverStatus() {
182
182
  */
183
183
  async function checkQualityGates() {
184
184
  // For now, return a placeholder
185
- // In full implementation, this would run actual gate checks
185
+ // Quality gates are available via CLI or MCP
186
186
  return {
187
187
  checked: false,
188
- message: 'Run: node apps/tools/caws/gates.js for full gate status',
188
+ message: 'Run: caws quality-gates or use MCP tool caws_quality_gates_run for full gate status',
189
189
  };
190
190
  }
191
191
 
@@ -23,9 +23,8 @@ async function initializeToolSystem() {
23
23
  if (toolLoader) return toolLoader;
24
24
 
25
25
  try {
26
- toolLoader = new ToolLoader({
27
- toolsDir: path.join(process.cwd(), 'apps/tools/caws'),
28
- });
26
+ // ToolLoader now checks .caws/tools first, then falls back to legacy location
27
+ toolLoader = new ToolLoader();
29
28
 
30
29
  toolValidator = new ToolValidator();
31
30
 
@@ -49,15 +49,19 @@ function initializeGlobalSetup() {
49
49
  function loadProvenanceTools() {
50
50
  if (provenanceTools) return provenanceTools; // Already loaded
51
51
 
52
- // Try multiple possible locations for provenance tools
52
+ // Provenance tools are now handled by CLI command (caws provenance)
53
+ // Legacy tool loading removed - use CLI instead
54
+ // Try multiple possible locations for provenance tools (legacy support)
53
55
  const possiblePaths = [
54
- // 1. Bundled templates in CLI package (for global installs)
55
- path.join(__dirname, '../../templates/apps/tools/caws/provenance.js'),
56
- // 2. Local project templates
56
+ // 1. New location (if someone manually adds it)
57
+ path.join(process.cwd(), '.caws/tools/provenance.js'),
58
+ // 2. Legacy location (for backward compatibility)
57
59
  path.join(process.cwd(), 'apps/tools/caws/provenance.js'),
58
- // 3. Template package in monorepo
60
+ // 3. Bundled templates in CLI package (legacy)
61
+ path.join(__dirname, '../../templates/.caws/tools/provenance.js'),
62
+ // 4. Template package in monorepo (legacy)
59
63
  path.join(__dirname, '../../../caws-template/apps/tools/caws/provenance.js'),
60
- // 4. Detected setup template directory
64
+ // 5. Detected setup template directory
61
65
  null, // Will be set from setup if available
62
66
  ];
63
67
 
@@ -65,7 +69,7 @@ function loadProvenanceTools() {
65
69
  try {
66
70
  const setup = cawsSetup || initializeGlobalSetup();
67
71
  if (setup?.hasTemplateDir && setup?.templateDir) {
68
- possiblePaths[3] = path.join(setup.templateDir, 'apps/tools/caws/provenance.js');
72
+ possiblePaths[4] = path.join(setup.templateDir, '.caws/tools/provenance.js');
69
73
  }
70
74
  } catch (setupError) {
71
75
  // Continue without detected setup
@@ -97,8 +101,13 @@ function initializeLanguageSupport() {
97
101
  if (languageSupport) return languageSupport;
98
102
 
99
103
  try {
100
- // Try multiple possible locations for language support
104
+ // Language support tools removed - use CLI instead
105
+ // Try multiple possible locations for language support (legacy support)
101
106
  const possiblePaths = [
107
+ // New location (if someone manually adds it)
108
+ path.join(process.cwd(), '.caws/tools/language-support.js'),
109
+ // Legacy locations
110
+ path.join(process.cwd(), 'apps/tools/caws/language-support.js'),
102
111
  path.join(__dirname, '../../../caws-template/apps/tools/caws/language-support.js'),
103
112
  path.join(__dirname, '../../../../caws-template/apps/tools/caws/language-support.js'),
104
113
  path.join(process.cwd(), 'packages/caws-template/apps/tools/caws/language-support.js'),
@@ -42,16 +42,28 @@ function generateWorkingSpec(answers) {
42
42
  .split(',')
43
43
  .map((s) => s.trim())
44
44
  .filter((s) => s),
45
- out: (answers.scopeOut || 'node_modules/, dist/')
45
+ out: (answers.scopeOut || 'node_modules/, dist/, build/')
46
46
  .split(',')
47
47
  .map((s) => s.trim())
48
- .filter((s) => s),
48
+ .filter((s) => s)
49
+ // Remove glob patterns - scope.out should only contain directory paths
50
+ .filter((s) => !s.includes('*') && !s.includes('?'))
51
+ // Ensure paths end with / for directories or are explicit file paths
52
+ .map((s) => {
53
+ // If it's a directory pattern without trailing slash, add it
54
+ if (!s.includes('.') && !s.endsWith('/')) {
55
+ return s + '/';
56
+ }
57
+ return s;
58
+ }),
49
59
  },
50
60
  invariants: (answers.projectInvariants || 'System maintains data consistency')
51
61
  .split('\n')
52
62
  .map((i) => i.trim())
53
63
  .filter((i) => i),
54
- acceptance: (answers.acceptanceCriteria || 'Given current state, when action occurs, then expected result')
64
+ acceptance: (
65
+ answers.acceptanceCriteria || 'Given current state, when action occurs, then expected result'
66
+ )
55
67
  .split('\n')
56
68
  .filter((a) => a.trim())
57
69
  .map((criteria, index) => {
@@ -107,7 +119,7 @@ function generateWorkingSpec(answers) {
107
119
  },
108
120
  ];
109
121
  }
110
-
122
+
111
123
  // For Tier 1 & 2, provide minimal project_setup contract if none specified
112
124
  const riskTier = answers.riskTier || 2;
113
125
  if (riskTier === 1 || riskTier === 2) {
@@ -115,11 +127,12 @@ function generateWorkingSpec(answers) {
115
127
  {
116
128
  type: 'project_setup',
117
129
  path: '.caws/working-spec.yaml',
118
- description: 'Project-level CAWS configuration. Feature-specific contracts will be added as features are developed.',
130
+ description:
131
+ 'Project-level CAWS configuration. Feature-specific contracts will be added as features are developed.',
119
132
  },
120
133
  ];
121
134
  }
122
-
135
+
123
136
  // Tier 3 doesn't require contracts
124
137
  return [];
125
138
  })(),
@@ -138,6 +138,100 @@ if [ ! -d ".caws" ]; then
138
138
  exit 0
139
139
  fi
140
140
 
141
+ # Check for git locks before proceeding
142
+ if [ -f ".git/index.lock" ]; then
143
+ LOCK_AGE=$(($(date +%s) - $(stat -f %m .git/index.lock 2>/dev/null || stat -c %Y .git/index.lock 2>/dev/null || echo 0)))
144
+ LOCK_AGE_MINUTES=$((LOCK_AGE / 60))
145
+
146
+ if [ $LOCK_AGE_MINUTES -gt 5 ]; then
147
+ echo "⚠️ Stale git lock detected (${LOCK_AGE_MINUTES} minutes old)"
148
+ echo "💡 This may indicate a crashed git process"
149
+ echo "💡 Remove stale lock: rm .git/index.lock"
150
+ echo "⚠️ Warning: Check for running git/editor processes before removing"
151
+ exit 1
152
+ else
153
+ echo "⚠️ Git lock detected (${LOCK_AGE_MINUTES} minutes old)"
154
+ echo "💡 Another git process may be running"
155
+ echo "💡 Wait for the other process to complete, or check for running processes"
156
+ exit 1
157
+ fi
158
+ fi
159
+
160
+ # Validate YAML syntax for all CAWS spec files
161
+ echo "🔍 Validating YAML syntax for CAWS spec files..."
162
+ YAML_VALIDATION_FAILED=false
163
+
164
+ # Find all staged .yaml/.yml files in .caws directory
165
+ STAGED_YAML_FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.caws/.*\.(yaml|yml)$' || true)
166
+
167
+ if [ -n "$STAGED_YAML_FILES" ]; then
168
+ # Use Node.js to validate YAML if available
169
+ if command -v node >/dev/null 2>&1; then
170
+ # Try to use CAWS CLI for validation
171
+ if command -v caws >/dev/null 2>&1; then
172
+ for file in $STAGED_YAML_FILES; do
173
+ if [ -f "$file" ]; then
174
+ # Use Node.js to validate YAML syntax
175
+ if ! node -e "
176
+ const yaml = require('js-yaml');
177
+ const fs = require('fs');
178
+ try {
179
+ const content = fs.readFileSync('$file', 'utf8');
180
+ yaml.load(content);
181
+ process.exit(0);
182
+ } catch (error) {
183
+ console.error('❌ Invalid YAML in $file');
184
+ console.error(' Error:', error.message);
185
+ if (error.mark) {
186
+ console.error(' Line:', error.mark.line + 1, 'Column:', error.mark.column + 1);
187
+ if (error.mark.snippet) console.error(' ' + error.mark.snippet);
188
+ }
189
+ process.exit(1);
190
+ }
191
+ " 2>&1; then
192
+ YAML_VALIDATION_FAILED=true
193
+ fi
194
+ fi
195
+ done
196
+ else
197
+ # Fallback: use node directly with js-yaml
198
+ for file in $STAGED_YAML_FILES; do
199
+ if [ -f "$file" ]; then
200
+ if ! node -e "
201
+ const yaml = require('js-yaml');
202
+ const fs = require('fs');
203
+ try {
204
+ const content = fs.readFileSync('$file', 'utf8');
205
+ yaml.load(content);
206
+ process.exit(0);
207
+ } catch (error) {
208
+ console.error('❌ Invalid YAML in $file');
209
+ console.error(' Error:', error.message);
210
+ if (error.mark) {
211
+ console.error(' Line:', error.mark.line + 1, 'Column:', error.mark.column + 1);
212
+ if (error.mark.snippet) console.error(' ' + error.mark.snippet);
213
+ }
214
+ process.exit(1);
215
+ }
216
+ " 2>&1; then
217
+ YAML_VALIDATION_FAILED=true
218
+ fi
219
+ fi
220
+ done
221
+ fi
222
+ else
223
+ echo "⚠️ Node.js not available - skipping YAML validation"
224
+ echo "💡 Install Node.js to enable YAML syntax validation"
225
+ fi
226
+ fi
227
+
228
+ if [ "$YAML_VALIDATION_FAILED" = true ]; then
229
+ echo "❌ YAML syntax validation failed - commit blocked"
230
+ echo "💡 Fix YAML syntax errors above before committing"
231
+ echo "💡 Consider using 'caws specs create <id>' instead of manual creation"
232
+ exit 1
233
+ fi
234
+
141
235
  # Fallback chain for quality gates:
142
236
  # 1. Try Node.js script (if exists)
143
237
  # 2. Try CAWS CLI
@@ -231,38 +325,41 @@ fi
231
325
  # Run hidden TODO analysis on staged files only (if available)
232
326
  if [ "$QUALITY_GATES_RAN" = true ]; then
233
327
  echo "🔍 Checking for hidden TODOs in staged files..."
234
- # Try quality gates package TODO analyzer first (published package)
328
+
329
+ # Find TODO analyzer .mjs file (preferred - no Python dependency)
330
+ TODO_ANALYZER=""
331
+
332
+ # Try quality gates package TODO analyzer (published package)
235
333
  if [ -f "node_modules/@paths.design/quality-gates/todo-analyzer.mjs" ]; then
236
- if command -v node >/dev/null 2>&1; then
237
- if node node_modules/@paths.design/quality-gates/todo-analyzer.mjs --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
238
- echo "✅ No critical hidden TODOs found in staged files"
239
- else
240
- echo "❌ Critical hidden TODOs detected in staged files - commit blocked"
241
- echo "💡 Fix stub implementations and placeholder code before committing"
242
- echo "📖 See docs/PLACEHOLDER-DETECTION-GUIDE.md for classification"
243
- echo ""
244
- echo "🔍 Running detailed analysis on staged files..."
245
- node node_modules/@paths.design/quality-gates/todo-analyzer.mjs --staged-only --min-confidence 0.8
246
- exit 1
247
- fi
248
- fi
334
+ TODO_ANALYZER="node_modules/@paths.design/quality-gates/todo-analyzer.mjs"
249
335
  # Try quality gates package TODO analyzer (monorepo/local copy)
250
336
  elif [ -f "node_modules/@caws/quality-gates/todo-analyzer.mjs" ]; then
251
- if command -v node >/dev/null 2>&1; then
252
- if node node_modules/@caws/quality-gates/todo-analyzer.mjs --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
253
- echo "✅ No critical hidden TODOs found in staged files"
254
- else
255
- echo "❌ Critical hidden TODOs detected in staged files - commit blocked"
256
- echo "💡 Fix stub implementations and placeholder code before committing"
257
- echo "📖 See docs/PLACEHOLDER-DETECTION-GUIDE.md for classification"
258
- echo ""
259
- echo "🔍 Running detailed analysis on staged files..."
260
- node node_modules/@caws/quality-gates/todo-analyzer.mjs --staged-only --min-confidence 0.8
261
- exit 1
262
- fi
337
+ TODO_ANALYZER="node_modules/@caws/quality-gates/todo-analyzer.mjs"
338
+ # Try monorepo structure (development)
339
+ elif [ -f "packages/quality-gates/todo-analyzer.mjs" ]; then
340
+ TODO_ANALYZER="packages/quality-gates/todo-analyzer.mjs"
341
+ # Try local copy in scripts directory (if scaffolded)
342
+ elif [ -f "scripts/todo-analyzer.mjs" ]; then
343
+ TODO_ANALYZER="scripts/todo-analyzer.mjs"
344
+ fi
345
+
346
+ # Run TODO analyzer if found
347
+ if [ -n "$TODO_ANALYZER" ] && command -v node >/dev/null 2>&1; then
348
+ if node "$TODO_ANALYZER" --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
349
+ echo "✅ No critical hidden TODOs found in staged files"
350
+ else
351
+ echo "❌ Critical hidden TODOs detected in staged files - commit blocked"
352
+ echo "💡 Fix stub implementations and placeholder code before committing"
353
+ echo "📖 See docs/PLACEHOLDER-DETECTION-GUIDE.md for classification"
354
+ echo ""
355
+ echo "🔍 Running detailed analysis on staged files..."
356
+ node "$TODO_ANALYZER" --staged-only --min-confidence 0.8
357
+ exit 1
263
358
  fi
264
- # Fallback to legacy Python analyzer
359
+ # Fallback to legacy Python analyzer (deprecated - will be removed)
265
360
  elif command -v python3 >/dev/null 2>&1 && [ -f "scripts/v3/analysis/todo_analyzer.py" ]; then
361
+ echo "⚠️ Using legacy Python TODO analyzer (deprecated)"
362
+ echo "💡 Install @paths.design/quality-gates for Node.js version: npm install --save-dev @paths.design/quality-gates"
266
363
  if python3 scripts/v3/analysis/todo_analyzer.py --staged-only --ci-mode --min-confidence 0.8 >/dev/null 2>&1; then
267
364
  echo "✅ No critical hidden TODOs found in staged files"
268
365
  else
@@ -274,8 +371,9 @@ if [ "$QUALITY_GATES_RAN" = true ]; then
274
371
  python3 scripts/v3/analysis/todo_analyzer.py --staged-only --min-confidence 0.8
275
372
  exit 1
276
373
  fi
277
- elif command -v python3 >/dev/null 2>&1; then
278
- echo "⚠️ Python3 found but TODO analyzer not available - skipping"
374
+ else
375
+ echo "⚠️ TODO analyzer not available - skipping hidden TODO check"
376
+ echo "💡 Install @paths.design/quality-gates for TODO analysis: npm install --save-dev @paths.design/quality-gates"
279
377
  fi
280
378
  fi
281
379