workflow-loop 0.3.1__tar.gz → 0.3.3__tar.gz

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 (116) hide show
  1. {workflow_loop-0.3.1/src/workflow_loop.egg-info → workflow_loop-0.3.3}/PKG-INFO +12 -13
  2. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/README.md +11 -12
  3. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/pyproject.toml +1 -1
  4. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/__init__.py +2 -2
  5. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/acceptance_records.py +11 -6
  6. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/artifact_validation.py +88 -24
  7. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/bug_record.py +3 -2
  8. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/cli.py +1406 -260
  9. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/acceptance/acceptance.md +7 -5
  10. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/acceptance/acceptance_plan.md +10 -4
  11. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/code_design/code_design.md +18 -26
  12. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/code_design/update_code_design.md +5 -5
  13. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/global/workflow_lifecycle.md +18 -10
  14. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/impl/code_implementation.md +10 -5
  15. workflow_loop-0.3.3/src/workflow_loop/data/Standardized_Repository/impl/impl.md +168 -0
  16. workflow_loop-0.3.3/src/workflow_loop/data/Standardized_Repository/qa/test.md +170 -0
  17. workflow_loop-0.3.3/src/workflow_loop/data/Standardized_Repository/qa/test_code.md +107 -0
  18. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/qa/test_code_implementation.md +10 -10
  19. workflow_loop-0.3.3/src/workflow_loop/data/Standardized_Repository/qa/test_plan.md +185 -0
  20. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/spec/spec.md +1 -1
  21. workflow_loop-0.3.3/src/workflow_loop/data/Standardized_Repository/spike/spike.md +208 -0
  22. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/acceptance/acceptance_plan.md +18 -10
  23. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/acceptance/acceptance_result.md +1 -1
  24. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/code_design/code_design.md +8 -9
  25. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/impl/impl.md +55 -20
  26. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/qa/test.md +6 -3
  27. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/qa/test_plan.md +13 -10
  28. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/reproduce/reproduce.md +2 -0
  29. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/spike/spike.md +27 -10
  30. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/diagnostics.py +1 -0
  31. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/installer.py +1 -1
  32. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/markdown_links.py +21 -5
  33. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/path_composer.py +23 -37
  34. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/project.py +3 -3
  35. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/role_doc.py +8 -28
  36. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/rollback.py +1022 -108
  37. workflow_loop-0.3.3/src/workflow_loop/spike_reuse.py +666 -0
  38. workflow_loop-0.3.3/src/workflow_loop/spike_validation.py +827 -0
  39. workflow_loop-0.3.3/src/workflow_loop/stages/base.py +322 -0
  40. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/stages/stages.py +246 -16
  41. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/state.py +169 -3
  42. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/test_execution.py +15 -7
  43. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/topic.py +19 -10
  44. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/topic_relations.py +29 -2
  45. workflow_loop-0.3.3/src/workflow_loop/traceability.py +945 -0
  46. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/verification.py +1158 -229
  47. {workflow_loop-0.3.1 → workflow_loop-0.3.3/src/workflow_loop.egg-info}/PKG-INFO +12 -13
  48. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop.egg-info/SOURCES.txt +3 -1
  49. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_acceptance_records.py +113 -31
  50. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_bug_validation.py +34 -0
  51. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_commands.py +480 -15
  52. workflow_loop-0.3.3/tests/test_current_workflow_qa.py +819 -0
  53. workflow_loop-0.3.3/tests/test_diagnostics.py +391 -0
  54. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_installer.py +1 -1
  55. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_light_task.py +3 -6
  56. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_path_composer.py +20 -20
  57. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_public_project.py +6 -4
  58. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_release_workflow.py +4 -11
  59. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_rollback.py +477 -11
  60. workflow_loop-0.3.3/tests/test_spike_assets.py +1000 -0
  61. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_spike_validation.py +14 -12
  62. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_stages.py +202 -14
  63. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_verification.py +522 -8
  64. workflow_loop-0.3.1/src/workflow_loop/data/Standardized_Repository/code_design/revise_code_design.md +0 -32
  65. workflow_loop-0.3.1/src/workflow_loop/data/Standardized_Repository/impl/impl.md +0 -166
  66. workflow_loop-0.3.1/src/workflow_loop/data/Standardized_Repository/qa/test.md +0 -174
  67. workflow_loop-0.3.1/src/workflow_loop/data/Standardized_Repository/qa/test_code.md +0 -129
  68. workflow_loop-0.3.1/src/workflow_loop/data/Standardized_Repository/qa/test_plan.md +0 -81
  69. workflow_loop-0.3.1/src/workflow_loop/data/Standardized_Repository/spike/spike.md +0 -236
  70. workflow_loop-0.3.1/src/workflow_loop/spike_validation.py +0 -379
  71. workflow_loop-0.3.1/src/workflow_loop/stages/base.py +0 -164
  72. workflow_loop-0.3.1/src/workflow_loop/traceability.py +0 -565
  73. workflow_loop-0.3.1/tests/test_diagnostics.py +0 -216
  74. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/LICENSE +0 -0
  75. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/setup.cfg +0 -0
  76. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/artifact_paths.py +0 -0
  77. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/code_design/project_design_init.md +0 -0
  78. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/global/document_writing.md +0 -0
  79. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/reproduce/reproduce.md +0 -0
  80. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/code_design/project_design_init_evidence.md +0 -0
  81. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/spec/spec.md +0 -0
  82. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/journal.py +0 -0
  83. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/process_runner.py +0 -0
  84. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/snapshots.py +0 -0
  85. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/stage_materials.py +0 -0
  86. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/stages/__init__.py +0 -0
  87. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/test_entry.py +0 -0
  88. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/test_mapping.py +0 -0
  89. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/test_report.py +0 -0
  90. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop/test_runner.py +0 -0
  91. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop.egg-info/dependency_links.txt +0 -0
  92. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop.egg-info/entry_points.txt +0 -0
  93. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop.egg-info/requires.txt +0 -0
  94. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/src/workflow_loop.egg-info/top_level.txt +0 -0
  95. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_architecture_validation.py +0 -0
  96. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_artifact_paths.py +0 -0
  97. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_bug_record.py +0 -0
  98. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_current_workflow_contracts.py +0 -0
  99. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_maintenance.py +0 -0
  100. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_maintenance_scripts.py +0 -0
  101. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_markdown_links.py +0 -0
  102. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_process_runner.py +0 -0
  103. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_project.py +0 -0
  104. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_project_design_init.py +0 -0
  105. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_release_script.py +0 -0
  106. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_snapshots.py +0 -0
  107. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_stage_materials.py +0 -0
  108. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_state.py +0 -0
  109. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_test_entry.py +0 -0
  110. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_test_execution.py +0 -0
  111. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_test_mapping.py +0 -0
  112. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_test_report.py +0 -0
  113. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_test_runner.py +0 -0
  114. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_topic_relations.py +0 -0
  115. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_traceability.py +0 -0
  116. {workflow_loop-0.3.1 → workflow_loop-0.3.3}/tests/test_workflow_acceptance.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: workflow-loop
