@guanlin4924/devflow-pi 0.1.18 → 0.1.20

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 (30) hide show
  1. package/README.md +20 -1
  2. package/package.json +3 -3
  3. package/plugins/devflow-core/extensions/devflow-core.ts +339 -20
  4. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/acceptance_test_runner.py +394 -0
  5. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/acceptance_test_suite.rb +86 -0
  6. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/advance_state.rb +192 -1
  7. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/api_test_matrix.py +829 -0
  8. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/execution_contract.rb +7 -5
  9. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/init_state.rb +11 -1
  10. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/inspect_state.rb +5 -1
  11. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/machine_evidence.rb +39 -3
  12. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/requirement_graph.rb +309 -23
  13. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/tdd_evidence.py +311 -0
  14. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/test_command_policy.py +53 -0
  15. package/plugins/devflow-core/skills/workflow-orchestrator/scripts/test_task_binding_check.py +254 -0
  16. package/plugins/devflow-core/skills/workflow-orchestrator/templates/feature-development.yaml +109 -4
  17. package/plugins/devflow-core/skills/workflow-orchestrator/templates/uat-remediation.yaml +21 -1
  18. package/plugins/devflow-design/skills/workflow-api-contract/SKILL.md +38 -0
  19. package/plugins/devflow-implementation/agents/implementation-worker.md +3 -0
  20. package/plugins/devflow-implementation/skills/workflow-change-plan/SKILL.md +7 -0
  21. package/plugins/devflow-implementation/skills/workflow-change-plan/references/output-template.md +2 -0
  22. package/plugins/devflow-implementation/skills/workflow-execute-phase/SKILL.md +3 -3
  23. package/plugins/devflow-quality/skills/workflow-acceptance-test-design/SKILL.md +63 -0
  24. package/plugins/devflow-quality/skills/workflow-acceptance-test-design/agents/openai.yaml +4 -0
  25. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/SKILL.md +7 -6
  26. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/references/intermediate-format.md +3 -0
  27. package/plugins/devflow-quality/skills/workflow-generate-mainflow-cases/scripts/compile_dsl.py +49 -3
  28. package/plugins/devflow-quality/skills/workflow-run-acceptance-tests/SKILL.md +48 -0
  29. package/plugins/devflow-quality/skills/workflow-run-acceptance-tests/agents/openai.yaml +4 -0
  30. package/plugins/devflow-quality/skills/workflow-verify-work/SKILL.md +9 -3
@@ -32,6 +32,7 @@ governance:
32
32
  api-contract:
33
33
  - requirement-graph-check
34
34
  - contract-coverage-check
35
+ - api-test-schema-check
35
36
  - change-impact-check
36
37
  architecture-feasibility:
37
38
  - requirement-graph-check
@@ -41,13 +42,34 @@ governance:
41
42
  - slice-independence-check
42
43
  - contract-coverage-check
43
44
  - change-impact-check
45
+ acceptance-test-design:
46
+ - requirement-graph-check
47
+ - contract-coverage-check
48
+ - acceptance-coverage-check
49
+ - api-test-matrix-check
50
+ - test-coverage-check
51
+ - test-obligation-check
52
+ - change-impact-check
44
53
  change-plan:
45
54
  - requirement-graph-check
46
55
  - slice-independence-check
47
56
  - contract-coverage-check
57
+ - api-test-matrix-check
58
+ - test-coverage-check
59
+ - test-obligation-check
60
+ - test-task-binding-check
61
+ - change-impact-check
62
+ execute:
63
+ - tdd-evidence-check
64
+ - change-impact-check
65
+ run-acceptance-tests:
66
+ - api-test-matrix-check
67
+ - test-coverage-check
68
+ - acceptance-test-results-check
48
69
  - change-impact-check
49
70
  verify:
50
71
  - acceptance-coverage-check
72
+ - acceptance-test-results-check
51
73
  - change-impact-check
52
74
 
53
75
  artifact_registry:
@@ -250,7 +272,7 @@ checkpoints:
250
272
  - approve
251
273
  - needs_fix
252
274
  skip_policy: never
253
- resume_behavior: "user confirms, then continue with change-plan"
275
+ resume_behavior: "user confirms, then derive the independent acceptance test suite before change-plan"
254
276
  CP-3:
255
277
  name: Change plan confirmation
256
278
  gate_after: change-plan
@@ -263,13 +285,21 @@ checkpoints:
263
285
  - traceability_status
264
286
  - uncovered_requirement_count
265
287
  - orphan_task_count
288
+ - test_case_count
289
+ - test_coverage_status
290
+ - candidate_test_suite_graph_revision
291
+ - candidate_test_suite_fingerprint
266
292
  summary_fields:
267
293
  - task_count
268
294
  - ddl_count
269
295
  - migration_steps
270
296
  - verification_steps
297
+ - test_case_count
298
+ - automated_test_case_count
299
+ - manual_test_case_count
300
+ - blocked_test_case_count
271
301
  - risks
272
- prompt: "确认变更清单中的 DDL、代码任务、上线步骤和验收标准可执行;每项 REQ 都有任务、每项任务都有 REQ 来源,并允许进入代码执行。"
302
+ prompt: "确认变更清单、冻结的 TC 验收测试集和 TDD/专项测试义务均可执行;每项 REQ 都有任务、每项 TC 都有实现责任,并允许进入代码执行。"
273
303
  confirm_options:
