cc-devflow 4.2.0 → 4.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (119) hide show
  1. package/.claude/commands/flow/CLAUDE.md +0 -4
  2. package/.claude/docs/examples/design-inspiration-pool.md +59 -0
  3. package/.claude/docs/examples/ui-prototype-constitution-checklist.md +75 -0
  4. package/.claude/docs/implementation-summary-v7.md +449 -0
  5. package/.claude/docs/spec-format-guide.md +349 -0
  6. package/.claude/docs/state-consolidation-design.md +323 -0
  7. package/.claude/docs/templates/ARCHITECTURE_TEMPLATE.md +85 -386
  8. package/.claude/docs/templates/DESIGN_TEMPLATE.md +157 -0
  9. package/.claude/docs/templates/PROPOSAL_TEMPLATE.md +91 -0
  10. package/.claude/docs/templates/SPEC_TEMPLATE_DELTA.md +139 -0
  11. package/.claude/docs/templates/SPEC_TEMPLATE_PROJECT.md +93 -0
  12. package/.claude/docs/templates/STYLE_TEMPLATE.md +114 -901
  13. package/.claude/docs/templates/UI_PROTOTYPE_TEMPLATE.md +143 -1205
  14. package/.claude/hooks/inject-agent-context.ts +9 -9
  15. package/.claude/scripts/.claude/commands/flow/export-openspec.md +221 -0
  16. package/.claude/scripts/.claude/commands/flow/import-openspec.md +171 -0
  17. package/.claude/scripts/__tests__/openspec.test.js +212 -0
  18. package/.claude/scripts/delta-parser.ts +112 -2
  19. package/.claude/scripts/export-openspec.js +222 -0
  20. package/.claude/scripts/import-openspec.js +272 -0
  21. package/.claude/scripts/validate-scope.sh +200 -0
  22. package/.claude/skills/{workflow/flow-init → flow-init}/SKILL.md +25 -4
  23. package/.claude/skills/{workflow/flow-release → flow-release}/SKILL.md +14 -3
  24. package/.claude/skills/{workflow/flow-spec → flow-spec}/SKILL.md +30 -2
  25. package/.claude/skills/utility/npm-release/CLAUDE.md +55 -0
  26. package/.claude/skills/utility/npm-release/SKILL.md +111 -46
  27. package/.claude/skills/utility/npm-release/references/version-decision-guide.md +134 -0
  28. package/.claude/skills/utility/npm-release/scripts/atomic-version-bump.sh +95 -0
  29. package/.claude/skills/utility/npm-release/scripts/validate-version-sync.sh +82 -0
  30. package/.claude/skills/utility/npm-release/scripts/version-decision-tree.sh +44 -0
  31. package/.claude/tsc-cache/70d2fc6d-2936-429b-b529-429f1aae8c88/affected-repos.txt +1 -0
  32. package/.claude/tsc-cache/70d2fc6d-2936-429b-b529-429f1aae8c88/edited-files.log +2 -0
  33. package/CHANGELOG.md +40 -0
  34. package/README.md +2 -1
  35. package/README.zh-CN.md +2 -1
  36. package/docs/v4.3.0-migration-guide.md +276 -0
  37. package/lib/harness/CLAUDE.md +5 -4
  38. package/lib/harness/__tests__/planner.tdd.test.js +125 -0
  39. package/lib/harness/index.js +4 -2
  40. package/lib/harness/operations/dispatch.js +13 -0
  41. package/lib/harness/operations/plan.js +55 -1
  42. package/lib/harness/operations/release.js +87 -0
  43. package/lib/harness/operations/verify.js +14 -0
  44. package/lib/harness/planner.js +131 -0
  45. package/lib/harness/query.js +126 -0
  46. package/lib/harness/schemas.js +22 -1
  47. package/package.json +1 -1
  48. package/.claude/commands/flow/checklist.md +0 -18
  49. package/.claude/commands/flow/clarify.md +0 -18
  50. package/.claude/commands/flow/new.md +0 -23
  51. package/.claude/commands/flow/quality.md +0 -21
  52. package/.claude/docs/templates/EPIC_TEMPLATE.md +0 -805
  53. package/.claude/docs/templates/PRD_TEMPLATE.md +0 -562
  54. package/.claude/docs/templates/TASKS_TEMPLATE.md +0 -523
  55. package/.claude/docs/templates/TECH_DESIGN_TEMPLATE.md +0 -1019
  56. package/.claude/skills/workflow/CLAUDE.md +0 -24
  57. /package/.claude/skills/{domain/attention-refresh → attention-refresh}/SKILL.md +0 -0
  58. /package/.claude/skills/{domain/brainstorming → brainstorming}/SKILL.md +0 -0
  59. /package/.claude/skills/{guardrail/constitution-guardian → constitution-guardian}/SKILL.md +0 -0
  60. /package/.claude/skills/{utility/constitution-quick-ref → constitution-quick-ref}/SKILL.md +0 -0
  61. /package/.claude/skills/{domain/debugging → debugging}/SKILL.md +0 -0
  62. /package/.claude/skills/{utility/file-standards → file-standards}/SKILL.md +0 -0
  63. /package/.claude/skills/{domain/finishing-branch → finishing-branch}/SKILL.md +0 -0
  64. /package/.claude/skills/{workflow/flow-dev → flow-dev}/CLAUDE.md +0 -0
  65. /package/.claude/skills/{workflow/flow-dev → flow-dev}/SKILL.md +0 -0
  66. /package/.claude/skills/{workflow/flow-dev → flow-dev}/assets/IMPLEMENTATION_PLAN_TEMPLATE.md +0 -0
  67. /package/.claude/skills/{workflow/flow-dev → flow-dev}/context.jsonl +0 -0
  68. /package/.claude/skills/{workflow/flow-dev → flow-dev}/dev-implementer.jsonl +0 -0
  69. /package/.claude/skills/{workflow/flow-dev → flow-dev}/scripts/entry-gate.sh +0 -0
  70. /package/.claude/skills/{workflow/flow-dev → flow-dev}/scripts/exit-gate.sh +0 -0
  71. /package/.claude/skills/{workflow/flow-dev → flow-dev}/scripts/task-orchestrator.sh +0 -0
  72. /package/.claude/skills/{workflow/flow-fix → flow-fix}/SKILL.md +0 -0
  73. /package/.claude/skills/{workflow/flow-fix → flow-fix}/context.jsonl +0 -0
  74. /package/.claude/skills/{workflow/flow-fix → flow-fix}/references/bug-analyzer.md +0 -0
  75. /package/.claude/skills/{workflow/flow-init → flow-init}/assets/BRAINSTORM_TEMPLATE.md +0 -0
  76. /package/.claude/skills/{workflow/flow-init → flow-init}/assets/INIT_FLOW_TEMPLATE.md +0 -0
  77. /package/.claude/skills/{workflow/flow-init → flow-init}/assets/RESEARCH_TEMPLATE.md +0 -0
  78. /package/.claude/skills/{workflow/flow-init → flow-init}/context.jsonl +0 -0
  79. /package/.claude/skills/{workflow/flow-init → flow-init}/references/flow-researcher.md +0 -0
  80. /package/.claude/skills/{workflow/flow-init → flow-init}/scripts/check-prerequisites.sh +0 -0
  81. /package/.claude/skills/{workflow/flow-init → flow-init}/scripts/consolidate-research.sh +0 -0
  82. /package/.claude/skills/{workflow/flow-init → flow-init}/scripts/create-requirement.sh +0 -0
  83. /package/.claude/skills/{workflow/flow-init → flow-init}/scripts/generate-research-tasks.sh +0 -0
  84. /package/.claude/skills/{workflow/flow-init → flow-init}/scripts/populate-research-tasks.sh +0 -0
  85. /package/.claude/skills/{workflow/flow-init → flow-init}/scripts/validate-research.sh +0 -0
  86. /package/.claude/skills/{workflow/flow-quality → flow-quality}/SKILL.md +0 -0
  87. /package/.claude/skills/{workflow/flow-quality → flow-quality}/context.jsonl +0 -0
  88. /package/.claude/skills/{workflow/flow-quality → flow-quality}/references/code-quality-reviewer.md +0 -0
  89. /package/.claude/skills/{workflow/flow-quality → flow-quality}/references/qa-tester.md +0 -0
  90. /package/.claude/skills/{workflow/flow-quality → flow-quality}/references/security-reviewer.md +0 -0
  91. /package/.claude/skills/{workflow/flow-quality → flow-quality}/references/spec-reviewer.md +0 -0
  92. /package/.claude/skills/{workflow/flow-release → flow-release}/context.jsonl +0 -0
  93. /package/.claude/skills/{workflow/flow-release → flow-release}/references/release-manager.md +0 -0
  94. /package/.claude/skills/{workflow/flow-spec → flow-spec}/CLAUDE.md +0 -0
  95. /package/.claude/skills/{workflow/flow-spec → flow-spec}/context.jsonl +0 -0
  96. /package/.claude/skills/{workflow/flow-spec → flow-spec}/scripts/entry-gate.sh +0 -0
  97. /package/.claude/skills/{workflow/flow-spec → flow-spec}/scripts/exit-gate.sh +0 -0
  98. /package/.claude/skills/{workflow/flow-spec → flow-spec}/scripts/parallel-orchestrator.sh +0 -0
  99. /package/.claude/skills/{workflow/flow-spec → flow-spec}/scripts/team-communication.sh +0 -0
  100. /package/.claude/skills/{workflow/flow-spec → flow-spec}/scripts/team-init.sh +0 -0
  101. /package/.claude/skills/{workflow/flow-spec → flow-spec}/scripts/test-team-mode.sh +0 -0
  102. /package/.claude/skills/{workflow/flow-spec → flow-spec}/team-config.json +0 -0
  103. /package/.claude/skills/{workflow/flow-verify → flow-verify}/CLAUDE.md +0 -0
  104. /package/.claude/skills/{workflow/flow-verify → flow-verify}/SKILL.md +0 -0
  105. /package/.claude/skills/{workflow/flow-verify → flow-verify}/context.jsonl +0 -0
  106. /package/.claude/skills/{utility/fractal-docs → fractal-docs}/SKILL.md +0 -0
  107. /package/.claude/skills/{utility/journey-checker → journey-checker}/SKILL.md +0 -0
  108. /package/.claude/skills/{utility/journey-checker → journey-checker}/pressure-scenarios.md +0 -0
  109. /package/.claude/skills/{domain/receiving-review → receiving-review}/SKILL.md +0 -0
  110. /package/.claude/skills/{utility/skill-creator → skill-creator}/LICENSE.txt +0 -0
  111. /package/.claude/skills/{utility/skill-creator → skill-creator}/SKILL.md +0 -0
  112. /package/.claude/skills/{utility/skill-creator → skill-creator}/references/output-patterns.md +0 -0
  113. /package/.claude/skills/{utility/skill-creator → skill-creator}/references/workflows.md +0 -0
  114. /package/.claude/skills/{utility/skill-creator → skill-creator}/scripts/init_skill.py +0 -0
  115. /package/.claude/skills/{utility/skill-creator → skill-creator}/scripts/package_skill.py +0 -0
  116. /package/.claude/skills/{utility/skill-creator → skill-creator}/scripts/quick_validate.py +0 -0
  117. /package/.claude/skills/{domain/tdd → tdd}/SKILL.md +0 -0
  118. /package/.claude/skills/{guardrail/tdd-enforcer → tdd-enforcer}/SKILL.md +0 -0
  119. /package/.claude/skills/{domain/verification → verification}/SKILL.md +0 -0
