@paths.design/caws-cli 7.0.1 → 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 (121) hide show
  1. package/dist/budget-derivation.js +5 -4
  2. package/dist/commands/diagnose.js +26 -20
  3. package/dist/commands/init.js +72 -5
  4. package/dist/commands/specs.js +40 -1
  5. package/dist/commands/status.js +2 -2
  6. package/dist/commands/templates.js +10 -0
  7. package/dist/commands/tool.js +2 -3
  8. package/dist/commands/validate.js +12 -0
  9. package/dist/config/index.js +17 -8
  10. package/dist/generators/working-spec.js +42 -9
  11. package/dist/index.js +3 -1
  12. package/dist/scaffold/cursor-hooks.js +10 -2
  13. package/dist/scaffold/git-hooks.js +189 -32
  14. package/dist/scaffold/index.js +105 -17
  15. package/dist/templates/.caws/tools/README.md +20 -0
  16. package/dist/templates/.cursor/README.md +311 -0
  17. package/dist/templates/.cursor/hooks/audit.sh +55 -0
  18. package/dist/templates/.cursor/hooks/block-dangerous.sh +83 -0
  19. package/dist/templates/.cursor/hooks/caws-quality-check.sh +52 -0
  20. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +130 -0
  21. package/dist/templates/.cursor/hooks/caws-tool-validation.sh +121 -0
  22. package/dist/templates/.cursor/hooks/format.sh +38 -0
  23. package/dist/templates/.cursor/hooks/naming-check.sh +64 -0
  24. package/dist/templates/.cursor/hooks/scan-secrets.sh +46 -0
  25. package/dist/templates/.cursor/hooks/scope-guard.sh +52 -0
  26. package/dist/templates/.cursor/hooks/validate-spec.sh +83 -0
  27. package/dist/templates/.cursor/hooks.json +59 -0
  28. package/dist/templates/.cursor/rules/00-claims-verification.mdc +144 -0
  29. package/dist/templates/.cursor/rules/01-working-style.mdc +50 -0
  30. package/dist/templates/.cursor/rules/02-quality-gates.mdc +370 -0
  31. package/dist/templates/.cursor/rules/03-naming-and-refactor.mdc +33 -0
  32. package/dist/templates/.cursor/rules/04-logging-language-style.mdc +23 -0
  33. package/dist/templates/.cursor/rules/05-safe-defaults-guards.mdc +23 -0
  34. package/dist/templates/.cursor/rules/06-typescript-conventions.mdc +36 -0
  35. package/dist/templates/.cursor/rules/07-process-ops.mdc +20 -0
  36. package/dist/templates/.cursor/rules/08-solid-and-architecture.mdc +16 -0
  37. package/dist/templates/.cursor/rules/09-docstrings.mdc +89 -0
  38. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +390 -0
  39. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +385 -0
  40. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +516 -0
  41. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +588 -0
  42. package/dist/templates/.cursor/rules/README.md +148 -0
  43. package/dist/templates/.github/copilot/instructions.md +311 -0
  44. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +5 -0
  45. package/dist/templates/.idea/runConfigurations/CAWS_Validate.xml +5 -0
  46. package/dist/templates/.vscode/launch.json +56 -0
  47. package/dist/templates/.vscode/settings.json +93 -0
  48. package/dist/templates/.windsurf/workflows/caws-guided-development.md +92 -0
  49. package/dist/templates/COMMIT_CONVENTIONS.md +86 -0
  50. package/dist/templates/OIDC_SETUP.md +300 -0
  51. package/dist/templates/agents.md +1047 -0
  52. package/dist/templates/codemod/README.md +1 -0
  53. package/dist/templates/codemod/test.js +93 -0
  54. package/dist/templates/docs/README.md +150 -0
  55. package/dist/templates/scripts/quality-gates/check-god-objects.js +146 -0
  56. package/dist/templates/scripts/quality-gates/run-quality-gates.js +50 -0
  57. package/dist/templates/scripts/v3/analysis/todo_analyzer.py +1997 -0
  58. package/dist/tool-loader.js +6 -1
  59. package/dist/tool-validator.js +8 -2
  60. package/dist/utils/detection.js +34 -6
  61. package/dist/utils/git-lock.js +118 -0
  62. package/dist/utils/gitignore-updater.js +148 -0
  63. package/dist/utils/quality-gates.js +47 -7
  64. package/dist/utils/spec-resolver.js +23 -3
  65. package/dist/utils/yaml-validation.js +155 -0
  66. package/dist/validation/spec-validation.js +105 -2
  67. package/package.json +2 -2
  68. package/templates/.caws/schemas/waivers.schema.json +30 -0
  69. package/templates/.caws/schemas/working-spec.schema.json +133 -0
  70. package/templates/.caws/templates/working-spec.template.yml +74 -0
  71. package/templates/.caws/tools/README.md +20 -0
  72. package/templates/.caws/tools/scope-guard.js +208 -0
  73. package/templates/.caws/tools-allow.json +331 -0
  74. package/templates/.caws/waivers.yml +19 -0
  75. package/templates/.cursor/hooks/scope-guard.sh +2 -2
  76. package/templates/.cursor/hooks/validate-spec.sh +42 -7
  77. package/templates/apps/tools/caws/COMPLETION_REPORT.md +0 -331
  78. package/templates/apps/tools/caws/MIGRATION_SUMMARY.md +0 -360
  79. package/templates/apps/tools/caws/README.md +0 -463
  80. package/templates/apps/tools/caws/TEST_STATUS.md +0 -365
  81. package/templates/apps/tools/caws/attest.js +0 -357
  82. package/templates/apps/tools/caws/ci-optimizer.js +0 -642
  83. package/templates/apps/tools/caws/config.ts +0 -245
  84. package/templates/apps/tools/caws/cross-functional.js +0 -876
  85. package/templates/apps/tools/caws/dashboard.js +0 -1112
  86. package/templates/apps/tools/caws/flake-detector.ts +0 -362
  87. package/templates/apps/tools/caws/gates.js +0 -198
  88. package/templates/apps/tools/caws/gates.ts +0 -271
  89. package/templates/apps/tools/caws/language-adapters.ts +0 -381
  90. package/templates/apps/tools/caws/language-support.d.ts +0 -367
  91. package/templates/apps/tools/caws/language-support.d.ts.map +0 -1
  92. package/templates/apps/tools/caws/language-support.js +0 -585
  93. package/templates/apps/tools/caws/legacy-assessment.ts +0 -408
  94. package/templates/apps/tools/caws/legacy-assessor.js +0 -764
  95. package/templates/apps/tools/caws/mutant-analyzer.js +0 -734
  96. package/templates/apps/tools/caws/perf-budgets.ts +0 -349
  97. package/templates/apps/tools/caws/prompt-lint.js.backup +0 -274
  98. package/templates/apps/tools/caws/property-testing.js +0 -707
  99. package/templates/apps/tools/caws/provenance.d.ts +0 -14
  100. package/templates/apps/tools/caws/provenance.d.ts.map +0 -1
  101. package/templates/apps/tools/caws/provenance.js +0 -132
  102. package/templates/apps/tools/caws/provenance.js.backup +0 -73
  103. package/templates/apps/tools/caws/provenance.ts +0 -211
  104. package/templates/apps/tools/caws/security-provenance.ts +0 -483
  105. package/templates/apps/tools/caws/shared/base-tool.ts +0 -281
  106. package/templates/apps/tools/caws/shared/config-manager.ts +0 -366
  107. package/templates/apps/tools/caws/shared/gate-checker.ts +0 -849
  108. package/templates/apps/tools/caws/shared/types.ts +0 -444
  109. package/templates/apps/tools/caws/shared/validator.ts +0 -305
  110. package/templates/apps/tools/caws/shared/waivers-manager.ts +0 -174
  111. package/templates/apps/tools/caws/spec-test-mapper.ts +0 -391
  112. package/templates/apps/tools/caws/test-quality.js +0 -578
  113. package/templates/apps/tools/caws/validate.js +0 -76
  114. package/templates/apps/tools/caws/validate.ts +0 -228
  115. package/templates/apps/tools/caws/waivers.js +0 -344
  116. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/waivers.schema.json +0 -0
  117. /package/{templates/apps/tools/caws → dist/templates/.caws}/schemas/working-spec.schema.json +0 -0
  118. /package/{templates/apps/tools/caws → dist/templates/.caws}/templates/working-spec.template.yml +0 -0
  119. /package/{templates/apps/tools/caws → dist/templates/.caws/tools}/scope-guard.js +0 -0
  120. /package/{templates/apps/tools/caws → dist/templates/.caws}/tools-allow.json +0 -0
  121. /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
 