274
304
  - approve
275
305
  - needs_fix
@@ -678,25 +708,73 @@ steps:
678
708
  label: Change plan
679
709
  skill: workflow-change-plan
680
710
  depends_on:
681
- - integration-verify
711
+ - acceptance-test-design
682
712
  inputs:
683
713
  - ".planning/features/{feature}/api-contract.md"
684
714
  - ".planning/features/{feature}/integration-report.md"
685
715
  - ".planning/features/{feature}/前端技术方案.md"
686
716
  - ".planning/features/{feature}/后端技术方案.md"
687
717
  - ".planning/features/{feature}/功能点梳理.md"
718
+ - ".planning/features/{feature}/验收测试设计.md"
719
+ - ".planning/requirements/{feature}/tests.json"
688
720
  outputs:
689
721
  - path: ".planning/features/{feature}/变更清单.md"
690
722
  type: change-plan
691
723
  required: true
724
+ - path: ".planning/features/{feature}/test-bindings.json"
725
+ type: test-task-bindings
726
+ required: true
692
727
  meta_output:
693
728
  path: ".planning/features/{feature}/变更清单.meta.json"
694
729
  fields:
695
730
  traceability_status: { type: string, required: true }
696
731
  uncovered_requirement_count: { type: integer, required: true }
697
732
  orphan_task_count: { type: integer, required: true }
733
+ test_case_count: { type: integer, required: true }
734
+ test_coverage_status: { type: string, required: true }
735
+ candidate_test_suite_graph_revision: { type: integer, required: true }
736
+ candidate_test_suite_fingerprint: { type: string, required: true }
698
737
  checkpoint: CP-3
699
738
 
739
+ - id: acceptance-test-design
740
+ order: 59
741
+ label: Acceptance test design
742
+ skill: workflow-acceptance-test-design
743
+ depends_on:
744
+ - integration-verify
745
+ inputs:
746
+ - ".planning/requirements/{feature}/governance.json"
747
+ - ".planning/requirements/{feature}/tests.json"
748
+ - ".planning/features/{feature}/integration-report.md"
749
+ - ".planning/features/{feature}/api-contract.md"
750
+ - ".planning/features/{feature}/UI-SPEC.md"
751
+ - ".planning/features/{feature}/前端技术方案.md"
752
+ - ".planning/features/{feature}/后端技术方案.md"
753
+ - ".planning/toolchain.md"
754
+ outputs:
755
+ - path: ".planning/features/{feature}/验收测试设计.md"
756
+ type: acceptance-test-design
757
+ required: true
758
+ - path: ".planning/requirements/{feature}/tests.json"
759
+ type: acceptance-test-suite
760
+ required: true
761
+ - path: ".planning/requirements/{feature}/api-test-matrix.json"
762
+ type: api-test-matrix
763
+ required: true
764
+ - path: ".planning/features/{feature}/完整API验收测试用例.md"
765
+ type: api-test-cases-view
766
+ required: true
767
+ meta_output:
768
+ path: ".planning/features/{feature}/验收测试设计.meta.json"
769
+ fields:
770
+ test_case_count: { type: integer, required: true }
771
+ automated_test_case_count: { type: integer, required: true }
772
+ manual_test_case_count: { type: integer, required: true }
773
+ blocked_test_case_count: { type: integer, required: true }
774
+ test_coverage_status: { type: string, required: true }
775
+ candidate_test_suite_graph_revision: { type: integer, required: true }
776
+ candidate_test_suite_fingerprint: { type: string, required: true }
777
+
700
778
  - id: phase-structure
701
779
  order: 70
702
780
  label: Phase structure
@@ -705,6 +783,7 @@ steps:
705
783
  - change-plan
706
784
  inputs:
707
785
  - ".planning/features/{feature}/变更清单.md"
786
+ - ".planning/features/{feature}/test-bindings.json"
708
787
  outputs:
709
788
  - path: ".planning/ROADMAP.md"
710
789
  type: roadmap
@@ -788,7 +867,7 @@ steps:
788
867
  - ".planning/features/{feature}/后端技术方案.md"
789
868
  - ".planning/features/{feature}/变更清单.md"
790
869
  - ".planning/features/{feature}/PROGRESS.md"
791
- - ".planning/phases/{phase}/SUMMARY.md"
870
+ - ".planning/requirements/{feature}/tests.json"
792
871
  outputs:
793
872
  - path: ".planning/generated-cases/{feature}/source-map.md"
794
873
  type: mainflow-source-map
@@ -809,6 +888,25 @@ steps:
809
888
  type: mainflow-cases-summary
810
889
  required: true
811
890
 
891
+ - id: run-acceptance-tests
892
+ order: 88
893
+ label: Run frozen acceptance tests
894
+ skill: workflow-run-acceptance-tests
895
+ depends_on:
896
+ - code-review
897
+ inputs:
898
+ - ".planning/requirements/{feature}/tests.json"
899
+ - ".planning/code-index/index.sqlite"
900
+ - ".planning/code-index/relations.jsonl"
901
+ - ".planning/phases/{phase}/REVIEW.md"
902
+ outputs:
903
+ - path: ".planning/features/{feature}/acceptance-test-bindings.json"
904
+ type: acceptance-test-bindings
905
+ required: true
906
+ - path: ".planning/test-runs/{feature}/acceptance-results.json"
907
+ type: acceptance-test-results
908
+ required: true
909
+
812
910
  - id: verify
