@paths.design/caws-cli 9.3.2 → 10.1.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.
Files changed (286) hide show
  1. package/README.md +71 -32
  2. package/dist/budget-derivation.js +221 -74
  3. package/dist/commands/archive.js +67 -28
  4. package/dist/commands/burnup.js +20 -11
  5. package/dist/commands/diagnose.js +34 -22
  6. package/dist/commands/evaluate.js +41 -15
  7. package/dist/commands/gates.js +149 -0
  8. package/dist/commands/init.js +150 -19
  9. package/dist/commands/iterate.js +81 -4
  10. package/dist/commands/parallel.js +4 -0
  11. package/dist/commands/plan.js +9 -19
  12. package/dist/commands/provenance.js +53 -17
  13. package/dist/commands/quality-monitor.js +64 -45
  14. package/dist/commands/scope.js +264 -0
  15. package/dist/commands/sidecar.js +74 -0
  16. package/dist/commands/specs.js +381 -45
  17. package/dist/commands/status.js +117 -9
  18. package/dist/commands/templates.js +0 -8
  19. package/dist/commands/tutorial.js +10 -9
  20. package/dist/commands/validate.js +70 -6
  21. package/dist/commands/verify-acs.js +48 -76
  22. package/dist/commands/waivers.js +212 -13
  23. package/dist/commands/worktree.js +131 -26
  24. package/dist/error-handler.js +2 -13
  25. package/dist/gates/budget-limit.js +121 -0
  26. package/dist/gates/feedback.js +260 -0
  27. package/dist/gates/format.js +179 -0
  28. package/dist/gates/god-object.js +117 -0
  29. package/dist/gates/pipeline.js +167 -0
  30. package/dist/gates/scope-boundary.js +93 -0
  31. package/dist/gates/spec-completeness.js +109 -0
  32. package/dist/gates/todo-detection.js +205 -0
  33. package/dist/index.js +157 -151
  34. package/dist/parallel/parallel-manager.js +3 -3
  35. package/dist/policy/PolicyManager.js +51 -17
  36. package/dist/scaffold/claude-hooks.js +24 -1
  37. package/dist/scaffold/git-hooks.js +45 -102
  38. package/dist/scaffold/index.js +4 -3
  39. package/dist/session/session-manager.js +105 -14
  40. package/dist/sidecars/index.js +33 -0
  41. package/dist/sidecars/listeners.js +40 -0
  42. package/dist/sidecars/provenance-summary.js +238 -0
  43. package/dist/sidecars/quality-gaps.js +258 -0
  44. package/dist/sidecars/schema.js +149 -0
  45. package/dist/sidecars/spec-drift.js +151 -0
  46. package/dist/sidecars/waiver-draft.js +176 -0
  47. package/dist/templates/.caws/schemas/policy.schema.json +112 -0
  48. package/dist/templates/.caws/schemas/scope.schema.json +3 -3
  49. package/dist/templates/.caws/schemas/waivers.schema.json +96 -20
  50. package/dist/templates/.caws/schemas/working-spec.schema.json +264 -57
  51. package/dist/templates/.caws/schemas/worktrees.schema.json +3 -1
  52. package/dist/templates/.caws/templates/working-spec.template.yml +10 -4
  53. package/dist/templates/.caws/tools/scope-guard.js +66 -15
  54. package/dist/templates/.claude/README.md +1 -1
  55. package/dist/templates/.claude/hooks/audit.sh +0 -0
  56. package/dist/templates/.claude/hooks/block-dangerous.sh +52 -11
  57. package/dist/templates/.claude/hooks/classify_command.py +592 -0
  58. package/dist/templates/.claude/hooks/doc-frontmatter-check.sh +173 -0
  59. package/dist/templates/.claude/hooks/protected-paths.sh +39 -0
  60. package/dist/templates/.claude/hooks/quality-check.sh +23 -10
  61. package/dist/templates/.claude/hooks/scope-guard.sh +136 -55
  62. package/dist/templates/.claude/hooks/session-caws-status.sh +2 -2
  63. package/dist/templates/.claude/hooks/session-log.sh +76 -3
  64. package/dist/templates/.claude/hooks/stop-worktree-check.sh +1 -1
  65. package/dist/templates/.claude/hooks/test_classify_command.py +370 -0
  66. package/dist/templates/.claude/hooks/test_wrapper_smoke.sh +96 -0
  67. package/dist/templates/.claude/hooks/worktree-guard.sh +2 -2
  68. package/dist/templates/.claude/hooks/worktree-write-guard.sh +97 -4
  69. package/dist/templates/.claude/settings.json +31 -0
  70. package/dist/templates/.cursor/hooks/caws-quality-check.sh +4 -4
  71. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +1 -1
  72. package/dist/templates/.cursor/hooks/session-log.sh +924 -0
  73. package/dist/templates/.cursor/hooks.json +25 -0
  74. package/dist/templates/.cursor/rules/02-quality-gates.mdc +3 -5
  75. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +6 -11
  76. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +14 -18
  77. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +4 -4
  78. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +3 -13
  79. package/dist/templates/.github/copilot-instructions.md +5 -5
  80. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +1 -1
  81. package/dist/templates/.junie/guidelines.md +2 -2
  82. package/dist/templates/.vscode/settings.json +3 -1
  83. package/dist/templates/.windsurf/rules/caws-quality-standards.md +2 -2
  84. package/dist/templates/.windsurf/workflows/caws-guided-development.md +3 -3
  85. package/dist/templates/CLAUDE.md +77 -8
  86. package/dist/templates/agents.md +50 -9
  87. package/dist/templates/docs/README.md +8 -7
  88. package/dist/templates/scripts/new_feature.sh +80 -0
  89. package/dist/test-analysis.js +43 -30
  90. package/dist/tool-loader.js +1 -1
  91. package/dist/utils/agent-session.js +202 -0
  92. package/dist/utils/detection.js +8 -2
  93. package/dist/utils/event-log.js +584 -0
  94. package/dist/utils/event-renderer.js +521 -0
  95. package/dist/utils/finalization.js +7 -6
  96. package/dist/utils/gitignore-updater.js +3 -0
  97. package/dist/utils/lifecycle-events.js +94 -0
  98. package/dist/utils/quality-gates-utils.js +29 -44
  99. package/dist/utils/schema-validator.js +50 -0
  100. package/dist/utils/spec-resolver.js +93 -21
  101. package/dist/utils/working-state.js +530 -0
  102. package/dist/validation/spec-validation.js +191 -31
  103. package/dist/waivers-manager.js +144 -6
  104. package/dist/worktree/worktree-manager.js +598 -95
  105. package/package.json +9 -8
  106. package/templates/.caws/schemas/policy.schema.json +112 -0
  107. package/templates/.caws/schemas/scope.schema.json +3 -3
  108. package/templates/.caws/schemas/waivers.schema.json +96 -20
  109. package/templates/.caws/schemas/working-spec.schema.json +264 -57
  110. package/templates/.caws/schemas/worktrees.schema.json +3 -1
  111. package/templates/.caws/templates/working-spec.template.yml +10 -4
  112. package/templates/.caws/tools/scope-guard.js +66 -15
  113. package/templates/.claude/README.md +1 -1
  114. package/templates/.claude/hooks/block-dangerous.sh +52 -11
  115. package/templates/.claude/hooks/classify_command.py +592 -0
  116. package/templates/.claude/hooks/doc-frontmatter-check.sh +173 -0
  117. package/templates/.claude/hooks/protected-paths.sh +39 -0
  118. package/templates/.claude/hooks/quality-check.sh +23 -10
  119. package/templates/.claude/hooks/scope-guard.sh +136 -55
  120. package/templates/.claude/hooks/session-caws-status.sh +2 -2
  121. package/templates/.claude/hooks/session-log.sh +76 -3
  122. package/templates/.claude/hooks/stop-worktree-check.sh +1 -1
  123. package/templates/.claude/hooks/test_classify_command.py +370 -0
  124. package/templates/.claude/hooks/test_wrapper_smoke.sh +96 -0
  125. package/templates/.claude/hooks/worktree-guard.sh +2 -2
  126. package/templates/.claude/hooks/worktree-write-guard.sh +97 -4
  127. package/templates/.claude/settings.json +31 -0
  128. package/templates/.cursor/hooks/caws-quality-check.sh +4 -4
  129. package/templates/.cursor/hooks/caws-scope-guard.sh +1 -1
  130. package/templates/.cursor/hooks/session-log.sh +924 -0
  131. package/templates/.cursor/hooks.json +25 -0
  132. package/templates/.cursor/rules/02-quality-gates.mdc +3 -5
  133. package/templates/.cursor/rules/10-documentation-quality-standards.mdc +6 -11
  134. package/templates/.cursor/rules/11-scope-management-waivers.mdc +14 -18
  135. package/templates/.cursor/rules/12-implementation-completeness.mdc +4 -4
  136. package/templates/.cursor/rules/13-language-agnostic-standards.mdc +3 -13
  137. package/templates/.github/copilot-instructions.md +5 -5
  138. package/templates/.idea/runConfigurations/CAWS_Evaluate.xml +1 -1
  139. package/templates/.junie/guidelines.md +2 -2
  140. package/templates/.vscode/settings.json +3 -1
  141. package/templates/.windsurf/rules/caws-quality-standards.md +2 -2
  142. package/templates/.windsurf/workflows/caws-guided-development.md +3 -3
  143. package/templates/CLAUDE.md +77 -8
  144. package/templates/{AGENTS.md → agents.md} +50 -9
  145. package/templates/docs/README.md +8 -7
  146. package/templates/scripts/new_feature.sh +80 -0
  147. package/dist/budget-derivation.d.ts +0 -74
  148. package/dist/budget-derivation.d.ts.map +0 -1
  149. package/dist/cicd-optimizer.d.ts +0 -142
  150. package/dist/cicd-optimizer.d.ts.map +0 -1
  151. package/dist/commands/archive.d.ts +0 -51
  152. package/dist/commands/archive.d.ts.map +0 -1
  153. package/dist/commands/burnup.d.ts +0 -6
  154. package/dist/commands/burnup.d.ts.map +0 -1
  155. package/dist/commands/diagnose.d.ts +0 -52
  156. package/dist/commands/diagnose.d.ts.map +0 -1
  157. package/dist/commands/evaluate.d.ts +0 -8
  158. package/dist/commands/evaluate.d.ts.map +0 -1
  159. package/dist/commands/init.d.ts +0 -5
  160. package/dist/commands/init.d.ts.map +0 -1
  161. package/dist/commands/iterate.d.ts +0 -8
  162. package/dist/commands/iterate.d.ts.map +0 -1
  163. package/dist/commands/mode.d.ts +0 -25
  164. package/dist/commands/mode.d.ts.map +0 -1
  165. package/dist/commands/parallel.d.ts +0 -7
  166. package/dist/commands/parallel.d.ts.map +0 -1
  167. package/dist/commands/plan.d.ts +0 -49
  168. package/dist/commands/plan.d.ts.map +0 -1
  169. package/dist/commands/provenance.d.ts +0 -32
  170. package/dist/commands/provenance.d.ts.map +0 -1
  171. package/dist/commands/quality-gates.d.ts +0 -6
  172. package/dist/commands/quality-gates.d.ts.map +0 -1
  173. package/dist/commands/quality-gates.js +0 -444
  174. package/dist/commands/quality-monitor.d.ts +0 -17
  175. package/dist/commands/quality-monitor.d.ts.map +0 -1
  176. package/dist/commands/session.d.ts +0 -7
  177. package/dist/commands/session.d.ts.map +0 -1
  178. package/dist/commands/specs.d.ts +0 -77
  179. package/dist/commands/specs.d.ts.map +0 -1
  180. package/dist/commands/status.d.ts +0 -44
  181. package/dist/commands/status.d.ts.map +0 -1
  182. package/dist/commands/templates.d.ts +0 -74
  183. package/dist/commands/templates.d.ts.map +0 -1
  184. package/dist/commands/tool.d.ts +0 -13
  185. package/dist/commands/tool.d.ts.map +0 -1
  186. package/dist/commands/troubleshoot.d.ts +0 -8
  187. package/dist/commands/troubleshoot.d.ts.map +0 -1
  188. package/dist/commands/troubleshoot.js +0 -104
  189. package/dist/commands/tutorial.d.ts +0 -55
  190. package/dist/commands/tutorial.d.ts.map +0 -1
  191. package/dist/commands/validate.d.ts +0 -15
  192. package/dist/commands/validate.d.ts.map +0 -1
  193. package/dist/commands/waivers.d.ts +0 -8
  194. package/dist/commands/waivers.d.ts.map +0 -1
  195. package/dist/commands/workflow.d.ts +0 -85
  196. package/dist/commands/workflow.d.ts.map +0 -1
  197. package/dist/commands/worktree.d.ts +0 -7
  198. package/dist/commands/worktree.d.ts.map +0 -1
  199. package/dist/config/index.d.ts +0 -29
  200. package/dist/config/index.d.ts.map +0 -1
  201. package/dist/config/lite-scope.d.ts +0 -33
  202. package/dist/config/lite-scope.d.ts.map +0 -1
  203. package/dist/config/modes.d.ts +0 -264
  204. package/dist/config/modes.d.ts.map +0 -1
  205. package/dist/constants/spec-types.d.ts +0 -93
  206. package/dist/constants/spec-types.d.ts.map +0 -1
  207. package/dist/error-handler.d.ts +0 -151
  208. package/dist/error-handler.d.ts.map +0 -1
  209. package/dist/generators/jest-config-generator.d.ts +0 -32
  210. package/dist/generators/jest-config-generator.d.ts.map +0 -1
  211. package/dist/generators/jest-config.d.ts +0 -32
  212. package/dist/generators/jest-config.d.ts.map +0 -1
  213. package/dist/generators/jest-config.js +0 -242
  214. package/dist/generators/working-spec.d.ts +0 -13
  215. package/dist/generators/working-spec.d.ts.map +0 -1
  216. package/dist/index-new.d.ts +0 -5
  217. package/dist/index-new.d.ts.map +0 -1
  218. package/dist/index-new.js +0 -317
  219. package/dist/index.d.ts +0 -5
  220. package/dist/index.d.ts.map +0 -1
  221. package/dist/index.js.backup +0 -4711
  222. package/dist/minimal-cli.d.ts +0 -3
  223. package/dist/minimal-cli.d.ts.map +0 -1
  224. package/dist/parallel/parallel-manager.d.ts +0 -67
  225. package/dist/parallel/parallel-manager.d.ts.map +0 -1
  226. package/dist/policy/PolicyManager.d.ts +0 -104
  227. package/dist/policy/PolicyManager.d.ts.map +0 -1
  228. package/dist/scaffold/claude-hooks.d.ts +0 -28
  229. package/dist/scaffold/claude-hooks.d.ts.map +0 -1
  230. package/dist/scaffold/cursor-hooks.d.ts +0 -7
  231. package/dist/scaffold/cursor-hooks.d.ts.map +0 -1
  232. package/dist/scaffold/git-hooks.d.ts +0 -38
  233. package/dist/scaffold/git-hooks.d.ts.map +0 -1
  234. package/dist/scaffold/index.d.ts +0 -17
  235. package/dist/scaffold/index.d.ts.map +0 -1
  236. package/dist/session/session-manager.d.ts +0 -94
  237. package/dist/session/session-manager.d.ts.map +0 -1
  238. package/dist/spec/SpecFileManager.d.ts +0 -146
  239. package/dist/spec/SpecFileManager.d.ts.map +0 -1
  240. package/dist/templates/.cursor/hooks/caws-tool-validation.sh +0 -121
  241. package/dist/templates/.github/copilot/instructions.md +0 -311
  242. package/dist/test-analysis.d.ts +0 -231
  243. package/dist/test-analysis.d.ts.map +0 -1
  244. package/dist/tool-interface.d.ts +0 -236
  245. package/dist/tool-interface.d.ts.map +0 -1
  246. package/dist/tool-loader.d.ts +0 -77
  247. package/dist/tool-loader.d.ts.map +0 -1
  248. package/dist/tool-validator.d.ts +0 -72
  249. package/dist/tool-validator.d.ts.map +0 -1
  250. package/dist/utils/async-utils.d.ts +0 -73
  251. package/dist/utils/async-utils.d.ts.map +0 -1
  252. package/dist/utils/command-wrapper.d.ts +0 -66
  253. package/dist/utils/command-wrapper.d.ts.map +0 -1
  254. package/dist/utils/detection.d.ts +0 -14
  255. package/dist/utils/detection.d.ts.map +0 -1
  256. package/dist/utils/error-categories.d.ts +0 -52
  257. package/dist/utils/error-categories.d.ts.map +0 -1
  258. package/dist/utils/finalization.d.ts +0 -17
  259. package/dist/utils/finalization.d.ts.map +0 -1
  260. package/dist/utils/git-lock.d.ts +0 -13
  261. package/dist/utils/git-lock.d.ts.map +0 -1
  262. package/dist/utils/gitignore-updater.d.ts +0 -39
  263. package/dist/utils/gitignore-updater.d.ts.map +0 -1
  264. package/dist/utils/ide-detection.d.ts +0 -89
  265. package/dist/utils/ide-detection.d.ts.map +0 -1
  266. package/dist/utils/project-analysis.d.ts +0 -34
  267. package/dist/utils/project-analysis.d.ts.map +0 -1
  268. package/dist/utils/promise-utils.d.ts +0 -30
  269. package/dist/utils/promise-utils.d.ts.map +0 -1
  270. package/dist/utils/quality-gates-utils.d.ts +0 -49
  271. package/dist/utils/quality-gates-utils.d.ts.map +0 -1
  272. package/dist/utils/quality-gates.d.ts +0 -49
  273. package/dist/utils/quality-gates.d.ts.map +0 -1
  274. package/dist/utils/quality-gates.js +0 -402
  275. package/dist/utils/spec-resolver.d.ts +0 -80
  276. package/dist/utils/spec-resolver.d.ts.map +0 -1
  277. package/dist/utils/typescript-detector.d.ts +0 -66
  278. package/dist/utils/typescript-detector.d.ts.map +0 -1
  279. package/dist/utils/yaml-validation.d.ts +0 -32
  280. package/dist/utils/yaml-validation.d.ts.map +0 -1
  281. package/dist/validation/spec-validation.d.ts +0 -43
  282. package/dist/validation/spec-validation.d.ts.map +0 -1
  283. package/dist/waivers-manager.d.ts +0 -167
  284. package/dist/waivers-manager.d.ts.map +0 -1
  285. package/dist/worktree/worktree-manager.d.ts +0 -54
  286. package/dist/worktree/worktree-manager.d.ts.map +0 -1