3
- Version: 0.3.1
3
+ Version: 0.3.3
4
4
  Summary: 为 AI 驱动的软件开发提供有状态、可验证、可回退的工作流管理。
5
5
  Author: yuzyf
6
6
  License-Expression: MIT
@@ -90,29 +90,29 @@ flowchart TD
90
90
  - 安装时能够访问 GitHub 和 PyPI(Python 公共软件包仓库)。
91
91
  - 执行安装命令前,先进入要由 Workflow Loop 管理的项目根目录。
92
92
 
93
- ## 安装 0.3.1
93
+ ## 安装 0.3.3
94
94
 
95
95
  安装器先进行只读检查并列出项目侧和电脑侧可能发生的全部持久修改。用户确认一次后,安装器才安装或复用全局 `workflow` 命令,并把智能体契约、产物模板和工作规范写入当前项目;用户取消或安装失败时不会留下只完成一部分的安装。
96
96
 
97
97
  ### macOS
98
98
 
99
99
  ```bash
100
- curl -fsSL https://github.com/yuzyf/workflow_loop/releases/download/v0.3.1/install.sh | bash
100
+ curl -fsSL https://github.com/yuzyf/workflow_loop/releases/download/v0.3.3/install.sh | bash
101
101
  ```
102
102
 
103
103
  ### Linux
104
104
 
105
105
  ```bash
106
- curl -fsSL https://github.com/yuzyf/workflow_loop/releases/download/v0.3.1/install.sh | bash
106
+ curl -fsSL https://github.com/yuzyf/workflow_loop/releases/download/v0.3.3/install.sh | bash
107
107
  ```
