@openprd/cli 0.1.0 → 0.1.8

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 (138) hide show
  1. package/.openprd/README.md +43 -69
  2. package/.openprd/README_EN.md +84 -0
  3. package/.openprd/benchmarks/index.md +7 -0
  4. package/.openprd/benchmarks/sources.yaml +25 -3
  5. package/.openprd/discovery/config.json +16 -2
  6. package/.openprd/engagements/active/flows.md +19 -14
  7. package/.openprd/engagements/active/handoff.md +11 -4
  8. package/.openprd/engagements/active/prd.md +99 -71
  9. package/.openprd/engagements/active/review.html +4 -4
  10. package/.openprd/engagements/active/roles.md +9 -8
  11. package/.openprd/engagements/work-units/wu-20260524015648-6d33ded7.json +4 -4
  12. package/.openprd/engagements/work-units/wu-20260602113956-a99b5b88.json +18 -0
  13. package/.openprd/engagements/work-units/wu-20260602122244-78656aaf.json +18 -0
  14. package/.openprd/engagements/work-units/wu-20260602122442-e96489e2.json +18 -0
  15. package/.openprd/engagements/work-units/wu-20260602132835-695429e8.json +18 -0
  16. package/.openprd/knowledge/candidates/candidate-turn-1780116203372-5f266a79e968c758/candidate.json +78 -0
  17. package/.openprd/knowledge/candidates/candidate-turn-1780116203372-5f266a79e968c758/diagnostic-report.json +129 -0
  18. package/.openprd/knowledge/candidates/candidate-turn-1780116203372-5f266a79e968c758/root-cause-candidates.json +41 -0
  19. package/.openprd/knowledge/candidates/candidate-turn-1780116203372-5f266a79e968c758/timeline.json +14 -0
  20. package/.openprd/knowledge/drafts/openprd-experience-diagnostic-candidate-turn-1780116203372-5f266a79e968c758/SKILL.md +49 -0
  21. package/.openprd/knowledge/index.json +44 -4
  22. package/.openprd/reviews/v0001.html +195 -129
  23. package/.openprd/reviews/v0002.html +1150 -0
  24. package/.openprd/reviews/v0003.html +1150 -0
  25. package/.openprd/reviews/v0004.html +1150 -0
  26. package/.openprd/reviews/v0005.html +1150 -0
  27. package/.openprd/standards/config.json +12 -9
  28. package/.openprd/state/changes.json +17 -2
  29. package/.openprd/state/current.json +399 -63
  30. package/.openprd/state/release-ledger.json +344 -0
  31. package/.openprd/state/version-index.json +52 -0
  32. package/.openprd/state/versions/v0002.json +264 -0
  33. package/.openprd/state/versions/v0002.md +183 -0
  34. package/.openprd/state/versions/v0003.json +269 -0
  35. package/.openprd/state/versions/v0003.md +188 -0
  36. package/.openprd/state/versions/v0004.json +274 -0
  37. package/.openprd/state/versions/v0004.md +193 -0
  38. package/.openprd/state/versions/v0005.json +299 -0
  39. package/.openprd/state/versions/v0005.md +189 -0
  40. package/.openprd/templates/agent/intake.md +5 -4
  41. package/.openprd/templates/b2b/intake.md +5 -4
  42. package/.openprd/templates/base/intake.md +10 -4
  43. package/.openprd/templates/company/README.md +9 -7
  44. package/.openprd/templates/company/README_EN.md +12 -0
  45. package/.openprd/templates/consumer/intake.md +5 -4
  46. package/.openprd/templates/industry/README.md +12 -10
  47. package/.openprd/templates/industry/README_EN.md +18 -0
  48. package/.openprd/templates/project/README.md +11 -9
  49. package/.openprd/templates/project/README_EN.md +16 -0
  50. package/.openprd/templates/session/README.md +11 -9
  51. package/.openprd/templates/session/README_EN.md +16 -0
  52. package/AGENTS.md +12 -8
  53. package/README.md +402 -441
  54. package/README_CN.md +4 -578
  55. package/README_EN.md +850 -0
  56. package/docs/assets/openprd-requirement-routing-en.png +0 -0
  57. package/docs/assets/openprd-requirement-routing-en.svg +102 -0
  58. package/docs/assets/openprd-requirement-routing-zh-refined.png +0 -0
  59. package/docs/assets/openprd-requirement-routing-zh.png +0 -0
  60. package/docs/assets/openprd-requirement-routing-zh.svg +102 -0
  61. package/package.json +6 -2
  62. package/scripts/dev-check-wrapup-copy.mjs +110 -0
  63. package/scripts/openprd-github-release-notes.mjs +99 -0
  64. package/scripts/quality-perf-check.mjs +203 -0
  65. package/skills/openprd-benchmark-router/SKILL.md +1 -0
  66. package/skills/openprd-benchmark-router/references/benchmark-sources.md +1 -0
  67. package/skills/openprd-benchmark-router/references/source-policy.md +2 -0
  68. package/skills/openprd-discovery-loop/SKILL.md +2 -2
  69. package/skills/openprd-harness/SKILL.md +46 -24
  70. package/skills/openprd-harness/references/workflow-gates.md +15 -0
  71. package/skills/openprd-quality/SKILL.md +10 -4
  72. package/skills/openprd-requirement-intake/SKILL.md +39 -23
  73. package/skills/openprd-requirement-intake/references/prd-template-lenses.md +6 -6
  74. package/skills/openprd-requirement-intake/references/routing-rubric.md +22 -8
  75. package/skills/openprd-router/SKILL.md +2 -2
  76. package/skills/openprd-shared/SKILL.md +51 -23
  77. package/skills/openprd-standards/SKILL.md +2 -1
  78. package/src/agent-integration.js +265 -65
  79. package/src/benchmark/constants.js +107 -0
  80. package/src/benchmark/operations.js +235 -0
  81. package/src/benchmark/registry.js +64 -0
  82. package/src/benchmark/render.js +115 -0
  83. package/src/benchmark/source.js +617 -0
  84. package/src/benchmark/storage.js +121 -0
  85. package/src/benchmark/verify.js +235 -0
  86. package/src/benchmark.js +50 -851
  87. package/src/change-summary.js +339 -0
  88. package/src/cli/args.js +67 -6
  89. package/src/cli/basic-print.js +365 -0
  90. package/src/cli/benchmark-print.js +91 -0
  91. package/src/cli/change-print.js +221 -0
  92. package/src/cli/doctor-print.js +268 -0
  93. package/src/cli/growth-print.js +176 -0
  94. package/src/cli/print.js +73 -1384
  95. package/src/cli/quality-print.js +284 -0
  96. package/src/cli/run-print.js +297 -0
  97. package/src/cli/shared-print.js +127 -0
  98. package/src/cli/workflow-print.js +195 -0
  99. package/src/codex-hook-runner-template.mjs +639 -117
  100. package/src/codex-runtime.js +324 -0
  101. package/src/dev-standards.js +178 -5
  102. package/src/diagram-core.js +5 -5
  103. package/src/discovery.js +2 -1
  104. package/src/execution-strategy.js +369 -0
  105. package/src/fleet.js +4 -0
  106. package/src/github-release.js +156 -0
  107. package/src/growth.js +311 -13
  108. package/src/html-artifact-utils.js +25 -0
  109. package/src/html-artifacts.js +157 -1596
  110. package/src/knowledge.js +1176 -75
  111. package/src/language-policy.js +2 -112
  112. package/src/learning-html-artifact.js +1031 -0
  113. package/src/learning-review.js +3 -2
  114. package/src/loop.js +280 -9
  115. package/src/openprd.js +341 -38
  116. package/src/openspec/change-validate.js +0 -9
  117. package/src/openspec/execute.js +79 -3
  118. package/src/openspec/generate.js +33 -20
  119. package/src/openspec/tasks.js +33 -2
  120. package/src/prd-core.js +10 -9
  121. package/src/product-type-copy.js +69 -0
  122. package/src/quality-html-artifact.js +108 -9
  123. package/src/quality-learning.js +30 -0
  124. package/src/quality-visual-review.js +237 -0
  125. package/src/quality.js +329 -43
  126. package/src/registry-hygiene.js +54 -0
  127. package/src/release-ledger.js +413 -0
  128. package/src/review-presentation.js +12 -6
  129. package/src/run-harness.js +722 -48
  130. package/src/self-update.js +1 -1
  131. package/src/session-binding.js +40 -3
  132. package/src/session-registry.js +159 -0
  133. package/src/standards.js +5 -3
  134. package/src/test-strategy.js +386 -0
  135. package/src/visual-compare.js +915 -34
  136. package/src/work-unit-migration.js +5 -1
  137. package/src/workspace-core.js +343 -19
  138. package/src/workspace-workflow.js +538 -134
