@paths.design/caws-cli 9.3.2 → 10.0.1

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 (273) hide show
  1. package/README.md +58 -27
  2. package/dist/commands/archive.js +67 -28
  3. package/dist/commands/burnup.js +20 -11
  4. package/dist/commands/diagnose.js +34 -22
  5. package/dist/commands/evaluate.js +27 -15
  6. package/dist/commands/gates.js +122 -0
  7. package/dist/commands/init.js +143 -15
  8. package/dist/commands/iterate.js +77 -4
  9. package/dist/commands/parallel.js +4 -0
  10. package/dist/commands/plan.js +9 -19
  11. package/dist/commands/provenance.js +53 -17
  12. package/dist/commands/quality-monitor.js +64 -45
  13. package/dist/commands/sidecar.js +71 -0
  14. package/dist/commands/specs.js +233 -44
  15. package/dist/commands/status.js +113 -9
  16. package/dist/commands/tutorial.js +10 -9
  17. package/dist/commands/validate.js +49 -6
  18. package/dist/commands/verify-acs.js +35 -78
  19. package/dist/commands/waivers.js +69 -12
  20. package/dist/commands/worktree.js +50 -25
  21. package/dist/error-handler.js +2 -13
  22. package/dist/gates/budget-limit.js +116 -0
  23. package/dist/gates/feedback.js +260 -0
  24. package/dist/gates/format.js +179 -0
  25. package/dist/gates/god-object.js +117 -0
  26. package/dist/gates/pipeline.js +167 -0
  27. package/dist/gates/scope-boundary.js +93 -0
  28. package/dist/gates/spec-completeness.js +102 -0
  29. package/dist/gates/todo-detection.js +205 -0
  30. package/dist/index.js +130 -151
  31. package/dist/parallel/parallel-manager.js +3 -3
  32. package/dist/policy/PolicyManager.js +42 -10
  33. package/dist/scaffold/claude-hooks.js +24 -1
  34. package/dist/scaffold/git-hooks.js +45 -102
  35. package/dist/scaffold/index.js +4 -3
  36. package/dist/session/session-manager.js +71 -14
  37. package/dist/sidecars/index.js +33 -0
  38. package/dist/sidecars/listeners.js +40 -0
  39. package/dist/sidecars/provenance-summary.js +238 -0
  40. package/dist/sidecars/quality-gaps.js +258 -0
  41. package/dist/sidecars/schema.js +149 -0
  42. package/dist/sidecars/spec-drift.js +151 -0
  43. package/dist/sidecars/waiver-draft.js +176 -0
  44. package/dist/templates/.caws/schemas/policy.schema.json +50 -0
  45. package/dist/templates/.caws/schemas/waivers.schema.json +30 -24
  46. package/dist/templates/.caws/schemas/working-spec.schema.json +51 -8
  47. package/dist/templates/.caws/schemas/worktrees.schema.json +3 -1
  48. package/dist/templates/.caws/templates/working-spec.template.yml +7 -3
  49. package/dist/templates/.claude/hooks/audit.sh +0 -0
  50. package/dist/templates/.claude/hooks/block-dangerous.sh +52 -11
  51. package/dist/templates/.claude/hooks/classify_command.py +592 -0
  52. package/dist/templates/.claude/hooks/doc-frontmatter-check.sh +173 -0
  53. package/dist/templates/.claude/hooks/quality-check.sh +23 -10
  54. package/dist/templates/.claude/hooks/scope-guard.sh +34 -32
  55. package/dist/templates/.claude/hooks/session-caws-status.sh +2 -2
  56. package/dist/templates/.claude/hooks/session-log.sh +76 -3
  57. package/dist/templates/.claude/hooks/stop-worktree-check.sh +1 -1
  58. package/dist/templates/.claude/hooks/test_classify_command.py +370 -0
  59. package/dist/templates/.claude/hooks/test_wrapper_smoke.sh +96 -0
  60. package/dist/templates/.claude/hooks/worktree-guard.sh +2 -2
  61. package/dist/templates/.claude/hooks/worktree-write-guard.sh +1 -1
  62. package/dist/templates/.claude/settings.json +26 -0
  63. package/dist/templates/.cursor/hooks/caws-quality-check.sh +4 -4
  64. package/dist/templates/.cursor/hooks/caws-scope-guard.sh +1 -1
  65. package/dist/templates/.cursor/hooks/session-log.sh +924 -0
  66. package/dist/templates/.cursor/hooks.json +25 -0
  67. package/dist/templates/.cursor/rules/02-quality-gates.mdc +3 -5
  68. package/dist/templates/.cursor/rules/10-documentation-quality-standards.mdc +6 -11
  69. package/dist/templates/.cursor/rules/11-scope-management-waivers.mdc +14 -18
  70. package/dist/templates/.cursor/rules/12-implementation-completeness.mdc +4 -4
  71. package/dist/templates/.cursor/rules/13-language-agnostic-standards.mdc +3 -13
  72. package/dist/templates/.github/copilot-instructions.md +5 -5
  73. package/dist/templates/.idea/runConfigurations/CAWS_Evaluate.xml +1 -1
  74. package/dist/templates/.junie/guidelines.md +2 -2
  75. package/dist/templates/.vscode/settings.json +3 -1
  76. package/dist/templates/.windsurf/rules/caws-quality-standards.md +2 -2
  77. package/dist/templates/.windsurf/workflows/caws-guided-development.md +3 -3
  78. package/dist/templates/CLAUDE.md +43 -8
  79. package/dist/templates/agents.md +29 -9
  80. package/dist/templates/docs/README.md +8 -7
  81. package/dist/templates/scripts/new_feature.sh +80 -0
  82. package/dist/test-analysis.js +43 -30
  83. package/dist/tool-loader.js +1 -1
  84. package/dist/utils/agent-session.js +202 -0
  85. package/dist/utils/detection.js +8 -2
  86. package/dist/utils/finalization.js +7 -6
  87. package/dist/utils/gitignore-updater.js +3 -0
  88. package/dist/utils/lifecycle-events.js +94 -0
  89. package/dist/utils/quality-gates-utils.js +29 -44
  90. package/dist/utils/schema-validator.js +42 -0
  91. package/dist/utils/spec-resolver.js +93 -21
  92. package/dist/utils/working-state.js +505 -0
  93. package/dist/validation/spec-validation.js +92 -22
  94. package/dist/waivers-manager.js +60 -6
  95. package/dist/worktree/worktree-manager.js +390 -93
  96. package/package.json +6 -6
  97. package/templates/.caws/schemas/policy.schema.json +50 -0
  98. package/templates/.caws/schemas/waivers.schema.json +30 -24
  99. package/templates/.caws/schemas/working-spec.schema.json +51 -8
  100. package/templates/.caws/schemas/worktrees.schema.json +3 -1
  101. package/templates/.caws/templates/working-spec.template.yml +7 -3
  102. package/templates/.claude/hooks/block-dangerous.sh +52 -11
  103. package/templates/.claude/hooks/classify_command.py +592 -0
  104. package/templates/.claude/hooks/doc-frontmatter-check.sh +173 -0
  105. package/templates/.claude/hooks/quality-check.sh +23 -10
  106. package/templates/.claude/hooks/scope-guard.sh +34 -32
  107. package/templates/.claude/hooks/session-caws-status.sh +2 -2
  108. package/templates/.claude/hooks/session-log.sh +76 -3
  109. package/templates/.claude/hooks/stop-worktree-check.sh +1 -1
  110. package/templates/.claude/hooks/test_classify_command.py +370 -0
  111. package/templates/.claude/hooks/test_wrapper_smoke.sh +96 -0
  112. package/templates/.claude/hooks/worktree-guard.sh +2 -2
  113. package/templates/.claude/hooks/worktree-write-guard.sh +1 -1
  114. package/templates/.claude/settings.json +26 -0
  115. package/templates/.cursor/hooks/caws-quality-check.sh +4 -4
  116. package/templates/.cursor/hooks/caws-scope-guard.sh +1 -1
  117. package/templates/.cursor/hooks/session-log.sh +924 -0
  118. package/templates/.cursor/hooks.json +25 -0
  119. package/templates/.cursor/rules/02-quality-gates.mdc +3 -5
  120. package/templates/.cursor/rules/10-documentation-quality-standards.mdc +6 -11
  121. package/templates/.cursor/rules/11-scope-management-waivers.mdc +14 -18
  122. package/templates/.cursor/rules/12-implementation-completeness.mdc +4 -4
  123. package/templates/.cursor/rules/13-language-agnostic-standards.mdc +3 -13
  124. package/templates/.github/copilot-instructions.md +5 -5
  125. package/templates/.idea/runConfigurations/CAWS_Evaluate.xml +1 -1
  126. package/templates/.junie/guidelines.md +2 -2
  127. package/templates/.vscode/settings.json +3 -1
  128. package/templates/.windsurf/rules/caws-quality-standards.md +2 -2
  129. package/templates/.windsurf/workflows/caws-guided-development.md +3 -3
  130. package/templates/CLAUDE.md +43 -8
  131. package/templates/{AGENTS.md → agents.md} +29 -9
  132. package/templates/docs/README.md +8 -7
  133. package/templates/scripts/new_feature.sh +80 -0
  134. package/dist/budget-derivation.d.ts +0 -74
  135. package/dist/budget-derivation.d.ts.map +0 -1
  136. package/dist/cicd-optimizer.d.ts +0 -142
  137. package/dist/cicd-optimizer.d.ts.map +0 -1
  138. package/dist/commands/archive.d.ts +0 -51
  139. package/dist/commands/archive.d.ts.map +0 -1
  140. package/dist/commands/burnup.d.ts +0 -6
  141. package/dist/commands/burnup.d.ts.map +0 -1
  142. package/dist/commands/diagnose.d.ts +0 -52
  143. package/dist/commands/diagnose.d.ts.map +0 -1
  144. package/dist/commands/evaluate.d.ts +0 -8
  145. package/dist/commands/evaluate.d.ts.map +0 -1
  146. package/dist/commands/init.d.ts +0 -5
  147. package/dist/commands/init.d.ts.map +0 -1
  148. package/dist/commands/iterate.d.ts +0 -8
  149. package/dist/commands/iterate.d.ts.map +0 -1
  150. package/dist/commands/mode.d.ts +0 -25
  151. package/dist/commands/mode.d.ts.map +0 -1
  152. package/dist/commands/parallel.d.ts +0 -7
  153. package/dist/commands/parallel.d.ts.map +0 -1
  154. package/dist/commands/plan.d.ts +0 -49
  155. package/dist/commands/plan.d.ts.map +0 -1
  156. package/dist/commands/provenance.d.ts +0 -32
  157. package/dist/commands/provenance.d.ts.map +0 -1
  158. package/dist/commands/quality-gates.d.ts +0 -6
  159. package/dist/commands/quality-gates.d.ts.map +0 -1
  160. package/dist/commands/quality-gates.js +0 -444
  161. package/dist/commands/quality-monitor.d.ts +0 -17
  162. package/dist/commands/quality-monitor.d.ts.map +0 -1
  163. package/dist/commands/session.d.ts +0 -7
  164. package/dist/commands/session.d.ts.map +0 -1
  165. package/dist/commands/specs.d.ts +0 -77
  166. package/dist/commands/specs.d.ts.map +0 -1
  167. package/dist/commands/status.d.ts +0 -44
  168. package/dist/commands/status.d.ts.map +0 -1
  169. package/dist/commands/templates.d.ts +0 -74
  170. package/dist/commands/templates.d.ts.map +0 -1
  171. package/dist/commands/tool.d.ts +0 -13
  172. package/dist/commands/tool.d.ts.map +0 -1
  173. package/dist/commands/troubleshoot.d.ts +0 -8
  174. package/dist/commands/troubleshoot.d.ts.map +0 -1
  175. package/dist/commands/troubleshoot.js +0 -104
  176. package/dist/commands/tutorial.d.ts +0 -55
  177. package/dist/commands/tutorial.d.ts.map +0 -1
  178. package/dist/commands/validate.d.ts +0 -15
  179. package/dist/commands/validate.d.ts.map +0 -1
  180. package/dist/commands/waivers.d.ts +0 -8
  181. package/dist/commands/waivers.d.ts.map +0 -1
  182. package/dist/commands/workflow.d.ts +0 -85
  183. package/dist/commands/workflow.d.ts.map +0 -1
  184. package/dist/commands/worktree.d.ts +0 -7
  185. package/dist/commands/worktree.d.ts.map +0 -1
  186. package/dist/config/index.d.ts +0 -29
  187. package/dist/config/index.d.ts.map +0 -1
  188. package/dist/config/lite-scope.d.ts +0 -33
  189. package/dist/config/lite-scope.d.ts.map +0 -1
  190. package/dist/config/modes.d.ts +0 -264
  191. package/dist/config/modes.d.ts.map +0 -1
  192. package/dist/constants/spec-types.d.ts +0 -93
  193. package/dist/constants/spec-types.d.ts.map +0 -1
  194. package/dist/error-handler.d.ts +0 -151
  195. package/dist/error-handler.d.ts.map +0 -1
  196. package/dist/generators/jest-config-generator.d.ts +0 -32
  197. package/dist/generators/jest-config-generator.d.ts.map +0 -1
  198. package/dist/generators/jest-config.d.ts +0 -32
  199. package/dist/generators/jest-config.d.ts.map +0 -1
  200. package/dist/generators/jest-config.js +0 -242
  201. package/dist/generators/working-spec.d.ts +0 -13
  202. package/dist/generators/working-spec.d.ts.map +0 -1
  203. package/dist/index-new.d.ts +0 -5
  204. package/dist/index-new.d.ts.map +0 -1
  205. package/dist/index-new.js +0 -317
  206. package/dist/index.d.ts +0 -5
  207. package/dist/index.d.ts.map +0 -1
  208. package/dist/index.js.backup +0 -4711
  209. package/dist/minimal-cli.d.ts +0 -3
  210. package/dist/minimal-cli.d.ts.map +0 -1
  211. package/dist/parallel/parallel-manager.d.ts +0 -67
  212. package/dist/parallel/parallel-manager.d.ts.map +0 -1
  213. package/dist/policy/PolicyManager.d.ts +0 -104
  214. package/dist/policy/PolicyManager.d.ts.map +0 -1
  215. package/dist/scaffold/claude-hooks.d.ts +0 -28
  216. package/dist/scaffold/claude-hooks.d.ts.map +0 -1
  217. package/dist/scaffold/cursor-hooks.d.ts +0 -7
  218. package/dist/scaffold/cursor-hooks.d.ts.map +0 -1
  219. package/dist/scaffold/git-hooks.d.ts +0 -38
  220. package/dist/scaffold/git-hooks.d.ts.map +0 -1
  221. package/dist/scaffold/index.d.ts +0 -17
  222. package/dist/scaffold/index.d.ts.map +0 -1
  223. package/dist/session/session-manager.d.ts +0 -94
  224. package/dist/session/session-manager.d.ts.map +0 -1
  225. package/dist/spec/SpecFileManager.d.ts +0 -146
  226. package/dist/spec/SpecFileManager.d.ts.map +0 -1
  227. package/dist/templates/.cursor/hooks/caws-tool-validation.sh +0 -121
  228. package/dist/templates/.github/copilot/instructions.md +0 -311
  229. package/dist/test-analysis.d.ts +0 -231
  230. package/dist/test-analysis.d.ts.map +0 -1
  231. package/dist/tool-interface.d.ts +0 -236
  232. package/dist/tool-interface.d.ts.map +0 -1
  233. package/dist/tool-loader.d.ts +0 -77
  234. package/dist/tool-loader.d.ts.map +0 -1
  235. package/dist/tool-validator.d.ts +0 -72
  236. package/dist/tool-validator.d.ts.map +0 -1
  237. package/dist/utils/async-utils.d.ts +0 -73
  238. package/dist/utils/async-utils.d.ts.map +0 -1
  239. package/dist/utils/command-wrapper.d.ts +0 -66
  240. package/dist/utils/command-wrapper.d.ts.map +0 -1
  241. package/dist/utils/detection.d.ts +0 -14
  242. package/dist/utils/detection.d.ts.map +0 -1
  243. package/dist/utils/error-categories.d.ts +0 -52
  244. package/dist/utils/error-categories.d.ts.map +0 -1
  245. package/dist/utils/finalization.d.ts +0 -17
  246. package/dist/utils/finalization.d.ts.map +0 -1
  247. package/dist/utils/git-lock.d.ts +0 -13
  248. package/dist/utils/git-lock.d.ts.map +0 -1
  249. package/dist/utils/gitignore-updater.d.ts +0 -39
  250. package/dist/utils/gitignore-updater.d.ts.map +0 -1
  251. package/dist/utils/ide-detection.d.ts +0 -89
  252. package/dist/utils/ide-detection.d.ts.map +0 -1
  253. package/dist/utils/project-analysis.d.ts +0 -34
  254. package/dist/utils/project-analysis.d.ts.map +0 -1
  255. package/dist/utils/promise-utils.d.ts +0 -30
  256. package/dist/utils/promise-utils.d.ts.map +0 -1
  257. package/dist/utils/quality-gates-utils.d.ts +0 -49
  258. package/dist/utils/quality-gates-utils.d.ts.map +0 -1
  259. package/dist/utils/quality-gates.d.ts +0 -49
  260. package/dist/utils/quality-gates.d.ts.map +0 -1
  261. package/dist/utils/quality-gates.js +0 -402
  262. package/dist/utils/spec-resolver.d.ts +0 -80
  263. package/dist/utils/spec-resolver.d.ts.map +0 -1
  264. package/dist/utils/typescript-detector.d.ts +0 -66
  265. package/dist/utils/typescript-detector.d.ts.map +0 -1
  266. package/dist/utils/yaml-validation.d.ts +0 -32
  267. package/dist/utils/yaml-validation.d.ts.map +0 -1
  268. package/dist/validation/spec-validation.d.ts +0 -43
  269. package/dist/validation/spec-validation.d.ts.map +0 -1
  270. package/dist/waivers-manager.d.ts +0 -167
  271. package/dist/waivers-manager.d.ts.map +0 -1
  272. package/dist/worktree/worktree-manager.d.ts +0 -54
  273. package/dist/worktree/worktree-manager.d.ts.map +0 -1