@@ -0,0 +1,276 @@
1
+ # CC-DevFlow v4.3.0 Migration Guide
2
+
3
+ ## Overview
4
+
5
+ CC-DevFlow v4.3.0 introduces automatic TDD order validation and OpenSpec interoperability to solve requirement drift problems. This guide helps you migrate from v4.2.x to v4.3.0.
6
+
7
+ ---
8
+
9
+ ## What's New in v4.3.0
10
+
11
+ ### 1. Automatic TDD Order Validation
12
+
13
+ **Feature**: The harness planner now automatically validates TDD order when parsing TASKS.md.
14
+
15
+ **Impact**:
16
+ - [IMPL] tasks MUST depend on corresponding [TEST] tasks
17
+ - [TEST] tasks CANNOT depend on [IMPL] tasks
18
+ - Violations throw detailed error messages at `harness:plan` time
19
+
20
+ **Example Error**:
21
+ ```
22
+ TDD Order Validation Failed (Constitution Article VI):
23
+
24
+ 1. Task T002 (用户登录实现) missing corresponding TEST task.
25
+ Constitution Article VI requires: NO PRODUCTION CODE WITHOUT A FAILING TEST FIRST.
26
+
27
+ 2. Task T004 (用户注册实现) must depend on T003 (用户注册测试).
28
+ TDD violation: Implementation must come AFTER test.
29
+ ```
30
+
31
+ **Migration Steps**:
32
+ 1. Review your existing TASKS.md files
33
+ 2. Ensure all [IMPL] tasks have corresponding [TEST] tasks
34
+ 3. Add `dependsOn` to [IMPL] tasks pointing to [TEST] tasks
35
+ 4. Use `[P]` marker for parallel tasks that don't follow TEST→IMPL pattern
36
+
37
+ **Example Fix**:
38
+ ```markdown
39
+ <!-- Before (INVALID) -->
40
+ - [ ] T001 [IMPL] 用户登录实现
41
+ - [ ] T002 [TEST] 用户登录测试
42
+
43
+ <!-- After (VALID) -->
44
+ - [ ] T001 [TEST] 用户登录测试
45
+ - [ ] T002 [IMPL] 用户登录实现 (dependsOn:T001)
46
+ ```
47
+
48
+ ### 2. OpenSpec Interoperability
49
+
50
+ **Feature**: Bidirectional conversion between OpenSpec and CC-DevFlow formats.
51
+
52
+ **New Commands**:
53
+ - `/flow:import-openspec` - Import OpenSpec spec.md to CC-DevFlow
54
+ - `/flow:export-openspec` - Export CC-DevFlow spec.md to OpenSpec
55
+
56
+ **Use Cases**:
57
+
58
+ #### Import from OpenSpec
59
+ ```bash
60
+ /flow:import-openspec "/path/to/openspec/specs/auth/spec.md" \
61
+ --req-id "REQ-123" \
62
+ --title "用户认证系统"
63
+ ```
64
+
65
+ **What happens**:
66
+ 1. Parses OpenSpec format (Purpose + Requirements + BDD scenarios)
67
+ 2. Generates CC-DevFlow spec.md with YAML frontmatter
68
+ 3. Auto-generates TDD tasks (TEST + IMPL pairs with correct dependencies)
69
+ 4. Adds Design section with [NEEDS CLARIFICATION] markers
70
+ 5. Generates Verification checklist
71
+
72
+ #### Export to OpenSpec
73
+ ```bash
74
+ /flow:export-openspec "REQ-123" \
75
+ --output "/path/to/openspec/specs/auth/spec.md"
76
+ ```
77
+
78
+ **What happens**:
79
+ 1. Parses CC-DevFlow spec.md
80
+ 2. Strips YAML frontmatter and metadata
81
+ 3. Removes Design, Tasks, Verification sections
82
+ 4. Removes [NEEDS CLARIFICATION] markers
83
+ 5. Outputs pure Requirements in OpenSpec format
84
+
85
+ **Round-Trip Guarantee**: Requirements are preserved through import→export→import cycles.
86
+
87
+ ---
88
+
89
+ ## Breaking Changes
90
+
91
+ ### 1. TASKS.md Validation
92
+
93
+ **Before v4.3.0**: TDD order was recommended but not enforced.
94
+
95
+ **After v4.3.0**: TDD order is enforced at `harness:plan` time.
96
+
97
+ **Migration**: Update existing TASKS.md files to follow TDD order.
98
+
99
+ ### 2. Task Type Detection
100
+
101
+ **Before v4.3.0**: Task types were not tracked.
102
+
103
+ **After v4.3.0**: Tasks are classified as TEST/IMPL/OTHER based on markers.
104
+
105
+ **Migration**: Ensure your TASKS.md uses `[TEST]` and `[IMPL]` markers consistently.
106
+
107
+ ---
108
+
109
+ ## Feature Name Matching Algorithm
110
+
111
+ The TDD validator uses intelligent fuzzy matching to pair TEST and IMPL tasks:
112
+
113
+ **Normalization Rules**:
114
+ - Removes suffixes: "测试", "实现", "功能", "开发", "编写"
115
+ - Trims whitespace
116
+ - Compares core feature names
117
+
118
+ **Examples**:
119
+ ```
120
+ "用户登录功能测试" ↔ "用户登录功能实现" ✅ Match
121
+ "用户登录测试" ↔ "用户登录实现" ✅ Match
122
+ "用户登录" ↔ "用户登录功能" ✅ Match
123
+ "用户登录" ↔ "用户注册" ❌ No match
124
+ ```
125
+
126
+ ---
127
+
128
+ ## Parallel Tasks
129
+
130
+ For tasks that don't follow TEST→IMPL pattern, use the `[P]` marker:
131
+
132
+ ```markdown
133
+ - [ ] T001 [TEST] 用户登录测试
134
+ - [ ] T002 [IMPL] 用户登录实现 (dependsOn:T001)
135
+ - [ ] T003 [OTHER] 数据库迁移 [P]
136
+ - [ ] T004 [OTHER] 配置文件更新 [P]
137
+ ```
138
+
139
+ The `[P]` marker tells the validator to skip dependency checks for that task.
140
+
141
+ ---
142
+
143
+ ## OpenSpec Format Reference
144
+
145
+ ### OpenSpec Format (Input)
146
+ ```markdown
147
+ # Authentication Module
148
+
149
+ ## Purpose
150
+ Provides secure authentication and session management.
151
+
152
+ ## Requirements
153
+
154
+ ### Requirement: User Login
155
+ The system SHALL allow users to log in with email and password.
156
+
157
+ #### Scenario: Valid credentials
158
+ - GIVEN a registered user
159
+ - WHEN the user submits valid email and password
160
+ - THEN a JWT token is issued
161
+ - AND the user is redirected to dashboard
162
+ ```
163
+
164
+ ### CC-DevFlow Format (Output)
165
+ ```markdown
166
+ ---
167
+ req_id: "REQ-123"
168
+ title: "用户认证系统"
169
+ created_at: "2026-03-13T10:00:00Z"
170
+ version: "1.0.0"
171
+ status: "draft"
172
+ source: "openspec"
173
+ ---
174
+
175
+ # Authentication Module
176
+
177
+ ## Purpose
178
+ Provides secure authentication and session management.
179
+
180
+ ## Requirements
181
+
182
+ ### Requirement: User Login
183
+ The system SHALL allow users to log in with email and password.
184
+
185
+ #### Scenario: Valid credentials
186
+ - GIVEN a registered user
187
+ - WHEN the user submits valid email and password
188
+ - THEN a JWT token is issued
189
+ - AND the user is redirected to dashboard
190
+
191
+ ## Design
192
+ [NEEDS CLARIFICATION: 技术实现方案]
193
+
194
+ ## Tasks
195
+ - [ ] T001 [TEST] User Login - 测试
196
+ - [ ] T002 [IMPL] User Login - 实现 (dependsOn:T001)
197
+
198
+ ## Verification
199
+ - [ ] User Login
200
+ - [ ] Valid credentials
201
+ ```
202
+
203
+ ---
204
+
205
+ ## Testing
206
+
207
+ All v4.3.0 features are covered by automated tests:
208
+
209
+ ```bash
210
+ # Run all tests
211
+ npm test
212
+
213
+ # Run TDD validation tests only
214
+ npm test -- planner.tdd.test.js
215
+
216
+ # Run OpenSpec interop tests only
217
+ npm test -- openspec.test.js
218
+ ```
219
+
220
+ **Test Coverage**:
221
+ - TDD validation: 10 tests (all passing)
222
+ - OpenSpec interop: 5 tests (all passing)
223
+ - Total: 233 tests (all passing)
224
+
225
+ ---
226
+
227
+ ## Troubleshooting
228
+
229
+ ### Error: "Task T002 missing corresponding TEST task"
230
+
231
+ **Cause**: An [IMPL] task has no matching [TEST] task.
232
+
233
+ **Solution**: Add a [TEST] task with similar feature name before the [IMPL] task.
234
+
235
+ ### Error: "Task T002 must depend on T001"
236
+
237
+ **Cause**: An [IMPL] task doesn't depend on its corresponding [TEST] task.
238
+
239
+ **Solution**: Add `(dependsOn:T001)` to the [IMPL] task.
240
+
241
+ ### Error: "Task T001 depends on IMPL tasks"
242
+
243
+ **Cause**: A [TEST] task depends on an [IMPL] task (reverse TDD order).
244
+
245
+ **Solution**: Remove the dependency or reorder tasks.
246
+
247
+ ### Feature Name Mismatch
248
+
249
+ **Cause**: TEST and IMPL tasks have very different feature names.
250
+
251
+ **Solution**: Rename tasks to have similar core feature names, or use `[P]` marker if they're truly independent.
252
+
253
+ ---
254
+
255
+ ## Rollback
256
+
257
+ If you need to rollback to v4.2.0:
258
+
259
+ ```bash
260
+ npm install cc-devflow@4.2.0
261
+ ```
262
+
263
+ Note: v4.2.0 does not have TDD validation or OpenSpec interop features.
264
+
265
+ ---
266
+
267
+ ## Support
268
+
269
+ - GitHub Issues: https://github.com/anthropics/cc-devflow/issues
270
+ - Documentation: https://github.com/anthropics/cc-devflow/tree/main/docs
271
+ - Constitution: `.claude/rules/project-constitution.md`
272
+
273
+ ---
274
+
275
+ **Last Updated**: 2026-03-13
276
+ **Version**: 4.3.0
@@ -3,16 +3,17 @@
3
3
 