@@ -481,9 +484,12 @@ async function diagnoseCommand(options = {}) {
481
484
 
482
485
  if (issueCount === 0) {
483
486
  console.log(chalk.blue('📚 Next steps:'));
484
- console.log(chalk.blue(' • Run: caws status to view project health'));
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
- console.log(chalk.blue(' • Run: node apps/tools/caws/gates.js for quality gates'));
489
+ console.log(chalk.blue(' • Optional: Create .caws/policy.yaml for custom budgets'));
490
+ console.log(
491
+ chalk.blue(' • Start implementing: caws iterate --current-state "Ready to begin"')
492
+ );
487
493
  }
488
494
  } catch (error) {
489
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,17 +528,37 @@ 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
- console.log('3. Run "caws validate" to check your setup');
531
+
532
+ // Show contract requirements if Tier 1 or 2
533
+ // Use answers if available (interactive mode), otherwise default to 2
534
+ const riskTier = answers?.riskTier || 2;
535
+ if (riskTier === 1 || riskTier === 2) {
536
+ console.log(chalk.yellow('\n⚠️ Important: Contract Requirements'));
537
+ console.log(` Tier ${riskTier} changes require at least one contract.`);
538
+ console.log(' For infrastructure/setup work, add a minimal contract:');
539
+ console.log(chalk.gray(' contracts:'));
540
+ console.log(chalk.gray(' - type: "project_setup"'));
541
+ console.log(chalk.gray(' path: ".caws/working-spec.yaml"'));
542
+ console.log(chalk.gray(' description: "Project-level CAWS configuration"'));
543
+ console.log(' Or use "chore" mode for maintenance work (mode: chore)');
544
+ }
545
+
546
+ console.log('\n📋 Recommended Setup Workflow:');
547
+ console.log(' 1. Review .caws/working-spec.yaml');
548
+ console.log(' 2. Run: caws scaffold (adds tools and templates)');
549
+ console.log(' 3. Run: caws validate (verify setup)');
550
+ console.log(' 4. Run: caws diagnose (check health)');
551
+ console.log(' 5. Optional: Create .caws/policy.yaml for custom budgets');
485
552
  if (answers?.useCursorHooks || options.interactive === false) {
486
- console.log('4. Restart Cursor IDE to activate quality gates');
553
+ console.log(' 6. Restart Cursor IDE to activate quality gates');
487
554
  }
488
- console.log('5. Start implementing your features!');
555
+ console.log('\n💡 Quick start: caws scaffold && caws validate && caws diagnose');
489
556
  } catch (error) {
490
557
  console.error(chalk.red('❌ Error during initialization:'), error.message);
491
558
  if (error.stack) {
492
559
  console.error(chalk.gray(error.stack));
493
560
  }
494
-
561
+
495
562
  // Cleanup on error (only for new directory creation)
496
563
  if (projectName && projectName !== '.' && fs.existsSync(projectName)) {
497
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
 
@@ -7,6 +7,7 @@
7
7
  const fs = require('fs-extra');
8
8
  const path = require('path');
9
9
  const chalk = require('chalk');
10
+ const { findPackageRoot } = require('../utils/detection');
10
11
 
11
12
  /**
12
13
  * Built-in template definitions
@@ -64,11 +65,20 @@ const BUILTIN_TEMPLATES = {
64
65
 
65
66
  /**
66
67
  * Get template directory path
68
+ * Works in both development and global install scenarios
67
69
  * @returns {string|null} Template directory path or null
68
70
  */
69
71
  function getTemplateDir() {
72
+ // Find package root using shared utility
73
+ const packageRoot = findPackageRoot(__dirname);
74
+
70
75
  const possiblePaths = [
76
+ // First: Try templates relative to package root (works in dev and global install)
77
+ path.join(packageRoot, 'templates'),
78
+ // Fallback: Try relative to current file location (for development)
71
79
  path.join(__dirname, '../../templates'),
80
+ path.join(__dirname, '../templates'),
81
+ // Legacy fallbacks
72
82
  path.join(process.cwd(), 'packages/caws-cli/templates'),
73
83
  path.join(process.cwd(), 'templates'),
74
84
  ];
@@ -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
 
@@ -194,6 +194,18 @@ async function validateCommand(specFile, options = {}) {
194
194
  if (error.suggestion) {
195
195
  console.log(` ${chalk.blue('💡 ' + error.suggestion)}`);
196
196
  }
197
+ if (error.example) {
198
+ console.log(` ${chalk.gray('Example:')}`);
199
+ if (error.example.contracts) {
200
+ error.example.contracts.forEach((contract) => {
201
+ console.log(` ${chalk.gray('- type: ' + contract.type)}`);
202
+ console.log(` ${chalk.gray('path: ' + contract.path)}`);
203
+ if (contract.description) {
204
+ console.log(` ${chalk.gray('description: ' + contract.description)}`);
205
+ }
206
+ });
207
+ }
208
+ }
197
209
  });
198
210
 
199
211
  // Show warnings
@@ -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) => {
@@ -97,12 +109,33 @@ function generateWorkingSpec(answers) {
97
109
  .map((s) => s.trim())
98
110
  .filter((s) => s),
99
111
  },
100
- contracts: [
101
- {
102
- type: answers.contractType || '',
103
- path: answers.contractPath || '',
104
- },
105
- ],
112
+ contracts: (() => {
113
+ // If contract type/path provided, use it
114
+ if (answers.contractType && answers.contractPath) {
115
+ return [
116
+ {
117
+ type: answers.contractType,
118
+ path: answers.contractPath,
119
+ },
120
+ ];
121
+ }
122
+
123
+ // For Tier 1 & 2, provide minimal project_setup contract if none specified
124
+ const riskTier = answers.riskTier || 2;
125
+ if (riskTier === 1 || riskTier === 2) {
126
+ return [
127
+ {
128
+ type: 'project_setup',
129
+ path: '.caws/working-spec.yaml',
130
+ description:
131
+ 'Project-level CAWS configuration. Feature-specific contracts will be added as features are developed.',
132
+ },
133
+ ];
134
+ }
135
+
136
+ // Tier 3 doesn't require contracts
137
+ return [];
138
+ })(),
106
139
  observability: {
107
140
  logs: (answers.observabilityLogs || '')
108
141
  .split(',')
package/dist/index.js CHANGED
@@ -138,7 +138,7 @@ program
138
138
  .option('--json', 'Output machine-readable JSON to stdout', false)
139
139
  .option(
140
140
  '--gates <gates>',
141
- 'Run only specific gates (comma-separated: naming,code_freeze,duplication,god_objects,documentation)',
141
+ 'Run only specific gates (comma-separated: naming,code_freeze,duplication,god_objects,hidden-todo,documentation,placeholders)',
142
142
  ''
143
143
  )
144
144
  .option('--fix', 'Attempt automatic fixes (experimental)', false)
@@ -168,7 +168,9 @@ VALID GATES:
168
168
  code_freeze Enforce code freeze compliance
169
169
  duplication Detect functional duplication
170
170
  god_objects Prevent oversized files
171
+ hidden-todo Detect hidden incomplete implementations
171
172
  documentation Check documentation quality
173
+ placeholders Placeholder governance (explicit degradations)
172
174
 
173
175
  EXAMPLES:
174
176
  # Run all gates in development mode
@@ -9,7 +9,7 @@ const path = require('path');
9
9
  const chalk = require('chalk');
10
10
 
11
11
  // Import detection utilities
12
- const { detectCAWSSetup } = require('../utils/detection');
12
+ const { detectCAWSSetup, findPackageRoot } = require('../utils/detection');
13
13
 
14
14
  /**
15
15
  * Scaffold Cursor hooks for a CAWS project
@@ -28,9 +28,17 @@ async function scaffoldCursorHooks(projectDir, levels = ['safety', 'quality', 's
28
28
 
29
29
  // Determine template directory - prefer bundled templates
30
30
  const setup = detectCAWSSetup(projectDir);
31
- const bundledTemplateDir = path.join(__dirname, '../../templates');
31
+
32
+ // Find package root using shared utility
33
+ const packageRoot = findPackageRoot(__dirname);
34
+
35
+ // Try templates relative to package root first (works in both dev and global install)
36
+ const bundledTemplateDir = path.join(packageRoot, 'templates');
37
+ const fallbackTemplateDir = path.join(__dirname, '../../templates');
32
38
  const templateDir = fs.existsSync(bundledTemplateDir)
33
39
  ? bundledTemplateDir
40
+ : fs.existsSync(fallbackTemplateDir)
41
+ ? fallbackTemplateDir
34
42
  : setup.templateDir || path.resolve(__dirname, '../templates');
35
43
 
36
44
  const cursorTemplateDir = path.join(templateDir, '.cursor');