package/dist/index.js CHANGED
@@ -8,14 +8,16 @@
8
8
  */
9
9
 
10
10
  const { Command } = require('commander');
11
- // eslint-disable-next-line no-unused-vars
12
- const fs = require('fs-extra');
13
- // eslint-disable-next-line no-unused-vars
14
- const path = require('path');
15
- // eslint-disable-next-line no-unused-vars
16
- const yaml = require('js-yaml');
17
11
  const chalk = require('chalk');
18
12
 
13
+ if (
14
+ process.argv.includes('--json') ||
15
+ process.argv.includes('--quiet') ||
16
+ process.argv.includes('-q')
17
+ ) {
18
+ process.env.CAWS_QUIET = '1';
19
+ }
20
+
19
21
  // Import configuration and utilities
20
22
  const {
21
23
  CLI_VERSION,
@@ -42,8 +44,7 @@ const { iterateCommand } = require('./commands/iterate');
42
44
  const { waiversCommand } = require('./commands/waivers');
43
45
  const { workflowCommand } = require('./commands/workflow');
44
46
  const { qualityMonitorCommand } = require('./commands/quality-monitor');
45
- const { qualityGatesCommand } = require('./commands/quality-gates');
46
- const { troubleshootCommand } = require('./commands/troubleshoot');
47
+ const { gatesCommand } = require('./commands/gates');
47
48
  const { archiveCommand } = require('./commands/archive');
48
49
  const { specsCommand } = require('./commands/specs');
49
50
  const { modeCommand } = require('./commands/mode');
@@ -53,6 +54,8 @@ const { worktreeCommand } = require('./commands/worktree');
53
54
  const { sessionCommand } = require('./commands/session');
54
55
  const { parallelCommand } = require('./commands/parallel');
55
56
  const { verifyAcsCommand } = require('./commands/verify-acs');
57
+ const { sidecarCommand } = require('./commands/sidecar');
58
+ const { scopeCommand } = require('./commands/scope');
56
59
 
57
60
  // Import scaffold functionality
58
61
  const { scaffoldProject, setScaffoldDependencies } = require('./scaffold');
@@ -60,16 +63,8 @@ const { scaffoldProject, setScaffoldDependencies } = require('./scaffold');
60
63
  // Import git hooks functionality
61
64
  const { scaffoldGitHooks, removeGitHooks, checkGitHooksStatus } = require('./scaffold/git-hooks');
62
65
 
63
- // Import validation functionality
64
- // eslint-disable-next-line no-unused-vars
65
- const { validateWorkingSpecWithSuggestions } = require('./validation/spec-validation');
66
-
67
66
  // Import finalization utilities
68
67
  const {
69
- // eslint-disable-next-line no-unused-vars
70
- finalizeProject,
71
- // eslint-disable-next-line no-unused-vars
72
- continueToSuccess,
73
68
  setFinalizationDependencies,
74
69
  } = require('./utils/finalization');
75
70
 
@@ -139,84 +134,40 @@ program
139
134
  .option('--format <format>', 'Output format (text, json)', 'text')
140
135
  .action(validateCommand);
141
136
 
142
- // Quality Gates command
137
+ // Gates command group (v2 pipeline)
138
+ const gatesCmd = program
139
+ .command('gates')
140
+ .description('Run quality gate checks');
141
+
142
+ gatesCmd
143
+ .command('run')
144
+ .description('Run quality gates against staged files or a specific file')
145
+ .option('--context <context>', 'Execution context (cli, commit, edit)', 'cli')
146
+ .option('--spec-id <id>', 'Target spec ID')
147
+ .option('--file <path>', 'Single file to check (for edit context)')
148
+ .option('--json', 'Output as JSON', false)
149
+ .option('--quiet', 'Minimal output', false)
150
+ .action((options) => gatesCommand(options));
151
+
152
+ // Quality Gates command (legacy alias — delegates to gates command)
143
153
  program
144
154
  .command('quality-gates')
145
- .description('Run comprehensive quality gates (naming, duplication, god objects, documentation)')
155
+ .description('Run quality gates (alias for "caws gates run")')
146
156
  .option('--ci', 'CI mode - exit with error code if violations found', false)
147
157
  .option('--json', 'Output machine-readable JSON to stdout', false)
148
- .option(
149
- '--gates <gates>',
150
- 'Run only specific gates (comma-separated: naming,code_freeze,duplication,god_objects,hidden-todo,documentation,placeholders)',
151
- ''
152
- )
153
- .option('--fix', 'Attempt automatic fixes (experimental)', false)
154
- .option('--context <context>', 'Execution context: commit (staged files), push (all tracked files), or ci (all tracked files)', 'commit')
158
+ .option('--context <context>', 'Execution context: commit, push, ci', 'commit')
155
159
  .option('--all-files', 'Check all tracked files (equivalent to --context=ci)', false)
156
- .option('--help', 'Show detailed help and usage examples', false)
160
+ .option('--spec-id <id>', 'Target spec ID')
161
+ .option('--quiet', 'Minimal output', false)
157
162
  .action(async (options) => {
158
- // Handle --help flag
159
- if (options.help) {
160
- console.log(`
161
- CAWS Quality Gates - Enterprise Code Quality Enforcement
162
-
163
- USAGE:
164
- caws quality-gates [options]
165
-
166
- DESCRIPTION:
167
- Runs comprehensive quality gates to maintain code quality standards.
168
- Supports selective gate execution, JSON output, and CI/CD integration.
169
-
170
- OPTIONS:
171
- --ci CI mode - exit with error code if violations found
172
- --json Output machine-readable JSON to stdout
173
- --gates=<gates> Run only specific gates (comma-separated)
174
- --fix Attempt automatic fixes (experimental)
175
- --context=<ctx> Execution context: commit (staged files), push (all tracked), ci (all tracked)
176
- --all-files Check all tracked files (shortcut for --context=ci)
177
- --help Show this help message
178
-
179
- VALID GATES:
180
- naming Check naming conventions and banned modifiers
181
- code_freeze Enforce code freeze compliance
182
- duplication Detect functional duplication
183
- god_objects Prevent oversized files
184
- hidden-todo Detect hidden incomplete implementations
185
- documentation Check documentation quality
186
- placeholders Placeholder governance (explicit degradations)
187
-
188
- EXAMPLES:
189
- # Run all gates in development mode
190
- caws quality-gates
191
-
192
- # Run only specific gates
193
- caws quality-gates --gates=naming,duplication
194
-
195
- # CI mode with JSON output
196
- caws quality-gates --ci --json
197
-
198
- # Check all files in repository (not just staged)
199
- caws quality-gates --all-files
200
-
201
- # Use specific context
202
- caws quality-gates --context=ci
203
-
204
- # Show detailed help
205
- caws quality-gates --help
206
-
207
- OUTPUT:
208
- - Console: Human-readable results with enforcement levels
209
- - JSON: Machine-readable structured data (--json flag)
210
- - Artifacts: docs-status/quality-gates-report.json
211
- - GitHub Actions: Automatic step summaries when GITHUB_STEP_SUMMARY is set
212
-
213
- For more information, see: packages/quality-gates/README.md
214
- `);
215
- process.exit(0);
216
- }
217
-
218
- // Call the actual quality gates runner
219
- await qualityGatesCommand(options);
163
+ // Map legacy options to new gates command options
164
+ const gateOpts = {
165
+ context: options.allFiles ? 'ci' : (options.context || 'cli'),
166
+ specId: options.specId,
167
+ json: options.json,
168
+ quiet: options.quiet,
169
+ };
170
+ await gatesCommand(gateOpts);
220
171
  });
221
172
 
222
173
  // Status command
@@ -234,6 +185,7 @@ program
234
185
  .command('archive <change-id>')
235
186
  .description('Archive completed change')
236
187
  .option('--spec-id <id>', 'Feature-specific spec ID (e.g., user-auth)')
188
+ .option('-s, --spec <path>', 'Path to spec file (explicit override)')
237
189
  .option('-f, --force', 'Force archive even if criteria not met', false)
238
190
  .option('--dry-run', 'Preview archive without performing it', false)
239
191
  .action(archiveCommand);
@@ -300,6 +252,38 @@ specsCmd
300
252
  .description('Show available spec types')
301
253
  .action(() => specsCommand('types', {}));
302
254
 
255
+ // Sidecar command group
256
+ const sidecarCmd = program.command('sidecar').description('Advisory analysis tools (drift, gaps, waivers, provenance)');
257
+
258
+ sidecarCmd
259
+ .command('drift')
260
+ .description('Analyze spec drift vs implementation evidence')
261
+ .option('--spec-id <id>', 'Target spec ID')
262
+ .option('--json', 'Output as JSON', false)
263
+ .action((options) => sidecarCommand('drift', options));
264
+
265
+ sidecarCmd
266
+ .command('gaps')
267
+ .description('Diagnose quality gaps preventing phase advancement')
268
+ .option('--spec-id <id>', 'Target spec ID')
269
+ .option('--json', 'Output as JSON', false)
270
+ .action((options) => sidecarCommand('gaps', options));
271
+
272
+ sidecarCmd
273
+ .command('waiver-draft')
274
+ .description('Generate pre-filled waiver templates from gate failures')
275
+ .option('--spec-id <id>', 'Target spec ID')
276
+ .option('--gate <gate>', 'Specific gate to draft waiver for')
277
+ .option('--json', 'Output as JSON', false)
278
+ .action((options) => sidecarCommand('waiver-draft', options));
279
+
280
+ sidecarCmd
281
+ .command('provenance')
282
+ .description('Summarize work provenance for merge readiness')
283
+ .option('--spec-id <id>', 'Target spec ID')
284
+ .option('--json', 'Output as JSON', false)
285
+ .action((options) => sidecarCommand('provenance', options));
286
+
303
287
  // Mode command group
304
288
  const modeCmd = program.command('mode').description('Manage CAWS complexity tiers');
305
289
 
@@ -314,13 +298,6 @@ modeCmd
314
298
  .description('Set CAWS complexity tier')
315
299
  .action((mode) => modeCommand('set', { mode }));
316
300
 
317
- modeCmd
318
- .command('set')
319
- .description('Set CAWS complexity tier (interactive)')
320
- .option('-i, --interactive', 'Interactive mode selection', false)
321
- .option('-m, --mode <mode>', 'Specific mode to set')
322
- .action((options) => modeCommand('set', options));
323
-
324
301
  modeCmd
325
302
  .command('compare')
326
303
  .description('Compare all available tiers')
@@ -393,15 +370,33 @@ worktreeCmd
393
370
  .command('prune')
394
371
  .description('Clean up stale worktree entries')
395
372
  .option('--max-age <days>', 'Remove entries older than N days', '30')
373
+ .option('--force', 'Allow pruning entries owned by other sessions', false)
396
374
  .action((options) => worktreeCommand('prune', options));
397
375
 
398
376
  worktreeCmd
399
377
  .command('repair')
400
378
  .description('Reconcile registry with git and filesystem state')
401
379
  .option('--dry-run', 'Report only, do not persist changes', false)
402
- .option('--prune', 'Remove destroyed and stale-merged entries', false)
380
+ .option('--prune', 'Remove destroyed, stale-merged, and missing entries', false)
381
+ .option('--force', 'Allow pruning entries owned by other sessions', false)
403
382
  .action((options) => worktreeCommand('repair', options));
404
383
 
384
+ worktreeCmd
385
+ .command('bind <spec-id>')
386
+ .description('Bind a spec to this worktree (fixes mutual reference)')
387
+ .option('--name <name>', 'Worktree name (auto-detected from cwd if omitted)')
388
+ .action((specId, options) => worktreeCommand('bind', { specId, ...options }));
389
+
390
+ // Scope command group
391
+ const scopeCmd = program
392
+ .command('scope')
393
+ .description('Inspect and manage scope boundaries');
394
+
395
+ scopeCmd
396
+ .command('show')
397
+ .description('Show effective scope for the current context')
398
+ .action(() => scopeCommand('show'));
399
+
405
400
  // Session command group
406
401
  const sessionCmd = program
407
402
  .command('session')
@@ -525,6 +520,14 @@ program
525
520
  .option('-v, --verbose', 'Show detailed error information', false)
526
521
  .action(iterateCommand);
527
522
 
523
+ // Burnup command
524
+ program
525
+ .command('burnup [spec-file]')
526
+ .description('Generate budget burn-up report for scope visibility')
527
+ .option('--spec-id <id>', 'Feature-specific spec ID (e.g., user-auth)')
528
+ .option('-v, --verbose', 'Show detailed error information', false)
529
+ .action(burnupCommand);
530
+
528
531
  // Waivers command group
529
532
  const waiversCmd = program.command('waivers').description('Manage CAWS quality gate waivers');
530
533
 
@@ -566,8 +569,17 @@ waiversCmd
566
569
  .option('-v, --verbose', 'Show detailed error information', false)
567
570
  .action((id, options) => waiversCommand('revoke', { ...options, id }));
568
571
 
572
+ waiversCmd
573
+ .command('prune')
574
+ .description('Prune expired waivers (dry-run by default; use --apply to persist)')
575
+ .option('--expired', 'Prune active waivers whose expires_at is in the past')
576
+ .option('--apply', 'Actually transition status (default: dry run)')
577
+ .option('--json', 'Emit machine-readable JSON output')
578
+ .option('-v, --verbose', 'Show detailed error information', false)
579
+ .action((options) => waiversCommand('prune', options));
580
+
569
581
  // Workflow command group
570
- const workflowCmd = program
582
+ program
571
583
  .command('workflow <type>')
572
584
  .description('Get workflow-specific guidance')
573
585
  .option('--spec-id <id>', 'Feature-specific spec ID (e.g., user-auth)')
@@ -603,7 +615,9 @@ program
603
615
  .command('test-analysis <subcommand> [options...]')
604
616
  .description('Statistical analysis for budget prediction')
605
617
  .option('--spec-id <id>', 'Feature-specific spec ID (e.g., user-auth)')
606
- .action(testAnalysisCommand);
618
+ .action((subcommand, optionArgs, command) => {
619
+ testAnalysisCommand(subcommand, optionArgs, command.opts());
620
+ });
607
621
 
608
622
  // Provenance command group
609
623
  const provenanceCmd = program.command('provenance').description('Manage CAWS provenance tracking');
@@ -613,6 +627,8 @@ provenanceCmd
613
627
  .command('update')
614
628
  .description('Add new commit to provenance chain')
615
629
  .requiredOption('-c, --commit <hash>', 'Git commit hash')
630
+ .option('--spec-id <id>', 'Feature-specific spec ID')
631
+ .option('-s, --spec <path>', 'Path to spec file (explicit override)')
616
632
  .option('-m, --message <msg>', 'Commit message')
617
633
  .option('-a, --author <info>', 'Author information')
618
634
  .option('-q, --quiet', 'Suppress output')
@@ -649,6 +665,8 @@ provenanceCmd
649
665
  provenanceCmd
650
666
  .command('init')
651
667
  .description('Initialize provenance tracking for the project')
668
+ .option('--spec-id <id>', 'Feature-specific spec ID')
669
+ .option('-s, --spec <path>', 'Path to spec file (explicit override)')
652
670
  .option('-o, --output <path>', 'Output path for provenance files', '.caws/provenance')
653
671
  .option('--cursor-api <url>', 'Cursor tracking API endpoint')
654
672
  .option('--cursor-key <key>', 'Cursor API key')
@@ -725,6 +743,37 @@ program.configureHelp({
725
743
  showError: () => {}, // Suppress default error display
726
744
  });
727
745
 
746
+ const VALID_COMMANDS = [
747
+ 'init',
748
+ 'validate',
749
+ 'scaffold',
750
+ 'status',
751
+ 'archive',
752
+ 'specs',
753
+ 'sidecar',
754
+ 'mode',
755
+ 'tutorial',
756
+ 'plan',
757
+ 'templates',
758
+ 'diagnose',
759
+ 'evaluate',
760
+ 'iterate',
761
+ 'waivers',
762
+ 'workflow',
763
+ 'quality-monitor',
764
+ 'quality-gates',
765
+ 'gates',
766
+ 'provenance',
767
+ 'hooks',
768
+ 'burnup',
769
+ 'tool',
770
+ 'worktree',
771
+ 'session',
772
+ 'parallel',
773
+ 'verify-acs',
774
+ 'scope',
775
+ ];
776
+
728
777
  program.exitOverride((err) => {
729
778
  // Handle help and version requests gracefully
730
779
  if (
@@ -739,34 +788,7 @@ program.exitOverride((err) => {
739
788
 
740
789
  // Check for unknown command
741
790
  if (err.code === 'commander.unknownCommand') {
742
- const validCommands = [
743
- 'init',
744
- 'validate',
745
- 'scaffold',
746
- 'status',
747
- 'archive',
748
- 'specs',
749
- 'mode',
750
- 'tutorial',
751
- 'plan',
752
- 'templates',
753
- 'diagnose',
754
- 'evaluate',
755
- 'iterate',
756
- 'waivers',
757
- 'workflow',
758
- 'quality-monitor',
759
- 'troubleshoot',
760
- 'provenance',
761
- 'hooks',
762
- 'burnup',
763
- 'tool',
764
- 'worktree',
765
- 'session',
766
- 'parallel',
767
- 'verify-acs',
768
- ];
769
- const similar = findSimilarCommand(commandName, validCommands);
791
+ const similar = findSimilarCommand(commandName, VALID_COMMANDS);
770
792
 
771
793
  console.error(chalk.red(`\nUnknown command: ${commandName}`));
772
794
 
@@ -774,9 +796,7 @@ program.exitOverride((err) => {
774
796
  console.error(chalk.yellow(`\nDid you mean: caws ${similar}?`));
775
797
  }
776
798
 
777
- console.error(
778
- chalk.yellow('Available commands: init, validate, scaffold, provenance, hooks')
779
- );
799
+ console.error(chalk.yellow('Run: caws --help for the full command list'));
780
800
  console.error(chalk.yellow('Try: caws --help for full command list'));
781
801
  console.error(
782
802
  chalk.blue(
@@ -821,6 +841,12 @@ program.exitOverride((err) => {
821
841
  process.exit(1);
822
842
  });
823
843
 
844
+ // Register sidecar lifecycle listeners (non-fatal hints)
845
+ try {
846
+ const { registerSidecarListeners } = require('./sidecars/listeners');
847
+ registerSidecarListeners();
848
+ } catch { /* sidecars module not available — non-fatal */ }
849
+
824
850
  // Parse and run
825
851
  if (require.main === module) {
826
852
  try {
@@ -844,25 +870,7 @@ if (require.main === module) {
844
870
 
845
871
  // Check for unknown command
846
872
  if (error.code === 'commander.unknownCommand') {
847
- const validCommands = [
848
- 'init',
849
- 'validate',
850
- 'scaffold',
851
- 'status',
852
- 'archive',
853
- 'specs',
854
- 'mode',
855
- 'tutorial',
856
- 'plan',
857
- 'provenance',
858
- 'hooks',
859
- 'burnup',
860
- 'tool',
861
- 'worktree',
862
- 'session',
863
- 'parallel',
864
- ];
865
- const similar = findSimilarCommand(commandName, validCommands);
873
+ const similar = findSimilarCommand(commandName, VALID_COMMANDS);
866
874
 
867
875
  console.error(chalk.red(`\nUnknown command: ${commandName}`));
868
876
 
@@ -870,9 +878,7 @@ if (require.main === module) {
870
878
  console.error(chalk.yellow(`\nDid you mean: caws ${similar}?`));
871
879
  }
872
880
 
873
- console.error(
874
- chalk.yellow('Available commands: init, validate, scaffold, provenance, hooks, parallel')
875
- );
881
+ console.error(chalk.yellow('Run: caws --help for the full command list'));
876
882
  console.error(chalk.yellow('Try: caws --help for full command list'));
877
883
  console.error(
878
884
  chalk.blue(
@@ -192,7 +192,7 @@ function getParallelStatus() {
192
192
  let commitCount = 0;
193
193
  let dirty = false;
194
194
 
195
- if (wt && wt.status === 'active') {
195
+ if (wt && (wt.status === 'active' || wt.status === 'fresh' || wt.status === 'merged')) {
196
196
  try {
197
197
  const log = execFileSync(
198
198
  'git',
@@ -250,7 +250,7 @@ function detectFileConflicts(baseBranch, agentStatuses) {
250
250
  const filesByAgent = {};
251
251
 
252
252
  for (const agent of agentStatuses) {
253
- if (agent.status !== 'active') continue;
253
+ if (agent.status !== 'active' && agent.status !== 'fresh' && agent.status !== 'merged') continue;
254
254
  try {
255
255
  const diff = execFileSync(
256
256
  'git',
@@ -302,7 +302,7 @@ function mergeParallel(options = {}) {
302
302
  const wt = worktrees.find((w) => w.name === a.name);
303
303
  return wt ? { ...a, ...wt } : null;
304
304
  })
305
- .filter((a) => a && a.status === 'active');
305
+ .filter((a) => a && (a.status === 'active' || a.status === 'fresh' || a.status === 'merged'));
306
306
 
307
307
  // Check for dirty worktrees
308
308
  for (const agent of activeAgents) {
@@ -8,6 +8,7 @@
8
8
  const fs = require('fs-extra');
9
9
  const path = require('path');
10
10
  const yaml = require('js-yaml');
11
+ const { createValidator, getSchemaPath } = require('../utils/schema-validator');
11
12
 
12
13
  /**
13
14
  * Policy Manager - Handles policy loading with intelligent caching
@@ -86,6 +87,34 @@ class PolicyManager {
86
87
  }
87
88
 
88
89
  if (policyPath && policyContent) {
90
+ // Schema validation (warn and fall back to defaults on failure)
91
+ try {
92
+ const schemaFilePath = getSchemaPath('policy.schema.json', projectRoot);
93
+ const validate = createValidator(schemaFilePath);
94
+ const schemaResult = validate(policyContent);
95
+ if (!schemaResult.valid) {
96
+ console.warn('Policy has schema violations:', schemaResult.errors);
97
+ console.warn('Falling back to default policy');
98
+ const defaultPolicy = this.getDefaultPolicy();
99
+ if (this.enableCaching) {
100
+ this.policyCache.set(projectRoot, {
101
+ policy: defaultPolicy,
102
+ cachedAt: Date.now(),
103
+ ttl: cacheTTL,
104
+ });
105
+ }
106
+ return {
107
+ ...defaultPolicy,
108
+ _isDefault: true,
109
+ _schemaErrors: schemaResult.errors,
110
+ _cacheHit: false,
111
+ _loadDuration: Date.now() - startTime,
112
+ };
113
+ }
114
+ } catch (schemaErr) {
115
+ console.warn('Could not validate policy schema:', schemaErr.message);
116
+ }
117
+
89
118
  // Validate policy structure
90
119
  this.validatePolicy(policyContent);
91
120
 
@@ -241,15 +270,17 @@ class PolicyManager {
241
270
  throw new Error('Policy missing risk_tiers configuration');
242
271
  }
243
272
 
244
- // Validate all tiers have required fields
245
- for (const tier of [1, 2, 3]) {
246
- const budget = policy.risk_tiers[tier];
247
- if (!budget) {
248
- throw new Error(`Policy missing risk tier ${tier} configuration`);
273
+ const tierKeys = Object.keys(policy.risk_tiers);
274
+ if (tierKeys.length === 0) {
275
+ throw new Error('Policy risk_tiers must define at least one risk tier (1, 2, or 3)');
276
+ }
277
+ for (const key of tierKeys) {
278
+ if (!/^[1-3]$/.test(key)) {
279
+ throw new Error(`Policy risk_tiers has unknown tier '${key}' (expected 1, 2, or 3)`);
249
280
  }
250
-
281
+ const budget = policy.risk_tiers[key];
251
282
  if (typeof budget.max_files !== 'number' || typeof budget.max_loc !== 'number') {
252
- throw new Error(`Risk tier ${tier} missing or invalid budget limits`);
283
+ throw new Error(`Risk tier ${key} missing or invalid budget limits`);
253
284
  }
254
285
  }
255
286
 
@@ -299,27 +330,30 @@ class PolicyManager {
299
330
  gates: {
300
331
  budget_limit: {
301
332
  enabled: true,
333
+ mode: 'block',
302
334
  description: 'Enforce change budget limits',
303
335
  },
304
336
  spec_completeness: {
305
337
  enabled: true,
338
+ mode: 'block',
306
339
  description: 'Require complete working specifications',
307
340
  },
308
- contract_compliance: {
309
- enabled: true,
310
- description: 'Validate API contracts',
311
- },
312
- coverage_threshold: {
341
+ scope_boundary: {
313
342
  enabled: true,
314
- description: 'Maintain test coverage requirements',
343
+ mode: 'block',
344
+ description: 'Enforce spec scope boundaries',
315
345
  },
316
- mutation_threshold: {
346
+ god_object: {
317
347
  enabled: true,
318
- description: 'Require mutation testing for T1/T2 changes',
348
+ mode: 'warn',
349
+ thresholds: { warning: 1750, critical: 2000 },
350
+ description: 'Detect oversized source files',
319
351
  },
320
- security_scan: {
352
+ todo_detection: {
321
353
  enabled: true,
322
- description: 'Run security vulnerability scans',
354
+ mode: 'warn',
355
+ thresholds: { min_confidence: 0.8 },
356
+ description: 'Scan for TODO/FIXME/HACK/XXX markers',
323
357
  },
324
358
  },
325
359
  };
@@ -54,7 +54,7 @@ async function scaffoldClaudeHooks(projectDir, levels = ['safety', 'quality', 's
54
54
  // Map levels to hook scripts
55
55
  const hookMapping = {
56
56
  safety: ['block-dangerous.sh', 'scan-secrets.sh', 'worktree-guard.sh', 'worktree-write-guard.sh', 'stop-worktree-check.sh', 'session-caws-status.sh'],
57
- quality: ['quality-check.sh', 'validate-spec.sh'],
57
+ quality: ['quality-check.sh', 'validate-spec.sh', 'doc-frontmatter-check.sh'],
58
58
  scope: ['scope-guard.sh', 'naming-check.sh'],
59
59
  audit: ['audit.sh', 'session-log.sh'],
60
60
  lite: ['block-dangerous.sh', 'scope-guard.sh', 'lite-sprawl-check.sh', 'simplification-guard.sh'],
@@ -81,6 +81,7 @@ async function scaffoldClaudeHooks(projectDir, levels = ['safety', 'quality', 's
81
81
  'block-dangerous.sh',
82
82
  'scope-guard.sh',
83
83
  'naming-check.sh',
84
+ 'doc-frontmatter-check.sh',
84
85
  'lite-sprawl-check.sh',
85
86
  'simplification-guard.sh',
86
87
  'worktree-guard.sh',
@@ -90,6 +91,23 @@ async function scaffoldClaudeHooks(projectDir, levels = ['safety', 'quality', 's
90
91
  'session-log.sh',
91
92
  ];
92
93
 
94
+ // Copy supporting scripts (not hooks themselves, but used by hooks)
95
+ const supportingScripts = [
96
+ 'classify_command.py',
97
+ 'test_classify_command.py',
98
+ 'test_wrapper_smoke.sh',
99
+ ];
100
+
101
+ for (const script of supportingScripts) {
102
+ const sourcePath = path.join(claudeHooksTemplateDir, script);
103
+ const destPath = path.join(claudeHooksDir, script);
104
+
105
+ if (fs.existsSync(sourcePath)) {
106
+ await fs.copy(sourcePath, destPath);
107
+ await fs.chmod(destPath, 0o755);
108
+ }
109
+ }
110
+
93
111
  for (const script of allHookScripts) {
94
112
  if (enabledHooks.has(script)) {
95
113
  const sourcePath = path.join(claudeHooksTemplateDir, script);
@@ -254,6 +272,11 @@ function generateClaudeSettings(levels, _enabledHooks) {
254
272
  command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/validate-spec.sh',
255
273
  timeout: 15,
256
274
  },
275
+ {
276
+ type: 'command',
277
+ command: '"$CLAUDE_PROJECT_DIR"/.claude/hooks/doc-frontmatter-check.sh',
278
+ timeout: 10,
279
+ },
257
280
  ],
258
281
  });
259
282
  }