4
4
  成员清单
5
5
  index.js: 聚合导出 harness 基础模块,供 CLI 与测试统一引用。
6
- schemas.js: 定义 manifest/report/checkpoint 的 Zod 契约,阻断脏数据进入执行层。
6
+ schemas.js: 定义 manifest/report/checkpoint/harness-state 的 Zod 契约,阻断脏数据进入执行层。
7
7
  store.js: 提供路径规范、JSON/文本读写、JSONL 事件记录与 shell 命令执行。
8
8
  planner.js: 将 TASKS.md 解析为 dependency-aware 的 task-manifest.json。
9
+ query.js: 聚合分散状态文件,提供 getProgress/getNextTask/getFullState 查询函数。
9
10
  cli.js: 解析命令参数并分发到 operations 子模块。
10
11
  operations/init.js: 初始化 requirement 与 runtime 目录并写入 harness-state。
11
12
  operations/pack.js: 采集 git 与脚本事实,生成 context-package.md。
12
- operations/plan.js: 调用 planner 生成 task-manifest.json。
13
- operations/dispatch.js: 依据依赖图与文件冲突并行执行任务,写 checkpoint 与 events。
13
+ operations/plan.js: 调用 planner 生成 task-manifest.json,更新 harness-state 为 planned
14
+ operations/dispatch.js: 依据依赖图与文件冲突并行执行任务,写 checkpoint 与 events,更新 harness-state 为 in_progress
14
15
  operations/resume.js: 恢复中断任务并复用 dispatch 继续执行。