813
911
  order: 90
814
912
  label: Verify
@@ -816,12 +914,14 @@ steps:
816
914
  depends_on:
817
915
  - code-review
818
916
  - generate-mainflow-cases
917
+ - run-acceptance-tests
819
918
  inputs:
820
919
  - ".planning/features/{feature}/PROGRESS.md"
821
920
  - ".planning/phases/{phase}/SUMMARY.md"
822
921
  - ".planning/phases/{phase}/MAINFLOW-CASES.md"
823
922
  - ".planning/generated-cases/{feature}/validation-report.md"
824
923
  - ".planning/generated-cases/{feature}/case-import-payloads.json"
924
+ - ".planning/test-runs/{feature}/acceptance-results.json"
825
925
  outputs:
826
926
  - path: ".planning/phases/{phase}/01-UAT.md"
827
927
  type: uat-report
@@ -837,6 +937,11 @@ steps:
837
937
  uat_skipped: { type: integer, required: true }
838
938
  gate_passed: { type: integer, required: true }
839
939
  gate_total: { type: integer, required: true }
940
+ acceptance_tc_passed: { type: integer, required: true }
941
+ acceptance_tc_failed: { type: integer, required: true }
942
+ acceptance_tc_blocked: { type: integer, required: true }
943
+ acceptance_suite_graph_revision: { type: integer, required: true }
944
+ acceptance_results_fingerprint: { type: string, required: true }
840
945
  known_issues: { type: array, required: true }
841
946
  checkpoint: CP-4
842
947
 
@@ -40,6 +40,7 @@ state_contract:
40
40
  - diagnose
41
41
  - execute-fix
42
42
  - code-index-refresh
43
+ - run-acceptance-tests
43
44
  - reverify
44
45
  - lesson
45
46
 
@@ -76,6 +77,7 @@ steps:
76
77
  - ".planning/phases/{phase}/01-VERIFICATION.md"
77
78
  - ".planning/phases/{phase}/SUMMARY.md"
78
79
  - ".planning/features/{feature}/PROGRESS.md"
80
+ - ".planning/test-runs/{feature}/acceptance-results.json"
79
81
  - ".planning/artifacts/index.yaml"
80
82
  outputs:
81
83
  - path: ".planning/phases/{phase}/REMEDIATION.md"
@@ -120,10 +122,11 @@ steps:
120
122
  label: Reverify
121
123
  skill: workflow-verify-work
122
124
  depends_on:
123
- - code-index-refresh
125
+ - run-acceptance-tests
124
126
  inputs:
125
127
  - ".planning/phases/{phase}/REMEDIATION-SUMMARY.md"
126
128
  - ".planning/features/{feature}/PROGRESS.md"
129
+ - ".planning/test-runs/{feature}/acceptance-results.json"
127
130
  outputs:
128
131
  - path: ".planning/phases/{phase}/01-UAT.md"
129
132
  type: uat-report
@@ -133,6 +136,23 @@ steps:
133
136
  required: true
134
137
  checkpoint: CP-4
135
138
 
139
+ - id: run-acceptance-tests
140
+ order: 28
141
+ label: Re-run frozen acceptance tests
142
+ skill: workflow-run-acceptance-tests
143
+ depends_on:
144
+ - code-index-refresh
145
+ inputs:
146
+ - ".planning/requirements/{feature}/tests.json"
147
+ - ".planning/features/{feature}/acceptance-test-bindings.json"
148
+ - ".planning/test-runs/{feature}/acceptance-results.json"
149
+ - ".planning/code-index/index.sqlite"
150
+ - ".planning/code-index/AUDIT.md"
151
+ outputs:
152
+ - path: ".planning/test-runs/{feature}/acceptance-results.json"
153
+ type: acceptance-test-results
154
+ required: true
155
+
136
156
  - id: lesson
137
157
  order: 40
138
158
  label: Record lesson if needed
@@ -47,6 +47,44 @@ The meta file must also set `traceability_status: "passed"` only after every API
47
47
  5. **切片对齐** — 若 baseline 包含 `SL-*`,先读取 `skill://workflow-pipeline/references/slice-safety-guide.md`,只为当前执行切片定义 API。后置切片接口不得提前进入契约。
48
48
  6. **既有接口优先查事实索引** — 当 `.planning/code-index/` 存在时,先用 Symbol/Relation 定位候选接口、调用方和处理器,再读取源码证据;缺失或过期时再按 navigation 和 `rg` 兜底。
49
49
 