108
108
 
109
109
  ### 原生 Windows
110
110
 
111
111
  ```powershell
112
- powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://github.com/yuzyf/workflow_loop/releases/download/v0.3.1/install.ps1 | iex"
112
+ powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://github.com/yuzyf/workflow_loop/releases/download/v0.3.3/install.ps1 | iex"
113
113
  ```
114
114
 
115
- 安装命令固定读取 `v0.3.1` 正式发布中的脚本;不会跟随内容可能变化的 `latest`(最新版本)地址。
115
+ 安装命令固定读取 `v0.3.3` 正式发布中的脚本;不会跟随内容可能变化的 `latest`(最新版本)地址。
116
116
 
117
117
  ## 更新与卸载
118
118
 
@@ -120,7 +120,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://github.com/y
120
120
 
121
121
  ```bash
122
122
  workflow update
123
- workflow update --version 0.3.1
123
+ workflow update --version 0.3.3
124
124
  ```
125
125
 
126
126
  更新按需补齐电脑全局命令和当前项目,只直接覆盖项目根 `AGENTS.md`、`.workflow_loop/Template_Repository/`、`.workflow_loop/Standardized_Repository/`,以及 `.workflow_loop/project.json` 中的安装版本字段。更新不创建备份,不回滚已经完成的步骤;当前轮次状态、历史、回退资料、业务代码和正式产物保持不变。失败后重新执行同一命令即可继续补齐。
@@ -223,10 +223,10 @@ uv run python -m build
223
223
 
224
224
  ## 发布正式版本
225
225
 
226
- 项目维护者确认当前仓库内容可以直接发布后,在仓库根目录执行下面的命令,并把 `0.3.1` 替换成要发布的新版本号:
226
+ 项目维护者确认当前仓库内容可以直接发布后,在仓库根目录执行下面的命令,并把 `0.3.3` 替换成要发布的新版本号:
227
227
 
228
228
  ```bash
229
- uv run python scripts/release.py 0.3.1
229
+ uv run python scripts/release.py 0.3.3
230
230
  ```
231
231
 
232
232
  运行这条命令本身就表示维护者接受当前仓库状态并承担跳过本地发布检查的风险。脚本不会再次确认,也不会在本地运行测试、构建或远程版本查询。它依次执行:
@@ -258,8 +258,7 @@ workflow_loop/
258
258
  ├── update.ps1 Windows 旧版本更新脚本
259
259
  ├── uninstall.sh macOS 和 Linux 旧版本卸载脚本
260
260
  ├── uninstall.ps1 Windows 旧版本卸载脚本
261
- ├── CONTEXT.md 产品术语、规则和限制
262
- └── DESIGN.md 实现设计文档
261
+ └── docs/adr/ 已经发生的架构决策及其取代关系
263
262
  ```
264
263
 
265
264
  ## 详细文档
@@ -271,8 +270,8 @@ workflow_loop/
271
270
  - [发布正式版本](spec/功能_发布正式版本.md):人工发布命令、版本更新范围、执行顺序和失败边界。
272
271
  - [处理无需开发任务](spec/功能_处理无需开发任务.md):简单流程适用边界、逐项确认、完成和异常处理规则。
273
272
  - [代码架构设计](spec/代码架构设计.md):功能到代码模块、状态和外部依赖的对应关系。
274
- - [实现设计文档](DESIGN.md):命令、数据模型、工作意图、阶段路径和门禁的实现形态。
275
- - [产品事实与约束](CONTEXT.md):当前有效的术语、约束和设计决策。
273
+ - [原生 Windows PowerShell 决策](docs/adr/0001-support-native-windows-powershell.md):为什么正式支持原生 Windows PowerShell。
274
+ - [首版版本策略决策](docs/adr/0002-fix-product-version-at-0-1-0.md):首版版本号决定及其被后续功能取代的状态。
276
275
  - [需求交付追踪表](需求交付追踪表.md):每轮需求从设计到验收的完整追踪入口。
277
276
 
278
277
  ## 许可证
@@ -71,29 +71,29 @@ flowchart TD
71
71
  - 安装时能够访问 GitHub 和 PyPI(Python 公共软件包仓库)。
72
72
  - 执行安装命令前,先进入要由 Workflow Loop 管理的项目根目录。
73
73
 
74
- ## 安装 0.3.1
74
+ ## 安装 0.3.3
75
75
 
76
76
  安装器先进行只读检查并列出项目侧和电脑侧可能发生的全部持久修改。用户确认一次后,安装器才安装或复用全局 `workflow` 命令,并把智能体契约、产物模板和工作规范写入当前项目;用户取消或安装失败时不会留下只完成一部分的安装。
77
77
 
78
78
  ### macOS
79
79
 
80
80
  ```bash
