openspec-cn 0.23.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 (235) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +153 -0
  3. package/bin/openspec.js +3 -0
  4. package/dist/cli/index.d.ts +2 -0
  5. package/dist/cli/index.js +480 -0
  6. package/dist/commands/change.d.ts +35 -0
  7. package/dist/commands/change.js +277 -0
  8. package/dist/commands/completion.d.ts +72 -0
  9. package/dist/commands/completion.js +257 -0
  10. package/dist/commands/config.d.ts +8 -0
  11. package/dist/commands/config.js +198 -0
  12. package/dist/commands/feedback.d.ts +9 -0
  13. package/dist/commands/feedback.js +183 -0
  14. package/dist/commands/schema.d.ts +6 -0
  15. package/dist/commands/schema.js +869 -0
  16. package/dist/commands/show.d.ts +14 -0
  17. package/dist/commands/show.js +132 -0
  18. package/dist/commands/spec.d.ts +15 -0
  19. package/dist/commands/spec.js +225 -0
  20. package/dist/commands/validate.d.ts +24 -0
  21. package/dist/commands/validate.js +294 -0
  22. package/dist/commands/workflow/index.d.ts +17 -0
  23. package/dist/commands/workflow/index.js +12 -0
  24. package/dist/commands/workflow/instructions.d.ts +29 -0
  25. package/dist/commands/workflow/instructions.js +381 -0
  26. package/dist/commands/workflow/new-change.d.ts +11 -0
  27. package/dist/commands/workflow/new-change.js +44 -0
  28. package/dist/commands/workflow/schemas.d.ts +10 -0
  29. package/dist/commands/workflow/schemas.js +34 -0
  30. package/dist/commands/workflow/shared.d.ts +52 -0
  31. package/dist/commands/workflow/shared.js +111 -0
  32. package/dist/commands/workflow/status.d.ts +14 -0
  33. package/dist/commands/workflow/status.js +58 -0
  34. package/dist/commands/workflow/templates.d.ts +16 -0
  35. package/dist/commands/workflow/templates.js +68 -0
  36. package/dist/core/archive.d.ts +11 -0
  37. package/dist/core/archive.js +280 -0
  38. package/dist/core/artifact-graph/graph.d.ts +56 -0
  39. package/dist/core/artifact-graph/graph.js +141 -0
  40. package/dist/core/artifact-graph/index.d.ts +7 -0
  41. package/dist/core/artifact-graph/index.js +13 -0
  42. package/dist/core/artifact-graph/instruction-loader.d.ts +143 -0
  43. package/dist/core/artifact-graph/instruction-loader.js +214 -0
  44. package/dist/core/artifact-graph/resolver.d.ts +81 -0
  45. package/dist/core/artifact-graph/resolver.js +257 -0
  46. package/dist/core/artifact-graph/schema.d.ts +13 -0
  47. package/dist/core/artifact-graph/schema.js +108 -0
  48. package/dist/core/artifact-graph/state.d.ts +12 -0
  49. package/dist/core/artifact-graph/state.js +54 -0
  50. package/dist/core/artifact-graph/types.d.ts +45 -0
  51. package/dist/core/artifact-graph/types.js +43 -0
  52. package/dist/core/command-generation/adapters/amazon-q.d.ts +13 -0
  53. package/dist/core/command-generation/adapters/amazon-q.js +26 -0
  54. package/dist/core/command-generation/adapters/antigravity.d.ts +13 -0
  55. package/dist/core/command-generation/adapters/antigravity.js +26 -0
  56. package/dist/core/command-generation/adapters/auggie.d.ts +13 -0
  57. package/dist/core/command-generation/adapters/auggie.js +27 -0
  58. package/dist/core/command-generation/adapters/claude.d.ts +13 -0
  59. package/dist/core/command-generation/adapters/claude.js +50 -0
  60. package/dist/core/command-generation/adapters/cline.d.ts +14 -0
  61. package/dist/core/command-generation/adapters/cline.js +27 -0
  62. package/dist/core/command-generation/adapters/codebuddy.d.ts +13 -0
  63. package/dist/core/command-generation/adapters/codebuddy.js +28 -0
  64. package/dist/core/command-generation/adapters/codex.d.ts +13 -0
  65. package/dist/core/command-generation/adapters/codex.js +27 -0
  66. package/dist/core/command-generation/adapters/continue.d.ts +13 -0
  67. package/dist/core/command-generation/adapters/continue.js +28 -0
  68. package/dist/core/command-generation/adapters/costrict.d.ts +13 -0
  69. package/dist/core/command-generation/adapters/costrict.js +27 -0
  70. package/dist/core/command-generation/adapters/crush.d.ts +13 -0
  71. package/dist/core/command-generation/adapters/crush.js +30 -0
  72. package/dist/core/command-generation/adapters/cursor.d.ts +14 -0
  73. package/dist/core/command-generation/adapters/cursor.js +44 -0
  74. package/dist/core/command-generation/adapters/factory.d.ts +13 -0
  75. package/dist/core/command-generation/adapters/factory.js +27 -0
  76. package/dist/core/command-generation/adapters/gemini.d.ts +13 -0
  77. package/dist/core/command-generation/adapters/gemini.js +26 -0
  78. package/dist/core/command-generation/adapters/github-copilot.d.ts +13 -0
  79. package/dist/core/command-generation/adapters/github-copilot.js +26 -0
  80. package/dist/core/command-generation/adapters/iflow.d.ts +13 -0
  81. package/dist/core/command-generation/adapters/iflow.js +29 -0
  82. package/dist/core/command-generation/adapters/index.d.ts +27 -0
  83. package/dist/core/command-generation/adapters/index.js +27 -0
  84. package/dist/core/command-generation/adapters/kilocode.d.ts +14 -0
  85. package/dist/core/command-generation/adapters/kilocode.js +23 -0
  86. package/dist/core/command-generation/adapters/opencode.d.ts +13 -0
  87. package/dist/core/command-generation/adapters/opencode.js +26 -0
  88. package/dist/core/command-generation/adapters/qoder.d.ts +13 -0
  89. package/dist/core/command-generation/adapters/qoder.js +30 -0
  90. package/dist/core/command-generation/adapters/qwen.d.ts +13 -0
  91. package/dist/core/command-generation/adapters/qwen.js +26 -0
  92. package/dist/core/command-generation/adapters/roocode.d.ts +14 -0
  93. package/dist/core/command-generation/adapters/roocode.js +27 -0
  94. package/dist/core/command-generation/adapters/windsurf.d.ts +14 -0
  95. package/dist/core/command-generation/adapters/windsurf.js +51 -0
  96. package/dist/core/command-generation/generator.d.ts +21 -0
  97. package/dist/core/command-generation/generator.js +27 -0
  98. package/dist/core/command-generation/index.d.ts +22 -0
  99. package/dist/core/command-generation/index.js +24 -0
  100. package/dist/core/command-generation/registry.d.ts +36 -0
  101. package/dist/core/command-generation/registry.js +88 -0
  102. package/dist/core/command-generation/types.d.ts +55 -0
  103. package/dist/core/command-generation/types.js +8 -0
  104. package/dist/core/completions/command-registry.d.ts +7 -0
  105. package/dist/core/completions/command-registry.js +456 -0
  106. package/dist/core/completions/completion-provider.d.ts +60 -0
  107. package/dist/core/completions/completion-provider.js +102 -0
  108. package/dist/core/completions/factory.d.ts +64 -0
  109. package/dist/core/completions/factory.js +75 -0
  110. package/dist/core/completions/generators/bash-generator.d.ts +32 -0
  111. package/dist/core/completions/generators/bash-generator.js +174 -0
  112. package/dist/core/completions/generators/fish-generator.d.ts +32 -0
  113. package/dist/core/completions/generators/fish-generator.js +157 -0
  114. package/dist/core/completions/generators/powershell-generator.d.ts +33 -0
  115. package/dist/core/completions/generators/powershell-generator.js +207 -0
  116. package/dist/core/completions/generators/zsh-generator.d.ts +44 -0
  117. package/dist/core/completions/generators/zsh-generator.js +250 -0
  118. package/dist/core/completions/installers/bash-installer.d.ts +87 -0
  119. package/dist/core/completions/installers/bash-installer.js +318 -0
  120. package/dist/core/completions/installers/fish-installer.d.ts +43 -0
  121. package/dist/core/completions/installers/fish-installer.js +143 -0
  122. package/dist/core/completions/installers/powershell-installer.d.ts +88 -0
  123. package/dist/core/completions/installers/powershell-installer.js +327 -0
  124. package/dist/core/completions/installers/zsh-installer.d.ts +125 -0
  125. package/dist/core/completions/installers/zsh-installer.js +449 -0
  126. package/dist/core/completions/templates/bash-templates.d.ts +6 -0
  127. package/dist/core/completions/templates/bash-templates.js +24 -0
  128. package/dist/core/completions/templates/fish-templates.d.ts +7 -0
  129. package/dist/core/completions/templates/fish-templates.js +39 -0
  130. package/dist/core/completions/templates/powershell-templates.d.ts +6 -0
  131. package/dist/core/completions/templates/powershell-templates.js +25 -0
  132. package/dist/core/completions/templates/zsh-templates.d.ts +6 -0
  133. package/dist/core/completions/templates/zsh-templates.js +36 -0
  134. package/dist/core/completions/types.d.ts +79 -0
  135. package/dist/core/completions/types.js +2 -0
  136. package/dist/core/config-prompts.d.ts +9 -0
  137. package/dist/core/config-prompts.js +34 -0
  138. package/dist/core/config-schema.d.ts +76 -0
  139. package/dist/core/config-schema.js +200 -0
  140. package/dist/core/config.d.ts +17 -0
  141. package/dist/core/config.js +30 -0
  142. package/dist/core/converters/json-converter.d.ts +6 -0
  143. package/dist/core/converters/json-converter.js +51 -0
  144. package/dist/core/global-config.d.ts +39 -0
  145. package/dist/core/global-config.js +115 -0
  146. package/dist/core/index.d.ts +2 -0
  147. package/dist/core/index.js +3 -0
  148. package/dist/core/init.d.ts +32 -0
  149. package/dist/core/init.js +433 -0
  150. package/dist/core/legacy-cleanup.d.ts +162 -0
  151. package/dist/core/legacy-cleanup.js +501 -0
  152. package/dist/core/list.d.ts +9 -0
  153. package/dist/core/list.js +171 -0
  154. package/dist/core/parsers/change-parser.d.ts +13 -0
  155. package/dist/core/parsers/change-parser.js +193 -0
  156. package/dist/core/parsers/markdown-parser.d.ts +22 -0
  157. package/dist/core/parsers/markdown-parser.js +187 -0
  158. package/dist/core/parsers/requirement-blocks.d.ts +37 -0
  159. package/dist/core/parsers/requirement-blocks.js +201 -0
  160. package/dist/core/project-config.d.ts +64 -0
  161. package/dist/core/project-config.js +223 -0
  162. package/dist/core/schemas/base.schema.d.ts +13 -0
  163. package/dist/core/schemas/base.schema.js +13 -0
  164. package/dist/core/schemas/change.schema.d.ts +73 -0
  165. package/dist/core/schemas/change.schema.js +31 -0
  166. package/dist/core/schemas/index.d.ts +4 -0
  167. package/dist/core/schemas/index.js +4 -0
  168. package/dist/core/schemas/spec.schema.d.ts +18 -0
  169. package/dist/core/schemas/spec.schema.js +15 -0
  170. package/dist/core/shared/index.d.ts +8 -0
  171. package/dist/core/shared/index.js +8 -0
  172. package/dist/core/shared/skill-generation.d.ts +41 -0
  173. package/dist/core/shared/skill-generation.js +74 -0
  174. package/dist/core/shared/tool-detection.d.ts +66 -0
  175. package/dist/core/shared/tool-detection.js +140 -0
  176. package/dist/core/specs-apply.d.ts +73 -0
  177. package/dist/core/specs-apply.js +384 -0
  178. package/dist/core/styles/palette.d.ts +7 -0
  179. package/dist/core/styles/palette.js +8 -0
  180. package/dist/core/templates/index.d.ts +8 -0
  181. package/dist/core/templates/index.js +9 -0
  182. package/dist/core/templates/skill-templates.d.ts +112 -0
  183. package/dist/core/templates/skill-templates.js +2893 -0
  184. package/dist/core/update.d.ts +42 -0
  185. package/dist/core/update.js +306 -0
  186. package/dist/core/validation/constants.d.ts +34 -0
  187. package/dist/core/validation/constants.js +40 -0
  188. package/dist/core/validation/types.d.ts +18 -0
  189. package/dist/core/validation/types.js +2 -0
  190. package/dist/core/validation/validator.d.ts +33 -0
  191. package/dist/core/validation/validator.js +409 -0
  192. package/dist/core/view.d.ts +8 -0
  193. package/dist/core/view.js +168 -0
  194. package/dist/index.d.ts +3 -0
  195. package/dist/index.js +3 -0
  196. package/dist/prompts/searchable-multi-select.d.ts +27 -0
  197. package/dist/prompts/searchable-multi-select.js +149 -0
  198. package/dist/telemetry/config.d.ts +32 -0
  199. package/dist/telemetry/config.js +68 -0
  200. package/dist/telemetry/index.d.ts +31 -0
  201. package/dist/telemetry/index.js +145 -0
  202. package/dist/ui/ascii-patterns.d.ts +16 -0
  203. package/dist/ui/ascii-patterns.js +133 -0
  204. package/dist/ui/welcome-screen.d.ts +10 -0
  205. package/dist/ui/welcome-screen.js +146 -0
  206. package/dist/utils/change-metadata.d.ts +51 -0
  207. package/dist/utils/change-metadata.js +147 -0
  208. package/dist/utils/change-utils.d.ts +62 -0
  209. package/dist/utils/change-utils.js +121 -0
  210. package/dist/utils/file-system.d.ts +36 -0
  211. package/dist/utils/file-system.js +281 -0
  212. package/dist/utils/index.d.ts +5 -0
  213. package/dist/utils/index.js +7 -0
  214. package/dist/utils/interactive.d.ts +18 -0
  215. package/dist/utils/interactive.js +21 -0
  216. package/dist/utils/item-discovery.d.ts +4 -0
  217. package/dist/utils/item-discovery.js +72 -0
  218. package/dist/utils/match.d.ts +3 -0
  219. package/dist/utils/match.js +22 -0
  220. package/dist/utils/shell-detection.d.ts +20 -0
  221. package/dist/utils/shell-detection.js +41 -0
  222. package/dist/utils/task-progress.d.ts +8 -0
  223. package/dist/utils/task-progress.js +36 -0
  224. package/package.json +84 -0
  225. package/schemas/spec-driven/schema.yaml +148 -0
  226. package/schemas/spec-driven/templates/design.md +19 -0
  227. package/schemas/spec-driven/templates/proposal.md +23 -0
  228. package/schemas/spec-driven/templates/spec.md +8 -0
  229. package/schemas/spec-driven/templates/tasks.md +9 -0
  230. package/schemas/tdd/schema.yaml +213 -0
  231. package/schemas/tdd/templates/docs.md +15 -0
  232. package/schemas/tdd/templates/implementation.md +11 -0
  233. package/schemas/tdd/templates/spec.md +11 -0
  234. package/schemas/tdd/templates/test.md +11 -0
  235. package/scripts/postinstall.js +147 -0