15
- operations/verify.js: 执行 quick/strict 质量门禁并输出 report-card.json。
16
+ operations/verify.js: 执行 quick/strict 质量门禁并输出 report-card.json,通过时更新 harness-state 为 verified
16
17
  operations/release.js: 读取通过的 report-card,生成 RELEASE_NOTE 并标记 released。
17
18
  operations/janitor.js: 清理过期 runtime 工件,保留运行中任务状态。
18
19
 
@@ -0,0 +1,125 @@
1
+ /**
2
+ * TDD Order Validation Tests
3
+ *
4
+ * Tests for Constitution Article VI enforcement in planner.js
5
+ */
6
+
7
+ const { parseTasksMarkdown } = require('../planner');
8
+
9
+ describe('TDD Order Validation', () => {
10
+ describe('Valid TDD sequences', () => {
11
+ test('should accept TEST before IMPL with correct dependency', () => {
12
+ const markdown = `
13
+ - [ ] T001 [TEST] 用户登录功能测试
14
+ - [ ] T002 [IMPL] 用户登录功能实现 (dependsOn:T001)
15
+ `.trim();
16
+
17
+ expect(() => parseTasksMarkdown(markdown)).not.toThrow();
18
+ });
19
+
20
+ test('should accept multiple TEST-IMPL pairs', () => {
21
+ const markdown = `
22
+ - [ ] T001 [TEST] 用户登录测试
23
+ - [ ] T002 [IMPL] 用户登录实现 (dependsOn:T001)
24
+ - [ ] T003 [TEST] 用户注册测试 [P]
25
+ - [ ] T004 [IMPL] 用户注册实现 (dependsOn:T003)
26
+ `.trim();
27
+
28
+ expect(() => parseTasksMarkdown(markdown)).not.toThrow();
29
+ });
30
+
31
+ test('should accept tasks without TEST/IMPL markers', () => {
32
+ const markdown = `
33
+ - [ ] T001 初始化项目结构
34
+ - [ ] T002 配置开发环境
35
+ `.trim();
36
+
37
+ expect(() => parseTasksMarkdown(markdown)).not.toThrow();
38
+ });
39
+ });
40
+
41
+ describe('TDD violations', () => {
42
+ test('should reject IMPL without corresponding TEST', () => {
43
+ const markdown = `
44
+ - [ ] T001 [IMPL] 用户登录功能实现
45
+ `.trim();
46
+
47
+ expect(() => parseTasksMarkdown(markdown)).toThrow(
48
+ /missing corresponding TEST task/
49
+ );
50
+ });
51
+
52
+ test('should reject IMPL not depending on TEST', () => {
53
+ const markdown = `
54
+ - [ ] T001 [TEST] 用户登录功能测试
55
+ - [ ] T002 [IMPL] 用户登录功能实现 [P]
56
+ `.trim();
57
+
58
+ expect(() => parseTasksMarkdown(markdown)).toThrow(
59
+ /must depend on T001/
60
+ );
61
+ });
62
+
63
+ test('should reject TEST depending on IMPL', () => {
64
+ const markdown = `
65
+ - [ ] T001 [IMPL] 用户登录功能实现
66
+ - [ ] T002 [TEST] 用户登录功能测试 (dependsOn:T001)
67
+ `.trim();
68
+
69
+ expect(() => parseTasksMarkdown(markdown)).toThrow(
70
+ /Tests must be written BEFORE implementation/
71
+ );
72
+ });
73
+
74
+ test('should reject IMPL depending on wrong TEST', () => {
75
+ const markdown = `
76
+ - [ ] T001 [TEST] 用户注册测试
77
+ - [ ] T002 [IMPL] 用户登录实现 (dependsOn:T001)
78
+ `.trim();
79
+
80
+ expect(() => parseTasksMarkdown(markdown)).toThrow(
81
+ /missing corresponding TEST task/
82
+ );
83
+ });
84
+ });
85
+
86
+ describe('Feature name extraction', () => {
87
+ test('should match TEST and IMPL with same feature name', () => {
88
+ const markdown = `
89
+ - [ ] T001 [TEST] 实现用户认证功能
90
+ - [ ] T002 [IMPL] 实现用户认证功能 (dependsOn:T001)
91
+ `.trim();
92
+
93
+ expect(() => parseTasksMarkdown(markdown)).not.toThrow();
94
+ });
95
+
96
+ test('should handle case-insensitive markers', () => {
97
+ const markdown = `
98
+ - [ ] T001 [test] 用户登录
99
+ - [ ] T002 [impl] 用户登录 (dependsOn:T001)
100
+ `.trim();
101
+
102
+ expect(() => parseTasksMarkdown(markdown)).not.toThrow();
103
+ });
104
+ });
105
+
106
+ describe('Error messages', () => {
107
+ test('should provide clear violation details', () => {
108
+ const markdown = `
109
+ - [ ] T001 [IMPL] 功能A
110
+ - [ ] T002 [TEST] 功能B
111
+ - [ ] T003 [IMPL] 功能B
112
+ `.trim();
113
+
114
+ try {
115
+ parseTasksMarkdown(markdown);
116
+ fail('Should have thrown TDD violation error');
117
+ } catch (error) {
118
+ expect(error.message).toContain('TDD Order Validation Failed');
119
+ expect(error.message).toContain('Constitution Article VI');
120
+ expect(error.message).toContain('T001');
121
+ expect(error.message).toContain('missing corresponding TEST task');
122
+ }
123
+ });
124
+ });
125
+ });
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * [INPUT]: 依赖 harness 各模块。
3
- * [OUTPUT]: 统一导出 schema/store/planner 与 operations 入口。
3
+ * [OUTPUT]: 统一导出 schema/store/planner/query 与 operations 入口。
4
4
  * [POS]: harness 模块聚合出口,被 bin 与测试代码使用。