@@ -13,6 +13,34 @@ const chalk = require('chalk');
13
13
  // Import SPEC_TYPES from constants for consistent display
14
14
  const { SPEC_TYPES } = require('../constants/spec-types');
15
15
  const { findProjectRoot } = require('./detection');
16
+ const { createValidator, getSchemaPath } = require('./schema-validator');
17
+
18
+ /**
19
+ * Validate a spec object against the working-spec schema.
20
+ * Throws with schema errors included in the message.
21
+ * @param {Object} spec - Parsed spec object
22
+ * @param {string} specPath - Path to the spec file (for error context)
23
+ */
24
+ function validateSpecSchema(spec, specPath) {
25
+ try {
26
+ const schemaPath = getSchemaPath('working-spec.schema.json', getProjectRoot());
27
+ const validate = createValidator(schemaPath);
28
+ const result = validate(spec);
29
+ if (!result.valid) {
30
+ const errorDetails = result.errors
31
+ .map(e => ` ${e.path}: ${e.message}`)
32
+ .join('\n');
33
+ // Schema violations are warnings, not fatal — the spec is still loadable.
34
+ // Commands like validate will report these; other commands shouldn't be blocked.
35
+ if (process.env.CAWS_QUIET !== '1') {
36
+ console.warn(`Schema warnings for ${specPath}:\n${errorDetails}`);
37
+ }
38
+ }
39
+ } catch (schemaErr) {
40
+ // Schema loading/compilation errors are non-fatal — warn and continue
41
+ console.warn('Could not validate spec schema:', schemaErr.message);
42
+ }
43
+ }
16
44
 