50
+ ## 可测试 API 契约(强制)
51
+
52
+ 每个 `api` 图谱节点除现有 `request/response/errors` 摘要外,必须提交 `test_schema`。它是字段边界、pairwise 组合和错误码用例的机器事实源;只有 Markdown 中的“string (max 100)”不够,不能作为可冻结测试的输入。
53
+
54
+ 在本步骤通过 `devflow_requirement_graph(action="propose")` 提交 `kind: "api"` 候选,并把 `requirement_refs`、`behavior_ref` 与本文档中的契约摘要、`test_schema` 一并写入;按项目图谱约定连接相关 REQ/BEH。**不要**调用 `confirm`:用户批准 `CP-API` 时,Core 会原子地确认完整 API 候选。没有图谱 API 节点的 no-op 契约仍正常通过。
55
+
56
+ `test_schema` 使用受控键名(避免与图谱保留键冲突):
57
+
58
+ ```json
59
+ {
60
+ "schema_version": 1,
61
+ "method": "POST",
62
+ "path": "/api/v1/orders",
63
+ "preconditions": ["专用测试租户和测试身份已准备"],
64
+ "valid_request": { "body": { "email": "buyer@example.com", "quantity": 1 } },
65
+ "success": { "http_status": 201 },
66
+ "fields": [{
67
+ "field_key": "email", "location": "body", "pointer": "/email",
68
+ "type": "string", "required": true, "nullable": false,
69
+ "constraints": { "min_length": 5, "max_length": 64, "format": "email" },
70
+ "coverage": {
71
+ "pattern": { "state": "not_applicable", "reason": "email format 是唯一语法约束" },
72
+ "enum": { "state": "not_applicable", "reason": "自由输入,不是枚举" }
73
+ }
74
+ }],
75
+ "errors": [{
76
+ "error_key": "invalid-email", "code": "INVALID_EMAIL", "http_status": 422,
77
+ "covers": ["email:missing", "email:null", "email:wrong_type", "email:below_min_length", "email:above_max_length", "email:invalid_format"]
78
+ }]
79
+ }
80
+ ```
81
+
82
+ - 每个字段必须声明其类型相关边界;确实没有的约束只能写 `coverage.<边界>.state: not_applicable` 并给出理由,不能静默跳过。
83
+ - `valid_request` 是完整有效基准请求,所有字段通过 `location + pointer` 指向其中的值;`fields` 用 `field_key`,错误目录用 `error_key`,HTTP 状态统一用 `http_status`。
84
+ - 有最小/最大约束时,生成器会把恰好最小、恰好最大纳入有效等价类和 pairwise,再生成刚越界反例;字段同时有长度/范围与 `format`、`pattern` 或 `enum` 时,必须在 `examples` 提供对应的 `at_*`、`below_*` / `above_*` 隔离值。生成器不会用一个同时破坏格式和长度的假数据去冒充“只验证最大长度”。
85
+ - `errors[].covers` 把每个负向分区精确映射到一个错误码;非字段错误使用 `scenario: { preconditions, request_mutations }`。每个错误目录项二选一,不能既没有覆盖分区也没有可重放场景。
86
+ - 设计时不自行编造约束、最大长度或错误码。缺少这些业务事实时必须回流为待决问题,后续验收测试不会冻结。
87
+
50
88
  ## 产出模板
51
89
 
52
90
  ```
@@ -9,6 +9,7 @@ tools:
9
9
  - bash
10
10
  - edit
11
11
  - write
12
+ - devflow_tdd_evidence
12
13
  model: "@task"
13
14
  thinkingLevel: medium
14
15
  autoloadSkills:
@@ -19,4 +20,6 @@ Implement only the assigned plan slice. Do not re-plan the feature, compare alte
19
20
 
20
21
  If the execution contract is missing, ambiguous, or contradicted by the code, stop before editing and return `STATUS: escalate` with the conflicting evidence. Run the smallest focused validation once; report failures rather than repeatedly trying speculative fixes.
21
22
 
23
+ For a task whose frozen `test-bindings.json` marks `test_mode: tdd_required`, use the Core tool in this exact order: `devflow_tdd_evidence(action="prepare")` before changing declared production paths; create/change the test and record `red`; implement; record `green`; then record `regression`. Do not mark the task done if any phase is missing or fails. The tool may write only its own Core-owned TDD evidence record; this exception does not authorize edits to any other Devflow control-plane file.
24
+
22
25
  Return `STATUS`, changed files, validation evidence, and one escalation/blocker if needed. Never edit `.planning/STATE.md`, `.planning/artifacts/index.yaml`, workflow definitions, or checkpoint decisions; the parent session owns those through Devflow tools.
@@ -59,6 +59,7 @@ description: "Use after workflow-integration-verify has passed or produced an ap
59
59
  6. 读取 baseline.md 的审查结论和风险标记
60
60
  7. 若输入包含 `SL-*` 切片计划,读取 `skill://workflow-pipeline/references/slice-safety-guide.md`,只生成当前执行切片的任务。后置切片只能写入风险/后续范围,不得生成实现任务。
61
61
  8. 读取 `.planning/requirements/{feature}/traceability.json`;它是任务覆盖判断的唯一 REQ 清单,不能仅凭技术方案标题推断覆盖。
62
+ 9. 读取候选态的 `.planning/requirements/{feature}/tests.json`。它定义本次验收意图;不得从实现摘要或预期代码结构补造测试范围。该测试意图会与变更清单一起在 CP-3 冻结。
62
63
 
63
64
  ### 第二阶段:扫描项目上下文
64
65
 
@@ -71,6 +72,8 @@ description: "Use after workflow-integration-verify has passed or produced an ap
71
72
 
72
73
  输出到 `.planning/features/{feature}/变更清单.md`。
73
74
 