81
- curl -fsSL https://github.com/yuzyf/workflow_loop/releases/download/v0.3.1/install.sh | bash
81
+ curl -fsSL https://github.com/yuzyf/workflow_loop/releases/download/v0.3.3/install.sh | bash
82
82
  ```
83
83
 
84
84
  ### Linux
85
85
 
86
86
  ```bash
87
- curl -fsSL https://github.com/yuzyf/workflow_loop/releases/download/v0.3.1/install.sh | bash
87
+ curl -fsSL https://github.com/yuzyf/workflow_loop/releases/download/v0.3.3/install.sh | bash
88
88
  ```
89
89
 
90
90
  ### 原生 Windows
91
91
 
92
92
  ```powershell
93
- powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://github.com/yuzyf/workflow_loop/releases/download/v0.3.1/install.ps1 | iex"
93
+ powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://github.com/yuzyf/workflow_loop/releases/download/v0.3.3/install.ps1 | iex"
94
94
  ```
95
95
 
96
- 安装命令固定读取 `v0.3.1` 正式发布中的脚本;不会跟随内容可能变化的 `latest`(最新版本)地址。
96
+ 安装命令固定读取 `v0.3.3` 正式发布中的脚本;不会跟随内容可能变化的 `latest`(最新版本)地址。
97
97
 
98
98
  ## 更新与卸载
99
99
 
@@ -101,7 +101,7 @@ powershell -NoProfile -ExecutionPolicy Bypass -Command "irm https://github.com/y
101
101
 
102
102
  ```bash
103
103
  workflow update
104
- workflow update --version 0.3.1
104
+ workflow update --version 0.3.3
105
105
  ```
106
106
 
107
107
  更新按需补齐电脑全局命令和当前项目,只直接覆盖项目根 `AGENTS.md`、`.workflow_loop/Template_Repository/`、`.workflow_loop/Standardized_Repository/`,以及 `.workflow_loop/project.json` 中的安装版本字段。更新不创建备份,不回滚已经完成的步骤;当前轮次状态、历史、回退资料、业务代码和正式产物保持不变。失败后重新执行同一命令即可继续补齐。
@@ -204,10 +204,10 @@ uv run python -m build
204
204
 
205
205
  ## 发布正式版本
206
206
 
207
- 项目维护者确认当前仓库内容可以直接发布后,在仓库根目录执行下面的命令,并把 `0.3.1` 替换成要发布的新版本号:
207
+ 项目维护者确认当前仓库内容可以直接发布后,在仓库根目录执行下面的命令,并把 `0.3.3` 替换成要发布的新版本号:
208
208
 
209
209
  ```bash
210
- uv run python scripts/release.py 0.3.1
210
+ uv run python scripts/release.py 0.3.3
211
211
  ```
212
212
 
213
213
  运行这条命令本身就表示维护者接受当前仓库状态并承担跳过本地发布检查的风险。脚本不会再次确认,也不会在本地运行测试、构建或远程版本查询。它依次执行:
@@ -239,8 +239,7 @@ workflow_loop/
239
239
  ├── update.ps1 Windows 旧版本更新脚本
240
240
  ├── uninstall.sh macOS 和 Linux 旧版本卸载脚本
241
241
  ├── uninstall.ps1 Windows 旧版本卸载脚本
242
- ├── CONTEXT.md 产品术语、规则和限制
243
- └── DESIGN.md 实现设计文档
242
+ └── docs/adr/ 已经发生的架构决策及其取代关系
244
243
  ```
245
244
 
246
245
  ## 详细文档
@@ -252,8 +251,8 @@ workflow_loop/
252
251
  - [发布正式版本](spec/功能_发布正式版本.md):人工发布命令、版本更新范围、执行顺序和失败边界。
253
252
  - [处理无需开发任务](spec/功能_处理无需开发任务.md):简单流程适用边界、逐项确认、完成和异常处理规则。
254
253
  - [代码架构设计](spec/代码架构设计.md):功能到代码模块、状态和外部依赖的对应关系。