5
5
  * [PROTOCOL]: 变更时更新此头部,然后检查 CLAUDE.md
6
6
  */
@@ -8,9 +8,11 @@
8
8
  const store = require('./store');
9
9
  const schemas = require('./schemas');
10
10
  const planner = require('./planner');
11
+ const query = require('./query');
11
12
 
12
13
  module.exports = {
13
14
  ...store,
14
15
  ...schemas,
15
- ...planner
16
+ ...planner,
17
+ ...query
16
18
  };
@@ -13,6 +13,7 @@ const {
13
13
  readJson,
14
14
  runCommand,
15
15
  getTaskManifestPath,
16
+ getHarnessStatePath,
16
17
  getRuntimeTaskDir,
17
18
  getEventsPath,
18
19
  getCheckpointPath
@@ -203,6 +204,18 @@ async function runDispatch({ repoRoot, changeId, parallel = 3, maxRetries, resum
203
204
  const manifestPath = getTaskManifestPath(repoRoot, changeId);
204
205
  const manifest = parseManifest(await readJson(manifestPath));
205
206
 
207
+ // Update harness-state.json to in_progress on first dispatch
208
+ const statePath = getHarnessStatePath(repoRoot, changeId);
209
+ const stateExists = require('fs').existsSync(statePath);
210
+ if (stateExists) {
211
+ const state = await readJson(statePath);
212
+ if (state.status === 'planned' || state.status === 'initialized') {
213
+ state.status = 'in_progress';
214
+ state.updatedAt = nowIso();
215
+ await writeJson(statePath, state);
216
+ }
217
+ }
218
+
206
219
  if (resume) {
207
220
  for (const task of manifest.tasks) {
208
221
  if (task.status === 'running') {
@@ -6,9 +6,53 @@
6
6
  */
7
7
 
8
8
  const { createTaskManifest } = require('../planner');
9
- const { getTaskManifestPath } = require('../store');
9
+ const { getTaskManifestPath, getHarnessStatePath, exists, readText, readJson, writeJson } = require('../store');
10
+ const path = require('path');
11
+ const { execSync } = require('child_process');
10
12
 
11
13
  async function runPlan({ repoRoot, changeId, goal, overwrite }) {
14
+ // v4.3: 检查是否存在 proposal.md(新架构)
15
+ const reqDir = path.join(repoRoot, 'devflow', 'requirements', changeId);
16
+ const proposalPath = path.join(reqDir, 'proposal.md');
17
+ const hasProposal = await exists(proposalPath);
18
+
19
+ if (hasProposal) {
20
+ console.log(`[v4.3] Detected proposal.md, generating design.md and Delta specs...`);
21
+
22
+ // 注意:实际的 design.md 和 Delta specs 生成由 Claude Agent 在 /flow:spec 中完成
23
+ // 这里只是检测并提示,不执行生成逻辑
24
+ // 生成逻辑在 .claude/skills/flow-spec/SKILL.md 的 Execution Steps 中定义
25
+
26
+ const designPath = path.join(reqDir, 'design.md');
27
+ const specsDir = path.join(reqDir, 'specs');
28
+ const scopeReportPath = path.join(reqDir, 'scope-creep-report.md');
29
+
30
+ // 检查必需产物是否存在
31
+ const hasDesign = await exists(designPath);
32
+ const hasSpecs = await exists(specsDir);
33
+ const hasScopeReport = await exists(scopeReportPath);
34
+
35
+ if (!hasDesign) {
36
+ console.warn(`[v4.3] WARNING: design.md not found. Expected at ${designPath}`);
37
+ }
38
+
39
+ if (!hasSpecs) {
40
+ console.warn(`[v4.3] WARNING: specs/ directory not found. Expected at ${specsDir}`);
41
+ }
42
+
43
+ if (!hasScopeReport) {
44
+ console.warn(`[v4.3] WARNING: scope-creep-report.md not found. Run validate-scope.sh`);
45
+ }
46
+
47
+ // 如果存在 scope-creep-report.md,检查是否有阻塞性警告
48
+ if (hasScopeReport) {
49
+ const reportContent = await readText(scopeReportPath);
50
+ if (reportContent.includes('⚠️') && reportContent.includes('Potential scope creep')) {
51
+ console.warn(`[v4.3] WARNING: Scope creep detected. Review ${scopeReportPath}`);
52
+ }
53
+ }
54
+ }
55
+
12
56
  const manifest = await createTaskManifest({
13
57
  repoRoot,
14
58
  changeId,
@@ -16,6 +60,16 @@ async function runPlan({ repoRoot, changeId, goal, overwrite }) {
16
60
  overwrite
17
61
  });
18
62
 
63
+ // Update harness-state.json with plannedAt timestamp
64
+ const statePath = getHarnessStatePath(repoRoot, changeId);
65
+ if (await exists(statePath)) {
66
+ const state = await readJson(statePath);
67
+ state.status = 'planned';
68
+ state.plannedAt = new Date().toISOString();
69
+ state.updatedAt = new Date().toISOString();
70
+ await writeJson(statePath, state);
71
+ }
72
+
19
73
  return {
20
74
  changeId,
21
75
  manifestPath: getTaskManifestPath(repoRoot, changeId),
@@ -10,12 +10,16 @@ const {
10
10
  readJson,
11
11
  writeText,
12
12
  writeJson,
13
+ exists,
13
14
  getReportCardPath,
14
15
  getTaskManifestPath,
15
16
  getReleaseNotePath,
16
17
  getHarnessStatePath
17
18
  } = require('../store');
18
19
  const { parseReportCard, parseManifest } = require('../schemas');
20
+ const path = require('path');
21
+ const { execSync } = require('child_process');
22
+ const fs = require('fs').promises;
19
23
 
20
24
  function formatReleaseNote({ changeId, manifest, report }) {
21
25
  const passedTasks = manifest.tasks.filter((task) => task.status === 'passed');
@@ -59,6 +63,89 @@ async function runRelease({ repoRoot, changeId }) {
59
63
  throw new Error('Release blocked: report-card overall is not pass');
60
64
  }
61
65
 
66
+ // v4.3: 合并 Delta specs 到项目级 specs/
67
+ const reqDir = path.join(repoRoot, 'devflow', 'requirements', changeId);
68
+ const deltaSpecsDir = path.join(reqDir, 'specs');
69
+ const projectSpecsDir = path.join(repoRoot, 'devflow', 'specs');
70
+ const hasDeltaSpecs = await exists(deltaSpecsDir);
71
+
72
+ if (hasDeltaSpecs) {
73
+ console.log(`[v4.3] Merging Delta specs to project-level specs/...`);
74
+
75
+ try {
76
+ // 遍历所有 Delta spec.md 文件
77
+ const modules = await fs.readdir(deltaSpecsDir);
78
+ const mergeResults = [];
79
+
80
+ for (const module of modules) {
81
+ const deltaSpecPath = path.join(deltaSpecsDir, module, 'spec.md');
82
+ const projectSpecPath = path.join(projectSpecsDir, module, 'spec.md');
83
+
84
+ if (!(await exists(deltaSpecPath))) {
85
+ console.warn(`[v4.3] WARNING: Delta spec not found: ${deltaSpecPath}`);
86
+ continue;
87
+ }
88
+
89
+ if (!(await exists(projectSpecPath))) {
90
+ console.warn(`[v4.3] WARNING: Project spec not found: ${projectSpecPath}`);
91
+ console.log(`[v4.3] Creating new project spec for module: ${module}`);
92
+
93
+ // 如果项目级 spec 不存在,创建目录并复制 Delta 作为初始版本
94
+ await fs.mkdir(path.dirname(projectSpecPath), { recursive: true });
95
+ await fs.copyFile(deltaSpecPath, projectSpecPath);
96
+
97
+ mergeResults.push({ module, status: 'created', newVersion: '1.0.0' });
98
+ continue;
99
+ }
100
+
101
+ // 调用 delta-parser.ts merge 命令
102
+ const deltaParserPath = path.join(repoRoot, '.claude', 'scripts', 'delta-parser.ts');
103
+
104
+ try {
105
+ const output = execSync(
106
+ `npx ts-node "${deltaParserPath}" merge "${projectSpecPath}" "${deltaSpecPath}"`,
107
+ { cwd: repoRoot, encoding: 'utf-8' }
108
+ );
109
+
110
+ // 解析输出获取新版本号
111
+ const versionMatch = output.match(/New version: ([\d.]+)/);
112
+ const newVersion = versionMatch ? versionMatch[1] : 'unknown';
113
+
114
+ mergeResults.push({ module, status: 'merged', newVersion });
115
+ console.log(`[v4.3] ✅ Merged ${module}: ${newVersion}`);
116
+ } catch (mergeError) {
117
+ console.error(`[v4.3] ❌ Failed to merge ${module}:`, mergeError.message);
118
+ mergeResults.push({ module, status: 'failed', error: mergeError.message });
119
+ }
120
+ }
121
+
122
+ // 记录合并结果到 RELEASE_NOTE
123
+ const mergeReport = mergeResults
124
+ .map(r => {
125
+ if (r.status === 'merged') {
126
+ return `- ✅ ${r.module}: merged to v${r.newVersion}`;
127
+ } else if (r.status === 'created') {
128
+ return `- 🆕 ${r.module}: created v${r.newVersion}`;
129
+ } else {
130
+ return `- ❌ ${r.module}: ${r.error}`;
131
+ }
132
+ })
133
+ .join('\n');
134
+
135
+ console.log(`[v4.3] Delta merge summary:\n${mergeReport}`);
136
+
137
+ // 将合并结果添加到 release note
138
+ manifest.metadata = manifest.metadata || {};
139
+ manifest.metadata.deltaMergeResults = mergeResults;
140
+
141
+ } catch (error) {
142
+ console.error(`[v4.3] ERROR during Delta merge:`, error);
143
+ throw new Error(`Delta merge failed: ${error.message}`);
144
+ }
145
+ } else {
146
+ console.log(`[v4.3] No Delta specs found, skipping merge.`);
147
+ }
148
+
62
149
  const note = formatReleaseNote({ changeId, manifest, report });
63
150
  const releaseNotePath = getReleaseNotePath(repoRoot, changeId);
64
151
 
@@ -12,6 +12,7 @@ const {
12
12
  writeJson,
13
13
  runCommand,
14
14
  getTaskManifestPath,
15
+ getHarnessStatePath,
15
16
  getReportCardPath
16
17
  } = require('../store');
17
18
  const { parseManifest, parseReportCard } = require('../schemas');
@@ -150,6 +151,19 @@ async function runVerify({ repoRoot, changeId, strict = false, skipReview = fals
150
151
  const outputPath = getReportCardPath(repoRoot, changeId);
151
152
  await writeJson(outputPath, report);
152
153
 
154
+ // Update harness-state.json with verifiedAt timestamp if passed
155
+ if (!hasFailures) {
156
+ const statePath = getHarnessStatePath(repoRoot, changeId);
157
+ const stateExists = require('fs').existsSync(statePath);
158
+ if (stateExists) {
159
+ const state = await readJson(statePath);
160
+ state.status = 'verified';
161
+ state.verifiedAt = nowIso();
162
+ state.updatedAt = nowIso();
163
+ await writeJson(statePath, state);
164
+ }
165
+ }
166
+
153
167
  return {
154
168
  changeId,
155
169
  outputPath,