@chenguangyao/devflow-kit 0.1.43

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 (198) hide show
  1. package/CHANGELOG.md +232 -0
  2. package/LICENSE +21 -0
  3. package/README.md +539 -0
  4. package/bin/devflow.js +9 -0
  5. package/docs/RFC-001-devflow-kit.md +617 -0
  6. package/docs/RFC-002-workflow-kernel.md +134 -0
  7. package/docs/enterprise-integration-supplement.md +274 -0
  8. package/docs/internal-gitlab-setup.md +426 -0
  9. package/docs/marketplace-skills.md +231 -0
  10. package/docs/migration-from-arb.md +232 -0
  11. package/docs/tooling-overview.md +774 -0
  12. package/docs/workflow-orchestration.md +695 -0
  13. package/docs/workflow-ui-prototype.html +271 -0
  14. package/package.json +52 -0
  15. package/schemas/config.schema.json +51 -0
  16. package/schemas/delta.schema.json +22 -0
  17. package/schemas/state.schema.json +130 -0
  18. package/schemas/status-surface.schema.json +197 -0
  19. package/schemas/workflow-confirmation-surface.schema.json +70 -0
  20. package/schemas/workflow-picker.schema.json +94 -0
  21. package/scripts/postinstall.js +101 -0
  22. package/scripts/render-workflow-ui-prototype.js +271 -0
  23. package/skills/apply/SKILL.md +313 -0
  24. package/skills/apply/references/discipline-checklist.md +145 -0
  25. package/skills/apply/references/subagent-implementer-prompt.md +113 -0
  26. package/skills/apply/references/subagent-orchestration.md +150 -0
  27. package/skills/apply/references/subagent-reviewer-prompt.md +180 -0
  28. package/skills/apply/references/tdd-loop.md +287 -0
  29. package/skills/apply/references/when-plan-is-wrong.md +279 -0
  30. package/skills/apply/references/worktree-swarm.md +292 -0
  31. package/skills/archive/SKILL.md +229 -0
  32. package/skills/archive/references/conflict-resolution.md +336 -0
  33. package/skills/archive/references/knowledge-deposit.md +381 -0
  34. package/skills/archive/references/spec-merge.md +365 -0
  35. package/skills/brainstorm/SKILL.md +123 -0
  36. package/skills/brainstorm/references/proposal-template.md +244 -0
  37. package/skills/brainstorm/references/question-catalog.md +168 -0
  38. package/skills/brainstorm/references/session-template.md +184 -0
  39. package/skills/ci-fix/SKILL.md +63 -0
  40. package/skills/ci-fix/references/loop.md +25 -0
  41. package/skills/code-review/SKILL.md +279 -0
  42. package/skills/code-review/references/escalation-playbook.md +192 -0
  43. package/skills/code-review/references/language-cheatsheets/go.md +175 -0
  44. package/skills/code-review/references/language-cheatsheets/java-spring-mybatis.md +246 -0
  45. package/skills/code-review/references/language-cheatsheets/python.md +170 -0
  46. package/skills/code-review/references/language-cheatsheets/vue.md +199 -0
  47. package/skills/code-review/references/output-template.md +275 -0
  48. package/skills/code-review/references/review-checklist.md +251 -0
  49. package/skills/complexity-grading/SKILL.md +259 -0
  50. package/skills/deliver/SKILL.md +271 -0
  51. package/skills/deliver/references/delivery-modes.md +299 -0
  52. package/skills/deliver/references/notify.md +359 -0
  53. package/skills/deliver/references/pr-description.md +319 -0
  54. package/skills/dependency-upgrade/SKILL.md +57 -0
  55. package/skills/dependency-upgrade/references/risk-matrix.md +38 -0
  56. package/skills/df-orchestrator/SKILL.md +407 -0
  57. package/skills/df-orchestrator/references/complexity-grading.md +177 -0
  58. package/skills/df-orchestrator/references/escalation-matrix.md +191 -0
  59. package/skills/df-orchestrator/references/routing-rules.md +290 -0
  60. package/skills/df-orchestrator/references/workflow-state-machine.md +208 -0
  61. package/skills/frontend-quality/SKILL.md +61 -0
  62. package/skills/frontend-quality/references/checklist.md +35 -0
  63. package/skills/handoff-resume/SKILL.md +59 -0
  64. package/skills/handoff-resume/references/handoff-template.md +54 -0
  65. package/skills/plan/SKILL.md +166 -0
  66. package/skills/plan/references/task-breakdown.md +207 -0
  67. package/skills/plan/references/task-sequencing.md +143 -0
  68. package/skills/plan/references/task-template.md +248 -0
  69. package/skills/requirement-analysis/SKILL.md +499 -0
  70. package/skills/requirement-analysis/references/acceptance-criteria.md +183 -0
  71. package/skills/requirement-analysis/references/code-recon.md +151 -0
  72. package/skills/requirement-analysis/references/edge-case-catalog.md +164 -0
  73. package/skills/requirement-analysis/references/requirement-template.md +339 -0
  74. package/skills/requirement-analysis/references/scope-negotiation.md +162 -0
  75. package/skills/security-hardening/SKILL.md +60 -0
  76. package/skills/security-hardening/references/checklist.md +42 -0
  77. package/skills/tech-spec/SKILL.md +388 -0
  78. package/skills/tech-spec/references/api-contract-design.md +172 -0
  79. package/skills/tech-spec/references/decision-records.md +110 -0
  80. package/skills/tech-spec/references/design-template.md +301 -0
  81. package/skills/tech-spec/references/rollout-and-rollback.md +203 -0
  82. package/skills/tech-spec/references/spec-delta-conventions.md +250 -0
  83. package/skills/tech-spec/references/transaction-patterns.md +212 -0
  84. package/skills/test-spec/SKILL.md +219 -0
  85. package/skills/test-spec/references/coverage-strategy.md +218 -0
  86. package/skills/test-spec/references/edge-case-to-test.md +143 -0
  87. package/skills/test-spec/references/test-case-template.md +276 -0
  88. package/skills/verify/SKILL.md +232 -0
  89. package/skills/verify/references/nfr-verification.md +292 -0
  90. package/skills/verify/references/report-templates.md +510 -0
  91. package/skills/verify/references/self-test-guide.md +240 -0
  92. package/skills/verify/references/verify-rollback-map.md +247 -0
  93. package/src/cli/commands/_helpers.js +108 -0
  94. package/src/cli/commands/_submit.js +718 -0
  95. package/src/cli/commands/apply.js +198 -0
  96. package/src/cli/commands/archive.js +180 -0
  97. package/src/cli/commands/checkpoint.js +113 -0
  98. package/src/cli/commands/deliver.js +377 -0
  99. package/src/cli/commands/deploy.js +504 -0
  100. package/src/cli/commands/design.js +158 -0
  101. package/src/cli/commands/disable.js +21 -0
  102. package/src/cli/commands/doctor.js +178 -0
  103. package/src/cli/commands/enable.js +21 -0
  104. package/src/cli/commands/flow.js +645 -0
  105. package/src/cli/commands/help.js +93 -0
  106. package/src/cli/commands/ingest.js +602 -0
  107. package/src/cli/commands/init.js +341 -0
  108. package/src/cli/commands/knowledge.js +523 -0
  109. package/src/cli/commands/logs.js +43 -0
  110. package/src/cli/commands/new.js +202 -0
  111. package/src/cli/commands/plan.js +49 -0
  112. package/src/cli/commands/propose.js +27 -0
  113. package/src/cli/commands/provider.js +698 -0
  114. package/src/cli/commands/report.js +143 -0
  115. package/src/cli/commands/requirement.js +227 -0
  116. package/src/cli/commands/review.js +301 -0
  117. package/src/cli/commands/skills.js +457 -0
  118. package/src/cli/commands/status.js +925 -0
  119. package/src/cli/commands/switch.js +27 -0
  120. package/src/cli/commands/sync.js +47 -0
  121. package/src/cli/commands/test.js +366 -0
  122. package/src/cli/commands/uninstall.js +32 -0
  123. package/src/cli/commands/update.js +74 -0
  124. package/src/cli/commands/verify.js +354 -0
  125. package/src/cli/commands/worktree.js +78 -0
  126. package/src/cli/index.js +72 -0
  127. package/src/cli/parse-args.js +102 -0
  128. package/src/core/autodetect.js +271 -0
  129. package/src/core/change.js +208 -0
  130. package/src/core/checkpoint.js +217 -0
  131. package/src/core/config.js +60 -0
  132. package/src/core/delta.js +290 -0
  133. package/src/core/markers.js +59 -0
  134. package/src/core/paths.js +173 -0
  135. package/src/core/plan-tasks.js +36 -0
  136. package/src/core/project-routing.js +285 -0
  137. package/src/core/projects.js +200 -0
  138. package/src/core/state.js +200 -0
  139. package/src/core/workflow-check.js +177 -0
  140. package/src/core/workflow-init.js +34 -0
  141. package/src/core/workflow-picker.js +154 -0
  142. package/src/core/workflow-policy.js +119 -0
  143. package/src/core/workflow-suggest.js +181 -0
  144. package/src/core/workflow-verify.js +88 -0
  145. package/src/core/workflow.js +433 -0
  146. package/src/core/worktree.js +241 -0
  147. package/src/knowledge/categories.js +107 -0
  148. package/src/knowledge/classify.js +125 -0
  149. package/src/knowledge/deposit.js +414 -0
  150. package/src/knowledge/migrate.js +149 -0
  151. package/src/knowledge/mr.js +219 -0
  152. package/src/knowledge/query.js +131 -0
  153. package/src/knowledge/registry.js +151 -0
  154. package/src/knowledge/sync.js +179 -0
  155. package/src/providers/base.js +74 -0
  156. package/src/providers/drivers/api-yapi.js +78 -0
  157. package/src/providers/drivers/ci-jenkins.js +109 -0
  158. package/src/providers/drivers/intake-confluence.js +544 -0
  159. package/src/providers/drivers/kb-git.js +549 -0
  160. package/src/providers/drivers/kb-weknora.js +472 -0
  161. package/src/providers/drivers/notify-smtp.js +515 -0
  162. package/src/providers/drivers/observability-oss.js +43 -0
  163. package/src/providers/drivers/observability-sls.js +50 -0
  164. package/src/providers/lifecycle.js +135 -0
  165. package/src/providers/loader.js +132 -0
  166. package/src/providers/local.js +190 -0
  167. package/src/providers/userconfig.js +283 -0
  168. package/src/reports/aggregate.js +185 -0
  169. package/src/reports/coverage.js +163 -0
  170. package/src/reports/detect.js +143 -0
  171. package/src/reports/parse.js +236 -0
  172. package/src/templates/files/ci/github.yml +38 -0
  173. package/src/templates/files/ci/gitlab.yml +27 -0
  174. package/src/templates/files/design.md +63 -0
  175. package/src/templates/files/ide/devflow-workflow.md +58 -0
  176. package/src/templates/files/ide/project-overview-reference.md +1 -0
  177. package/src/templates/files/ide/project-overview.md +27 -0
  178. package/src/templates/files/knowledge-index.json +17 -0
  179. package/src/templates/files/knowledge.md +28 -0
  180. package/src/templates/files/meta.json +8 -0
  181. package/src/templates/files/plan.md +38 -0
  182. package/src/templates/files/proposal.md +33 -0
  183. package/src/templates/files/reports/contract-test.md +40 -0
  184. package/src/templates/files/reports/e2e-test.md +30 -0
  185. package/src/templates/files/reports/integration-test.md +36 -0
  186. package/src/templates/files/reports/joint-test.md +58 -0
  187. package/src/templates/files/reports/perf.md +24 -0
  188. package/src/templates/files/reports/regression.md +20 -0
  189. package/src/templates/files/reports/remote-test.md +55 -0
  190. package/src/templates/files/reports/self-test.md +43 -0
  191. package/src/templates/files/reports/smoke-test.md +22 -0
  192. package/src/templates/files/reports/unit-test.md +36 -0
  193. package/src/templates/files/requirement.md +51 -0
  194. package/src/templates/files/review.md +38 -0
  195. package/src/templates/files/tests.md +36 -0
  196. package/src/templates/files/verify.md +32 -0
  197. package/src/templates/index.js +21 -0
  198. package/src/utils/log.js +37 -0