255
- - [实现设计文档](DESIGN.md):命令、数据模型、工作意图、阶段路径和门禁的实现形态。
256
- - [产品事实与约束](CONTEXT.md):当前有效的术语、约束和设计决策。
254
+ - [原生 Windows PowerShell 决策](docs/adr/0001-support-native-windows-powershell.md):为什么正式支持原生 Windows PowerShell。
255
+ - [首版版本策略决策](docs/adr/0002-fix-product-version-at-0-1-0.md):首版版本号决定及其被后续功能取代的状态。
257
256
  - [需求交付追踪表](需求交付追踪表.md):每轮需求从设计到验收的完整追踪入口。
258
257
 
259
258
  ## 许可证
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "workflow-loop"
3
- version = "0.3.1"
3
+ version = "0.3.3"
4
4
  description = "为 AI 驱动的软件开发提供有状态、可验证、可回退的工作流管理。"
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.11"
@@ -1,6 +1,6 @@
1
1
  # 包版本号,用于 pip/uv 安装时版本匹配
2
- __version__ = "0.3.1"
2
+ __version__ = "0.3.3"
3
3
  # 产品身份标识:workflow --version 输出、安装脚本身份核对和安装事务校验共用同一组常量
4
- # 本次发布版本为 0.3.1;后续发布使用尚未被 PyPI 占用的新版本号
4
+ # 本次发布版本为 0.3.3;后续发布使用尚未被 PyPI 占用的新版本号
5
5
  PRODUCT_NAME = "workflow-loop"
6
6
  PRODUCT_IDENTITY = f"{PRODUCT_NAME} {__version__}"
@@ -62,6 +62,13 @@ def automated_test_ids(project_root: str, topic: str, criterion_id: str) -> list
62
62
  ]
63
63
 
64
64
 