@@ -0,0 +1,365 @@
1
+ /*
2
+ * 核心功能
3
+ * 渲染 OpenPrd 基础工作流与初始化相关命令的人类可读输出或 JSON 输出。
4
+ *
5
+ * 输入
6
+ * 接收 validate、status、classify、clarify、capture、interview、playground、learning、init 等结果对象。
7
+ *
8
+ * 输出
9
+ * 向终端输出结构化摘要,或在 `--json` 模式下直出 JSON。
10
+ *
11
+ * 定位
12
+ * 位于 CLI 表现层的基础输出模块,负责相对稳定的 workspace 基础命令呈现。
13
+ *
14
+ * 依赖
15
+ * 仅依赖终端输出和 result 字段契约,不承担业务写入或子进程执行。
16
+ *
17
+ * 维护规则
18
+ * 新增基础工作流结果字段时同步更新文本输出与 JSON 可读性,保持对外提示风格一致。
19
+ */
20
+ import { formatProductTypeDisplay, formatTemplatePackDisplay } from '../product-type-copy.js';
21
+ import { printOptionalCapabilitySuggestions } from './shared-print.js';
22
+
23
+ function resolveActiveTemplatePack(ws) {
24
+ return ws.data.currentState?.templatePack ?? ws.data.config?.activeTemplatePack ?? 'base';
25
+ }
26
+
27
+ function printValidation(report, json) {
28
+ if (json) {
29
+ console.log(JSON.stringify(report, null, 2));
30
+ return;
31
+ }
32
+
33
+ if (report.valid) {
34
+ console.log('OpenPrd 校验通过');
35
+ if (report.warnings.length > 0) {
36
+ console.log('警告:');
37
+ for (const warning of report.warnings) {
38
+ console.log(`- ${warning}`);
39
+ }
40
+ }
41
+ return;
42
+ }
43
+
44
+ console.log('OpenPrd 校验失败');
45
+ for (const error of report.errors) {
46
+ console.log(`- ${error}`);
47
+ }
48
+ if (report.warnings.length > 0) {
49
+ console.log('警告:');
50
+ for (const warning of report.warnings) {
51
+ console.log(`- ${warning}`);
52
+ }
53
+ }
54
+ }
55
+
56
+ function printStatus(ws, report, guidance, json) {
57
+ const versionIndex = Array.isArray(ws.data.versionIndex) ? ws.data.versionIndex : [];
58
+ const learningReview = ws.data.config?.learningReview ?? null;
59
+ const projectRelease = ws.data.releaseLedger ?? null;
60
+ const currentRelease = projectRelease?.currentVersion
61
+ ? projectRelease.versions.find((entry) => entry.version === projectRelease.currentVersion) ?? null
62
+ : null;
63
+ const summary = {
64
+ projectRoot: ws.projectRoot,
65
+ workspaceRoot: ws.workspaceRoot,
66
+ schema: ws.data.schema?.name ?? null,
67
+ templatePack: resolveActiveTemplatePack(ws),
68
+ productTypes: ws.data.config?.supportedProductTypes ?? [],
69
+ prdVersion: ws.data.currentState?.prdVersion ?? 0,
70
+ latestVersionId: ws.data.currentState?.latestVersionId ?? versionIndex.at(-1)?.versionId ?? null,
71
+ versionCount: versionIndex.length,
72
+ valid: report.valid,
73
+ errors: report.errors,
74
+ warnings: report.warnings,
75
+ activeEngagementStatus: ws.data.currentState?.status ?? 'unknown',
76
+ scenario: guidance?.clarification?.scenario?.label ?? null,
77
+ userParticipationMode: guidance?.clarification?.scenario?.userParticipation ?? null,
78
+ currentGate: guidance?.gates?.currentGate ?? null,
79
+ upcomingGate: guidance?.gates?.upcomingGate ?? null,
80
+ projectRelease: projectRelease
81
+ ? {
82
+ enabled: projectRelease.enabled,
83
+ currentVersion: currentRelease?.version ?? projectRelease.currentVersion ?? null,
84
+ currentStatus: currentRelease?.status ?? null,
85
+ itemCount: currentRelease?.items?.length ?? 0,
86
+ }
87
+ : null,
88
+ learningReview,
89
+ learningCurrent: ws.data.learningCurrent ?? null,
90
+ };
91
+
92
+ if (json) {
93
+ console.log(JSON.stringify(summary, null, 2));
94
+ return;
95
+ }
96
+
97
+ console.log(`工作区: ${summary.workspaceRoot}`);
98
+ console.log(`Schema: ${summary.schema}`);
99
+ console.log(`场景模板: ${formatTemplatePackDisplay(summary.templatePack, { fallback: '待确认' })}`);
100
+ console.log(`支持的产品场景: ${summary.productTypes.length > 0 ? summary.productTypes.map((type) => formatProductTypeDisplay(type, { fallback: type })).join(' / ') : '待确认'}`);
101
+ console.log(`PRD 版本: ${summary.prdVersion}`);
102
+ console.log(`最新版本: ${summary.latestVersionId ?? '无'}`);
103
+ console.log(`版本数量: ${summary.versionCount}`);
104
+ if (summary.projectRelease?.enabled) {
105
+ console.log(`项目版本: ${summary.projectRelease.currentVersion ?? '未设置'}`);
106
+ if (summary.projectRelease.currentStatus) {
107
+ console.log(`项目版本状态: ${summary.projectRelease.currentStatus}`);
108
+ }
109
+ console.log(`版本条目数: ${summary.projectRelease.itemCount}`);
110
+ }
111
+ console.log(`状态: ${summary.activeEngagementStatus}`);
112
+ if (summary.scenario) {
113
+ console.log(`场景: ${summary.scenario}`);
114
+ }
115
+ if (summary.userParticipationMode) {
116
+ console.log(`用户参与模式: ${summary.userParticipationMode}`);
117
+ }
118
+ if (summary.currentGate) {
119
+ console.log(`当前门禁: ${summary.currentGate}`);
120
+ }
121
+ if (summary.upcomingGate) {
122
+ console.log(`后续门禁: ${summary.upcomingGate}`);
123
+ }
124
+ if (summary.learningReview) {
125
+ console.log(`复盘学习模式: ${summary.learningReview.enabled !== false ? '开启' : '关闭'}`);
126
+ console.log(`默认题材: ${summary.learningReview.defaultGenre ?? 'internet-product'}`);
127
+ console.log(`自动打开: ${summary.learningReview.autoOpen !== false ? '是' : '否'}`);
128
+ console.log(`来源范围: ${summary.learningReview.sourceScope ?? 'workspace'}`);
129
+ }
130
+ if (summary.learningCurrent?.packageId) {
131
+ console.log(`最近学习包: ${summary.learningCurrent.packageId}`);
132
+ }
133
+ console.log(`验证: ${summary.valid ? '通过' : '失败'}`);
134
+ if (summary.errors.length > 0) {
135
+ console.log('错误:');
136
+ for (const error of summary.errors) {
137
+ console.log(`- ${error}`);
138
+ }
139
+ }
140
+ if (summary.warnings.length > 0) {
141
+ console.log('警告:');
142
+ for (const warning of summary.warnings) {
143
+ console.log(`- ${warning}`);
144
+ }
145
+ }
146
+ }
147
+
148
+ function printReleaseResult(result, json) {
149
+ if (json) {
150
+ console.log(JSON.stringify(result, null, 2));
151
+ return;
152
+ }
153
+
154
+ if (!result.ok) {
155
+ console.log('OpenPrd release: 失败');
156
+ for (const error of result.errors ?? []) {
157
+ console.log(`- ${error}`);
158
+ }
159
+ return;
160
+ }
161
+
162
+ console.log(`OpenPrd release: ${result.changed ? '已更新' : '当前状态'}`);
163
+ console.log(`版本账本: ${result.releaseLedgerPath}`);
164
+ console.log(`已启用: ${result.summary.enabled ? '是' : '否'}`);
165
+ console.log(`当前项目版本: ${result.summary.currentVersion ?? '未设置'}`);
166
+ if (result.summary.currentStatus) {
167
+ console.log(`版本状态: ${result.summary.currentStatus}`);
168
+ }
169
+ console.log(`版本数量: ${result.summary.versionCount}`);
170
+ console.log(`当前版本条目: ${result.summary.itemCount}`);
171
+ if (result.summary.tag?.name) {
172
+ const tagState = result.summary.tag.localSha
173
+ ? `${result.summary.tag.name} -> ${result.summary.tag.localSha}`
174
+ : result.summary.tag.name;
175
+ console.log(`本地 tag: ${tagState}`);
176
+ }
177
+ if (result.changeSummary?.items?.length > 0) {
178
+ console.log('变化摘要:');
179
+ for (const item of result.changeSummary.items) {
180
+ console.log(`- ${item.sentence}`);
181
+ }
182
+ }
183
+ for (const warning of result.warnings ?? []) {
184
+ console.log(`- ${warning}`);
185
+ }
186
+ }
187
+
188
+ function printClassifyResult(result, json) {
189
+ if (json) {
190
+ console.log(JSON.stringify(result, null, 2));
191
+ return;
192
+ }
193
+
194
+ console.log(`已锁定产品场景: ${formatProductTypeDisplay(result.currentState.productType, { fallback: '待确认' })}`);
195
+ console.log(`场景模板: ${formatTemplatePackDisplay(result.currentState.templatePack, { fallback: '待确认' })}`);
196
+ }
197
+
198
+ function printClarifyResult(result, json) {
199
+ if (json) {
200
+ console.log(JSON.stringify(result, null, 2));
201
+ return;
202
+ }
203
+
204
+ const projectFraming = result.intakeReflection?.projectContext?.projectFraming ?? null;
205
+
206
+ console.log(`需要澄清: ${result.ws.workspaceRoot}`);
207
+ console.log(`场景: ${result.clarification.scenario.label}`);
208
+ console.log(`用户参与: ${result.clarification.scenario.userParticipation}`);
209
+ console.log(`待确认关键信息: ${result.clarification.missingRequiredFields}`);
210
+ console.log(`待确认问题: ${result.clarification.mustAskUser.length}`);
211
+ if (result.clarifyPresentation) {
212
+ console.log(`澄清呈现: ${result.clarifyPresentation.label}`);
213
+ console.log(`呈现原因: ${result.clarifyPresentation.reason}`);
214
+ }
215
+ console.log('建议先确认的问题:');
216
+ for (const item of result.clarification.mustAskUser) {
217
+ console.log(`- ${item.prompt}`);
218
+ }
219
+ if (projectFraming) {
220
+ console.log('首轮项目画像:');
221
+ console.log(`- 适用对象: ${projectFraming.audience}`);
222
+ console.log(`- 产品形态: ${projectFraming.productShape}`);
223
+ console.log(`- 第一版先做: ${projectFraming.firstSlice}`);
224
+ console.log(`- 暂不处理: ${projectFraming.nonGoals}`);
225
+ console.log(`- 不能破坏: ${projectFraming.guardrails}`);
226
+ console.log(`- 技术落点: ${projectFraming.architectureSignals}`);
227
+ if (projectFraming.riskProbeSummary !== '当前没有明显命中额外风险探针。') {
228
+ console.log(`- 风险探针: ${projectFraming.riskProbeSummary}`);
229
+ }
230
+ }
231
+ if (result.inlineClarification) {
232
+ console.log('对话内澄清提纲:');
233
+ for (const line of result.inlineClarification.lines) {
234
+ console.log(line);
235
+ }
236
+ console.log('无需打开 HTML;请把上面的项目画像、目标、范围、非目标和验收方式压缩给用户确认。');
237
+ }
238
+ if (result.clarification.canInferLater.length > 0) {
239
+ console.log('之后可以再补充或细化:');
240
+ for (const item of result.clarification.canInferLater.slice(0, 5)) {
241
+ console.log(`- ${item.prompt}`);
242
+ }
243
+ }
244
+ }
245
+
246
+ function printCaptureResult(result, json) {
247
+ if (json) {
248
+ console.log(JSON.stringify(result, null, 2));
249
+ return;
250
+ }
251
+
252
+ if (result.applied?.length > 1) {
253
+ console.log(`已捕获 ${result.applied.length} 个字段`);
254
+ for (const item of result.applied) {
255
+ console.log(`- ${item.field} (${item.source}): ${JSON.stringify(item.value)}`);
256
+ }
257
+ } else {
258
+ console.log(`已捕获 ${result.field}`);
259
+ console.log(`状态 key: ${result.stateKey}`);
260
+ console.log(`来源: ${result.source}`);
261
+ console.log(`值: ${JSON.stringify(result.value)}`);
262
+ }
263
+ if (result.artifactMarkdown) {
264
+ console.log(`来源 artifact markdown: ${result.artifactMarkdown}`);
265
+ }
266
+ console.log(`剩余缺失必填字段: ${result.analysis.missingRequiredFields}`);
267
+ }
268
+
269
+ function printInterviewResult(result, json) {
270
+ if (json) {
271
+ console.log(JSON.stringify(result, null, 2));
272
+ return;
273
+ }
274
+
275
+ console.log(`访谈模式: ${result.productType ?? '未分类'}`);
276
+ console.log(`来源文件: ${result.sourceFiles.join(', ')}`);
277
+ console.log(result.transcript);
278
+ }
279
+
280
+ function printPlaygroundResult(result, json) {
281
+ if (json) {
282
+ console.log(JSON.stringify(result, null, 2));
283
+ return;
284
+ }
285
+
286
+ console.log(`已生成 Playground: ${result.snapshot.title}`);
287
+ console.log(`HTML: ${result.htmlPath}`);
288
+ console.log(`Markdown 数据源: ${result.markdownPath}`);
289
+ console.log(`捕获补丁: ${result.patchPath}`);
290
+ console.log(`已打开: ${result.opened ? '是' : '否'}`);
291
+ }
292
+
293
+ function printLearningResult(result, json) {
294
+ if (json) {
295
+ console.log(JSON.stringify(result, null, 2));
296
+ return;
297
+ }
298
+
299
+ if (result.action === 'learning-review-config') {
300
+ console.log(`复盘学习模式: ${result.enabled ? '已开启' : '已关闭'}`);
301
+ console.log(`默认题材: ${result.config?.defaultGenre ?? 'internet-product'}`);
302
+ console.log(`自动打开: ${result.config?.autoOpen !== false ? '是' : '否'}`);
303
+ return;
304
+ }
305
+
306
+ if (result.skipped) {
307
+ console.log('复盘学习包: 已跳过');
308
+ console.log(`原因: ${result.reason}`);
309
+ return;
310
+ }
311
+
312
+ console.log(`复盘学习包: ${result.packageId}`);
313
+ console.log(`题材: ${result.genre?.label ?? result.packageMeta?.genreLabel ?? '未知'}`);
314
+ if (result.packageMeta?.styleLabel || result.content?.stylePromptPack?.label) {
315
+ console.log(`子风格: ${result.packageMeta?.styleLabel ?? result.content?.stylePromptPack?.label}`);
316
+ }
317
+ console.log(`主题: ${result.content?.topic ?? result.packageMeta?.topic ?? '未知'}`);
318
+ if (result.packageMeta?.authoringStatus) {
319
+ console.log(`写作状态: ${result.packageMeta.authoringStatus}`);
320
+ }
321
+ console.log(`HTML: ${result.packagePaths?.readerHtml ?? '无'}`);
322
+ console.log(`内容合同: ${result.packagePaths?.contentJson ?? '无'}`);
323
+ console.log(`证据清单: ${result.packagePaths?.evidenceManifest ?? '无'}`);
324
+ if (result.packagePaths?.agentPrompt) {
325
+ console.log(`Agent 写作提示: ${result.packagePaths.agentPrompt}`);
326
+ }
327
+ if (result.packagePaths?.agentContext) {
328
+ console.log(`Agent 上下文: ${result.packagePaths.agentContext}`);
329
+ }
330
+ console.log(`已打开: ${result.opened ? '是' : '否'}`);
331
+ }
332
+
333
+ function printInitResult(result, json) {
334
+ if (json) {
335
+ console.log(JSON.stringify(result, null, 2));
336
+ return;
337
+ }
338
+
339
+ console.log(`已初始化 OpenPrd 工作区: ${result.ws.workspaceRoot}`);
340
+ console.log(`场景模板: ${formatTemplatePackDisplay(result.currentState.templatePack, { fallback: '待确认' })}`);
341
+ console.log(`已复制种子文件: ${result.created}`);
342
+ if (result.standards) {
343
+ console.log(`标准化文档: ${result.standards.docsRoot}`);
344
+ }
345
+ if (result.agentIntegration) {
346
+ console.log(`Agent 引导: ${result.agentIntegration.ok ? '已启用' : '需修复'} (${result.agentIntegration.tools.join(', ')})`);
347
+ if (result.agentIntegration.hookProfile) {
348
+ console.log(`Hook 模式: ${result.agentIntegration.hookProfile}`);
349
+ }
350
+ printOptionalCapabilitySuggestions(result.agentIntegration.optionalCapabilities);
351
+ }
352
+ }
353
+
354
+ export {
355
+ printValidation,
356
+ printStatus,
357
+ printClassifyResult,
358
+ printClarifyResult,
359
+ printCaptureResult,
360
+ printInterviewResult,
361
+ printPlaygroundResult,
362
+ printLearningResult,
363
+ printInitResult,
364
+ printReleaseResult,
365
+ };
@@ -0,0 +1,91 @@
1
+ /*
2
+ * 核心功能
3
+ * 渲染 benchmark 子命令的人类可读输出或 JSON 输出。
4
+ *
5
+ * 输入
6
+ * 接收 benchmark add/observe/approve/list/verify 的结构化结果对象。
7
+ *
8
+ * 输出
9
+ * 向终端输出 benchmark registry、推荐与校验结论,或在 `--json` 模式下直出 JSON。
10
+ *
11
+ * 定位
12
+ * 位于 CLI 表现层的 benchmark 专属输出模块,避免继续扩大通用 print.js。
13
+ *
14
+ * 依赖
15
+ * 仅依赖终端输出和 benchmark result 字段契约。
16
+ *
17
+ * 维护规则
18
+ * benchmark 输出变更应优先在此处扩展,不回填到通用 barrel 文件。
19
+ */
20
+ function printBenchmarkResult(result, json) {
21
+ if (json) {
22
+ console.log(JSON.stringify(result, null, 2));
23
+ return;
24
+ }
25
+
26
+ if (result.action === 'benchmark-add') {
27
+ console.log(`OpenPrd benchmark add: ${result.ok ? '已加入 candidate' : '失败'}`);
28
+ if (result.source) {
29
+ console.log(`ID: ${result.source.id}`);
30
+ console.log(`标题: ${result.source.title}`);
31
+ console.log(`来源: ${result.source.url ?? result.source.path ?? 'unknown'}`);
32
+ console.log(`场景: ${result.source.scenarios.join(', ') || '未分类'}`);
33
+ }
34
+ if (result.error) {
35
+ console.log(`错误: ${result.error}`);
36
+ }
37
+ return;
38
+ }
39
+
40
+ if (result.action === 'benchmark-observe') {
41
+ console.log(`OpenPrd benchmark observe: ${result.created ? '已创建 candidate' : '已更新 candidate'}`);
42
+ console.log(`ID: ${result.source.id}`);
43
+ console.log(`标题: ${result.source.title}`);
44
+ console.log(`来源: ${result.source.url ?? result.source.path ?? 'unknown'}`);
45
+ console.log(`规范化信源: ${result.source.sourceKey ?? result.source.id}`);
46
+ console.log(`最近 ${result.source.promotion.windowDays} 天采纳: ${result.source.recentAdoptedCount}/${result.source.promotion.threshold}`);
47
+ console.log(`累计采纳: ${result.source.adoptedCount}`);
48
+ if (result.recommended) {
49
+ console.log(`推荐: 已达到阈值,确认后运行 ${result.recommendation.approveCommand}`);
50
+ }
51
+ return;
52
+ }
53
+
54
+ if (result.action === 'benchmark-approve') {
55
+ console.log('OpenPrd benchmark approve: 已加入 approved registry');
56
+ console.log(`ID: ${result.source.id}`);
57
+ console.log(`标题: ${result.source.title}`);
58
+ console.log(`已批准来源: ${result.counts.approved}`);
59
+ console.log(`待确认来源: ${result.counts.candidates}`);
60
+ return;
61
+ }
62
+
63
+ if (result.action === 'benchmark-verify') {
64
+ console.log(`OpenPrd benchmark verify: ${result.ok ? '通过' : '失败'}`);
65
+ for (const check of result.checks) {
66
+ console.log(`- ${check.ok ? '通过' : '失败'}: ${check.id}`);
67
+ for (const issue of check.issues) {
68
+ console.log(` ${issue.level === 'error' ? '错误' : '警告'}: ${issue.message}`);
69
+ }
70
+ }
71
+ return;
72
+ }
73
+
74
+ console.log(`OpenPrd benchmark list: approved ${result.counts.approved}, candidate ${result.counts.candidates}`);
75
+ for (const source of result.approved) {
76
+ console.log(`- approved ${source.id}: ${source.title}`);
77
+ }
78
+ for (const source of result.candidates) {
79
+ console.log(`- candidate ${source.id}: ${source.title}`);
80
+ if (source.promotion?.recommended) {
81
+ console.log(` 推荐: 最近 ${source.promotion.windowDays} 天已采纳 ${source.recentAdoptedCount}/${source.promotion.threshold} 次;确认后运行 ${source.promotion.approveCommand}`);
82
+ }
83
+ }
84
+ for (const recommendation of result.recommendations ?? []) {
85
+ console.log(`- 推荐纳入 benchmark: ${recommendation.sourceKey},最近 ${recommendation.windowDays} 天 ${recommendation.adoptedCount}/${recommendation.threshold} 次,累计 ${recommendation.totalAdoptedCount} 次;命令: ${recommendation.approveCommand}`);
86
+ }
87
+ }
88
+
89
+ export {
90
+ printBenchmarkResult,
91
+ };
@@ -0,0 +1,221 @@
1
+ /*
2
+ * 核心功能
3
+ * 渲染 discovery、change、spec、task 和 accepted specs 等 OpenPrd 变更编排输出。
4
+ *
5
+ * 输入
6
+ * 接收 discovery 运行、change 校验/生成、任务推进和 change lifecycle 的结构化结果对象。
7
+ *
8
+ * 输出
9
+ * 向终端输出变更状态、验证结果、任务进度和已接受 specs 摘要,或在 `--json` 模式下直出 JSON。
10
+ *
11
+ * 定位
12
+ * 位于 CLI 表现层的 change 输出模块,负责 OpenSpec/OpenPrd 变更生命周期的终端呈现。
13
+ *
14
+ * 依赖
15
+ * 仅依赖终端输出和 change/task result 字段契约。
16
+ *
17
+ * 维护规则
18
+ * change/task 输出要优先保留 changeId、验证结果和下一任务信息,避免把执行线索散落在多个模块里。
19
+ */
20
+ function printOpenSpecDiscoveryResult(result, json) {
21
+ if (json) {
22
+ console.log(JSON.stringify(result, null, 2));
23
+ return;
24
+ }
25
+
26
+ console.log(`OpenPrd discovery 运行: ${result.runId}`);
27
+ if (result.advanced) {
28
+ console.log(`已推进条目: ${result.advancedItem.id}`);
29
+ console.log(`条目状态: ${result.advancedItem.status}`);
30
+ if (result.claim) {
31
+ console.log(`Claim: ${result.claim.id}`);
32
+ }
33
+ }
34
+ if (result.verified) {
35
+ console.log(`验证: ${result.verification.valid ? '通过' : '失败'}`);
36
+ console.log(`完成: ${result.verification.complete ? '是' : '否'}`);
37
+ for (const check of result.verification.checks) {
38
+ console.log(`- ${check}`);
39
+ }
40
+ if (result.verification.errors.length > 0) {
41
+ console.log('错误:');
42
+ for (const error of result.verification.errors) {
43
+ console.log(`- ${error}`);
44
+ }
45
+ }
46
+ if (result.verification.warnings.length > 0) {
47
+ console.log('警告:');
48
+ for (const warning of result.verification.warnings) {
49
+ console.log(`- ${warning}`);
50
+ }
51
+ }
52
+ }
53
+ console.log(`是否恢复: ${result.resumed ? '是' : '否'}`);
54
+ console.log(`运行目录: ${result.runDir}`);
55
+ console.log(`模式: ${result.control.mode}`);
56
+ console.log(`状态: ${result.control.status}`);
57
+ console.log(`已索引来源文件: ${result.inventory.summary.files}`);
58
+ console.log(`覆盖待处理: ${result.coverageMatrix.summary.pending}/${result.coverageMatrix.summary.total}`);
59
+ console.log(`下一步动作: ${result.control.nextAction}`);
60
+ }
61
+
62
+ function printOpenSpecChangeValidationResult(result, json) {
63
+ if (json) {
64
+ console.log(JSON.stringify(result, null, 2));
65
+ return;
66
+ }
67
+
68
+ console.log(`OpenPrd change 验证: ${result.valid ? '通过' : '失败'}`);
69
+ console.log(`Change: ${result.changeId}`);
70
+ for (const check of result.checks) {
71
+ console.log(`- ${check}`);
72
+ }
73
+ if (result.errors.length > 0) {
74
+ console.log('错误:');
75
+ for (const error of result.errors) {
76
+ console.log(`- ${error}`);
77
+ }
78
+ }
79
+ if (result.warnings.length > 0) {
80
+ console.log('警告:');
81
+ for (const warning of result.warnings) {
82
+ console.log(`- ${warning}`);
83
+ }
84
+ }
85
+ }
86
+
87
+ function printOpenSpecGenerateResult(result, json) {
88
+ if (json) {
89
+ console.log(JSON.stringify(result, null, 2));
90
+ return;
91
+ }
92
+
93
+ console.log(`已生成 OpenPrd change: ${result.changeId}`);
94
+ console.log(`Capability: ${result.capability}`);
95
+ console.log(`任务数: ${result.taskCount}`);
96
+ console.log(`验证: ${result.validation.valid ? '通过' : '失败'}`);
97
+ console.log('文件:');
98
+ for (const file of result.files) {
99
+ console.log(`- ${file}`);
100
+ }
101
+ if (result.validation.errors.length > 0) {
102
+ console.log('错误:');
103
+ for (const error of result.validation.errors) {
104
+ console.log(`- ${error}`);
105
+ }
106
+ }
107
+ }
108
+
109
+ function printOpenSpecTaskResult(result, json) {
110
+ if (json) {
111
+ console.log(JSON.stringify(result, null, 2));
112
+ return;
113
+ }
114
+
115
+ console.log(`OpenPrd 任务: ${result.changeId}`);
116
+ if (result.action === 'list') {
117
+ console.log(`进度: ${result.summary.completed}/${result.summary.total} 已完成,${result.summary.pending} 待处理,${result.summary.blocked} 阻塞`);
118
+ if (result.summary.implementation) {
119
+ console.log(`实质实现任务: ${result.summary.implementation.completed}/${result.summary.implementation.total} 已完成,${result.summary.implementation.pending} 待处理`);
120
+ }
121
+ if (result.nextTask) {
122
+ console.log(`下一任务: ${result.nextTask.id} ${result.nextTask.title}`);
123
+ console.log(`验证命令: ${result.nextTask.metadata.verify}`);
124
+ } else {
125
+ console.log('下一任务: 无');
126
+ }
127
+ if (result.blockedTasks.length > 0) {
128
+ console.log('阻塞任务:');
129
+ for (const task of result.blockedTasks.slice(0, 10)) {
130
+ console.log(`- ${task.id}: ${[...task.missing, ...task.incomplete].join(', ')}`);
131
+ }
132
+ }
133
+ return;
134
+ }
135
+
136
+ console.log(`任务: ${result.task.id} ${result.task.title}`);
137
+ if (result.verification) {
138
+ console.log(`验证: ${result.verification.ok ? '通过' : '失败'} (${result.verification.command})`);
139
+ if (!result.verification.ok && result.verification.stderr) {
140
+ console.log(result.verification.stderr.trim());
141
+ }
142
+ }
143
+ if (result.action === 'advance') {
144
+ console.log(`已推进: ${result.advanced ? '是' : '否'}`);
145
+ if (result.summary) {
146
+ console.log(`进度: ${result.summary.completed}/${result.summary.total} 已完成`);
147
+ }
148
+ if (result.nextTask) {
149
+ console.log(`下一任务: ${result.nextTask.id} ${result.nextTask.title}`);
150
+ }
151
+ }
152
+ }
153
+
154
+ function printOpenPrdChangesResult(result, json) {
155
+ if (json) {
156
+ console.log(JSON.stringify(result, null, 2));
157
+ return;
158
+ }
159
+
160
+ console.log(`OpenPrd changes: ${result.changes.length}`);
161
+ console.log(`当前激活 change: ${result.activeChange ?? '无'}`);
162
+ for (const change of result.changes) {
163
+ const marker = change.active ? '*' : '-';
164
+ console.log(`${marker} ${change.id} | ${change.status} | ${change.source} | 任务 ${change.taskTotal - change.taskIncomplete}/${change.taskTotal}`);
165
+ }
166
+ }
167
+
168
+ function printOpenPrdChangeActionResult(result, json) {
169
+ if (json) {
170
+ console.log(JSON.stringify(result, null, 2));
171
+ return;
172
+ }
173
+
174
+ console.log(`OpenPrd change ${result.action}: ${result.changeId}`);
175
+ if (result.action === 'apply') {
176
+ console.log(`已应用: ${result.ok ? '是' : '否'}`);
177
+ if (result.appliedSpecs?.length > 0) {
178
+ console.log('已接受 specs:');
179
+ for (const spec of result.appliedSpecs) {
180
+ console.log(`- ${spec.capability}: ${spec.specPath}`);
181
+ }
182
+ }
183
+ if (result.errors?.length > 0) {
184
+ console.log('错误:');
185
+ for (const error of result.errors) {
186
+ console.log(`- ${error}`);
187
+ }
188
+ }
189
+ }
190
+ if (result.action === 'archive') {
191
+ console.log(`归档目录: ${result.archiveDir}`);
192
+ console.log(`已移除来源: ${result.removedSource ? '是' : '否'}`);
193
+ }
194
+ if (result.action === 'activate') {
195
+ console.log(`当前激活 change: ${result.changeId}`);
196
+ }
197
+ }
198
+
199
+ function printAcceptedSpecsResult(result, json) {
200
+ if (json) {
201
+ console.log(JSON.stringify(result, null, 2));
202
+ return;
203
+ }
204
+
205
+ console.log(`已接受 specs: ${result.specs.length}`);
206
+ for (const spec of result.specs) {
207
+ const source = spec.metadata?.sourceChange ? ` 来自 ${spec.metadata.sourceChange}` : '';
208
+ console.log(`- ${spec.capability}${source}: ${spec.specPath}`);
209
+ }
210
+ console.log(`已应用 changes: ${result.appliedChanges.length}`);
211
+ }
212
+
213
+ export {
214
+ printOpenSpecDiscoveryResult,
215
+ printOpenSpecChangeValidationResult,
216
+ printOpenSpecGenerateResult,
217
+ printOpenSpecTaskResult,
218
+ printOpenPrdChangesResult,
219
+ printOpenPrdChangeActionResult,
220
+ printAcceptedSpecsResult,
221
+ };