@@ -0,0 +1,294 @@
1
+ import ora from 'ora';
2
+ import path from 'path';
3
+ import { Validator } from '../core/validation/validator.js';
4
+ import { isInteractive, resolveNoInteractive } from '../utils/interactive.js';
5
+ import { getActiveChangeIds, getSpecIds } from '../utils/item-discovery.js';
6
+ import { nearestMatches } from '../utils/match.js';
7
+ export class ValidateCommand {
8
+ async execute(itemName, options = {}) {
9
+ const interactive = isInteractive(options);
10
+ // Handle bulk flags first
11
+ if (options.all || options.changes || options.specs) {
12
+ await this.runBulkValidation({
13
+ changes: !!options.all || !!options.changes,
14
+ specs: !!options.all || !!options.specs,
15
+ }, { strict: !!options.strict, json: !!options.json, concurrency: options.concurrency, noInteractive: resolveNoInteractive(options) });
16
+ return;
17
+ }
18
+ // No item and no flags
19
+ if (!itemName) {
20
+ if (interactive) {
21
+ await this.runInteractiveSelector({ strict: !!options.strict, json: !!options.json, concurrency: options.concurrency });
22
+ return;
23
+ }
24
+ this.printNonInteractiveHint();
25
+ process.exitCode = 1;
26
+ return;
27
+ }
28
+ // Direct item validation with type detection or override
29
+ const typeOverride = this.normalizeType(options.type);
30
+ await this.validateDirectItem(itemName, { typeOverride, strict: !!options.strict, json: !!options.json });
31
+ }
32
+ normalizeType(value) {
33
+ if (!value)
34
+ return undefined;
35
+ const v = value.toLowerCase();
36
+ if (v === 'change' || v === 'spec')
37
+ return v;
38
+ return undefined;
39
+ }
40
+ async runInteractiveSelector(opts) {
41
+ const { select } = await import('@inquirer/prompts');
42
+ const choice = await select({
43
+ message: 'What would you like to validate?',
44
+ choices: [
45
+ { name: 'All (changes + specs)', value: 'all' },
46
+ { name: 'All changes', value: 'changes' },
47
+ { name: 'All specs', value: 'specs' },
48
+ { name: 'Pick a specific change or spec', value: 'one' },
49
+ ],
50
+ });
51
+ if (choice === 'all')
52
+ return this.runBulkValidation({ changes: true, specs: true }, opts);
53
+ if (choice === 'changes')
54
+ return this.runBulkValidation({ changes: true, specs: false }, opts);
55
+ if (choice === 'specs')
56
+ return this.runBulkValidation({ changes: false, specs: true }, opts);
57
+ // one
58
+ const [changes, specs] = await Promise.all([getActiveChangeIds(), getSpecIds()]);
59
+ const items = [];
60
+ items.push(...changes.map(id => ({ name: `change/${id}`, value: { type: 'change', id } })));
61
+ items.push(...specs.map(id => ({ name: `spec/${id}`, value: { type: 'spec', id } })));
62
+ if (items.length === 0) {
63
+ console.error('No items found to validate.');
64
+ process.exitCode = 1;
65
+ return;
66
+ }
67
+ const picked = await select({ message: 'Pick an item', choices: items });
68
+ await this.validateByType(picked.type, picked.id, opts);
69
+ }
70
+ printNonInteractiveHint() {
71
+ console.error('Nothing to validate. Try one of:');
72
+ console.error(' openspec validate --all');
73
+ console.error(' openspec validate --changes');
74
+ console.error(' openspec validate --specs');
75
+ console.error(' openspec validate <item-name>');
76
+ console.error('Or run in an interactive terminal.');
77
+ }
78
+ async validateDirectItem(itemName, opts) {
79
+ const [changes, specs] = await Promise.all([getActiveChangeIds(), getSpecIds()]);
80
+ const isChange = changes.includes(itemName);
81
+ const isSpec = specs.includes(itemName);
82
+ const type = opts.typeOverride ?? (isChange ? 'change' : isSpec ? 'spec' : undefined);
83
+ if (!type) {
84
+ console.error(`Unknown item '${itemName}'`);
85
+ const suggestions = nearestMatches(itemName, [...changes, ...specs]);
86
+ if (suggestions.length)
87
+ console.error(`Did you mean: ${suggestions.join(', ')}?`);
88
+ process.exitCode = 1;
89
+ return;
90
+ }
91
+ if (!opts.typeOverride && isChange && isSpec) {
92
+ console.error(`Ambiguous item '${itemName}' matches both a change and a spec.`);
93
+ console.error('Pass --type change|spec, or use: openspec change validate / openspec spec validate');
94
+ process.exitCode = 1;
95
+ return;
96
+ }
97
+ await this.validateByType(type, itemName, opts);
98
+ }
99
+ async validateByType(type, id, opts) {
100
+ const validator = new Validator(opts.strict);
101
+ if (type === 'change') {
102
+ const changeDir = path.join(process.cwd(), 'openspec', 'changes', id);
103
+ const start = Date.now();
104
+ const report = await validator.validateChangeDeltaSpecs(changeDir);
105
+ const durationMs = Date.now() - start;
106
+ this.printReport('change', id, report, durationMs, opts.json);
107
+ // Non-zero exit if invalid (keeps enriched output test semantics)
108
+ process.exitCode = report.valid ? 0 : 1;
109
+ return;
110
+ }
111
+ const file = path.join(process.cwd(), 'openspec', 'specs', id, 'spec.md');
112
+ const start = Date.now();
113
+ const report = await validator.validateSpec(file);
114
+ const durationMs = Date.now() - start;
115
+ this.printReport('spec', id, report, durationMs, opts.json);
116
+ process.exitCode = report.valid ? 0 : 1;
117
+ }
118
+ printReport(type, id, report, durationMs, json) {
119
+ if (json) {
120
+ const out = { items: [{ id, type, valid: report.valid, issues: report.issues, durationMs }], summary: { totals: { items: 1, passed: report.valid ? 1 : 0, failed: report.valid ? 0 : 1 }, byType: { [type]: { items: 1, passed: report.valid ? 1 : 0, failed: report.valid ? 0 : 1 } } }, version: '1.0' };
121
+ console.log(JSON.stringify(out, null, 2));
122
+ return;
123
+ }
124
+ if (report.valid) {
125
+ console.log(`${type === 'change' ? 'Change' : 'Specification'} '${id}' is valid`);
126
+ }
127
+ else {
128
+ console.error(`${type === 'change' ? 'Change' : 'Specification'} '${id}' has issues`);
129
+ for (const issue of report.issues) {
130
+ const label = issue.level === 'ERROR' ? 'ERROR' : issue.level;
131
+ const prefix = issue.level === 'ERROR' ? '✗' : issue.level === 'WARNING' ? '⚠' : 'ℹ';
132
+ console.error(`${prefix} [${label}] ${issue.path}: ${issue.message}`);
133
+ }
134
+ this.printNextSteps(type);
135
+ }
136
+ }
137
+ printNextSteps(type) {
138
+ const bullets = [];
139
+ if (type === 'change') {
140
+ bullets.push('- Ensure change has deltas in specs/: use headers ## ADDED/MODIFIED/REMOVED/RENAMED Requirements');
141
+ bullets.push('- Each requirement MUST include at least one #### Scenario: block');
142
+ bullets.push('- Debug parsed deltas: openspec change show <id> --json --deltas-only');
143
+ }
144
+ else {
145
+ bullets.push('- Ensure spec includes ## Purpose and ## Requirements sections');
146
+ bullets.push('- Each requirement MUST include at least one #### Scenario: block');
147
+ bullets.push('- Re-run with --json to see structured report');
148
+ }
149
+ console.error('Next steps:');
150
+ bullets.forEach(b => console.error(` ${b}`));
151
+ }
152
+ async runBulkValidation(scope, opts) {
153
+ const spinner = !opts.json && !opts.noInteractive ? ora('Validating...').start() : undefined;
154
+ const [changeIds, specIds] = await Promise.all([
155
+ scope.changes ? getActiveChangeIds() : Promise.resolve([]),
156
+ scope.specs ? getSpecIds() : Promise.resolve([]),
157
+ ]);
158
+ const DEFAULT_CONCURRENCY = 6;
159
+ const maxSuggestions = 5; // used by nearestMatches
160
+ const concurrency = normalizeConcurrency(opts.concurrency) ?? normalizeConcurrency(process.env.OPENSPEC_CONCURRENCY) ?? DEFAULT_CONCURRENCY;
161
+ const validator = new Validator(opts.strict);
162
+ const queue = [];
163
+ for (const id of changeIds) {
164
+ queue.push(async () => {
165
+ const start = Date.now();
166
+ const changeDir = path.join(process.cwd(), 'openspec', 'changes', id);
167
+ const report = await validator.validateChangeDeltaSpecs(changeDir);
168
+ const durationMs = Date.now() - start;
169
+ return { id, type: 'change', valid: report.valid, issues: report.issues, durationMs };
170
+ });
171
+ }
172
+ for (const id of specIds) {
173
+ queue.push(async () => {
174
+ const start = Date.now();
175
+ const file = path.join(process.cwd(), 'openspec', 'specs', id, 'spec.md');
176
+ const report = await validator.validateSpec(file);
177
+ const durationMs = Date.now() - start;
178
+ return { id, type: 'spec', valid: report.valid, issues: report.issues, durationMs };
179
+ });
180
+ }
181
+ if (queue.length === 0) {
182
+ spinner?.stop();
183
+ const summary = {
184
+ totals: { items: 0, passed: 0, failed: 0 },
185
+ byType: {
186
+ ...(scope.changes ? { change: { items: 0, passed: 0, failed: 0 } } : {}),
187
+ ...(scope.specs ? { spec: { items: 0, passed: 0, failed: 0 } } : {}),
188
+ },
189
+ };
190
+ if (opts.json) {
191
+ const out = { items: [], summary, version: '1.0' };
192
+ console.log(JSON.stringify(out, null, 2));
193
+ }
194
+ else {
195
+ console.log('No items found to validate.');
196
+ }
197
+ process.exitCode = 0;
198
+ return;
199
+ }
200
+ const results = [];
201
+ let index = 0;
202
+ let running = 0;
203
+ let passed = 0;
204
+ let failed = 0;
205
+ await new Promise((resolve) => {
206
+ const next = () => {
207
+ while (running < concurrency && index < queue.length) {
208
+ const currentIndex = index++;
209
+ const task = queue[currentIndex];
210
+ running++;
211
+ if (spinner)
212
+ spinner.text = `Validating (${currentIndex + 1}/${queue.length})...`;
213
+ task()
214
+ .then(res => {
215
+ results.push(res);
216
+ if (res.valid)
217
+ passed++;
218
+ else
219
+ failed++;
220
+ })
221
+ .catch((error) => {
222
+ const message = error?.message || 'Unknown error';
223
+ const res = { id: getPlannedId(currentIndex, changeIds, specIds) ?? 'unknown', type: getPlannedType(currentIndex, changeIds, specIds) ?? 'change', valid: false, issues: [{ level: 'ERROR', path: 'file', message }], durationMs: 0 };
224
+ results.push(res);
225
+ failed++;
226
+ })
227
+ .finally(() => {
228
+ running--;
229
+ if (index >= queue.length && running === 0)
230
+ resolve();
231
+ else
232
+ next();
233
+ });
234
+ }
235
+ };
236
+ next();
237
+ });
238
+ spinner?.stop();
239
+ results.sort((a, b) => a.id.localeCompare(b.id));
240
+ const summary = {
241
+ totals: { items: results.length, passed, failed },
242
+ byType: {
243
+ ...(scope.changes ? { change: summarizeType(results, 'change') } : {}),
244
+ ...(scope.specs ? { spec: summarizeType(results, 'spec') } : {}),
245
+ },
246
+ };
247
+ if (opts.json) {
248
+ const out = { items: results, summary, version: '1.0' };
249
+ console.log(JSON.stringify(out, null, 2));
250
+ }
251
+ else {
252
+ for (const res of results) {
253
+ if (res.valid)
254
+ console.log(`✓ ${res.type}/${res.id}`);
255
+ else
256
+ console.error(`✗ ${res.type}/${res.id}`);
257
+ }
258
+ console.log(`Totals: ${summary.totals.passed} passed, ${summary.totals.failed} failed (${summary.totals.items} items)`);
259
+ }
260
+ process.exitCode = failed > 0 ? 1 : 0;
261
+ }
262
+ }
263
+ function summarizeType(results, type) {
264
+ const filtered = results.filter(r => r.type === type);
265
+ const items = filtered.length;
266
+ const passed = filtered.filter(r => r.valid).length;
267
+ const failed = items - passed;
268
+ return { items, passed, failed };
269
+ }
270
+ function normalizeConcurrency(value) {
271
+ if (!value)
272
+ return undefined;
273
+ const n = parseInt(value, 10);
274
+ if (Number.isNaN(n) || n <= 0)
275
+ return undefined;
276
+ return n;
277
+ }
278
+ function getPlannedId(index, changeIds, specIds) {
279
+ const totalChanges = changeIds.length;
280
+ if (index < totalChanges)
281
+ return changeIds[index];
282
+ const specIndex = index - totalChanges;
283
+ return specIds[specIndex];
284
+ }
285
+ function getPlannedType(index, changeIds, specIds) {
286
+ const totalChanges = changeIds.length;
287
+ if (index < totalChanges)
288
+ return 'change';
289
+ const specIndex = index - totalChanges;
290
+ if (specIndex >= 0 && specIndex < specIds.length)
291
+ return 'spec';
292
+ return undefined;
293
+ }
294
+ //# sourceMappingURL=validate.js.map
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Workflow CLI Commands
3
+ *
4
+ * Commands for the artifact-driven workflow: status, instructions, templates, schemas, new change.
5
+ */
6
+ export { statusCommand } from './status.js';
7
+ export type { StatusOptions } from './status.js';
8
+ export { instructionsCommand, applyInstructionsCommand } from './instructions.js';
9
+ export type { InstructionsOptions } from './instructions.js';
10
+ export { templatesCommand } from './templates.js';
11
+ export type { TemplatesOptions } from './templates.js';
12
+ export { schemasCommand } from './schemas.js';
13
+ export type { SchemasOptions } from './schemas.js';
14
+ export { newChangeCommand } from './new-change.js';
15
+ export type { NewChangeOptions } from './new-change.js';
16
+ export { DEFAULT_SCHEMA } from './shared.js';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Workflow CLI Commands
3
+ *
4
+ * Commands for the artifact-driven workflow: status, instructions, templates, schemas, new change.
5
+ */
6
+ export { statusCommand } from './status.js';
7
+ export { instructionsCommand, applyInstructionsCommand } from './instructions.js';
8
+ export { templatesCommand } from './templates.js';
9
+ export { schemasCommand } from './schemas.js';
10
+ export { newChangeCommand } from './new-change.js';
11
+ export { DEFAULT_SCHEMA } from './shared.js';
12
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Instructions Command
3
+ *
4
+ * Generates enriched instructions for creating artifacts or applying tasks.
5
+ * Includes both artifact instructions and apply instructions.
6
+ */
7
+ import { type ArtifactInstructions } from '../../core/artifact-graph/index.js';
8
+ import { type ApplyInstructions } from './shared.js';
9
+ export interface InstructionsOptions {
10
+ change?: string;
11
+ schema?: string;
12
+ json?: boolean;
13
+ }
14
+ export interface ApplyInstructionsOptions {
15
+ change?: string;
16
+ schema?: string;
17
+ json?: boolean;
18
+ }
19
+ export declare function instructionsCommand(artifactId: string | undefined, options: InstructionsOptions): Promise<void>;
20
+ export declare function printInstructionsText(instructions: ArtifactInstructions, isBlocked: boolean): void;
21
+ /**
22
+ * Generates apply instructions for implementing tasks from a change.
23
+ * Schema-aware: reads apply phase configuration from schema to determine
24
+ * required artifacts, tracking file, and instruction.
25
+ */
26
+ export declare function generateApplyInstructions(projectRoot: string, changeName: string, schemaName?: string): Promise<ApplyInstructions>;
27
+ export declare function applyInstructionsCommand(options: ApplyInstructionsOptions): Promise<void>;
28
+ export declare function printApplyInstructionsText(instructions: ApplyInstructions): void;
29
+ //# sourceMappingURL=instructions.d.ts.map