65
+ def _execution_stage(
66
+ wf_state: state_mod.WorkflowState,
67
+ ) -> state_mod.StageState | None:
68
+ """读取当前测试验证任务,并兼容尚未迁移的旧测试执行状态。"""
69
+ return wf_state.stages.get("qa") or wf_state.stages.get("test_execution")
70
+
71
+
65
72
  def record_is_current(
66
73
  record: state_mod.AcceptanceCriterionRecord,
67
74
  wf_state: state_mod.WorkflowState,
@@ -78,10 +85,8 @@ def record_is_current(
78
85
  if record.result != "passed" or record.record_id != compute_record_id(record):
79
86
  return False
80
87
  if record.method in ("自动化测试", "自动化测试 + 人工验收") and record.test_ids:
81
- tasks = wf_state.stages.get(
82
- "test_execution",
83
- state_mod.StageState(),
84
- ).test_tasks.get(record.topic, {})
88
+ execution_stage = _execution_stage(wf_state) or state_mod.StageState()
89
+ tasks = execution_stage.test_tasks.get(record.topic, {})
85
90
  current_ids: list[str] = []
86
91
  for test_id in record.test_ids:
87
92
  task = tasks.get(test_id)
@@ -106,9 +111,9 @@ def _automated_items_are_current(
106
111
  test_ids: list[str],
107
112
  ) -> tuple[bool, str, list[str]]:
108
113
  """核对每个测试项当前机器记录有效,并返回精确记录编号列表。"""
109
- stage_state = wf_state.stages.get("test_execution")
114
+ stage_state = _execution_stage(wf_state)
110
115
  if stage_state is None:
111
- return False, "缺少 test_execution(测试执行阶段)状态", []
116
+ return False, "缺少 qa(测试验证)或 test_execution(旧测试执行阶段)状态", []
112
117
  tasks = stage_state.test_tasks.get(topic, {})
113
118
  record_ids: list[str] = []
114
119
  for test_id in test_ids:
@@ -11,6 +11,7 @@ from . import artifact_paths as artifact_paths_mod
11
11
  from . import process_runner as process_runner_mod
12
12
  from . import test_runner as test_runner_mod
13
13
  from . import state as state_mod
14
+ from . import traceability as traceability_mod
14
15
  from .state import load_state
15
16
  from .test_mapping import (
16
17
  automated_topics,
@@ -18,7 +19,6 @@ from .test_mapping import (
18
19
  parse_test_plan_items,
19
20
  )
20
21
  from .topic import topic_file_key, topic_paths
21
- from .traceability import validate_structure as validate_traceability_structure
22
22
  from .topic_relations import relation_signature, read_topic_index
23
23
  from .verification import (
24
24
  compute_code_snapshot_hash,
@@ -86,6 +86,33 @@ def _field(content: str, label: str) -> str | None:
86
86
  return match.group(1).strip() if match else None
87
87
 
88
88
 
89
+ def _missing_fixed_field_reason(
90
+ content: str,
91
+ label: str,
92
+ *,
93
+ next_field_means_misplaced_value: bool = False,
94
+ ) -> str:
95
+ """说明固定字段缺值的真实格式原因,不把换行误说成普通空值。"""
96
+ field_line = re.search(
97
+ rf"^-[ \t]*{re.escape(label)}:[ \t]*(?P<value>[^\r\n]*)$",
98
+ content,
99
+ re.MULTILINE,
100
+ )
101
+ if field_line is None:
102
+ return "缺少具体内容;原因:缺少标签"
103
+ if field_line.group("value").strip():
104
+ return "缺少具体内容"
105
+
106
+ following = content[field_line.end() :].splitlines()
107
+ next_content = next((line.strip() for line in following if line.strip()), "")
108
+ if next_content and (
109
+ next_field_means_misplaced_value
110
+ or not re.match(r"^-[ \t]*[^:]+:", next_content)
111
+ ):
112
+ return "值必须写在标签同一行,下一行内容不会被读取"
113
+ return "标签同一行没有值,缺少具体内容"
114
+
115
+
89
116
  def _argv_text(argv: list[str]) -> str:
90
117
  """把参数数组编码成可读且可精确比对的单行 JSON。"""
91
118
  return json.dumps(argv, ensure_ascii=False, separators=(",", ":"))
@@ -1444,7 +1471,15 @@ def validate_reproduce_documents(
1444
1471
  failures.append(f"{filename} 必须写“根因状态:已确认”")
1445
1472
  topic = _field(content, "验收主题")
1446
1473
  if not _is_safe_topic_name(topic):
1447
- failures.append(f"{filename} 必须写清唯一验收主题")
1474
+ reason = _missing_fixed_field_reason(
1475
+ content,
1476
+ "验收主题",
1477
+ next_field_means_misplaced_value=True,
1478
+ )
1479
+ if topic is None:
1480
+ failures.append(f"{filename}“验收主题”字段:{reason}")
1481
+ else:
1482
+ failures.append(f"{filename} 必须写清唯一验收主题")
1448
1483
  else:
1449
1484
  topics.append(topic or "")
1450
1485
 
@@ -1491,7 +1526,7 @@ def validate_acceptance_plan_documents(
1491
1526
  if not index_ok:
1492
1527
  issues.append(f"{artifact_paths_mod.ACCEPTANCE_INDEX_DOC}:{index_detail}")
1493
1528
 
1494
- traceability_ok, traceability_detail = validate_traceability_structure(
1529
+ traceability_ok, traceability_detail = traceability_mod.validate_structure(
1495
1530
  project_root,
1496
1531
  workflow_id,
1497
1532
  topics,
@@ -1502,19 +1537,21 @@ def validate_acceptance_plan_documents(
1502
1537
 
1503
1538
  traceability_full_path = os.path.join(project_root, TRACEABILITY_PATH)
1504
1539
  traceability_rows: list[list[str]] = []
1540
+ traceability_headers: list[str] | None = None
1505
1541
  if os.path.isfile(traceability_full_path):
1506
1542
  traceability_content = _read_text(project_root, TRACEABILITY_PATH)
1507
1543
  workflow_content = _workflow_section(traceability_content, workflow_id)
1508
1544
  if workflow_content is None:
1509
1545
  issues.append(f"{TRACEABILITY_PATH}:缺少当前工作流章节 {workflow_id}")
1510
1546
  else:
1511
- traceability_rows = [
1512
- row
1513
- for row in _markdown_table_rows(workflow_content)
1514
- if len(row) == 9 and row[0] != "需求来源与设计依据"
1515
- ]
1547
+ for headers, table_rows in _markdown_tables(workflow_content):
1548
+ if headers not in traceability_mod.SUPPORTED_HEADERS:
1549
+ continue
1550
+ traceability_headers = headers
1551
+ traceability_rows = table_rows
1552
+ break
1516
1553
  if not traceability_rows:
1517
- issues.append(f"{TRACEABILITY_PATH}:当前工作流章节没有九列交付链路记录")
1554
+ issues.append(f"{TRACEABILITY_PATH}:当前工作流章节没有受支持的交付链路记录")
1518
1555
  elif traceability_ok:
1519
1556
  issues.append(f"{TRACEABILITY_PATH}:文件不存在")
1520
1557
 
@@ -1526,9 +1563,6 @@ def validate_acceptance_plan_documents(
1526
1563
  "通过标准",
1527
1564
  "不通过标准",
1528
1565
  "产品设计依据",
1529
- # 旧版字段在迁移期继续要求,确保旧校验器和正式文档含义一致。
1530
- "条件与触发",
1531
- "预期结果",
1532
1566
  )
1533
1567
  placeholder_values = {
1534
1568
  "待补充", "待确认", "待定", "todo", "tbd", "正常", "符合预期", "正确处理",
@@ -1574,7 +1608,10 @@ def validate_acceptance_plan_documents(
1574
1608
  for label in required_fields:
1575
1609
  value = _field(criterion_content, label)
1576
1610
  if value is None or not value.strip():
1577
- issues.append(f"{rel_path} {criterion_id}“{label}”字段:缺少具体内容")
1611
+ issues.append(
1612
+ f"{rel_path} {criterion_id}“{label}”字段:"
1613
+ f"{_missing_fixed_field_reason(criterion_content, label)}"
1614
+ )
1578
1615
  continue
1579
1616
  normalized = re.sub(r"[\s`*_.。,,::;;!?!?()()\[\]{}]", "", value or "").lower()
1580
1617
  if normalized in placeholder_values or not _has_real_text(value):
@@ -1596,10 +1633,15 @@ def validate_acceptance_plan_documents(
1596
1633
  all_criteria.append(f"{topic}:{criterion_id}")
1597
1634
  if not traceability_rows:
1598
1635
  continue
1636
+ if traceability_headers is None:
1637
+ continue
1638
+ topic_column = traceability_headers.index("验收主题")
1639
+ criterion_column = traceability_headers.index("验收条件")
1599
1640
  matching_rows = [
1600
1641
  row
1601
1642
  for row in traceability_rows
1602
- if paths["acceptance_plan"] in row[1] and criterion_id in row[2]
1643
+ if paths["acceptance_plan"] in row[topic_column]
1644
+ and criterion_id in row[criterion_column]
1603
1645
  ]
1604
1646
  if len(matching_rows) != 1:
1605
1647
  issues.append(
@@ -1607,13 +1649,34 @@ def validate_acceptance_plan_documents(
1607
1649
  )
1608
1650
  continue
1609
1651
  row = matching_rows[0]
1610
- expected_statuses = ["待制定", "待制定", "待执行", "待执行", "待执行", "待更新"]
1611
- if row[3:] != expected_statuses:
1652
+ expected_statuses = {
1653
+ "测试项": "待制定",
1654
+ "实施计划与任务": "待制定",
1655
+ "实施记录与代码": "待执行",
1656
+ "测试结果": "待执行",
1657
+ "验收结果": "待执行",
1658
+ "更新后的代码设计": "待更新",
1659
+ }
1660
+ actual_statuses = {
1661
+ header: row[traceability_headers.index(header)]
1662
+ for header in expected_statuses
1663
+ }
1664
+ if actual_statuses != expected_statuses:
1612
1665
  issues.append(
1613
- f"{TRACEABILITY_PATH} 主题“{topic}”{criterion_id} 后续六列:"
1614
- f"预期 {expected_statuses},实际 {row[3:]}"
1666
+ f"{TRACEABILITY_PATH} 主题“{topic}”{criterion_id} 后续状态列:"
1667
+ f"预期 {expected_statuses},实际 {actual_statuses}"
1615
1668
  )
1616
1669
 
1670
+ if traceability_headers is not None and "穿刺结论与可复用内容" in traceability_headers:
1671
+ try:
1672
+ traceability_mod.collect_spike_asset_acceptance_links(
1673
+ project_root,
1674
+ workflow_id,
1675
+ topics,
1676
+ )
1677
+ except ValueError as exc:
1678
+ issues.append(f"{TRACEABILITY_PATH} 穿刺结论与可复用内容:{exc}")
1679
+
1617
1680
  if issues:
1618
1681
  return False, "\n".join(
1619
1682
  f"{index}. {issue}" for index, issue in enumerate(dict.fromkeys(issues), start=1)
@@ -1807,7 +1870,7 @@ def validate_downstream_traceability(
1807
1870
  topics: list[str],
1808
1871
  ) -> tuple[bool, str]:
1809
1872
  """后续阶段共用的追踪表门禁,不要求测试计划正文结构。"""
1810
- return validate_traceability_structure(project_root, workflow_id, topics)
1873
+ return traceability_mod.validate_structure(project_root, workflow_id, topics)
1811
1874
 
1812
1875
 
1813
1876
  def validate_test_plan_documents(
@@ -2033,7 +2096,7 @@ def _validate_topic_acceptance_result(
2033
2096
  method = _field(criterion_content, "验收方式")
2034
2097
  if method not in valid_methods or method != methods.get(criterion_id):
2035
2098
  failures.append(f"{rel_path} 的 {criterion_id} 验收方式不合法")
2036
- for label in ("验收条件", "自动化依据", "实际结果", "验收证据", "程序记录"):
2099
+ for label in ("验收条件", "自动化依据", "实际结果", "验收证据", "验收记录编号"):
2037
2100
  if not _has_real_text(_field(criterion_content, label)):
2038
2101
  failures.append(f"{rel_path} 的 {criterion_id} 缺少具体“{label}”")
2039
2102
  if _field(criterion_content, "判定") != "通过":
@@ -2043,8 +2106,8 @@ def _validate_topic_acceptance_result(
2043
2106
  failures.append(f"{rel_path} 的 {criterion_id} 实际结果与程序记录不一致")
2044
2107
  if _field(criterion_content, "验收证据") != record.evidence:
2045
2108
  failures.append(f"{rel_path} 的 {criterion_id} 验收证据与程序记录不一致")
2046
- if _field(criterion_content, "程序记录") != record.record_id:
2047
- failures.append(f"{rel_path} 的 {criterion_id} 程序记录编号不一致")
2109
+ if _field(criterion_content, "验收记录编号") != record.record_id:
2110
+ failures.append(f"{rel_path} 的 {criterion_id} 验收记录编号不一致")
2048
2111
  else:
2049
2112
  failures.append(
2050
2113
  _unchecked(
@@ -2332,9 +2395,10 @@ def validate_test_execution_results(
2332
2395
  state = load_state(project_root)
2333
2396
  if state is None or state.workflow_id != workflow_id:
2334
2397
  return False, "找不到当前工作流的测试执行状态"
2335
- stage_state = state.stages.get("test_execution")
2398
+ # 新流程把任务和机器记录统一保存在 qa;旧轮次仍读取 test_execution
2399
+ stage_state = state.stages.get("qa") or state.stages.get("test_execution")
2336
2400
  if stage_state is None:
2337
- return False, "缺少 test_execution(测试执行阶段)状态,正式结果必须来自真实执行记录"
2401
+ return False, "缺少 qa(测试验证)或旧 test_execution 状态,正式结果必须来自真实执行记录"
2338
2402
  for topic in automated:
2339
2403
  topic_items = [item for item in automated_items if item.topic == topic]
2340
2404
  test_ok, test_detail = _validate_topic_test_execution_result(
@@ -12,8 +12,9 @@ from .topic import topic_paths
12
12
 
13
13
  BUG_DIR = "bug"
14
14
  BUG_INDEX = artifact_paths_mod.BUG_INDEX_DOC
15
- WORKFLOW_RE = re.compile(r"^-\s*工作流编号:\s*(.+?)\s*$", re.MULTILINE)
16
- TOPIC_RE = re.compile(r"^-\s*验收主题:\s*(.+?)\s*$", re.MULTILINE)
15
+ # 固定字段的空白只允许在同一行;``\s*`` 会吞掉换行,导致下一字段被误读。
16
+ WORKFLOW_RE = re.compile(r"^-[ \t]*工作流编号:[ \t]*([^\r\n]+?)[ \t]*$", re.MULTILINE)
17
+ TOPIC_RE = re.compile(r"^-[ \t]*验收主题:[ \t]*([^\r\n]+?)[ \t]*$", re.MULTILINE)
17
18
  RESULT_SECTION_RE = re.compile(
18
19
  r"^##\s+8\.\s*修复与验收结果\s*$\n(.*?)(?=^##\s+|\Z)",
19
20
  re.MULTILINE | re.DOTALL,