@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.
- package/.openprd/README.md +43 -69
- package/.openprd/README_EN.md +84 -0
- package/.openprd/benchmarks/index.md +7 -0
- package/.openprd/benchmarks/sources.yaml +25 -3
- package/.openprd/discovery/config.json +16 -2
- package/.openprd/engagements/active/flows.md +19 -14
- package/.openprd/engagements/active/handoff.md +11 -4
- package/.openprd/engagements/active/prd.md +99 -71
- package/.openprd/engagements/active/review.html +4 -4
- package/.openprd/engagements/active/roles.md +9 -8
- package/.openprd/engagements/work-units/wu-20260524015648-6d33ded7.json +4 -4
- package/.openprd/engagements/work-units/wu-20260602113956-a99b5b88.json +18 -0
- package/.openprd/engagements/work-units/wu-20260602122244-78656aaf.json +18 -0
- package/.openprd/engagements/work-units/wu-20260602122442-e96489e2.json +18 -0
- package/.openprd/engagements/work-units/wu-20260602132835-695429e8.json +18 -0
- package/.openprd/knowledge/candidates/candidate-turn-1780116203372-5f266a79e968c758/candidate.json +78 -0
- package/.openprd/knowledge/candidates/candidate-turn-1780116203372-5f266a79e968c758/diagnostic-report.json +129 -0
- package/.openprd/knowledge/candidates/candidate-turn-1780116203372-5f266a79e968c758/root-cause-candidates.json +41 -0
- package/.openprd/knowledge/candidates/candidate-turn-1780116203372-5f266a79e968c758/timeline.json +14 -0
- package/.openprd/knowledge/drafts/openprd-experience-diagnostic-candidate-turn-1780116203372-5f266a79e968c758/SKILL.md +49 -0
- package/.openprd/knowledge/index.json +44 -4
- package/.openprd/reviews/v0001.html +195 -129
- package/.openprd/reviews/v0002.html +1150 -0
- package/.openprd/reviews/v0003.html +1150 -0
- package/.openprd/reviews/v0004.html +1150 -0
- package/.openprd/reviews/v0005.html +1150 -0
- package/.openprd/standards/config.json +12 -9
- package/.openprd/state/changes.json +17 -2
- package/.openprd/state/current.json +399 -63
- package/.openprd/state/release-ledger.json +344 -0
- package/.openprd/state/version-index.json +52 -0
- package/.openprd/state/versions/v0002.json +264 -0
- package/.openprd/state/versions/v0002.md +183 -0
- package/.openprd/state/versions/v0003.json +269 -0
- package/.openprd/state/versions/v0003.md +188 -0
- package/.openprd/state/versions/v0004.json +274 -0
- package/.openprd/state/versions/v0004.md +193 -0
- package/.openprd/state/versions/v0005.json +299 -0
- package/.openprd/state/versions/v0005.md +189 -0
- package/.openprd/templates/agent/intake.md +5 -4
- package/.openprd/templates/b2b/intake.md +5 -4
- package/.openprd/templates/base/intake.md +10 -4
- package/.openprd/templates/company/README.md +9 -7
- package/.openprd/templates/company/README_EN.md +12 -0
- package/.openprd/templates/consumer/intake.md +5 -4
- package/.openprd/templates/industry/README.md +12 -10
- package/.openprd/templates/industry/README_EN.md +18 -0
- package/.openprd/templates/project/README.md +11 -9
- package/.openprd/templates/project/README_EN.md +16 -0
- package/.openprd/templates/session/README.md +11 -9
- package/.openprd/templates/session/README_EN.md +16 -0
- package/AGENTS.md +12 -8
- package/README.md +402 -441
- package/README_CN.md +4 -578
- package/README_EN.md +850 -0
- package/docs/assets/openprd-requirement-routing-en.png +0 -0
- package/docs/assets/openprd-requirement-routing-en.svg +102 -0
- package/docs/assets/openprd-requirement-routing-zh-refined.png +0 -0
- package/docs/assets/openprd-requirement-routing-zh.png +0 -0
- package/docs/assets/openprd-requirement-routing-zh.svg +102 -0
- package/package.json +6 -2
- package/scripts/dev-check-wrapup-copy.mjs +110 -0
- package/scripts/openprd-github-release-notes.mjs +99 -0
- package/scripts/quality-perf-check.mjs +203 -0
- package/skills/openprd-benchmark-router/SKILL.md +1 -0
- package/skills/openprd-benchmark-router/references/benchmark-sources.md +1 -0
- package/skills/openprd-benchmark-router/references/source-policy.md +2 -0
- package/skills/openprd-discovery-loop/SKILL.md +2 -2
- package/skills/openprd-harness/SKILL.md +46 -24
- package/skills/openprd-harness/references/workflow-gates.md +15 -0
- package/skills/openprd-quality/SKILL.md +10 -4
- package/skills/openprd-requirement-intake/SKILL.md +39 -23
- package/skills/openprd-requirement-intake/references/prd-template-lenses.md +6 -6
- package/skills/openprd-requirement-intake/references/routing-rubric.md +22 -8
- package/skills/openprd-router/SKILL.md +2 -2
- package/skills/openprd-shared/SKILL.md +51 -23
- package/skills/openprd-standards/SKILL.md +2 -1
- package/src/agent-integration.js +265 -65
- package/src/benchmark/constants.js +107 -0
- package/src/benchmark/operations.js +235 -0
- package/src/benchmark/registry.js +64 -0
- package/src/benchmark/render.js +115 -0
- package/src/benchmark/source.js +617 -0
- package/src/benchmark/storage.js +121 -0
- package/src/benchmark/verify.js +235 -0
- package/src/benchmark.js +50 -851
- package/src/change-summary.js +339 -0
- package/src/cli/args.js +67 -6
- package/src/cli/basic-print.js +365 -0
- package/src/cli/benchmark-print.js +91 -0
- package/src/cli/change-print.js +221 -0
- package/src/cli/doctor-print.js +268 -0
- package/src/cli/growth-print.js +176 -0
- package/src/cli/print.js +73 -1384
- package/src/cli/quality-print.js +284 -0
- package/src/cli/run-print.js +297 -0
- package/src/cli/shared-print.js +127 -0
- package/src/cli/workflow-print.js +195 -0
- package/src/codex-hook-runner-template.mjs +639 -117
- package/src/codex-runtime.js +324 -0
- package/src/dev-standards.js +178 -5
- package/src/diagram-core.js +5 -5
- package/src/discovery.js +2 -1
- package/src/execution-strategy.js +369 -0
- package/src/fleet.js +4 -0
- package/src/github-release.js +156 -0
- package/src/growth.js +311 -13
- package/src/html-artifact-utils.js +25 -0
- package/src/html-artifacts.js +157 -1596
- package/src/knowledge.js +1176 -75
- package/src/language-policy.js +2 -112
- package/src/learning-html-artifact.js +1031 -0
- package/src/learning-review.js +3 -2
- package/src/loop.js +280 -9
- package/src/openprd.js +341 -38
- package/src/openspec/change-validate.js +0 -9
- package/src/openspec/execute.js +79 -3
- package/src/openspec/generate.js +33 -20
- package/src/openspec/tasks.js +33 -2
- package/src/prd-core.js +10 -9
- package/src/product-type-copy.js +69 -0
- package/src/quality-html-artifact.js +108 -9
- package/src/quality-learning.js +30 -0
- package/src/quality-visual-review.js +237 -0
- package/src/quality.js +329 -43
- package/src/registry-hygiene.js +54 -0
- package/src/release-ledger.js +413 -0
- package/src/review-presentation.js +12 -6
- package/src/run-harness.js +722 -48
- package/src/self-update.js +1 -1
- package/src/session-binding.js +40 -3
- package/src/session-registry.js +159 -0
- package/src/standards.js +5 -3
- package/src/test-strategy.js +386 -0
- package/src/visual-compare.js +915 -34
- package/src/work-unit-migration.js +5 -1
- package/src/workspace-core.js +343 -19
- 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
|
+
};
|