75
+ 同时输出 `.planning/features/{feature}/test-bindings.json`。这是受控的任务—验收用例绑定。生成时它必须使用 `schema_version: 2` 与 `candidate_test_suite: { graph_revision, fingerprint }`,并通过 `test_task_binding_check.py --feature {feature} --stage candidate --json`。每个代码任务必须关联一个或多个候选 `TC-*`,并指定 `tdd_required`、`contract_first`、`integration_only` 或 `manual_justified` 测试模式;非 TDD 模式必须说明原因。`tdd_required` 还必须给出同一测试目标的 RED/GREEN 命令、RED 的预期失败标记、回归命令和生产代码路径。CP-3 会在同一次确认中核验候选绑定、冻结 TC 并写入 Core attestation;之后执行阶段以 `--stage frozen` 校验。所有 Core 实际执行的命令必须是无 shell 的 argv,且 runner 已在初始化生成的 `.planning/toolchain.md` 中被发现;不能用 `python -c`、`node -e` 或任意脚本解释器绕过。
76
+
74
77
  同时输出 `.planning/features/{feature}/变更清单.meta.json`。只有 `traceability_check.py --stage change-plan` 成功时才允许写入 `traceability_status: "passed"`;`uncovered_requirement_count` 和 `orphan_task_count` 必须为 0。
75
78
 
76
79
  ## 输出结构
@@ -118,6 +121,10 @@ description: "Use after workflow-integration-verify has passed or produced an ap
118
121
  - **相关经验教训**:lesson ID 或"无"
119
122
  - **执行前门禁**:编码前必须确认的事项(无则写"无")
120
123
  - **测试策略**:单元/集成/人工测试策略简述
124
+ - **测试模式**:`tdd_required` / `contract_first` / `integration_only` / `manual_justified`
125
+ - **保障的验收用例**:冻结的 `TC-*`;不得凭实现结果新增或删除
126
+ - **实现测试**:`UT-*` / `IT-*` 或测试文件与精确命令
127
+ - **TDD 证据**:当模式为 `tdd_required`,填写 RED/GREEN/REGRESSION 命令、RED 预期失败标记和生产代码路径;其他模式填写不能 TDD 的理由
121
128
  - **审查要求**:变更清单一致性、规范审查、兼容性检查
122
129
  - **变更内容**:(具体描述改什么,精确到类名/方法名/字段名,禁止 TBD/TODO)
123
130
  - **完成标准**:(每条必须使用 `- [ ]` checkbox 格式,可被 code_review 门禁自动验证)
@@ -18,6 +18,8 @@
18
18
  >
19
19
  > 完成标准在执行阶段由 `code_review` 门禁自动逐条验证。每条标准必须描述**可通过静态代码分析验证的具体条件**(精确到类名/方法名/字段名/返回值/文件行),不得使用"确保功能正确"、"用户体验良好"等模糊描述。标准模糊的条目将被标记为 `⚠️ UNVERIFIABLE`,无法通过自动化验证。
20
20
 
21
+ > **验收测试绑定:** 除 Markdown 外,必须生成 schema v2 的 `test-bindings.json`。它将每个任务绑定到候选 `TC-*`,并以 `candidate_test_suite: { graph_revision, fingerprint }` 固定候选测试意图;它必须通过 `test_task_binding_check.py --stage candidate`。CP-3 在同一次用户确认中验证该绑定、冻结 TC,并写入 Core-owned `test-suite-freeze.json`;之后才可按 `--stage frozen` 进入执行。所有 `tdd_required` 任务必须声明相同测试目标的 RED/GREEN 命令、RED 失败标记、回归命令与生产代码路径。
22
+
21
23
  ---
22
24
 