17
45
  /**
18
46
  * Spec resolution priority:
@@ -42,10 +70,11 @@ function getProjectRoot() {
42
70
  * @param {string} [options.specFile] - Explicit file path override
43
71
  * @param {boolean} [options.warnLegacy=true] - Warn when falling back to legacy spec
44
72
  * @param {boolean} [options.interactive=false] - Use interactive spec selection for multiple specs
73
+ * @param {boolean} [options.quiet=false] - Suppress informational logging for machine-readable output
45
74
  * @returns {Promise<{path: string, type: 'feature' | 'legacy', spec: Object}>}
46
75
  */
47
76
  async function resolveSpec(options = {}) {
48
- const { specId, specFile, warnLegacy = true, interactive = false } = options;
77
+ const { specId, specFile, warnLegacy = true, interactive = false, quiet = false } = options;
49
78
 
50
79
  // 1. Explicit file path takes highest priority
51
80
  if (specFile) {
@@ -54,7 +83,13 @@ async function resolveSpec(options = {}) {
54
83
  if (await fs.pathExists(explicitPath)) {
55
84
  const yaml = require('js-yaml');
56
85
  const content = await fs.readFile(explicitPath, 'utf8');
57
- const spec = yaml.load(content);
86
+ let spec;
87
+ try {
88
+ spec = yaml.load(content);
89
+ } catch (yamlError) {
90
+ throw new Error(`Invalid YAML in spec file ${explicitPath}: ${yamlError.message}`);
91
+ }
92
+ validateSpecSchema(spec, explicitPath);
58
93
 
59
94
  return {
60
95
  path: explicitPath,
@@ -74,8 +109,11 @@ async function resolveSpec(options = {}) {
74
109
  const yaml = require('js-yaml');
75
110
  const content = await fs.readFile(featurePath, 'utf8');
76
111
  const spec = yaml.load(content);
112
+ validateSpecSchema(spec, featurePath);
77
113
 
78
- console.log(chalk.green(`Using feature-specific spec: ${specId}`));
114
+ if (!quiet) {
115
+ console.log(chalk.green(`Using feature-specific spec: ${specId}`));
116
+ }
79
117
 
80
118
  return {
81
119
  path: featurePath,
@@ -102,8 +140,11 @@ async function resolveSpec(options = {}) {
102
140
  const yaml = require('js-yaml');
103
141
  const content = await fs.readFile(singleSpecPath, 'utf8');
104
142
  const spec = yaml.load(content);
143
+ validateSpecSchema(spec, singleSpecPath);
105
144
 
106
- console.log(chalk.blue(`Auto-detected single spec: ${singleSpecId}`));
145
+ if (!quiet) {
146
+ console.log(chalk.blue(`Auto-detected single spec: ${singleSpecId}`));
147
+ }
107
148
 
108
149
  return {
109
150
  path: singleSpecPath,
@@ -113,19 +154,23 @@ async function resolveSpec(options = {}) {
113
154
  }
114
155
  } else if (specIds.length > 1) {
115
156
  // Multiple specs - require explicit selection with enhanced guidance
116
- console.error(chalk.red('Multiple specs detected. Please specify which one:'));
157
+ if (!quiet) {
158
+ console.error(chalk.red('Multiple specs detected. Please specify which one:'));
159
+ }
117
160
 
118
161
  // Show specs with details
119
162
  const specsInfo = [];
120
163
  for (const id of specIds) {
121
- const specPath = path.join(SPECS_DIR, registry.specs[id].path);
164
+ const specPath = path.join(getProjectRoot(), SPECS_DIR, registry.specs[id].path);
122
165
  try {
123
166
  const content = await fs.readFile(specPath, 'utf8');
124
167
  let spec;
125
168
  try {
126
169
  spec = yaml.load(content);
127
170
  } catch (yamlError) {
128
- console.log(chalk.yellow(` - ${id} (YAML syntax error: ${yamlError.message})`));
171
+ if (!quiet) {
172
+ console.log(chalk.yellow(` - ${id} (YAML syntax error: ${yamlError.message})`));
173
+ }
129
174
  specsInfo.push({ id, type: 'unknown', status: 'unknown', title: 'YAML error' });
130
175
  continue;
131
176
  }
@@ -135,14 +180,18 @@ async function resolveSpec(options = {}) {
135
180
  status === 'active' ? chalk.green : status === 'completed' ? chalk.blue : chalk.yellow;
136
181
  const typeColor = SPEC_TYPES[type] ? SPEC_TYPES[type].color : chalk.white;
137
182
 
138
- console.log(
139
- chalk.yellow(
140
- ` - ${id} ${typeColor(`(${type})`)} ${statusColor(`[${status}]`)} - ${spec.title || 'Untitled'}`
141
- )
142
- );
183
+ if (!quiet) {
184
+ console.log(
185
+ chalk.yellow(
186
+ ` - ${id} ${typeColor(`(${type})`)} ${statusColor(`[${status}]`)} - ${spec.title || 'Untitled'}`
187
+ )
188
+ );
189
+ }
143
190
  specsInfo.push({ id, type, status, title: spec.title || 'Untitled' });
144
191
  } catch (error) {
145
- console.log(chalk.yellow(` - ${id} (error loading details: ${error.message})`));
192
+ if (!quiet) {
193
+ console.log(chalk.yellow(` - ${id} (error loading details: ${error.message})`));
194
+ }
146
195
  specsInfo.push({ id, type: 'unknown', status: 'unknown', title: 'Error loading' });
147
196
  }
148
197
  }
@@ -157,14 +206,17 @@ async function resolveSpec(options = {}) {
157
206
  specId: selectedSpecId,
158
207
  warnLegacy,
159
208
  interactive: false, // Prevent infinite recursion
209
+ quiet,
160
210
  });
161
211
  } catch (error) {
162
212
  throw new Error(`Interactive selection failed: ${error.message}`);
163
213
  }
164
214
  }
165
215
 
166
- console.log(chalk.blue('\n Usage: caws <command> --spec-id <spec-id>'));
167
- console.log(chalk.gray(` Example: caws validate --spec-id ${specIds[0]}`));
216
+ if (!quiet) {
217
+ console.log(chalk.blue('\n Usage: caws <command> --spec-id <spec-id>'));
218
+ console.log(chalk.gray(` Example: caws validate --spec-id ${specIds[0]}`));
219
+ }
168
220
 
169
221
  // Suggest most likely spec (active first, then by type priority)
170
222
  const priorityOrder = { active: 0, draft: 1, completed: 2 };
@@ -182,11 +234,15 @@ async function resolveSpec(options = {}) {
182
234
  return aTypePriority - bTypePriority;
183
235
  });
184
236
 
185
- console.log(chalk.green('\nQuick suggestion:'));
186
- console.log(chalk.gray(` Try: caws <command> --spec-id ${sortedSpecs[0]}`));
237
+ if (!quiet) {
238
+ console.log(chalk.green('\nQuick suggestion:'));
239
+ console.log(chalk.gray(` Try: caws <command> --spec-id ${sortedSpecs[0]}`));
240
+ }
187
241
 
188
242
  // Interactive mode suggestion
189
- console.log(chalk.blue('\n Interactive mode: caws <command> --interactive-spec-selection'));
243
+ if (!quiet) {
244
+ console.log(chalk.blue('\n Interactive mode: caws <command> --interactive-spec-selection'));
245
+ }
190
246
 
191
247
  throw new Error('Spec ID required when multiple specs exist');
192
248
  }
@@ -198,8 +254,9 @@ async function resolveSpec(options = {}) {
198
254
  const yaml = require('js-yaml');
199
255
  const content = await fs.readFile(legacyPath, 'utf8');
200
256
  const spec = yaml.load(content);
257
+ validateSpecSchema(spec, legacyPath);
201
258
 
202
- if (warnLegacy) {
259
+ if (warnLegacy && !quiet) {
203
260
  console.log(chalk.yellow('Using legacy working-spec.yaml'));
204
261
  console.log(chalk.gray(' For multi-agent workflows, use feature-specific specs:'));
205
262
  console.log(chalk.blue(' caws specs create <feature-id>'));
@@ -236,7 +293,19 @@ async function loadSpecsRegistry() {
236
293
 
237
294
  try {
238
295
  const registry = await fs.readJson(registryPath);
239
- return registry;
296
+ const sanitizedSpecs = {};
297
+
298
+ for (const [id, entry] of Object.entries(registry.specs || {})) {
299
+ const specPath = path.join(getProjectRoot(), SPECS_DIR, entry.path);
300
+ if (await fs.pathExists(specPath)) {
301
+ sanitizedSpecs[id] = entry;
302
+ }
303
+ }
304
+
305
+ return {
306
+ ...registry,
307
+ specs: sanitizedSpecs,
308
+ };
240
309
  } catch (error) {
241
310
  return {
242
311
  version: '1.0.0',
@@ -379,7 +448,10 @@ async function checkScopeConflicts(specIds) {
379
448
 
380
449
  // Load all specs and their scopes
381
450
  for (const id of specIds) {
382
- const specPath = path.join(SPECS_DIR, registry.specs[id].path);
451
+ const entry = registry.specs[id];
452
+ if (!entry) continue;
453
+
454
+ const specPath = path.join(getProjectRoot(), SPECS_DIR, entry.path);
383
455
 
384
456
  try {
385
457
  const content = await fs.readFile(specPath, 'utf8');