@@ -0,0 +1,271 @@
1
+ #!/usr/bin/env node
2
+ /* eslint-disable no-console */
3
+ 'use strict';
4
+
5
+ const fs = require('fs');
6
+ const os = require('os');
7
+ const path = require('path');
8
+ const childProcess = require('child_process');
9
+
10
+ function renderWorkflowUiPrototype(options = {}) {
11
+ const root = options.root || path.resolve(__dirname, '..');
12
+ const fixtures = options.pickers && options.card
13
+ ? { pickers: options.pickers, card: options.card }
14
+ : loadFixtureSurfaces({ root });
15
+ const sourceLabel = options.sourceLabel || fixtures.card.slug || fixtures.card.baseRecipe?.id || 'workflow';
16
+
17
+ return [
18
+ '<!doctype html>',
19
+ '<html lang="zh-CN">',
20
+ '<head>',
21
+ ' <meta charset="utf-8">',
22
+ ' <meta name="viewport" content="width=device-width, initial-scale=1">',
23
+ ' <title>devflow Workflow UI Prototype</title>',
24
+ ' <style>',
25
+ renderCss(),
26
+ ' </style>',
27
+ '</head>',
28
+ '<body>',
29
+ ' <main class="page">',
30
+ ' <section class="toolbar" aria-label="Workflow actions">',
31
+ ' <div>',
32
+ ' <h1>Workflow 编排</h1>',
33
+ ' <p>线性 skill 选项卡 + 推荐勾选 + workflow 确认卡。</p>',
34
+ ' </div>',
35
+ ` <code>${escapeHtml(sourceLabel)} · ${escapeHtml(fixtures.card.actions.picker || fixtures.card.nextAction || '-')}</code>`,
36
+ ' </section>',
37
+ fixtures.pickers.map((entry) => renderPickerSurface(entry.surface, entry.title)).join('\n'),
38
+ renderConfirmationSurface(fixtures.card),
39
+ ' </main>',
40
+ '</body>',
41
+ '</html>',
42
+ '',
43
+ ].join('\n');
44
+ }
45
+
46
+ function loadFixtureSurfaces({ root = path.resolve(__dirname, '..') } = {}) {
47
+ return {
48
+ pickers: [
49
+ { title: '默认推荐', surface: readJson(root, 'test/fixtures/workflow-surfaces/picker-default.json') },
50
+ { title: '风险推荐', surface: readJson(root, 'test/fixtures/workflow-surfaces/picker-risk-recommended.json') },
51
+ ],
52
+ card: readJson(root, 'test/fixtures/workflow-surfaces/confirmation-card.json'),
53
+ };
54
+ }
55
+
56
+ function loadWorkflowSurfacesFromCli({
57
+ root = path.resolve(__dirname, '..'),
58
+ slug,
59
+ cwd = process.cwd(),
60
+ execFileSync = childProcess.execFileSync,
61
+ } = {}) {
62
+ if (!slug) throw new Error('loadWorkflowSurfacesFromCli requires slug');
63
+ const picker = runDevflowJson(root, cwd, ['flow', 'picker', `--slug=${slug}`, '--json'], execFileSync);
64
+ const card = runDevflowJson(root, cwd, ['flow', 'card', `--slug=${slug}`, '--json'], execFileSync);
65
+ return {
66
+ pickers: [{ title: '当前 workflow', surface: picker }],
67
+ card,
68
+ };
69
+ }
70
+
71
+ function runDevflowJson(root, cwd, args, execFileSync) {
72
+ const out = execFileSync(process.execPath, [path.join(root, 'bin', 'devflow.js'), ...args], {
73
+ cwd,
74
+ encoding: 'utf8',
75
+ stdio: ['ignore', 'pipe', 'pipe'],
76
+ });
77
+ return JSON.parse(String(out));
78
+ }
79
+
80
+ function readJson(root, rel) {
81
+ return JSON.parse(fs.readFileSync(path.join(root, rel), 'utf8'));
82
+ }
83
+
84
+ function renderPickerSurface(surface, title) {
85
+ return [
86
+ ` <section class="surface" data-surface="workflow-picker" aria-label="${escapeAttr(title)}">`,
87
+ ` <div class="surface-head"><h2>${escapeHtml(title)}</h2><span>${escapeHtml(surface.baseRecipe.id)} / ${escapeHtml(surface.status)}</span></div>`,
88
+ ' <div class="groups">',
89
+ surface.groups.map(renderGroup).join('\n'),
90
+ ' </div>',
91
+ ' <div class="command-row">',
92
+ ` <code>${escapeHtml(surface.actions.applySelection)}</code>`,
93
+ ` <code>${escapeHtml(surface.actions.card)}</code>`,
94
+ ' </div>',
95
+ ' </section>',
96
+ ].join('\n');
97
+ }
98
+
99
+ function renderGroup(group) {
100
+ return [
101
+ ` <section class="group" aria-label="${escapeAttr(group.label)}">`,
102
+ ` <h3>${escapeHtml(group.label)}</h3>`,
103
+ ' <ol>',
104
+ group.items.map(renderItem).join('\n'),
105
+ ' </ol>',
106
+ ' </section>',
107
+ ].join('\n');
108
+ }
109
+
110
+ function renderItem(item) {
111
+ const state = item.selected ? '已选' : item.recommended ? '推荐' : '可选';
112
+ const tags = [
113
+ item.required ? 'required' : null,
114
+ item.optional ? 'optional' : null,
115
+ item.protected ? 'protected' : null,
116
+ item.locked ? 'locked' : null,
117
+ ].filter(Boolean);
118
+ const checkbox = item.locked
119
+ ? `<input type="checkbox" checked disabled aria-label="${escapeAttr(item.step)} locked">`
120
+ : `<input type="checkbox"${item.selected ? ' checked' : ''} aria-label="${escapeAttr(item.step)}">`;
121
+ const command = item.command ? `<code>${escapeHtml(item.command)}</code>` : '';
122
+ const reason = item.reason ? `<p>${escapeHtml(item.reason)}</p>` : '';
123
+ return [
124
+ ' <li>',
125
+ ` <label>${checkbox}<span>${escapeHtml(item.step)}</span></label>`,
126
+ ` <small>${escapeHtml(item.skill)} · ${escapeHtml(state)}${tags.length ? ` · ${escapeHtml(tags.join(' / '))}` : ''}</small>`,
127
+ reason ? ` ${reason}` : '',
128
+ command ? ` ${command}` : '',
129
+ ' </li>',
130
+ ].filter(Boolean).join('\n');
131
+ }
132
+
133
+ function renderConfirmationSurface(surface) {
134
+ const card = surface.confirmationCard;
135
+ return [
136
+ ' <section class="surface confirm" data-surface="workflow-card" aria-label="Workflow confirmation card">',
137
+ ` <div class="surface-head"><h2>确认卡</h2><span>${surface.ok ? 'ok' : 'blocked'} / ${escapeHtml(surface.status || '-')}</span></div>`,
138
+ ' <ol class="timeline">',
139
+ card.steps.map((step, idx) => renderTimelineStep(step, idx + 1)).join('\n'),
140
+ ' </ol>',
141
+ ' <div class="actions">',
142
+ ` <button type="button">${escapeHtml(card.primaryAction.id)}</button>`,
143
+ ` <code>${escapeHtml(card.primaryAction.command)}</code>`,
144
+ ` <code>${escapeHtml(card.secondaryActions[0].command)}</code>`,
145
+ ' </div>',
146
+ ' </section>',
147
+ ].join('\n');
148
+ }
149
+
150
+ function renderTimelineStep(step, num) {
151
+ const tags = [
152
+ step.required ? 'required' : null,
153
+ step.optional ? 'optional' : null,
154
+ step.protected ? 'protected' : null,
155
+ ].filter(Boolean).join(' / ');
156
+ return [
157
+ ' <li>',
158
+ ` <span>${num}</span>`,
159
+ ` <strong>${escapeHtml(step.id)}</strong>`,
160
+ ` <small>${escapeHtml(step.skill)}${tags ? ` · ${escapeHtml(tags)}` : ''}</small>`,
161
+ ' </li>',
162
+ ].join('\n');
163
+ }
164
+
165
+ function renderCss() {
166
+ return [
167
+ ' :root { color-scheme: light; --ink: #172026; --muted: #60707a; --line: #d8e0e5; --panel: #f8fafb; --accent: #146b5f; --warn: #b85c00; }',
168
+ ' * { box-sizing: border-box; }',
169
+ ' body { margin: 0; font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; color: var(--ink); background: #eef3f5; }',
170
+ ' .page { width: min(1180px, calc(100vw - 32px)); margin: 0 auto; padding: 28px 0 40px; }',
171
+ ' .toolbar { display: flex; align-items: end; justify-content: space-between; gap: 20px; padding: 10px 0 18px; }',
172
+ ' h1, h2, h3, p { margin: 0; }',
173
+ ' h1 { font-size: 28px; line-height: 1.15; }',
174
+ ' h2 { font-size: 18px; }',
175
+ ' h3 { font-size: 14px; color: var(--muted); }',
176
+ ' p { color: var(--muted); margin-top: 6px; }',
177
+ ' code { display: inline-block; max-width: 100%; overflow-wrap: anywhere; border: 1px solid var(--line); border-radius: 6px; padding: 5px 7px; background: white; font-size: 12px; color: #263840; }',
178
+ ' .surface { margin-top: 18px; border: 1px solid var(--line); border-radius: 8px; background: white; padding: 18px; }',
179
+ ' .surface-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-bottom: 14px; }',
180
+ ' .surface-head span { color: var(--muted); font-size: 13px; }',
181
+ ' .groups { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }',
182
+ ' .group { background: var(--panel); border: 1px solid var(--line); border-radius: 8px; padding: 12px; }',
183
+ ' ol { list-style: none; margin: 0; padding: 0; }',
184
+ ' .group li { min-height: 112px; display: grid; gap: 6px; align-content: start; border-top: 1px solid var(--line); padding: 10px 0; }',
185
+ ' .group li:first-child { border-top: 0; }',
186
+ ' label { display: flex; align-items: center; gap: 8px; font-weight: 700; }',
187
+ ' input { width: 16px; height: 16px; accent-color: var(--accent); }',
188
+ ' small { color: var(--muted); font-size: 12px; line-height: 1.35; }',
189
+ ' li p { color: var(--warn); font-size: 12px; margin: 0; }',
190
+ ' .command-row, .actions { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 14px; align-items: center; }',
191
+ ' .timeline { display: grid; grid-template-columns: repeat(8, minmax(96px, 1fr)); gap: 8px; overflow-x: auto; padding-bottom: 4px; }',
192
+ ' .timeline li { min-width: 96px; border: 1px solid var(--line); border-radius: 8px; padding: 10px; background: var(--panel); display: grid; gap: 5px; }',
193
+ ' .timeline span { display: grid; place-items: center; width: 22px; height: 22px; border-radius: 999px; background: var(--accent); color: white; font-size: 12px; font-weight: 700; }',
194
+ ' button { border: 0; border-radius: 6px; padding: 8px 12px; background: var(--accent); color: white; font-weight: 700; }',
195
+ ' @media (max-width: 860px) { .toolbar { align-items: start; flex-direction: column; } .groups { grid-template-columns: 1fr; } .timeline { grid-template-columns: repeat(4, minmax(96px, 1fr)); } }',
196
+ ].join('\n');
197
+ }
198
+
199
+ function escapeHtml(value) {
200
+ return String(value)
201
+ .replace(/&/g, '&amp;')
202
+ .replace(/</g, '&lt;')
203
+ .replace(/>/g, '&gt;')
204
+ .replace(/"/g, '&quot;')
205
+ .replace(/'/g, '&#39;');
206
+ }
207
+
208
+ function escapeAttr(value) {
209
+ return escapeHtml(value);
210
+ }
211
+
212
+ function writePrototype(options = {}) {
213
+ const root = options.root || path.resolve(__dirname, '..');
214
+ const html = renderWorkflowUiPrototype(options);
215
+ const out = options.out || outputPathFor({ root, slug: options.sourceLabel });
216
+ fs.writeFileSync(out, html, 'utf8');
217
+ return out;
218
+ }
219
+
220
+ function outputPathFor({ root = path.resolve(__dirname, '..'), slug = null } = {}) {
221
+ if (!slug) return path.join(root, 'docs', 'workflow-ui-prototype.html');
222
+ return path.join(os.tmpdir(), `devflow-workflow-ui-${slugify(slug)}.html`);
223
+ }
224
+
225
+ function slugify(value) {
226
+ return String(value)
227
+ .trim()
228
+ .replace(/[^a-zA-Z0-9._-]+/g, '-')
229
+ .replace(/^-+|-+$/g, '')
230
+ || 'workflow';
231
+ }
232
+
233
+ if (require.main === module) {
234
+ const args = parseArgs(process.argv.slice(2));
235
+ const root = args.root || path.resolve(__dirname, '..');
236
+ const surfaces = args.slug
237
+ ? loadWorkflowSurfacesFromCli({ root, slug: args.slug, cwd: args.cwd || process.cwd() })
238
+ : loadFixtureSurfaces({ root });
239
+ const options = {
240
+ root,
241
+ ...surfaces,
242
+ sourceLabel: args.slug,
243
+ out: args.out,
244
+ };
245
+ if (args.write) {
246
+ console.log(writePrototype(options));
247
+ } else {
248
+ process.stdout.write(renderWorkflowUiPrototype(options));
249
+ }
250
+ }
251
+
252
+ function parseArgs(argv) {
253
+ const out = { write: false };
254
+ for (const arg of argv) {
255
+ if (arg === '--write') out.write = true;
256
+ else if (arg.startsWith('--slug=')) out.slug = arg.slice('--slug='.length);
257
+ else if (arg.startsWith('--cwd=')) out.cwd = arg.slice('--cwd='.length);
258
+ else if (arg.startsWith('--root=')) out.root = arg.slice('--root='.length);
259
+ else if (arg.startsWith('--out=')) out.out = arg.slice('--out='.length);
260
+ }
261
+ return out;
262
+ }
263
+
264
+ module.exports = {
265
+ renderWorkflowUiPrototype,
266
+ loadFixtureSurfaces,
267
+ loadWorkflowSurfacesFromCli,
268
+ outputPathFor,
269
+ writePrototype,
270
+ parseArgs,
271
+ };
@@ -0,0 +1,313 @@
1
+ ---
2
+ name: devflow-apply
3
+ description: |
4
+ devflow-kit apply 阶段严格按 `plan.md` 执行编码。一个 task 一个 TDD 循环(写失败测试 → 最小实现 → 运行 → 提交),
5
+ 默认每个 task 在独立 worktree 运行。≥2 个互不依赖 task 必须由上层 agent 一次性并行分派多个
6
+ 子 agent,不能在父 agent 中顺序实现。触发时机:`devflow apply [--task N]` 或 `/df:apply`。
7
+ 不允许在 apply 阶段拍脑袋偷改 scope;发现 plan / design 有问题要回退到对应 phase。
8
+ 所有完成的 task 通过 `devflow apply --task N --done` 写进 state.json。
9
+ when_to_use: |
10
+ plan.md 通过硬闸后。每个 task 开一次 `devflow apply --task N --start` → 编码 → `--done`;直到所
11
+ 有 task done。之后由 `devflow-df-orchestrator` 触发 `devflow review --round`。
12
+ ---
13
+
14
+ # apply
15
+
16
+ **执行者身份**,不是决策者。plan.md 是你的剧本,tests.md(若存在)和 plan 的 Test 字段是验收,design.md 是参考;任何偏离都意味着前置 phase 有问题,必须**回退修正**,而不是在 apply 里偷偷改。
17
+
18
+ ## 前置检查
19
+
20
+ | 输入 | 必需 | 缺失时 |
21
+ | --- | --- | --- |
22
+ | `plan.md`(硬闸通过) | 是 | 回退 plan |
23
+ | `state.planReviewConfirmedAt` | 是 | 回到 plan 补审查确认;必须先展示计划审查卡并等用户确认 |
24
+ | `tests.md` | 可选;存在时必须遵守 | 缺失时以 plan.md 每个 task 的 Test 字段为验收 |
25
+ | `design.md` | 是 | 回退 tech-spec |
26
+ | `state.json`,phase=apply | 是 | orchestrator 修正 |
27
+ | 项目可编译 / 测试框架就绪 | 是 | `devflow doctor` 诊断 |
28
+
29
+ **旧状态兜底**:如果已经有 `plan.md`,但 `state.planReviewConfirmedAt` 缺失,说明计划还没有经过用户审查。必须停止 apply,回到 plan 补展示计划审查卡;用户确认后写入 `planReviewConfirmedAt` 才能继续。不要因为用户说"继续"就直接开 task、创建 worktree 或编码。
30
+
31
+ **并行授权规则**:plan 审查一旦确认,用户不需要再单独说"并行"、"用子 agent"或"分派 agent"。`devflow apply` / `/df:apply` 本身就是按 plan 执行的授权;如果 plan 的 ready wave 中有 ≥2 个互不依赖 task,必须自动使用 subagent + worktree 并行分派。只有用户明确选择 `applyMode: direct`、工具环境不支持 subagent,或 task 间有共享文件 / 强依赖时,才允许不并行;这种例外必须写进下一步卡片和 state note。
32
+
33
+ ## 一个 task 的 TDD 循环(硬)
34
+
35
+ 每个 task 都是 4-step 循环。少任何一步都是**错误**:
36
+
37
+ ```
38
+ 1. 读 task 的 5 要素(Files / Behavior / Test / Implementation / Commit)
39
+ 2. 写失败测试(先跑一次,确认失败,且失败原因正确)
40
+ 3. 最小实现(刚好让测试通过,不做"顺手重构")
41
+ 4. 跑所有相关测试(不仅新加的,防回归)→ 必须展示实际输出(见下 verification gate)
42
+ 5. commit(用 plan.md 里规定的 commit message)
43
+ 6. devflow apply --task N --done --note="commit <sha>"
44
+ ```
45
+
46
+ ### Verification Gate(--done 前强制)
47
+
48
+ > 借鉴 **verification-before-completion** 原则:没有实际输出就不能声称"通过"。
49
+
50
+ ```
51
+ NO COMPLETION CLAIMS WITHOUT FRESH TEST EVIDENCE
52
+
53
+ 在执行 --done 前必须展示:
54
+ ✅ 实际命令:go test ./... | npm test | pytest | mvn test
55
+ ✅ 实际输出:通过数 / 失败数 / 耗时
56
+ ✅ exit code 0
57
+
58
+ 禁止:
59
+ ❌ "我跑了测试,都过了" (未附输出)
60
+ ❌ "应该能过" / "看起来没问题"
61
+ ❌ 跳过运行直接 --done
62
+ ```
63
+
64
+ ### Baseline Attribution(防止编译空转)
65
+
66
+ apply 阶段的验证目标是证明"本轮 diff 没有引入新问题",不是反复证明"整个老项目已经完美 green"。遇到大仓 / DDD 多模块 / 历史编译红点时,必须走验证阶梯和基线归因。
67
+
68
+ **硬规则**:
69
+
70
+ 1. 改代码前先跑一次最小基线探测,记录 `baselineKnownFailures`。
71
+ 2. 本轮实现后优先跑 diff-scoped 验证:`git diff --check`、变更文件相关测试、最小 reactor slice。
72
+ 3. 验证失败必须先归因:命中新改文件 / 新增测试 / 本轮依赖链路 → 修;与改代码前基线一致且不涉及本轮 diff → 记录为基线问题。
73
+ 4. 基线失败不能无限重试:同一条已知基线错误最多复核一次;继续失败时停止消耗时间,输出 `DONE_WITH_CONCERNS` 或 `BLOCKED`,并在下一步卡片里让用户选择先修环境还是继续 review。
74
+ 5. 每轮验证有时间预算:单条 compile/test 建议 3-5 分钟;超时按阻塞/风险记录,不要换命令盲跑。
75
+
76
+ `baselineKnownFailures` 必须写清:
77
+
78
+ ```yaml
79
+ baselineKnownFailures:
80
+ - command: mvn -pl <entry-module> -am -DskipTests compile
81
+ symptom: "Lombok/config 类历史编译错误"
82
+ beforeChange: true
83
+ touchesCurrentDiff: false
84
+ decision: "treat as baseline; current diff verified with git diff --check + targeted tests"
85
+ ```
86
+
87
+ 如果只剩基线问题而本轮 diff-scoped 验证通过,result 用 `DONE_WITH_CONCERNS`,不要假装全绿;如果基线问题阻止判断本轮改动是否正确,result 用 `BLOCKED`。
88
+
89
+ ### 处理 Review Findings(实现反馈时)
90
+
91
+ > 借鉴 **receiving-code-review** 原则:技术核验 > 条件反射式修改。
92
+
93
+ ```
94
+ 收到 review.findings.json 后:
95
+
96
+ 1. READ 完整读一遍,不要边读边改
97
+ 2. VERIFY 先在代码里确认问题真实存在
98
+ - MUST 级:确认根因,不要只改表面症状
99
+ - SHOULD 级:评估是否真实影响,可合理 pushback
100
+ - NIT 级:直接改,无需讨论
101
+ 3. CLARIFY 若 finding 描述不清,先问清楚再动手
102
+ 4. IMPLEMENT 逐条修复,每条独立 commit
103
+ 5. 禁止:看到 finding 就盲改(可能改错方向)
104
+ ```
105
+
106
+ 详细的 TDD 每步该做 / 不该做见 [`references/tdd-loop.md`](references/tdd-loop.md)。
107
+
108
+ ## 硬约束
109
+
110
+ 1. **≥ 2 个 task 必须用子 agent**:不允许在父 agent 里顺序执行多个 task,必须分派子 agent
111
+ 2. **不连着做 2 个 task 再 commit**:每个 task 独立 commit,方便 review 和回滚
112
+ 3. **不改 Files 外的文件**:发现要改,先更新 plan.md,审计后再动
113
+ 4. **不跳过失败测试**:失败测试必须修;暂时修不了 → quarantine(@Disabled + 记 issue),不 skip
114
+ 5. **不在 apply 里改 design / tests / plan**(不是 proofreading 级的改动):任何业务改动必须回退到对应 phase
115
+ 6. **不提交编译不过 / 测试红的代码到主干**:工作区 OK,但每个 commit 都要 green
116
+
117
+ 更多 apply 阶段的坚守原则 + 常见偷懒的识别见 [`references/discipline-checklist.md`](references/discipline-checklist.md)。
118
+
119
+ ## 子 agent 编排模式(多 task 强制)
120
+
121
+ > **⛔ HARD GATE**:plan.md 中 task 数量 ≥ 2 时,**必须**使用子 agent 编排 + worktree。
122
+ > 直接在当前 agent 里顺序执行多个 task 是**反模式**,视同跳过质量门。
123
+ > **⛔ PARALLEL GATE**:同一批 ready task 中只要有 ≥ 2 个互不依赖、无共享文件,就必须在同一轮里并行启动多个实现子 agent。
124
+ > 把 T-02 做完再启动 T-03(两者本可并行)是**错误执行**,必须停下重排为并行 wave。
125
+
126
+ **授权规则(硬约束)**:
127
+
128
+ - 用户触发 `devflow apply` / `/df:apply`,且 `plan.md` 已通过用户审查后,devflow apply 本身就是子 agent 授权。
129
+ - 只要命中本节的多 task / 并行 gate,就不得再要求用户额外说"用子 agent"、"并行"或"分派 agent"。
130
+ - 如果当前系统提供 subagent / spawn_agent 工具,controller 必须直接按 ready wave 分派;不能退化为父 agent 顺序实现。
131
+ - 只有两种情况允许降级:所有未完成 task 都有强依赖 / 共享文件,或工具环境确实不支持子 agent。降级时必须在 STATUS 里写明原因。
132
+
133
+ **每个 ready wave 并行分派实现子 agent → wave 完成后逐 task 规格合规 reviewer → 代码质量 reviewer → `--done`**。
134
+
135
+ ```
136
+ controller(本 agent)读 plan.md 提取所有 task 全文,建 TodoWrite
137
+
138
+ Step 0: 根据 plan.md DAG 计算 ready wave
139
+ - 已完成依赖全部满足
140
+ - Files 无交集
141
+ - 不存在 contract→consumer / DDL→business 等强依赖
142
+
143
+ Per wave:
144
+ 1. 对 wave 内每个 task 先执行 devflow apply --task N --start,创建独立 worktree
145
+ 2. 在同一条工具消息里一次性分派多个实现子 agent(每个 agent 一个 task + 一个 worktree)
146
+ 3. 等 wave 内实现子 agent 返回后,逐 task 分派规格合规 reviewer 子 agent(传 diff + AC)
147
+ 4. 逐 task 分派代码质量 reviewer 子 agent(传 diff + cheatsheet)
148
+ 5. controller 对通过 pre-review 的 task 执行 devflow apply --task N --done --note="<sha>"
149
+ 6. 重新计算下一批 ready wave
150
+
151
+ 所有 task done → devflow review --round(正式 review,不省略)
152
+ ```
153
+
154
+ **模式选择(强制)**:
155
+
156
+ | task 数量 | 复杂度 | 执行模式 |
157
+ | --- | --- | --- |
158
+ | 1 个 task | 任意 | 当前 agent 直接做(无需子 agent) |
159
+ | ≥ 2 个 task 且存在强依赖 / 共享文件 | 任意 | 子 agent + worktree,按依赖 wave 串行推进 |
160
+ | ≥ 2 个 task 且同一 wave 内有 ≥ 2 个独立 task | 任意 | 子 agent + worktree,同一 wave 必须并行启动 |
161
+
162
+ **controller 职责**:只做协调(读文件、传上下文、回答问题、执行 `--done`),不写代码。
163
+
164
+ **并行启动要求**:如果 IDE 支持 subagent 工具,controller 必须在一条消息中发起多个子 agent 调用;不要先等 T-02 返回再发 T-03。若工具环境不支持并行子 agent,必须在状态输出中标记 `BLOCKED` 或 `DONE_WITH_CONCERNS`,说明原因,不能假装已按并行协议执行。
165
+
166
+ 详细编排流程、回审循环上限、反模式见 [`references/subagent-orchestration.md`](references/subagent-orchestration.md)。
167
+
168
+ 实现子 agent prompt 模板见 [`references/subagent-implementer-prompt.md`](references/subagent-implementer-prompt.md)。
169
+
170
+ reviewer 子 agent prompt 模板(规格合规 + 代码质量)见 [`references/subagent-reviewer-prompt.md`](references/subagent-reviewer-prompt.md)。
171
+
172
+ ## Worktree swarm(并行的单元)
173
+
174
+ 默认行为:`devflow apply --task N` 在 `.devflow-worktrees/<slug>/task-N/` 创建独立 worktree + 分支 `devflow/<slug>/task-N`。
175
+
176
+ 并行执行时:
177
+
178
+ ```
179
+ devflow apply --task 1 --start # 终端 A
180
+ devflow apply --task 2 --start # 终端 B(独立 worktree,不互相污染)
181
+ devflow apply --task 3 --start # 终端 C
182
+ ```
183
+
184
+ - 每个 worktree 独立 git 状态 / build 缓存 / 测试 watcher
185
+ - 同时跑的 task 之间**不能有依赖**(plan.md 的依赖图标了)
186
+ - 合并顺序按依赖,不按完成顺序
187
+
188
+ 清理:
189
+
190
+ ```
191
+ devflow worktree cleanup <slug> --task=N # 删 worktree + 删分支(合并后)
192
+ devflow worktree cleanup <slug> --task=N --keep-branch # 保留分支(pre-PR)
193
+ devflow worktree list <slug> # 看当前 worktree 状态
194
+ ```
195
+
196
+ worktree 用法、何时 `--no-worktree`、冲突处置、合并顺序见 [`references/worktree-swarm.md`](references/worktree-swarm.md)。
197
+
198
+ ## 什么时候**不**用 worktree
199
+
200
+ - L1 一行改 bug(`--no-worktree` 直接在 main 做)
201
+ - 纯 spike / POC(`--no-worktree`,做完 stash / reset)
202
+ - 只 1 个 task 的 plan(worktree 开销 > 好处)
203
+
204
+ ## 发现 plan / design 不对时
205
+
206
+ **第一反应**:停止编码。
207
+
208
+ ```
209
+ devflow apply --task N --pause --reason="<具体描述>"
210
+ ```
211
+
212
+ 然后按问题定位:
213
+
214
+ | 问题 | 回退到哪 |
215
+ | --- | --- |
216
+ | task 描述歧义 / 5 要素不全 | plan(`devflow plan --edit`) |
217
+ | 实现方式不对 / 架构缺陷 | tech-spec(`devflow tech-spec --revise`) |
218
+ | 需求里没定义这种情况 | requirement-analysis(Round 2 追加 Q) |
219
+
220
+ 回退后**一定**在对应 phase 的产物里留一段"第 N 次返工"的记录;然后 `devflow apply --task N --resume`。
221
+
222
+ 发现问题时的决策树、审计格式见 [`references/when-plan-is-wrong.md`](references/when-plan-is-wrong.md)。
223
+
224
+ ## 按语言加载 cheatsheet(全语言)
225
+
226
+ apply 阶段写实现时,agent 应按项目语言加载对应 cheatsheet(与 code-review / tech-spec 共享):
227
+
228
+ | detect.language | cheatsheet |
229
+ | --- | --- |
230
+ | `java` (Spring Boot + MyBatis / JPA) | `../code-review/references/language-cheatsheets/java-spring-mybatis.md` |
231
+ | `go` | `../code-review/references/language-cheatsheets/go.md` |
232
+ | `python` | `../code-review/references/language-cheatsheets/python.md` |
233
+ | `node`(Vue) | `../code-review/references/language-cheatsheets/vue.md` |
234
+
235
+ apply 时关注的重点与 review 不同:
236
+
237
+ - **review**:看"代码里**做了**什么错事"
238
+ - **apply**:看"写的时候**该**怎么避免那些错事"
239
+
240
+ 比如 cheatsheet 里 "MyBatis 全链路字段一致性" 一节,apply 时要主动**逐步核对**(Entity → Mapper XML → ResultMap),review 时则是**扫**有没有不一致。
241
+
242
+ ## 完成状态协议(phase 级)
243
+
244
+ 单个 task 完成由 `devflow apply --task N --done` 记入 state;当**所有 task done** 时,本 skill 整体 DONE:
245
+
246
+ ```
247
+ ---STATUS---
248
+ result: DONE | DONE_WITH_CONCERNS | BLOCKED | NEEDS_INPUT
249
+ outputs:
250
+ - devflow/changes/<slug>/state.json (updated)
251
+ - git commits: T-01..T-NN
252
+ - devflow/changes/<slug>/reports/test-report.md#unit (首次跑过后产出)
253
+ baselineKnownFailures:
254
+ - <command + symptom + whether it touches current diff>
255
+ tasksCompleted: K/K
256
+ iterations: N # 如果经历了 review 回退再 apply,这里是第几轮
257
+ nextAction: devflow review --slug=<slug> --round
258
+ ---END_STATUS---
259
+ ```
260
+
261
+ **下一步卡片(硬约束)**:
262
+
263
+ 任何 result 都必须在用户可见正文最后展示下一步卡片。每次用户可见回复收尾都要给出下一步,包含但不限于:启动/完成一个 task、完成一个 ready wave、修复一轮 review findings、pre-review 后返回、进入 `DONE_WITH_CONCERNS` / `BLOCKED` / `NEEDS_INPUT`。不能只列变更和校验,不能只写 `---STATUS---`,也不能让用户猜下一步。
264
+
265
+ ```markdown
266
+ ## 下一步
267
+ 状态:DONE | DONE_WITH_CONCERNS | BLOCKED | NEEDS_INPUT
268
+ 下一步:[一句话说明]
269
+ 命令:`<nextAction command>`
270
+ 需要你确认:[无 / 是否接受遗留风险并推进 / 需要补充的信息]
271
+ ```
272
+
273
+ 按 result 填写:
274
+
275
+ - `DONE`:下一步通常是正式 review;命令:`devflow review --slug=<slug> --round`。
276
+ - `DONE_WITH_CONCERNS`:必须列出遗留风险,并明确问用户是否推进到下一 phase;如果推进,给出命令:`devflow review --slug=<slug> --round`。
277
+ - `BLOCKED`:不要给推进命令;必须说明解除阻塞的最小动作,例如切换 JDK/toolchain、修复编译环境、回退 plan/design。
278
+ - `NEEDS_INPUT`:必须列出需要用户回答的问题或选择项,用户回复后才能继续。
279
+
280
+ 示例:
281
+
282
+ ```markdown
283
+ ## 下一步
284
+ 状态:DONE_WITH_CONCERNS
285
+ 下一步:建议先修复 Maven 实际 JDK / Lombok 环境后再进入正式 review,或者你确认接受该风险后继续 review。
286
+ 命令:`mvn -pl health-mall-app -am -DskipTests compile`
287
+ 需要你确认:是否先处理编译环境问题;若继续推进,回复“继续 review”。
288
+ ```
289
+
290
+ ## 反模式
291
+
292
+ - **⛔ 多 task 但不用子 agent,在父 agent 里顺序执行**:违反硬约束 1,跳过 pre-review 质量门
293
+ - **⛔ ≥ 2 task 但不开 worktree**:task 间文件互相污染,合并冲突风险高
294
+ - **先整块写再加测试**:违反 TDD,review 和 verify 都会返工
295
+ - **用 print / 手 test 代替自动化 test**:没留下可重跑的契约
296
+ - **一个 commit 包 5 个 task**:review 一口气咽 500 行,灾难
297
+ - **测试挂了 skip 继续**:挂了就修,quarantine 要走审计(reason + deadline)
298
+ - **偷偷改 plan / design**:行为不一致,下游 review 对不上,archive 时 delta 冲突
299
+ - **跨 task 编辑公用文件**:合并时冲突
300
+ - **在 worktree 里 `git rebase main`**:保持干净线性的诱惑,但会让依赖链混乱;让合并者 rebase
301
+ - **忘记 `--done` 标记**:state.json 认为 task 还在 in_progress,下次 apply 或 review 会 gate 挂
302
+ - **apply 阶段"顺手"优化 design 未涉及的代码**:所谓 scope creep,review 要反问"为什么这个不是单独 task"
303
+
304
+ ## 参考
305
+
306
+ - [`references/tdd-loop.md`](references/tdd-loop.md) — TDD 每步详解:写失败测试 / 最小实现 / 运行 / 提交 + 常见偏离识别
307
+ - [`references/discipline-checklist.md`](references/discipline-checklist.md) — apply 阶段的纪律 checklist(per-task before/during/after)
308
+ - [`references/worktree-swarm.md`](references/worktree-swarm.md) — worktree 并行执行、合并顺序、冲突处置
309
+ - [`references/when-plan-is-wrong.md`](references/when-plan-is-wrong.md) — 发现 plan / design 不对时的回退决策树与审计格式
310
+ - [`references/subagent-orchestration.md`](references/subagent-orchestration.md) — 子 agent 编排流程、回审循环上限、与正式 review 的边界
311
+ - [`references/subagent-implementer-prompt.md`](references/subagent-implementer-prompt.md) — 实现子 agent prompt 模板
312
+ - [`references/subagent-reviewer-prompt.md`](references/subagent-reviewer-prompt.md) — reviewer 子 agent prompt 模板(规格合规 + 代码质量)
313
+ - [`../code-review/references/language-cheatsheets/`](../code-review/references/language-cheatsheets/) — 按语言挑 1-2 份(apply 视角:写时避免;与 review 共享同一份内容)