23
25
  ```markdown
@@ -128,7 +128,7 @@ The worker must not treat existing code as more authoritative than explicit proj
128
128
  When the change list includes task-level `适用规范`, `相关经验教训`, `执行前门禁`, `测试策略`, or `审查要求`, those fields are mandatory execution inputs.
129
129
  When the change list includes `需求来源` or `CR-*` decision references, the worker must keep implementation inside those confirmed decisions and mention any deviation before editing.
130
130
 
131
- If a code task lacks a task-level test strategy, planned command, execution command placeholder, or skip-automation classification, the worker must stop before editing and report the task as blocked for change-list backfill. Do not invent a silent testing scope during implementation.
131
+ If a code task lacks a task-level test strategy, planned command, execution command placeholder, skip-automation classification, or frozen `TC-*` binding, the worker must stop before editing and report the task as blocked for change-list backfill. Do not invent a silent testing scope during implementation.
132
132
  </rule_activation_gate>
133
133
 
134
134
  <execution_discipline>
@@ -137,7 +137,7 @@ Preserve these generalized workflow rules from the project rule package when app
137
137
  1. Do not skip required workflow steps or verification because a change looks small unless the user explicitly approved simplification.
138
138
  2. Before editing, activate the relevant rules, lessons, toolchain, tests, generated artifacts, and compatibility gates for the task.
139
139
  3. Execute in dependency order derived from the change list and project architecture; do not hardcode outbound-call's Go layer order for non-Go projects.
140
- 4. Tests can be written before code (TDD) or incrementally within the same task, but task-level tests must not be deferred to a final standalone test wave.
140
+ 4. For every `tdd_required` task, call `devflow_tdd_evidence(action="prepare")` before changing its declared production paths; then record `red`, implement, record `green`, and record `regression`. A missing or failed stage means the task is blocked, not complete. Other modes must retain their declared non-TDD reason and still execute their implementation tests.
141
141
  5. Before marking a code task complete, add/update the required task-level tests unless the change list contains an acceptable or reviewed skip classification.
142
142
  6. Refine planning-level test commands into execution-level commands that are precise enough to rerun the changed tests, then run them and record the result.
143
143
  7. **Verification Iron Law** — Before marking ANY task complete, pass the verification gate:
@@ -256,7 +256,7 @@ Preserve these generalized workflow rules from the project rule package when app
256
256
  - 所需文件路径和变更类型(新增/修改/删除)
257
257
  - 参考实现位置
258
258
  - 适用规范编号
259
- - 测试策略、规划级命令、执行级命令占位或跳过自动化测试分级
259
+ - 测试策略、冻结的 `TC-*` 绑定、测试模式、规划级命令、执行级命令占位或跳过自动化测试分级
260
260
  - 完成验证命令和执行结果记录要求
261
261
 
262
262
  执行者仅凭任务描述 + 当前代码文件即可完成,无需回看整个变更清单或技术方案。
@@ -0,0 +1,63 @@
1
+ ---
2
+ name: workflow-acceptance-test-design
3
+ description: "Use after integration verification and before change planning to derive a frozen, requirement-baseline-driven acceptance test suite (TC-*) for API, page, permission, boundary, resilience, migration, and performance verification."
4
+ ---
5
+
6
+ # 验收测试设计
7
+
8
+ 在代码执行前,基于已确认的需求、契约和架构约束提出独立的 `TC-*` 验收测试候选。测试意图必须独立于实现:禁止读取 `SUMMARY.md`、实现源码、git diff 或 agent 交付自述来决定测试范围。
9
+
10
+ ## 输入
11
+
12
+ 按顺序读取:
13
+
14
+ 1. `devflow_requirement_graph(action="inspect")` 的已确认 `REQ/BR/BC/AC` 节点与当前 revision;
15
+ 2. `.planning/features/{feature}/integration-report.md`、API 契约、UI 方案、前后端技术方案;
16
+ 3. 当前图谱中的 `RISK/WSH/WLC/DECISION` 节点;
17
+ 4. `.planning/toolchain.md`、`.planning/execution-contract.md` 和项目测试能力。
18
+
19
+ 若需求、契约或架构事实不足以写出可观察 oracle,记录缺口并回流到上游;不得用实现猜测补全。
20
+
21
+ ## 生成规则
22
+
23
+ 先调用 `devflow_api_test_matrix(action="compile", feature="...")`(无 API 时也会写 no-op 测试资产),检查 `.planning/features/{feature}/完整API验收测试用例.md` 中的契约缺口;存在 `API-*` 时通过后调用 `devflow_api_test_matrix(action="import", feature="...")`。Core 会一次性生成并导入全部 API `TC-*`:
24
+
25
+ - 每个字段的缺失、`null`、错误类型、最小/最大(长度、数值、数组项)、超长、非法格式/模式、非法枚举;
26
+ - 仅由有效等价类构成的 pairwise 组合(负向值一项一测,避免错误码歧义);
27
+ - 错误目录中的每一个异常码场景。
28
+
29
+ 不得手写、删减或改写这些带 `generated_case_key` 的 API TC。缺少字段约束、错误码映射或可重放错误场景时,编译器会留下缺口并阻止本步骤/CP-3;不能以“接口已测主流程”替代。页面、权限、迁移、韧性和性能 TC 仍按下列规则单独提出。
30
+
31
+ 每个候选通过 `devflow_requirement_graph(action="propose")` 写入 `test_case`,并用 `verified_by` edge 从所有引用的 `REQ/BR/BC/AC` 指向 TC。候选必须包含:
32
+
33
+ ```json
34
+ {
35
+ "acceptance_refs": ["AC-0001"],
36
+ "requirement_refs": ["REQ-0001", "BR-0001"],
37
+ "test_type": "api|page|permission|boundary|resilience|migration|performance",
38
+ "target": "外部可观察的 API、页面或运行边界",
39
+ "preconditions": ["身份、数据和环境前置条件"],
40
+ "steps": ["测试操作"],
41
+ "oracle": "可观察的预期结果",
42
+ "automation_mode": "automated|manual|blocked"
43
+ }
44
+ ```
45
+
46
+ - `manual` 额外写 `manual_reason` 和 `owner`;`blocked` 额外写 `blocked_by` 和 `owner`。
47
+ - 当 TC 承接结构性专项义务时,额外带对应引用并建立同样的 `verified_by` edge:`api_refs`(API→`api`)、`workload_refs`(WSH/WLC→`performance` 或 `migration`)、`risk_refs`(架构 RISK→`resilience`)。跨数据域的 REQ 必须有 `permission` TC,BC 必须有 `boundary` TC。
48
+ - 页面/API 的具体 selector、endpoint URL、测试数据和 runner 命令属于后续执行绑定,不得改变本步骤的步骤或 oracle。
49
+ - 高风险边界、权限、迁移、外部依赖和工作负载事实必须产生相应 TC;`test-obligation-check` 是机器判定,不接受“无架构影响”的模型自述。环境未准备好只能标记 blocked,不得省略。
50
+
51
+ ## 输出
52
+
53
+ 写 `.planning/features/{feature}/验收测试设计.md` 作为派生视图,包含:TC 覆盖矩阵、自动/人工/阻塞数量、每项专项义务的 TC/环境前提和当前图谱 revision。写对应 `.meta.json`,其 revision/fingerprint 必须来自 Core 的 `tests.json` 视图。
54
+
55
+ API 完整测试资产由 Core 额外写入:
56
+
57
+ - `.planning/requirements/{feature}/api-test-matrix.json`:机器可读的请求、预期和派生义务;
58
+ - `.planning/features/{feature}/完整API验收测试用例.md`:可审查的人类视图;
59
+ - `.planning/features/{feature}/api-acceptance-bindings.template.json`:导入后的 TC 与 HTTP 执行绑定模板。
60
+
61
+ 运行 `devflow_requirement_graph(action="validate")` 和 machine evidence。通过后交给 `workflow-change-plan` 绑定实现任务。
62
+
63
+ TC 会在 CP-3 用户批准时由 Core 一次性冻结;Skill 只能用 `devflow_acceptance_tests(feature="...")` 查看状态,不得自行确认 TC,也不得在冻结后修改其意图。
@@ -0,0 +1,4 @@
1
+ interface:
2
+ display_name: "Acceptance Test Design"
3
+ short_description: "Design independent requirement-driven TC cases before coding"
4
+ default_prompt: "Use $workflow-acceptance-test-design to derive frozen acceptance tests from the confirmed baseline."
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: workflow-generate-mainflow-cases
3
- description: "Use after workflow-execute-phase when code is implemented and the OMP development agent must generate importable positive API/UI mainflow automation cases from planning artifacts, project specifications, navigation files, and actual code."
3
+ description: "Use after workflow-execute-phase to bind frozen API/page TC acceptance intent to importable positive mainflow automation cases."
4
4
  ---
5
5
 
6
6
  # 主流程自动化用例生成
@@ -13,6 +13,8 @@ description: "Use after workflow-execute-phase when code is implemented and the
13
13
  - MUST derive code roots from `.planning/navigation` and `.context/spec`.
14
14
  - MUST use `.planning/code-index/` for fine-grained entrypoint, route, component, API, call, import, and data-flow evidence when present.
15
15
  - MUST only generate `api-mainflow` and `ui-mainflow` cases.
16
+ - MUST read the frozen `.planning/requirements/{feature}/tests.json` before selecting case scope. Only frozen positive `TC-*` with `test_type: api` or `page` may produce mainflow cases. Core-generated API TC carrying `execution.expect.error_code` is a negative/exception case and is excluded here; it is executed by `run-acceptance-tests`.
17
+ - MUST NOT read `SUMMARY.md`, delivery self-reports, or diffs to decide what to test. Current code is allowed only to bind an already frozen TC to an entrypoint, selector, request, or runner adapter.
16
18
  - MUST run `scripts/compile_dsl.py` before final output.
17
19
  - MUST run `scripts/validate_case_payloads.py` before reporting success.
18
20
  - MUST block if codebase discovery fails.
@@ -60,7 +62,7 @@ Read these references before generating cases:
60
62
 
61
63
  Stop if it exits non-zero.
62
64
 
63
- 3. Read planning inputs when present:
65
+ 3. Read the frozen TC suite first. Record the source `TC-*` for every selected mainflow case; a missing or stale source TC is a blocker. Then read planning inputs when present:
64
66
  - `.planning/requirements/baseline.md`
65
67
  - `.planning/features/{feature}/功能点梳理.md`
66
68
  - `.planning/features/{feature}/UI-SPEC.md`
@@ -68,7 +70,6 @@ Read these references before generating cases:
68
70
  - `.planning/features/{feature}/后端技术方案.md`
69
71
  - `.planning/features/{feature}/变更清单.md`
70
72
  - `.planning/features/{feature}/PROGRESS.md`
71
- - `.planning/phases/{phase}/SUMMARY.md`
72
73
 
73
74
  4. Read discovery output, then read each discovered codebase's navigation and spec files. Select scan targets by codebase type:
74
75
  - Backend: router/controller, service/usecase, schema/dto/request/response, model/entity, API entry.
@@ -79,8 +80,8 @@ Read these references before generating cases:
79
80
  - Frontend/UI: route/page/component symbols, `routes_to`, `imports`, `calls` into API clients, store/hook relations.
80
81
  Read `evidence_path:evidence_line` before using an edge in case selection.
81
82
  6. Inspect actual code paths that are both relevant to `{feature}` and reachable from navigation/spec/code-index. Do not scan excluded historical modules.
82
- 7. Write `source-map.md` with planning evidence, code-index evidence when used, source evidence, and selected source files for each candidate case.
83
- 8. Write `mainflow-analysis.md` with included API/UI positive mainflows, excluded non-mainflows, assumptions, and traceability to source evidence.
83
+ 7. Write `source-map.md` with the frozen TC ID, planning evidence, code-index evidence when used, source evidence, and selected source files for each candidate case.
84
+ 8. Write `mainflow-analysis.md` with included API/UI positive mainflows, excluded non-mainflows, assumptions, and traceability to frozen TC plus source evidence.
84
85
  9. Write `case-descriptions.json` using the simplified format in `references/intermediate-format.md`. **Do NOT write raw DSL** — use locator strings like `"text:编辑"`, `"placeholder:请输入名称"`, `"css:.el-dialog__footer .el-button--primary"`.
85
86
  10. Compile descriptions into strict DSL:
86
87
 
@@ -111,7 +112,7 @@ Read these references before generating cases:
111
112
 
112
113
  AI is responsible for semantic judgment only:
113
114
 
114
- - Determine feature scope from `.planning`.
115
+ - Determine API/page test scope from frozen `TC-*`, not from implementation delivery prose.
115
116
  - Confirm implemented behavior from actual code.
116
117
  - Identify positive API mainflows.
117
118
  - Identify positive UI mainflows.
@@ -30,6 +30,7 @@ AI 产出的简化用例描述格式。locator 用 `"type:value"` 字符串,
30
30
 
31
31
  ```json
