workflow-loop 0.3.2__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 (107) hide show
  1. {workflow_loop-0.3.2/src/workflow_loop.egg-info → workflow_loop-0.3.3}/PKG-INFO +9 -9
  2. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/README.md +8 -8
  3. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/pyproject.toml +1 -1
  4. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/__init__.py +2 -2
  5. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/artifact_validation.py +40 -2
  6. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/bug_record.py +3 -2
  7. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/cli.py +366 -68
  8. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/acceptance/acceptance_plan.md +8 -0
  9. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/impl/code_implementation.md +3 -0
  10. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/impl/impl.md +9 -1
  11. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/acceptance/acceptance_plan.md +7 -0
  12. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/impl/impl.md +8 -0
  13. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/qa/test.md +2 -0
  14. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/qa/test_plan.md +2 -0
  15. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/reproduce/reproduce.md +2 -0
  16. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/rollback.py +733 -119
  17. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/stages/stages.py +120 -11
  18. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/topic.py +19 -10
  19. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/verification.py +183 -27
  20. {workflow_loop-0.3.2 → workflow_loop-0.3.3/src/workflow_loop.egg-info}/PKG-INFO +9 -9
  21. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_bug_validation.py +34 -0
  22. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_commands.py +367 -2
  23. workflow_loop-0.3.3/tests/test_diagnostics.py +391 -0
  24. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_rollback.py +398 -11
  25. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_spike_assets.py +7 -2
  26. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_stages.py +129 -1
  27. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_verification.py +71 -3
  28. workflow_loop-0.3.2/tests/test_diagnostics.py +0 -216
  29. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/LICENSE +0 -0
  30. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/setup.cfg +0 -0
  31. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/acceptance_records.py +0 -0
  32. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/artifact_paths.py +0 -0
  33. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/acceptance/acceptance.md +0 -0
  34. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/code_design/code_design.md +0 -0
  35. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/code_design/project_design_init.md +0 -0
  36. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/code_design/update_code_design.md +0 -0
  37. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/global/document_writing.md +0 -0
  38. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/global/workflow_lifecycle.md +0 -0
  39. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/qa/test.md +0 -0
  40. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/qa/test_code.md +0 -0
  41. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/qa/test_code_implementation.md +0 -0
  42. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/qa/test_plan.md +0 -0
  43. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/reproduce/reproduce.md +0 -0
  44. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/spec/spec.md +0 -0
  45. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Standardized_Repository/spike/spike.md +0 -0
  46. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/acceptance/acceptance_result.md +0 -0
  47. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/code_design/code_design.md +0 -0
  48. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/code_design/project_design_init_evidence.md +0 -0
  49. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/spec/spec.md +0 -0
  50. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/data/Template_Repository/spike/spike.md +0 -0
  51. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/diagnostics.py +0 -0
  52. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/installer.py +0 -0
  53. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/journal.py +0 -0
  54. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/markdown_links.py +0 -0
  55. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/path_composer.py +0 -0
  56. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/process_runner.py +0 -0
  57. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/project.py +0 -0
  58. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/role_doc.py +0 -0
  59. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/snapshots.py +0 -0
  60. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/spike_reuse.py +0 -0
  61. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/spike_validation.py +0 -0
  62. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/stage_materials.py +0 -0
  63. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/stages/__init__.py +0 -0
  64. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/stages/base.py +0 -0
  65. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/state.py +0 -0
  66. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/test_entry.py +0 -0
  67. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/test_execution.py +0 -0
  68. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/test_mapping.py +0 -0
  69. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/test_report.py +0 -0
  70. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/test_runner.py +0 -0
  71. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/topic_relations.py +0 -0
  72. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop/traceability.py +0 -0
  73. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop.egg-info/SOURCES.txt +0 -0
  74. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop.egg-info/dependency_links.txt +0 -0
  75. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop.egg-info/entry_points.txt +0 -0
  76. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop.egg-info/requires.txt +0 -0
  77. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/src/workflow_loop.egg-info/top_level.txt +0 -0
  78. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_acceptance_records.py +0 -0
  79. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_architecture_validation.py +0 -0
  80. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_artifact_paths.py +0 -0
  81. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_bug_record.py +0 -0
  82. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_current_workflow_contracts.py +0 -0
  83. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_current_workflow_qa.py +0 -0
  84. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_installer.py +0 -0
  85. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_light_task.py +0 -0
  86. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_maintenance.py +0 -0
  87. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_maintenance_scripts.py +0 -0
  88. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_markdown_links.py +0 -0
  89. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_path_composer.py +0 -0
  90. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_process_runner.py +0 -0
  91. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_project.py +0 -0
  92. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_project_design_init.py +0 -0
  93. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_public_project.py +0 -0
  94. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_release_script.py +0 -0
  95. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_release_workflow.py +0 -0
  96. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_snapshots.py +0 -0
  97. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_spike_validation.py +0 -0
  98. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_stage_materials.py +0 -0
  99. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_state.py +0 -0
  100. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_test_entry.py +0 -0
  101. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_test_execution.py +0 -0
  102. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_test_mapping.py +0 -0
  103. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_test_report.py +0 -0
  104. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_test_runner.py +0 -0
  105. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_topic_relations.py +0 -0
  106. {workflow_loop-0.3.2 → workflow_loop-0.3.3}/tests/test_traceability.py +0 -0
  107. {workflow_loop-0.3.2 → 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.2
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.2
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.2/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.2/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.2/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.2` 正式发布中的脚本;不会跟随内容可能变化的 `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.2
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.2` 替换成要发布的新版本号:
226
+ 项目维护者确认当前仓库内容可以直接发布后,在仓库根目录执行下面的命令,并把 `0.3.3` 替换成要发布的新版本号:
227
227
 
228
228
  ```bash
229
- uv run python scripts/release.py 0.3.2
229
+ uv run python scripts/release.py 0.3.3
230
230
  ```
231
231
 
232
232
  运行这条命令本身就表示维护者接受当前仓库状态并承担跳过本地发布检查的风险。脚本不会再次确认,也不会在本地运行测试、构建或远程版本查询。它依次执行:
@@ -71,29 +71,29 @@ flowchart TD
71
71
  - 安装时能够访问 GitHub 和 PyPI(Python 公共软件包仓库)。
72
72
  - 执行安装命令前,先进入要由 Workflow Loop 管理的项目根目录。
73
73
 
74
- ## 安装 0.3.2
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.2/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.2/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.2/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.2` 正式发布中的脚本;不会跟随内容可能变化的 `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.2
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.2` 替换成要发布的新版本号:
207
+ 项目维护者确认当前仓库内容可以直接发布后,在仓库根目录执行下面的命令,并把 `0.3.3` 替换成要发布的新版本号:
208
208
 
209
209
  ```bash
210
- uv run python scripts/release.py 0.3.2
210
+ uv run python scripts/release.py 0.3.3
211
211
  ```
212
212
 
213
213
  运行这条命令本身就表示维护者接受当前仓库状态并承担跳过本地发布检查的风险。脚本不会再次确认,也不会在本地运行测试、构建或远程版本查询。它依次执行:
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "workflow-loop"
3
- version = "0.3.2"
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.2"
2
+ __version__ = "0.3.3"
3
3
  # 产品身份标识:workflow --version 输出、安装脚本身份核对和安装事务校验共用同一组常量
4
- # 本次发布版本为 0.3.2;后续发布使用尚未被 PyPI 占用的新版本号
4
+ # 本次发布版本为 0.3.3;后续发布使用尚未被 PyPI 占用的新版本号
5
5
  PRODUCT_NAME = "workflow-loop"
6
6
  PRODUCT_IDENTITY = f"{PRODUCT_NAME} {__version__}"
@@ -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
 
@@ -1573,7 +1608,10 @@ def validate_acceptance_plan_documents(
1573
1608
  for label in required_fields:
1574
1609
  value = _field(criterion_content, label)
1575
1610
  if value is None or not value.strip():
1576
- 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
+ )
1577
1615
  continue
1578
1616
  normalized = re.sub(r"[\s`*_.。,,::;;!?!?()()\[\]{}]", "", value or "").lower()
1579
1617
  if normalized in placeholder_values or not _has_real_text(value):
@@ -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,