32
32
  {
33
+ "tc_id": "TC-0001",
33
34
  "project_id": 6,
34
35
  "name": "Case name",
35
36
  "description": "Positive mainflow purpose",
@@ -40,6 +41,8 @@ AI 产出的简化用例描述格式。locator 用 `"type:value"` 字符串,
40
41
  }
41
42
  ```
42
43
 
44
+ 当当前功能已经存在冻结 `tests.json` 时,`tc_id` 必填,且必须引用一个正向 `test_type` 为 `api` 或 `page` 的冻结 TC。带 `generated_case_key` 且 `execution.expect.error_code` 的 API TC 是异常/边界用例,不得伪装成主流程;源码只能补充所选 TC 的入口和选择器。
45
+
43
46
  ## Auth (optional)
44
47
 
45
48
  Only include if the case needs API login + token injection.
@@ -531,14 +531,25 @@ def compile_case(case_desc: dict[str, Any]) -> dict[str, Any]:
531
531
  }
532
532
 
533
533
 
534
- def compile_all(payload: dict[str, Any]) -> dict[str, Any]:
534
+ def compile_all(payload: dict[str, Any], frozen_mainflow_tc_ids: set[str] | None = None) -> dict[str, Any]:
535
535
  """Compile all cases in the payload."""
536
536
  metadata = dict(payload.get("metadata") or {})
537
- cases = [compile_case(c) for c in payload.get("cases", [])]
537
+ descriptions = list(payload.get("cases", []))
538
+ tc_ids: list[str] = []
539
+ if frozen_mainflow_tc_ids is not None:
540
+ for index, description in enumerate(descriptions):
541
+ tc_id = description.get("tc_id") if isinstance(description, dict) else None
542
+ if not isinstance(tc_id, str) or tc_id not in frozen_mainflow_tc_ids:
543
+ raise ValueError(f"cases[{index}].tc_id must reference a frozen api/page TC that is positive")
544
+ tc_ids.append(tc_id)
545
+ if len(tc_ids) != len(set(tc_ids)):
546
+ raise ValueError("each frozen positive api/page TC may generate at most one mainflow case")
547
+ cases = [compile_case(c) for c in descriptions]
538
548
 
539
549
  return {
540
550
  "metadata": {
541
551
  **metadata,
552
+ **({"frozen_tc_ids": tc_ids} if frozen_mainflow_tc_ids is not None else {}),
542
553
  "compiled_at": datetime.now(timezone.utc).isoformat(),
543
554
  "compiled_by": "compile_dsl.py (hard-constraint layer)",
544
555
  },
@@ -546,6 +557,41 @@ def compile_all(payload: dict[str, Any]) -> dict[str, Any]:
546
557
  }
547
558
 
548
559
 
560
+ def frozen_mainflow_tc_ids_from_cwd(cwd: Path) -> set[str] | None:
561
+ """Return the frozen API/page suite for new workflows, else preserve legacy compilation."""
562
+ state_path = cwd / ".planning" / "STATE.md"
563
+ if not state_path.is_file():
564
+ return None
565
+ match = re.search(r"^current_feature:\s*['\"]?([^'\"\n]+)", state_path.read_text(encoding="utf-8"), re.MULTILINE)
566
+ if not match:
567
+ return None
568
+ suite_path = cwd / ".planning" / "requirements" / match.group(1).strip() / "tests.json"
569
+ if not suite_path.is_file():
570
+ return None
571
+ suite = json.loads(suite_path.read_text(encoding="utf-8"))
572
+ if suite.get("frozen") is not True:
573
+ raise ValueError("current TC suite exists but is not frozen and fresh")
574
+ eligible = {
575
+ node.get("id")
576
+ for node in suite.get("nodes", [])
577
+ if isinstance(node, dict)
578
+ and node.get("kind") == "test_case"
579
+ and node.get("status") == "confirmed"
580
+ and isinstance(node.get("data"), dict)
581
+ and node["data"].get("test_type") in {"api", "page"}
582
+ # A generated API TC with an error-code oracle is a negative/exception
583
+ # test. It belongs to run-acceptance-tests, never to the positive
584
+ # mainflow importer even though its broad test_type is "api".
585
+ and not (
586
+ isinstance(node["data"].get("generated_case_key"), str)
587
+ and isinstance(node["data"].get("execution"), dict)
588
+ and isinstance(node["data"]["execution"].get("expect"), dict)
589
+ and "error_code" in node["data"]["execution"]["expect"]
590
+ )
591
+ }
592
+ return {value for value in eligible if isinstance(value, str)}
593
+
594
+
549
595
  # ---------------------------------------------------------------------------
550
596
  # CLI
551
597
  # ---------------------------------------------------------------------------
@@ -568,7 +614,7 @@ def main() -> int:
568
614
  raw = {"metadata": {}, "cases": raw}
569
615
 
570
616
  try:
571
- result = compile_all(raw)
617
+ result = compile_all(raw, frozen_mainflow_tc_ids_from_cwd(Path.cwd()))
572
618
  except ValueError as exc:
573
619
  print(f"COMPILE ERROR: {exc}", file=__import__("sys").stderr)
574
620
  return 1