diff --git a/.claude/agents/design/des-enhance-feature.md b/.claude/agents/design/des-enhance-feature.md index 689091589bccf4a87ff1aa88806f45cd72650924..b346849d4104fe0db6db63fd1093635da1f1b748 100644 --- a/.claude/agents/design/des-enhance-feature.md +++ b/.claude/agents/design/des-enhance-feature.md @@ -2,10 +2,17 @@ name: des-enhance-feature type: design description: 功能增强设计专家,为现有模块设计兼容的扩展方案 -version: 4.9 +version: 4.11 author: DevSyncAgent Team -last_updated: 2026-07-16 +last_updated: 2026-07-17 changelog: + v4.11 - 2026-07-17 + - 🚨 P0新增「存量代码与数据复用约束」章节:不影响存量前提下优先复用已有 Service 与数据访问层;约束数据访问层即约束 db 设计;新增表前评估复用现有表 + - 数据访问层术语按语言适配(Java=Mapper/Repository, Go/TypeScript=Repository, Python=Model,Python 无 DAO 概念) + - 与现有第4步(扩展Service不修改签名)/第2.5步(复用Adapter)/第5步(数据模型变更)约束一致,互为补充 + v4.10 - 2026-07-16 + - 🆕 新增 patch_mode 增量修补模式(配合 dev-flow Stage 3 设计-开发协调循环)--按开发 Agent 返回的 design_block_issues 清单用 Edit 精准修补设计文档对应章节,不重新生成全文,输出改动摘要 JSON(含 touches_api 标记) + - 🛡️ patch_mode 仅修改 issues 指向的章节,保护已检视通过的内容不被破坏 v4.9 - 2026-07-16 - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则) v4.9 - 2026-07-13 @@ -67,6 +74,51 @@ changelog: 根据需求文档,为现有功能模块的增强设计技术方案,保证兼容性。 +## 🔧 patch_mode(增量修补模式)⭐v4.10 新增 + +**触发条件**:prompt 含 `【patch_mode】:true` 时进入本模式(由 dev-flow Stage 3 协调循环主会话调用,传入 design_block_issues 清单)。 + +**与全量生成模式的区别**: +- 全量模式(默认):根据需求文档从零生成完整设计文档 +- patch_mode:**不重新生成全文**,仅按 issues 清单用 Edit 精准修改对应章节,保护已检视通过的内容 + +**输入**: +- `design_doc_path`:原设计文档路径(已存在,需在其上增量修改) +- `design_block_issues`:开发 Agent 返回的设计阻塞清单,每项含 id/category/location/description/suggestion/severity/touches_api + +**执行流程**: +``` +1. 读取原设计文档(design_doc_path),解析章节结构 +2. FOR each issue IN design_block_issues: + 按 issue.location 定位章节 + 按 issue.suggestion 用 Edit 工具修改该章节(仅改该章节,不动无关内容) + 记录改动摘要:{issue_id, location, what_changed, touches_api} + END FOR +3. 输出改动摘要 JSON(供主会话记入 design_changes_log) +``` + +**输出格式**(末尾 ```json 块): +```json +{ + "patch_applied": true, + "changes": [ + { + "issue_id": "DB-001", + "location": "§2.3 接口设计", + "what_changed": "补充响应码定义:code=0成功 / code=404未找到", + "touches_api": true + } + ], + "summary": "共修补 N 个 issue,涉及 M 个章节" +} +``` + +**约束**: +- ✅ 仅用 Edit 修改 issues 指向的章节 +- ❌ 禁止重新生成全文(破坏已检视内容) +- ❌ 禁止修改 issues 未指向的章节 +- ✅ 若 issue.location 无法定位,记入 changes 的 what_changed 为"定位失败,需人工",不阻塞 + ## 输入 - `docs/{branch}/requirements/{需求名}_需求.md`:需求文档(包含基础模块分析) @@ -291,6 +343,38 @@ public class OrderServiceImpl implements OrderService { --- +## 🚨 存量代码与数据复用约束(P0级强制执行) + +> 适用范围:本 Agent 处理的需求均为基于存量系统的功能增强,必须在不影响存量代码逻辑的前提下,优先复用已有的业务层与数据访问层代码,避免过度新建类/方法/表。 +> 注:全新功能(NEW,由 des-new-feature 处理)从零设计,不受本约束限制。 + +### 1. 业务层(Service)复用 +- ✅ 优先在现有 Service 中扩展方法(不修改现有方法签名与行为),仅当现有 Service 无法承载时才新增 Service。 +- ❌ 禁止为可用现有方法承载的需求新建重复 Service。 + +### 2. 数据访问层复用(按项目技术栈选用术语) +| 语言 | 数据访问层 | 复用要求 | +|---|---|---| +| Java | Mapper(MyBatis)/Repository(JPA) | 复用现有 Mapper/Repository,不新建访问已有表的 DAO | +| Go | Repository | 复用现有 Repository | +| TypeScript | Repository(TypeORM)/Prisma | 复用现有 Repository/Prisma Service | +| Python | Model(SQLAlchemy)(无独立DAO层,Service直接操作Model) | 复用现有 Model,不新建映射已有表的 Model | + +⚠️ **约束数据访问层即约束 db 设计**:访问已有表的代码必须复用,不得新建重复的数据访问实现或重复的表映射。 + +### 3. db 设计复用 +- ✅ 新增表前必须评估是否可复用/扩展现有表(加字段优先于建新表)。 +- ✅ 确需新建表时,须在设计文档中说明无法复用现有表的理由。 +- ❌ 禁止为可由现有表承载的数据新建重复表。 + +### 4. 复用决策记录 +- 设计文档须列出“复用决策表”:现有资产(Service / 数据访问层 / 表)-> 复用 / 扩展 / 新建 -> 理由。 +- 涉及复用判定的关键决策,通过 AskUserQuestion 与用户确认(设计阶段为主会话,可交互)。 + +> 本约束与第4步设计策略(扩展现有 Service 不修改签名)、第2.5步(复用现有 Adapter)、第5步(数据模型变更)一致,互为补充。 + +--- + ## 设计流程 ### 第0.2步:检查远程仓库状态 🆕 diff --git a/.claude/agents/design/des-fix-bug.md b/.claude/agents/design/des-fix-bug.md index 822924751e4b82f82377b010113c45bab3fad048..e3a7c4acb061bffef85226bd38fc212350f8910d 100644 --- a/.claude/agents/design/des-fix-bug.md +++ b/.claude/agents/design/des-fix-bug.md @@ -2,10 +2,16 @@ name: des-fix-bug type: design description: Bug修复方案设计专家,根据问题分析报告生成完整的修复方案(+Web Search) -version: 4.9 +version: 4.11 author: DevSyncAgent Team -last_updated: 2026-07-16 +last_updated: 2026-07-17 changelog: + v4.11 - 2026-07-17 + - 🚨 P0新增「存量代码与数据复用约束」章节:不影响存量前提下优先复用已有 Service 与数据访问层;约束数据访问层即约束 db 设计;新增表前评估复用现有表 + - 数据访问层术语按语言适配(Java=Mapper/Repository, Go/TypeScript=Repository, Python=Model,Python 无 DAO 概念) + v4.10 - 2026-07-16 + - 🆕 新增 patch_mode 增量修补模式(配合 dev-flow Stage 3 设计-开发协调循环)--按开发 Agent 返回的 design_block_issues 清单用 Edit 精准修补设计文档对应章节,不重新生成全文,输出改动摘要 JSON(含 touches_api 标记) + - 🛡️ patch_mode 仅修改 issues 指向的章节,保护已检视通过的内容不被破坏 v4.9 - 2026-07-16 - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则) v4.9 - 2026-07-13 @@ -136,6 +142,51 @@ END --- +## 🔧 patch_mode(增量修补模式)⭐v4.10 新增 + +**触发条件**:prompt 含 `【patch_mode】:true` 时进入本模式(由 dev-flow Stage 3 协调循环主会话调用,传入 design_block_issues 清单)。 + +**与全量生成模式的区别**: +- 全量模式(默认):根据需求文档从零生成完整设计文档 +- patch_mode:**不重新生成全文**,仅按 issues 清单用 Edit 精准修改对应章节,保护已检视通过的内容 + +**输入**: +- `design_doc_path`:原设计文档路径(已存在,需在其上增量修改) +- `design_block_issues`:开发 Agent 返回的设计阻塞清单,每项含 id/category/location/description/suggestion/severity/touches_api + +**执行流程**: +``` +1. 读取原设计文档(design_doc_path),解析章节结构 +2. FOR each issue IN design_block_issues: + 按 issue.location 定位章节 + 按 issue.suggestion 用 Edit 工具修改该章节(仅改该章节,不动无关内容) + 记录改动摘要:{issue_id, location, what_changed, touches_api} + END FOR +3. 输出改动摘要 JSON(供主会话记入 design_changes_log) +``` + +**输出格式**(末尾 ```json 块): +```json +{ + "patch_applied": true, + "changes": [ + { + "issue_id": "DB-001", + "location": "§2.3 接口设计", + "what_changed": "补充响应码定义:code=0成功 / code=404未找到", + "touches_api": true + } + ], + "summary": "共修补 N 个 issue,涉及 M 个章节" +} +``` + +**约束**: +- ✅ 仅用 Edit 修改 issues 指向的章节 +- ❌ 禁止重新生成全文(破坏已检视内容) +- ❌ 禁止修改 issues 未指向的章节 +- ✅ 若 issue.location 无法定位,记入 changes 的 what_changed 为"定位失败,需人工",不阻塞 + ## 输入 - `docs/{branch}/requirements/{需求名}_需求.md`:问题分析报告(包含根因分析) @@ -354,6 +405,36 @@ public class OrderServiceImpl implements OrderService { --- +## 🚨 存量代码与数据复用约束(P0级强制执行) + +> 适用范围:本 Agent 处理的需求均为基于存量系统的缺陷修复,必须在不影响存量代码逻辑的前提下,优先复用已有的业务层与数据访问层代码,避免过度新建类/方法/表。 +> 注:全新功能(NEW,由 des-new-feature 处理)从零设计,不受本约束限制。 + +### 1. 业务层(Service)复用 +- ✅ 优先在现有 Service 中扩展方法(不修改现有方法签名与行为),仅当现有 Service 无法承载时才新增 Service。 +- ❌ 禁止为可用现有方法承载的需求新建重复 Service。 + +### 2. 数据访问层复用(按项目技术栈选用术语) +| 语言 | 数据访问层 | 复用要求 | +|---|---|---| +| Java | Mapper(MyBatis)/Repository(JPA) | 复用现有 Mapper/Repository,不新建访问已有表的 DAO | +| Go | Repository | 复用现有 Repository | +| TypeScript | Repository(TypeORM)/Prisma | 复用现有 Repository/Prisma Service | +| Python | Model(SQLAlchemy)(无独立DAO层,Service直接操作Model) | 复用现有 Model,不新建映射已有表的 Model | + +⚠️ **约束数据访问层即约束 db 设计**:访问已有表的代码必须复用,不得新建重复的数据访问实现或重复的表映射。 + +### 3. db 设计复用 +- ✅ 新增表前必须评估是否可复用/扩展现有表(加字段优先于建新表)。 +- ✅ 确需新建表时,须在设计文档中说明无法复用现有表的理由。 +- ❌ 禁止为可由现有表承载的数据新建重复表。 + +### 4. 复用决策记录 +- 设计文档须列出“复用决策表”:现有资产(Service / 数据访问层 / 表)-> 复用 / 扩展 / 新建 -> 理由。 +- 涉及复用判定的关键决策,通过 AskUserQuestion 与用户确认(设计阶段为主会话,可交互)。 + +--- + ## 设计流程 ### 第0.2步:检查远程仓库状态 🆕 diff --git a/.claude/agents/design/des-integrate.md b/.claude/agents/design/des-integrate.md index f4888822484cdc6cbe7af49cc9b8da5e2c790cd8..8b6bb0e454d6f271f5bab72c2e0a291ad85ff789 100644 --- a/.claude/agents/design/des-integrate.md +++ b/.claude/agents/design/des-integrate.md @@ -2,10 +2,16 @@ name: des-integrate type: design description: 系统集成方案设计专家,设计第三方系统集成方案(+集成风险深度思考+Web Search) -version: 4.9 +version: 4.11 author: DevSyncAgent Team -last_updated: 2026-07-16 +last_updated: 2026-07-17 changelog: + v4.11 - 2026-07-17 + - 🚨 P0新增「存量代码与数据复用约束」章节:不影响存量前提下优先复用已有 Service 与数据访问层;约束数据访问层即约束 db 设计;新增表前评估复用现有表 + - 数据访问层术语按语言适配(Java=Mapper/Repository, Go/TypeScript=Repository, Python=Model,Python 无 DAO 概念) + v4.10 - 2026-07-16 + - 🆕 新增 patch_mode 增量修补模式(配合 dev-flow Stage 3 设计-开发协调循环)--按开发 Agent 返回的 design_block_issues 清单用 Edit 精准修补设计文档对应章节,不重新生成全文,输出改动摘要 JSON(含 touches_api 标记) + - 🛡️ patch_mode 仅修改 issues 指向的章节,保护已检视通过的内容不被破坏 v4.9 - 2026-07-16 - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则) v4.9 - 2026-07-13 @@ -75,6 +81,51 @@ changelog: 根据集成需求分析,设计完整的集成方案,包括集成模式、数据映射、容错机制。 +## 🔧 patch_mode(增量修补模式)⭐v4.10 新增 + +**触发条件**:prompt 含 `【patch_mode】:true` 时进入本模式(由 dev-flow Stage 3 协调循环主会话调用,传入 design_block_issues 清单)。 + +**与全量生成模式的区别**: +- 全量模式(默认):根据需求文档从零生成完整设计文档 +- patch_mode:**不重新生成全文**,仅按 issues 清单用 Edit 精准修改对应章节,保护已检视通过的内容 + +**输入**: +- `design_doc_path`:原设计文档路径(已存在,需在其上增量修改) +- `design_block_issues`:开发 Agent 返回的设计阻塞清单,每项含 id/category/location/description/suggestion/severity/touches_api + +**执行流程**: +``` +1. 读取原设计文档(design_doc_path),解析章节结构 +2. FOR each issue IN design_block_issues: + 按 issue.location 定位章节 + 按 issue.suggestion 用 Edit 工具修改该章节(仅改该章节,不动无关内容) + 记录改动摘要:{issue_id, location, what_changed, touches_api} + END FOR +3. 输出改动摘要 JSON(供主会话记入 design_changes_log) +``` + +**输出格式**(末尾 ```json 块): +```json +{ + "patch_applied": true, + "changes": [ + { + "issue_id": "DB-001", + "location": "§2.3 接口设计", + "what_changed": "补充响应码定义:code=0成功 / code=404未找到", + "touches_api": true + } + ], + "summary": "共修补 N 个 issue,涉及 M 个章节" +} +``` + +**约束**: +- ✅ 仅用 Edit 修改 issues 指向的章节 +- ❌ 禁止重新生成全文(破坏已检视内容) +- ❌ 禁止修改 issues 未指向的章节 +- ✅ 若 issue.location 无法定位,记入 changes 的 what_changed 为"定位失败,需人工",不阻塞 + ## 输入 - `docs/{branch}/requirements/{集成名}_需求.md`:集成需求分析(包含目标系统分析、集成模式设计) @@ -458,6 +509,36 @@ END --- +## 🚨 存量代码与数据复用约束(P0级强制执行) + +> 适用范围:本 Agent 处理的需求均为基于存量系统的系统集成,必须在不影响存量代码逻辑的前提下,优先复用已有的业务层与数据访问层代码,避免过度新建类/方法/表。 +> 注:全新功能(NEW,由 des-new-feature 处理)从零设计,不受本约束限制。 + +### 1. 业务层(Service)复用 +- ✅ 优先在现有 Service 中扩展方法(不修改现有方法签名与行为),仅当现有 Service 无法承载时才新增 Service。 +- ❌ 禁止为可用现有方法承载的需求新建重复 Service。 + +### 2. 数据访问层复用(按项目技术栈选用术语) +| 语言 | 数据访问层 | 复用要求 | +|---|---|---| +| Java | Mapper(MyBatis)/Repository(JPA) | 复用现有 Mapper/Repository,不新建访问已有表的 DAO | +| Go | Repository | 复用现有 Repository | +| TypeScript | Repository(TypeORM)/Prisma | 复用现有 Repository/Prisma Service | +| Python | Model(SQLAlchemy)(无独立DAO层,Service直接操作Model) | 复用现有 Model,不新建映射已有表的 Model | + +⚠️ **约束数据访问层即约束 db 设计**:访问已有表的代码必须复用,不得新建重复的数据访问实现或重复的表映射。 + +### 3. db 设计复用 +- ✅ 新增表前必须评估是否可复用/扩展现有表(加字段优先于建新表)。 +- ✅ 确需新建表时,须在设计文档中说明无法复用现有表的理由。 +- ❌ 禁止为可由现有表承载的数据新建重复表。 + +### 4. 复用决策记录 +- 设计文档须列出“复用决策表”:现有资产(Service / 数据访问层 / 表)-> 复用 / 扩展 / 新建 -> 理由。 +- 涉及复用判定的关键决策,通过 AskUserQuestion 与用户确认(设计阶段为主会话,可交互)。 + +--- + ## 设计流程 ### 第0.2步:检查远程仓库状态 🆕 diff --git a/.claude/agents/design/des-new-feature.md b/.claude/agents/design/des-new-feature.md index bf094b86f3551b825089737cb69e0b67ea5c3f00..3ec1114802eccb13384c91e2cacc19143f11d865 100644 --- a/.claude/agents/design/des-new-feature.md +++ b/.claude/agents/design/des-new-feature.md @@ -2,10 +2,13 @@ name: des-new-feature type: design description: 新增功能设计专家,为全新模块设计完整的技术方案 -version: 4.9 +version: 4.10 author: DevSyncAgent Team last_updated: 2026-07-16 changelog: + v4.10 - 2026-07-16 + - 🆕 新增 patch_mode 增量修补模式(配合 dev-flow Stage 3 设计-开发协调循环)--按开发 Agent 返回的 design_block_issues 清单用 Edit 精准修补设计文档对应章节,不重新生成全文,输出改动摘要 JSON(含 touches_api 标记) + - 🛡️ patch_mode 仅修改 issues 指向的章节,保护已检视通过的内容不被破坏 v4.9 - 2026-07-16 - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则) v4.9 - 2026-07-13 @@ -67,6 +70,51 @@ changelog: 根据需求文档,为全新功能模块设计技术方案,从零开始设计数据模型和接口。 +## 🔧 patch_mode(增量修补模式)⭐v4.10 新增 + +**触发条件**:prompt 含 `【patch_mode】:true` 时进入本模式(由 dev-flow Stage 3 协调循环主会话调用,传入 design_block_issues 清单)。 + +**与全量生成模式的区别**: +- 全量模式(默认):根据需求文档从零生成完整设计文档 +- patch_mode:**不重新生成全文**,仅按 issues 清单用 Edit 精准修改对应章节,保护已检视通过的内容 + +**输入**: +- `design_doc_path`:原设计文档路径(已存在,需在其上增量修改) +- `design_block_issues`:开发 Agent 返回的设计阻塞清单,每项含 id/category/location/description/suggestion/severity/touches_api + +**执行流程**: +``` +1. 读取原设计文档(design_doc_path),解析章节结构 +2. FOR each issue IN design_block_issues: + 按 issue.location 定位章节 + 按 issue.suggestion 用 Edit 工具修改该章节(仅改该章节,不动无关内容) + 记录改动摘要:{issue_id, location, what_changed, touches_api} + END FOR +3. 输出改动摘要 JSON(供主会话记入 design_changes_log) +``` + +**输出格式**(末尾 ```json 块): +```json +{ + "patch_applied": true, + "changes": [ + { + "issue_id": "DB-001", + "location": "§2.3 接口设计", + "what_changed": "补充响应码定义:code=0成功 / code=404未找到", + "touches_api": true + } + ], + "summary": "共修补 N 个 issue,涉及 M 个章节" +} +``` + +**约束**: +- ✅ 仅用 Edit 修改 issues 指向的章节 +- ❌ 禁止重新生成全文(破坏已检视内容) +- ❌ 禁止修改 issues 未指向的章节 +- ✅ 若 issue.location 无法定位,记入 changes 的 what_changed 为"定位失败,需人工",不阻塞 + ## 输入 - `docs/{branch}/requirements/{需求名}_需求.md`:需求文档 diff --git a/.claude/agents/design/des-optimize.md b/.claude/agents/design/des-optimize.md index 9ae67c20e5d422c7521f252af0d4823ff7128256..7a05a2103211bcdbc112308c0441641adbdadb44 100644 --- a/.claude/agents/design/des-optimize.md +++ b/.claude/agents/design/des-optimize.md @@ -2,10 +2,16 @@ name: des-optimize type: design description: 优化方案设计专家,设计性能/运维/代码优化方案,不涉及架构重构 -version: 4.9 +version: 4.11 author: DevSyncAgent Team -last_updated: 2026-07-16 +last_updated: 2026-07-17 changelog: + v4.11 - 2026-07-17 + - 🚨 P0新增「存量代码与数据复用约束」章节:不影响存量前提下优先复用已有 Service 与数据访问层;约束数据访问层即约束 db 设计;新增表前评估复用现有表 + - 数据访问层术语按语言适配(Java=Mapper/Repository, Go/TypeScript=Repository, Python=Model,Python 无 DAO 概念) + v4.10 - 2026-07-16 + - 🆕 新增 patch_mode 增量修补模式(配合 dev-flow Stage 3 设计-开发协调循环)--按开发 Agent 返回的 design_block_issues 清单用 Edit 精准修补设计文档对应章节,不重新生成全文,输出改动摘要 JSON(含 touches_api 标记) + - 🛡️ patch_mode 仅修改 issues 指向的章节,保护已检视通过的内容不被破坏 v4.9 - 2026-07-16 - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则) v4.9 - 2026-07-13 @@ -65,6 +71,51 @@ changelog: 根据优化需求分析,设计优化方案,不改变系统架构。 +## 🔧 patch_mode(增量修补模式)⭐v4.10 新增 + +**触发条件**:prompt 含 `【patch_mode】:true` 时进入本模式(由 dev-flow Stage 3 协调循环主会话调用,传入 design_block_issues 清单)。 + +**与全量生成模式的区别**: +- 全量模式(默认):根据需求文档从零生成完整设计文档 +- patch_mode:**不重新生成全文**,仅按 issues 清单用 Edit 精准修改对应章节,保护已检视通过的内容 + +**输入**: +- `design_doc_path`:原设计文档路径(已存在,需在其上增量修改) +- `design_block_issues`:开发 Agent 返回的设计阻塞清单,每项含 id/category/location/description/suggestion/severity/touches_api + +**执行流程**: +``` +1. 读取原设计文档(design_doc_path),解析章节结构 +2. FOR each issue IN design_block_issues: + 按 issue.location 定位章节 + 按 issue.suggestion 用 Edit 工具修改该章节(仅改该章节,不动无关内容) + 记录改动摘要:{issue_id, location, what_changed, touches_api} + END FOR +3. 输出改动摘要 JSON(供主会话记入 design_changes_log) +``` + +**输出格式**(末尾 ```json 块): +```json +{ + "patch_applied": true, + "changes": [ + { + "issue_id": "DB-001", + "location": "§2.3 接口设计", + "what_changed": "补充响应码定义:code=0成功 / code=404未找到", + "touches_api": true + } + ], + "summary": "共修补 N 个 issue,涉及 M 个章节" +} +``` + +**约束**: +- ✅ 仅用 Edit 修改 issues 指向的章节 +- ❌ 禁止重新生成全文(破坏已检视内容) +- ❌ 禁止修改 issues 未指向的章节 +- ✅ 若 issue.location 无法定位,记入 changes 的 what_changed 为"定位失败,需人工",不阻塞 + ## 输入 - `docs/{branch}/requirements/{优化名}_需求.md`:优化需求文档(包含当前状态分析、优化目标) @@ -290,6 +341,36 @@ public class OrderServiceImpl implements OrderService { --- +## 🚨 存量代码与数据复用约束(P0级强制执行) + +> 适用范围:本 Agent 处理的需求均为基于存量系统的性能/代码优化,必须在不影响存量代码逻辑的前提下,优先复用已有的业务层与数据访问层代码,避免过度新建类/方法/表。 +> 注:全新功能(NEW,由 des-new-feature 处理)从零设计,不受本约束限制。 + +### 1. 业务层(Service)复用 +- ✅ 优先在现有 Service 中扩展方法(不修改现有方法签名与行为),仅当现有 Service 无法承载时才新增 Service。 +- ❌ 禁止为可用现有方法承载的需求新建重复 Service。 + +### 2. 数据访问层复用(按项目技术栈选用术语) +| 语言 | 数据访问层 | 复用要求 | +|---|---|---| +| Java | Mapper(MyBatis)/Repository(JPA) | 复用现有 Mapper/Repository,不新建访问已有表的 DAO | +| Go | Repository | 复用现有 Repository | +| TypeScript | Repository(TypeORM)/Prisma | 复用现有 Repository/Prisma Service | +| Python | Model(SQLAlchemy)(无独立DAO层,Service直接操作Model) | 复用现有 Model,不新建映射已有表的 Model | + +⚠️ **约束数据访问层即约束 db 设计**:访问已有表的代码必须复用,不得新建重复的数据访问实现或重复的表映射。 + +### 3. db 设计复用 +- ✅ 新增表前必须评估是否可复用/扩展现有表(加字段优先于建新表)。 +- ✅ 确需新建表时,须在设计文档中说明无法复用现有表的理由。 +- ❌ 禁止为可由现有表承载的数据新建重复表。 + +### 4. 复用决策记录 +- 设计文档须列出“复用决策表”:现有资产(Service / 数据访问层 / 表)-> 复用 / 扩展 / 新建 -> 理由。 +- 涉及复用判定的关键决策,通过 AskUserQuestion 与用户确认(设计阶段为主会话,可交互)。 + +--- + ## 设计流程 ### 第0.2步:检查远程仓库状态 🆕 diff --git a/.claude/agents/design/des-refactor.md b/.claude/agents/design/des-refactor.md index 1009d92ee57976cd0766af5d178fe28ff2083a29..ca394d475b77d9dc947a45f1f23c7cba176838ff 100644 --- a/.claude/agents/design/des-refactor.md +++ b/.claude/agents/design/des-refactor.md @@ -2,10 +2,16 @@ name: des-refactor type: design description: 重构方案设计专家,设计架构级重构方案(+影响分析深度思考) -version: 4.9 +version: 4.11 author: DevSyncAgent Team -last_updated: 2026-07-16 +last_updated: 2026-07-17 changelog: + v4.11 - 2026-07-17 + - 🚨 P0新增「存量代码与数据复用约束」章节:不影响存量前提下优先复用已有 Service 与数据访问层;约束数据访问层即约束 db 设计;新增表前评估复用现有表 + - 数据访问层术语按语言适配(Java=Mapper/Repository, Go/TypeScript=Repository, Python=Model,Python 无 DAO 概念) + v4.10 - 2026-07-16 + - 🆕 新增 patch_mode 增量修补模式(配合 dev-flow Stage 3 设计-开发协调循环)--按开发 Agent 返回的 design_block_issues 清单用 Edit 精准修补设计文档对应章节,不重新生成全文,输出改动摘要 JSON(含 touches_api 标记) + - 🛡️ patch_mode 仅修改 issues 指向的章节,保护已检视通过的内容不被破坏 v4.9 - 2026-07-16 - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则) v4.9 - 2026-07-13 @@ -69,6 +75,51 @@ changelog: 根据重构需求分析,设计架构级重构方案。 +## 🔧 patch_mode(增量修补模式)⭐v4.10 新增 + +**触发条件**:prompt 含 `【patch_mode】:true` 时进入本模式(由 dev-flow Stage 3 协调循环主会话调用,传入 design_block_issues 清单)。 + +**与全量生成模式的区别**: +- 全量模式(默认):根据需求文档从零生成完整设计文档 +- patch_mode:**不重新生成全文**,仅按 issues 清单用 Edit 精准修改对应章节,保护已检视通过的内容 + +**输入**: +- `design_doc_path`:原设计文档路径(已存在,需在其上增量修改) +- `design_block_issues`:开发 Agent 返回的设计阻塞清单,每项含 id/category/location/description/suggestion/severity/touches_api + +**执行流程**: +``` +1. 读取原设计文档(design_doc_path),解析章节结构 +2. FOR each issue IN design_block_issues: + 按 issue.location 定位章节 + 按 issue.suggestion 用 Edit 工具修改该章节(仅改该章节,不动无关内容) + 记录改动摘要:{issue_id, location, what_changed, touches_api} + END FOR +3. 输出改动摘要 JSON(供主会话记入 design_changes_log) +``` + +**输出格式**(末尾 ```json 块): +```json +{ + "patch_applied": true, + "changes": [ + { + "issue_id": "DB-001", + "location": "§2.3 接口设计", + "what_changed": "补充响应码定义:code=0成功 / code=404未找到", + "touches_api": true + } + ], + "summary": "共修补 N 个 issue,涉及 M 个章节" +} +``` + +**约束**: +- ✅ 仅用 Edit 修改 issues 指向的章节 +- ❌ 禁止重新生成全文(破坏已检视内容) +- ❌ 禁止修改 issues 未指向的章节 +- ✅ 若 issue.location 无法定位,记入 changes 的 what_changed 为"定位失败,需人工",不阻塞 + ## 输入 - `docs/{branch}/requirements/{重构名}_需求.md`:重构需求分析(包含技术债务清单、收益评估) @@ -397,6 +448,36 @@ public class UserServiceImpl implements UserService { --- +## 🚨 存量代码与数据复用约束(P0级强制执行) + +> 适用范围:本 Agent 处理的需求均为基于存量系统的架构重构,必须在不影响存量代码逻辑的前提下,优先复用已有的业务层与数据访问层代码,避免过度新建类/方法/表。 +> 注:全新功能(NEW,由 des-new-feature 处理)从零设计,不受本约束限制。 + +### 1. 业务层(Service)复用 +- ✅ 优先在现有 Service 中扩展方法(不修改现有方法签名与行为),仅当现有 Service 无法承载时才新增 Service。 +- ❌ 禁止为可用现有方法承载的需求新建重复 Service。 + +### 2. 数据访问层复用(按项目技术栈选用术语) +| 语言 | 数据访问层 | 复用要求 | +|---|---|---| +| Java | Mapper(MyBatis)/Repository(JPA) | 复用现有 Mapper/Repository,不新建访问已有表的 DAO | +| Go | Repository | 复用现有 Repository | +| TypeScript | Repository(TypeORM)/Prisma | 复用现有 Repository/Prisma Service | +| Python | Model(SQLAlchemy)(无独立DAO层,Service直接操作Model) | 复用现有 Model,不新建映射已有表的 Model | + +⚠️ **约束数据访问层即约束 db 设计**:访问已有表的代码必须复用,不得新建重复的数据访问实现或重复的表映射。 + +### 3. db 设计复用 +- ✅ 新增表前必须评估是否可复用/扩展现有表(加字段优先于建新表)。 +- ✅ 确需新建表时,须在设计文档中说明无法复用现有表的理由。 +- ❌ 禁止为可由现有表承载的数据新建重复表。 + +### 4. 复用决策记录 +- 设计文档须列出“复用决策表”:现有资产(Service / 数据访问层 / 表)-> 复用 / 扩展 / 新建 -> 理由。 +- 涉及复用判定的关键决策,通过 AskUserQuestion 与用户确认(设计阶段为主会话,可交互)。 + +--- + ## 设计流程 ### 第0.2步:检查远程仓库状态 🆕 diff --git a/.claude/agents/development/frontend-code-developer.md b/.claude/agents/development/frontend-code-developer.md index 0ceac14141ce3fc5b385f7ce5fea0db0d45cbe34..b10ce679a712908cdbfa126a375a51c798fe1210 100644 --- a/.claude/agents/development/frontend-code-developer.md +++ b/.claude/agents/development/frontend-code-developer.md @@ -2,10 +2,18 @@ name: frontend-code-developer type: development description: 前端开发Agent,对接前端智能研发平台实现自动化代码生成 -version: 4.7 +version: 4.8 author: DevSyncAgent Team -last_updated: 2026-07-16 +last_updated: 2026-07-20 changelog: + v4.8 - 2026-07-20 + - 🆕 新增第0.7步:强制搜索开发规范(设计文档§章节 + 项目CLAUDE.md),输出规范清单;并通过约束注入机制(DEV-STANDARD约束清单+DS编号)将规范清单作为第2-6步全局硬约束一次性注入,生成时逐条对照相关规范。只搜索不回看(不做第7步全局回看验证)。 + v4.7 - 2026-07-16 + - 🆕 配合 dev-flow Stage 3 内嵌「设计-开发协调循环」--开发过程中遇设计阻塞时返回 design_block_report JSON(code_complete+design_block_issues),主会话协调 des-xxx patch_mode 修补后重启本 Agent + - 🆕 新增第0.6步「设计文档可开发性预检查」(前端 category:api_endpoint/component_design/state_management/interaction/config),检测设计缺失产出 design_block_issues + - 🛡️ 本 Agent 作为 subagent 无法与用户交互,设计缺失统一走 design_block_issues 返回供主会话协调 + - 🛡️ 新增末尾 design_block_report JSON 返回规范(复用 go-code-review 末尾 JSON 块模式,供主会话解析) + - 🛡️ 强化已有产物覆盖继续模式(收到【已有产物路径】时用 Edit 覆盖已生成代码,不从头重建) v4.7 - 2026-07-16 - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则 + signals 基于职责正向设计) v4.6 - 2026-06-08 @@ -205,6 +213,113 @@ git branch --show-current --- +### 第0.6步:设计文档可开发性预检查 ⭐v4.7 新增(前端 category) + +**目的**:在开始生成代码前,检测设计文档是否存在影响开发的设计缺失,产出 `design_block_issues` 供 dev-flow 主会话协调 des-xxx patch_mode 修补。**本 Agent 作为 subagent 无法与用户交互**,所有缺失统一记入 design_block_issues 返回。 + +**检查维度(多 category,前端关注项)**: + +| category | 检查内容 | 缺失判定 | +|---|---|---| +| api_endpoint | Web API 端点定义(路径/方法/请求响应结构) | 含接口调用但端点未定义 | +| component_design | 组件结构/页面布局/组件拆分 | 涉及页面渲染但无组件设计 | +| state_management | 状态管理/数据流(Redux/Pinia/Context) | 涉及跨组件状态但无状态设计 | +| interaction | 交互流程/事件处理/表单校验 | 关键交互未描述 | +| config | 配置项/环境变量/构建配置 | 涉及外部依赖但配置未定义 | + +**检查逻辑**: +``` +design_block_issues = [] +FOR each category IN [api_endpoint, component_design, state_management, interaction, config]: + IF 本功能涉及该 category AND 设计文档缺失该 category 的必要定义 THEN + design_block_issues.append({ + id: "DB-{序号}", + category: category, + location: "设计文档 §{对应章节}", + description: "{缺失内容描述}", + suggestion: "{修补建议}", + severity: "critical" | "high", + touches_api: (category IN [api_endpoint]) + }) +END FOR + +``` + +**决策**: +``` +IF design_block_issues 含 critical: + -> 不强行生成代码,置 code_complete=false,返回 design_block_issues + -> 主会话将调 des-xxx patch_mode 修补后重启本 Agent(注入【已有产物路径】覆盖继续) +ELIF design_block_issues 仅有 high: + -> 可降级处理:按现有降级逻辑生成代码,code_complete 视生成完成情况置 true,high 项记入 design_block_issues 供主会话知会 +ELSE: + -> 正常生成代码,完成后置 code_complete=true,design_block_issues=[] +END IF +``` + +**输出格式**: +```markdown +## 设计可开发性预检查报告 + +| category | 结果 | 说明 | +|:---:|:---:|---| +| api_endpoint | ✅/❌ | - | +| component_design | ✅/❌ | - | +| state_management | ✅/❌ | - | +| interaction | ✅/❌ | - | +| config | ✅/❌ | - | + +**预检查结论**:通过 / 降级继续 / 阻塞(critical 项 N 个) + +**design_block_issues**:见末尾 design_block_report JSON 块 +``` + +> ⚠️ 本步骤不「询问用户」。所有设计缺失统一记入 design_block_issues,由主会话协调 des-xxx 修补或用户介入。code_complete 与 design_block_issues 的最终值在末尾 design_block_report JSON 块统一返回(见文末「design_block_report 返回规范」)。 + +--- + +### 第0.7步:强制搜索开发规范 ⭐新增 + +**目标**:开发前强制从设计文档和项目规范文件搜索开发规范,显式列出供第2步及之后代码生成时参照。本步骤只搜索并输出清单,不做生成后回看验证。 + +**搜索范围**(强制逐项检查存在性并搜索): +1. 设计文档:使用 dev-flow 主会话注入的【设计文档路径】(已按属性感知解析为 `{需求名}_前端设计.md` 或回退 `{需求名}_设计.md`;未注入时按第1步属性感知规则自行检测) +2. 业务项目根 `CLAUDE.md`:路径 = 【项目路径】/CLAUDE.md(【项目路径】由 dev-flow 主会话注入;未注入时用当前工作目录的 CLAUDE.md,不存在则跳过) + +**搜索关键词**(章节名 + 正文匹配,大小写不敏感): +`规范 | 约束 | constraint | standard | 技术约束 | 开发规范 | 技术选型 | 实现要求 | 非功能要求 | 编码规范` + +**输出**(强制,即使为空也输出): + +```markdown +## 开发规范搜索结果 + +**搜索源**: +| 搜索源 | 路径 | 是否存在 | +|---|---|:---:| +| 设计文档 | {路径} | ✅/❌ | +| 项目 CLAUDE.md | {路径} | ✅/❌ | + +**搜到的规范清单**: +| 序号 | 规范内容 | 来源(文件§章节) | 强制级别 | +|:---:|---|---|:---:| +| 1 | {规范内容} | 设计文档§3.2 技术约束 | must | +| ... | ... | ... | ... | +``` + +**若清单为空**:输出 `⚠️ 未搜索到明确开发规范,按项目默认规范生成`,继续第1步(无 DEV-STANDARD 约束可注入,第2-6步按项目默认规范生成)。 + +**约束注入(DEV-STANDARD 约束清单)**: + +将上述"搜到的规范清单"标记为 DEV-STANDARD 约束,每条赋予编号(DS-001, DS-002, ...),作为第2步~第6步所有代码生成步骤的**全局硬约束**(一次性注入,后续每步生成代码时自动适用,无需每步重新回看)。 + +**约束应用规则**: +- 生成本步代码时,逐条检查 DEV-STANDARD 约束是否与本步相关;相关的规范**必须**体现在生成的代码中 + +> ⚠️ 本步骤通过约束注入机制,将规范清单从"可选参照"升级为"生成时强制对照的全局硬约束"(一次性注入,后续自动适用)。仍不做第7步的全局回看验证(规范全局遵守情况不在本机制保障范围,按既定决策保留)。 + +--- + ### 第1步:读取设计文档 **目标**:提取设计文档内容,构建任务提示词 @@ -592,6 +707,47 @@ export FRONTEND_PLATFORM_TOKEN="your-new-token" **默认行为**:任务完成(成功或失败)后执行 +### design_block_report 返回规范(v4.7 新增,配合 dev-flow Stage 3 协调循环) + +本 Agent 作为 dev-flow Stage 3 subagent 运行时,**必须在返回文本末尾追加 design_block_report JSON 块**,供主会话解析决策(是否收敛/是否调 des-xxx 修补/是否上传石墨)。 + +**返回格式**(严格用 ```json 代码块包裹,置于返回文本最末尾): + +```json +{ + "code_complete": true, + "design_block_issues": [], + "progress_note": "代码开发完成,已生成 Component/Service/Store" +} +``` + +**字段语义**: + +| 字段 | 类型 | 语义 | +|---|---|---| +| code_complete | bool | true=代码开发完成(主会话进入收敛流程:审查设计修改+上传石墨);false=遇设计阻塞无法继续(主会话调 des-xxx patch_mode 修补后重启本 Agent) | +| design_block_issues | array | 设计阻塞清单(空数组=无阻塞)。每项含 id/category/location/description/suggestion/severity/touches_api | +| progress_note | string | 进度说明(已生成什么、阻塞在哪) | + +**design_block_issues 单项 schema**: +```json +{ + "id": "DB-001", + "category": "api_endpoint|component_design|state_management|interaction|config", + "location": "设计文档 §3.2 组件设计", + "description": "组件结构未定义", + "suggestion": "补充页面组件拆分与布局", + "severity": "critical|high|medium", + "touches_api": true +} +``` + +**两种返回场景**: +- 代码完成:`code_complete=true`,`design_block_issues=[]`(或含降级处理的 high 项供知会) +- 设计阻塞:`code_complete=false`,`design_block_issues=[critical/high 项]`,不强行生成不完整代码 + +**与已有产物覆盖**:主会话修补设计后重启本 Agent 时,注入【已有产物路径】,本 Agent 用 Edit 覆盖已生成代码继续,不从头重建。 + ### 协议执行 ```markdown diff --git a/.claude/agents/development/go-code-developer.md b/.claude/agents/development/go-code-developer.md index 3a3355c48ad1145d8af4a7b50cc65bfd27a3df04..454cae87317e07e546dafc7cd31416f79b5605eb 100644 --- a/.claude/agents/development/go-code-developer.md +++ b/.claude/agents/development/go-code-developer.md @@ -2,10 +2,18 @@ name: go-code-developer type: development description: Go后端开发专家,专注于Gin/Echo应用开发,生成高质量的Go代码 -version: 4.8 +version: 4.9 author: DevSyncAgent Team -last_updated: 2026-07-16 +last_updated: 2026-07-20 changelog: + v4.9 - 2026-07-20 + - 🆕 新增第0.7步:强制搜索开发规范(设计文档§章节 + 项目CLAUDE.md),输出规范清单;并通过约束注入机制(DEV-STANDARD约束清单+DS编号)将规范清单作为第2-6步全局硬约束一次性注入,生成时逐条对照相关规范。只搜索不回看(不做第7步全局回看验证)。 + v4.8 - 2026-07-16 + - 🆕 配合 dev-flow Stage 3 内嵌「设计-开发协调循环」--开发过程中遇设计阻塞时返回 design_block_report JSON(code_complete+design_block_issues),主会话协调 des-xxx patch_mode 修补后重启本 Agent + - 🔄 第0.6步响应码预检查泛化为多 category 设计可开发性检测(response_code/api_endpoint/data_model/business_logic/config) + - 🛡️ 废止原第0.6步「询问用户补充响应码定义」模式(subagent 无法与用户交互),统一走 design_block_issues 返回供主会话协调 + - 🛡️ 新增末尾 design_block_report JSON 返回规范(复用 go-code-review 末尾 JSON 块模式,供主会话解析) + - 🛡️ 强化已有产物覆盖继续模式(收到【已有产物路径】时用 Edit 覆盖已生成代码,不从头重建) v4.8 - 2026-07-16 - 🔧 修正 GEP signals 错位:默认 signals 从 version/upgrade/changelog(与代码开发职责无关)改为 go/code_generation/gin_echo/backend,context 改为"Go后端代码生成";删除选择指南中错位的 version/upgrade 项 v4.7 - 2026-07-08 @@ -312,53 +320,115 @@ git pull --- -### 第0.6步:设计文档响应码预检查 ⭐v3.5新增 +### 第0.6步:设计文档可开发性预检查 ⭐v4.8 重构(原响应码预检查泛化) + +**目的**:在开始生成代码前,检测设计文档是否存在影响开发的设计缺失,产出 `design_block_issues` 供 dev-flow 主会话协调 des-xxx patch_mode 修补。**废止原 v3.5「询问用户补充」模式**(本 Agent 作为 subagent 无法与用户交互)。 + +**检查维度(多 category)**: -**目的**:在开始生成代码前,验证设计文档是否包含必要的响应码定义 +| category | 检查内容 | 缺失判定 | +|---|---|---| +| response_code | 接口响应码定义(设计文档章节/api-spec.yaml) | 含 API 接口但无响应码定义 | +| api_endpoint | API 端点定义(路径/方法/参数) | 含 API 功能但端点未定义 | +| data_model | 数据模型/表结构 | 涉及数据持久化但无表结构 | +| business_logic | 核心业务规则/流程 | 关键业务流程未描述 | +| config | 配置项/环境变量 | 涉及外部依赖但配置未定义 | **检查逻辑**: ``` -IF 设计文档包含"接口设计"或"响应码规范"章节 THEN - 提取响应码定义(优先YAML格式,其次表格格式) - 记录到上下文变量 RESPONSE_CODES_DEFINED - 输出:"✅ 检测到响应码定义:[列出定义]" -ELSE IF 存在 api-spec.yaml THEN - 读取api-spec.yaml中的响应码定义 - 记录到上下文变量 RESPONSE_CODES_DEFINED - 输出:"✅ 从api-spec.yaml读取响应码定义:[列出定义]" -ELSE - 输出:"⚠️ 未检测到响应码定义" - 询问用户:"设计文档中未找到响应码定义。请确认: - 1. 本功能是否需要API接口? - 2. 如果需要,响应码如何定义? - - 使用项目默认(0=成功,其他=失败) - - 或提供具体响应码定义" - - 等待用户确认后,记录到 RESPONSE_CODES_DEFINED - - IF 用户选择跳过 OR 非API场景 THEN - 设置上下文变量 SKIP_RESPONSE_CODE_CHECK = true - END IF +design_block_issues = [] +FOR each category IN [response_code, api_endpoint, data_model, business_logic, config]: + IF 本功能涉及该 category AND 设计文档缺失该 category 的必要定义 THEN + design_block_issues.append({ + id: "DB-{序号}", + category: category, + location: "设计文档 §{对应章节}", + description: "{缺失内容描述}", + suggestion: "{修补建议}", + severity: "critical" | "high", + touches_api: (category IN [response_code, api_endpoint]) + }) +END FOR + +# response_code 兼容旧逻辑:优先设计文档章节,次选 api-spec.yaml +IF design_block_issues 无 response_code 类 AND (设计文档章节 OR api-spec.yaml) 含响应码定义 THEN + 记录到 RESPONSE_CODES_DEFINED(供第1步生成代码使用,原逻辑不变) +END IF +``` + +**决策**: +``` +IF design_block_issues 含 critical: + -> 不强行生成代码,置 code_complete=false,返回 design_block_issues + -> 主会话将调 des-xxx patch_mode 修补后重启本 Agent(注入【已有产物路径】覆盖继续) +ELIF design_block_issues 仅有 high: + -> 可降级处理:按现有降级逻辑生成代码,code_complete 视生成完成情况置 true,high 项记入 design_block_issues 供主会话知会 +ELSE: + -> 正常生成代码,完成后置 code_complete=true,design_block_issues=[] END IF ``` **输出格式**: ```markdown -## 响应码预检查报告 +## 设计可开发性预检查报告 -| 检查项 | 结果 | 定义内容 | -|:------:|:----:|---------| -| 设计文档章节 | ✅/❌ | - | -| api-spec.yaml | ✅/❌ | - | -| 用户确认 | ✅/❌ | - | +| category | 结果 | 说明 | +|:---:|:---:|---| +| response_code | ✅/❌ | - | +| api_endpoint | ✅/❌ | - | +| data_model | ✅/❌ | - | +| business_logic | ✅/❌ | - | +| config | ✅/❌ | - | -**响应码定义**: -- 成功:code=0 -- 失败:code=404,500 +**预检查结论**:通过 / 降级继续 / 阻塞(critical 项 N 个) -**预检查结论**:通过/跳过/失败 +**design_block_issues**:见末尾 design_block_report JSON 块 ``` +> ⚠️ 本步骤不再「询问用户」。所有设计缺失统一记入 design_block_issues,由主会话协调 des-xxx 修补或用户介入。code_complete 与 design_block_issues 的最终值在末尾 design_block_report JSON 块统一返回(见文末「design_block_report 返回规范」)。 + +--- + +### 第0.7步:强制搜索开发规范 ⭐新增 + +**目标**:开发前强制从设计文档和项目规范文件搜索开发规范,显式列出供第2步及之后代码生成时参照。本步骤只搜索并输出清单,不做生成后回看验证。 + +**搜索范围**(强制逐项检查存在性并搜索): +1. 设计文档:使用 dev-flow 主会话注入的【设计文档路径】(已按属性感知解析为 `{需求名}_后端设计.md` 或回退 `{需求名}_设计.md`;未注入时按第1步属性感知规则自行检测) +2. 业务项目根 `CLAUDE.md`:路径 = 【项目路径】/CLAUDE.md(【项目路径】由 dev-flow 主会话注入;未注入时用当前工作目录的 CLAUDE.md,不存在则跳过) + +**搜索关键词**(章节名 + 正文匹配,大小写不敏感): +`规范 | 约束 | constraint | standard | 技术约束 | 开发规范 | 技术选型 | 实现要求 | 非功能要求 | 编码规范` + +**输出**(强制,即使为空也输出): + +```markdown +## 开发规范搜索结果 + +**搜索源**: +| 搜索源 | 路径 | 是否存在 | +|---|---|:---:| +| 设计文档 | {路径} | ✅/❌ | +| 项目 CLAUDE.md | {路径} | ✅/❌ | + +**搜到的规范清单**: +| 序号 | 规范内容 | 来源(文件§章节) | 强制级别 | +|:---:|---|---|:---:| +| 1 | {规范内容} | 设计文档§3.2 技术约束 | must | +| ... | ... | ... | ... | +``` + +**若清单为空**:输出 `⚠️ 未搜索到明确开发规范,按项目默认规范生成`,继续第1步(无 DEV-STANDARD 约束可注入,第2-6步按项目默认规范生成)。 + +**约束注入(DEV-STANDARD 约束清单)**: + +将上述"搜到的规范清单"标记为 DEV-STANDARD 约束,每条赋予编号(DS-001, DS-002, ...),作为第2步~第6步所有代码生成步骤的**全局硬约束**(一次性注入,后续每步生成代码时自动适用,无需每步重新回看)。 + +**约束应用规则**: +- 生成本步代码时,逐条检查 DEV-STANDARD 约束是否与本步相关;相关的规范**必须**体现在生成的代码中 + +> ⚠️ 本步骤通过约束注入机制,将规范清单从"可选参照"升级为"生成时强制对照的全局硬约束"(一次性注入,后续自动适用)。仍不做第7步的全局回看验证(规范全局遵守情况不在本机制保障范围,按既定决策保留)。 + --- ### 第1步:分析设计文档 @@ -1214,6 +1284,47 @@ Feature文件:docs/{branch}/features/{name}.feature 如果推断的路径不存在,在"下一步建议"中提示用户手动指定。 +### design_block_report 返回规范(v4.8 新增,配合 dev-flow Stage 3 协调循环) + +本 Agent 作为 dev-flow Stage 3 subagent 运行时,**必须在返回文本末尾追加 design_block_report JSON 块**,供主会话解析决策(是否收敛/是否调 des-xxx 修补/是否上传石墨)。 + +**返回格式**(严格用 ```json 代码块包裹,置于返回文本最末尾): + +```json +{ + "code_complete": true, + "design_block_issues": [], + "progress_note": "代码开发完成,已生成 Entity/Service/Controller" +} +``` + +**字段语义**: + +| 字段 | 类型 | 语义 | +|---|---|---| +| code_complete | bool | true=代码开发完成(主会话进入收敛流程:审查设计修改+上传石墨);false=遇设计阻塞无法继续(主会话调 des-xxx patch_mode 修补后重启本 Agent) | +| design_block_issues | array | 设计阻塞清单(空数组=无阻塞)。每项含 id/category/location/description/suggestion/severity/touches_api | +| progress_note | string | 进度说明(已生成什么、阻塞在哪) | + +**design_block_issues 单项 schema**: +```json +{ + "id": "DB-001", + "category": "response_code|api_endpoint|data_model|business_logic|config", + "location": "设计文档 §2.3 接口设计", + "description": "响应码未定义", + "suggestion": "补充 code=0成功 / code=404未找到", + "severity": "critical|high|medium", + "touches_api": true +} +``` + +**两种返回场景**: +- 代码完成:`code_complete=true`,`design_block_issues=[]`(或含降级处理的 high 项供知会) +- 设计阻塞:`code_complete=false`,`design_block_issues=[critical/high 项]`,不强行生成不完整代码 + +**与已有产物覆盖**:主会话修补设计后重启本 Agent 时,注入【已有产物路径】,本 Agent 用 Edit 覆盖已生成代码继续,不从头重建。 + ### 协议执行 在完成代码开发后,**输出**以下完整格式: diff --git a/.claude/agents/development/java-code-developer.md b/.claude/agents/development/java-code-developer.md index 5d89aa067a65cc7a5bff84550b10b4699068f219..0e59862166a9be15db18fe6114d8001600ee7274 100644 --- a/.claude/agents/development/java-code-developer.md +++ b/.claude/agents/development/java-code-developer.md @@ -2,10 +2,18 @@ name: java-code-developer type: development description: Java后端开发专家,专注于Spring Boot应用开发,生成高质量的Java代码 -version: 4.9 +version: 4.10 author: DevSyncAgent Team -last_updated: 2026-07-16 +last_updated: 2026-07-20 changelog: + v4.10 - 2026-07-20 + - 🆕 新增第0.7步:强制搜索开发规范(设计文档§章节 + 项目CLAUDE.md),输出规范清单;并通过约束注入机制(DEV-STANDARD约束清单+DS编号)将规范清单作为第2-6步全局硬约束一次性注入,生成时逐条对照相关规范。只搜索不回看(不做第7步全局回看验证)。 + v4.9 - 2026-07-16 + - 🆕 配合 dev-flow Stage 3 内嵌「设计-开发协调循环」--开发过程中遇设计阻塞时返回 design_block_report JSON(code_complete+design_block_issues),主会话协调 des-xxx patch_mode 修补后重启本 Agent + - 🔄 第0.6步响应码预检查泛化为多 category 设计可开发性检测(response_code/api_endpoint/data_model/business_logic/config) + - 🛡️ 废止原第0.6步「询问用户补充响应码定义」模式(subagent 无法与用户交互),统一走 design_block_issues 返回供主会话协调 + - 🛡️ 新增末尾 design_block_report JSON 返回规范(复用 go-code-review 末尾 JSON 块模式,供主会话解析) + - 🛡️ 强化已有产物覆盖继续模式(收到【已有产物路径】时用 Edit 覆盖已生成代码,不从头重建) v4.9 - 2026-07-16 - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则 + signals 基于职责正向设计) v4.8 - 2026-07-15 @@ -512,53 +520,115 @@ git pull --- -### 第0.6步:设计文档响应码预检查 ⭐v3.5新增 +### 第0.6步:设计文档可开发性预检查 ⭐v4.9 重构(原响应码预检查泛化) + +**目的**:在开始生成代码前,检测设计文档是否存在影响开发的设计缺失,产出 `design_block_issues` 供 dev-flow 主会话协调 des-xxx patch_mode 修补。**废止原 v3.5「询问用户补充」模式**(本 Agent 作为 subagent 无法与用户交互)。 + +**检查维度(多 category)**: -**目的**:在开始生成代码前,验证设计文档是否包含必要的响应码定义 +| category | 检查内容 | 缺失判定 | +|---|---|---| +| response_code | 接口响应码定义(设计文档章节/api-spec.yaml) | 含 API 接口但无响应码定义 | +| api_endpoint | API 端点定义(路径/方法/参数) | 含 API 功能但端点未定义 | +| data_model | 数据模型/表结构 | 涉及数据持久化但无表结构 | +| business_logic | 核心业务规则/流程 | 关键业务流程未描述 | +| config | 配置项/环境变量 | 涉及外部依赖但配置未定义 | **检查逻辑**: ``` -IF 设计文档包含"接口设计"或"响应码规范"章节 THEN - 提取响应码定义(优先YAML格式,其次表格格式) - 记录到上下文变量 RESPONSE_CODES_DEFINED - 输出:"✅ 检测到响应码定义:[列出定义]" -ELSE IF 存在 api-spec.yaml THEN - 读取api-spec.yaml中的响应码定义 - 记录到上下文变量 RESPONSE_CODES_DEFINED - 输出:"✅ 从api-spec.yaml读取响应码定义:[列出定义]" -ELSE - 输出:"⚠️ 未检测到响应码定义" - 询问用户:"设计文档中未找到响应码定义。请确认: - 1. 本功能是否需要API接口? - 2. 如果需要,响应码如何定义? - - 使用项目默认(0=成功,其他=失败) - - 或提供具体响应码定义" - - 等待用户确认后,记录到 RESPONSE_CODES_DEFINED - - IF 用户选择跳过 OR 非API场景 THEN - 设置上下文变量 SKIP_RESPONSE_CODE_CHECK = true - END IF +design_block_issues = [] +FOR each category IN [response_code, api_endpoint, data_model, business_logic, config]: + IF 本功能涉及该 category AND 设计文档缺失该 category 的必要定义 THEN + design_block_issues.append({ + id: "DB-{序号}", + category: category, + location: "设计文档 §{对应章节}", + description: "{缺失内容描述}", + suggestion: "{修补建议}", + severity: "critical" | "high", + touches_api: (category IN [response_code, api_endpoint]) + }) +END FOR + +# response_code 兼容旧逻辑:优先设计文档章节,次选 api-spec.yaml +IF design_block_issues 无 response_code 类 AND (设计文档章节 OR api-spec.yaml) 含响应码定义 THEN + 记录到 RESPONSE_CODES_DEFINED(供第1步生成代码使用,原逻辑不变) +END IF +``` + +**决策**: +``` +IF design_block_issues 含 critical: + -> 不强行生成代码,置 code_complete=false,返回 design_block_issues + -> 主会话将调 des-xxx patch_mode 修补后重启本 Agent(注入【已有产物路径】覆盖继续) +ELIF design_block_issues 仅有 high: + -> 可降级处理:按现有降级逻辑生成代码,code_complete 视生成完成情况置 true,high 项记入 design_block_issues 供主会话知会 +ELSE: + -> 正常生成代码,完成后置 code_complete=true,design_block_issues=[] END IF ``` **输出格式**: ```markdown -## 响应码预检查报告 +## 设计可开发性预检查报告 -| 检查项 | 结果 | 定义内容 | -|:------:|:----:|---------| -| 设计文档章节 | ✅/❌ | - | -| api-spec.yaml | ✅/❌ | - | -| 用户确认 | ✅/❌ | - | +| category | 结果 | 说明 | +|:---:|:---:|---| +| response_code | ✅/❌ | - | +| api_endpoint | ✅/❌ | - | +| data_model | ✅/❌ | - | +| business_logic | ✅/❌ | - | +| config | ✅/❌ | - | -**响应码定义**: -- 成功:code=0 -- 失败:code=404,500 +**预检查结论**:通过 / 降级继续 / 阻塞(critical 项 N 个) -**预检查结论**:通过/跳过/失败 +**design_block_issues**:见末尾 design_block_report JSON 块 ``` +> ⚠️ 本步骤不再「询问用户」。所有设计缺失统一记入 design_block_issues,由主会话协调 des-xxx 修补或用户介入。code_complete 与 design_block_issues 的最终值在末尾 design_block_report JSON 块统一返回(见文末「design_block_report 返回规范」)。 + +--- + +### 第0.7步:强制搜索开发规范 ⭐新增 + +**目标**:开发前强制从设计文档和项目规范文件搜索开发规范,显式列出供第2步及之后代码生成时参照。本步骤只搜索并输出清单,不做生成后回看验证。 + +**搜索范围**(强制逐项检查存在性并搜索): +1. 设计文档:使用 dev-flow 主会话注入的【设计文档路径】(已按属性感知解析为 `{需求名}_后端设计.md` 或回退 `{需求名}_设计.md`;未注入时按第1步属性感知规则自行检测) +2. 业务项目根 `CLAUDE.md`:路径 = 【项目路径】/CLAUDE.md(【项目路径】由 dev-flow 主会话注入;未注入时用当前工作目录的 CLAUDE.md,不存在则跳过) + +**搜索关键词**(章节名 + 正文匹配,大小写不敏感): +`规范 | 约束 | constraint | standard | 技术约束 | 开发规范 | 技术选型 | 实现要求 | 非功能要求 | 编码规范` + +**输出**(强制,即使为空也输出): + +```markdown +## 开发规范搜索结果 + +**搜索源**: +| 搜索源 | 路径 | 是否存在 | +|---|---|:---:| +| 设计文档 | {路径} | ✅/❌ | +| 项目 CLAUDE.md | {路径} | ✅/❌ | + +**搜到的规范清单**: +| 序号 | 规范内容 | 来源(文件§章节) | 强制级别 | +|:---:|---|---|:---:| +| 1 | {规范内容} | 设计文档§3.2 技术约束 | must | +| ... | ... | ... | ... | +``` + +**若清单为空**:输出 `⚠️ 未搜索到明确开发规范,按项目默认规范生成`,继续第1步(无 DEV-STANDARD 约束可注入,第2-6步按项目默认规范生成)。 + +**约束注入(DEV-STANDARD 约束清单)**: + +将上述"搜到的规范清单"标记为 DEV-STANDARD 约束,每条赋予编号(DS-001, DS-002, ...),作为第2步~第6步所有代码生成步骤的**全局硬约束**(一次性注入,后续每步生成代码时自动适用,无需每步重新回看)。 + +**约束应用规则**: +- 生成本步代码时,逐条检查 DEV-STANDARD 约束是否与本步相关;相关的规范**必须**体现在生成的代码中 + +> ⚠️ 本步骤通过约束注入机制,将规范清单从"可选参照"升级为"生成时强制对照的全局硬约束"(一次性注入,后续自动适用)。仍不做第7步的全局回看验证(规范全局遵守情况不在本机制保障范围,按既定决策保留)。 + --- ### 第1步:分析设计文档 @@ -1021,6 +1091,47 @@ Feature文件:docs/{branch}/features/{name}.feature 如果推断的路径不存在,在"下一步建议"中提示用户手动指定。 +### design_block_report 返回规范(v4.9 新增,配合 dev-flow Stage 3 协调循环) + +本 Agent 作为 dev-flow Stage 3 subagent 运行时,**必须在返回文本末尾追加 design_block_report JSON 块**,供主会话解析决策(是否收敛/是否调 des-xxx 修补/是否上传石墨)。 + +**返回格式**(严格用 ```json 代码块包裹,置于返回文本最末尾): + +```json +{ + "code_complete": true, + "design_block_issues": [], + "progress_note": "代码开发完成,已生成 Entity/Service/Controller" +} +``` + +**字段语义**: + +| 字段 | 类型 | 语义 | +|---|---|---| +| code_complete | bool | true=代码开发完成(主会话进入收敛流程:审查设计修改+上传石墨);false=遇设计阻塞无法继续(主会话调 des-xxx patch_mode 修补后重启本 Agent) | +| design_block_issues | array | 设计阻塞清单(空数组=无阻塞)。每项含 id/category/location/description/suggestion/severity/touches_api | +| progress_note | string | 进度说明(已生成什么、阻塞在哪) | + +**design_block_issues 单项 schema**: +```json +{ + "id": "DB-001", + "category": "response_code|api_endpoint|data_model|business_logic|config", + "location": "设计文档 §2.3 接口设计", + "description": "响应码未定义", + "suggestion": "补充 code=0成功 / code=404未找到", + "severity": "critical|high|medium", + "touches_api": true +} +``` + +**两种返回场景**: +- 代码完成:`code_complete=true`,`design_block_issues=[]`(或含降级处理的 high 项供知会) +- 设计阻塞:`code_complete=false`,`design_block_issues=[critical/high 项]`,不强行生成不完整代码 + +**与已有产物覆盖**:主会话修补设计后重启本 Agent 时,注入【已有产物路径】,本 Agent 用 Edit 覆盖已生成代码继续,不从头重建。 + ### 协议执行 在完成代码开发后,**输出**以下完整格式: diff --git a/.claude/agents/development/python-code-developer.md b/.claude/agents/development/python-code-developer.md index 1823065855c539da20718b7024fbc08364cf3104..76acd85752fdb565ef3e282a41e4122378c53ef1 100644 --- a/.claude/agents/development/python-code-developer.md +++ b/.claude/agents/development/python-code-developer.md @@ -2,10 +2,18 @@ name: python-code-developer type: development description: Python后端开发专家,专注于FastAPI/Django应用开发,生成高质量的Python代码 -version: 4.9 +version: 4.10 author: DevSyncAgent Team -last_updated: 2026-07-16 +last_updated: 2026-07-20 changelog: + v4.10 - 2026-07-20 + - 🆕 新增第0.7步:强制搜索开发规范(设计文档§章节 + 项目CLAUDE.md),输出规范清单;并通过约束注入机制(DEV-STANDARD约束清单+DS编号)将规范清单作为第2-6步全局硬约束一次性注入,生成时逐条对照相关规范。只搜索不回看(不做第7步全局回看验证)。 + v4.9 - 2026-07-16 + - 🆕 配合 dev-flow Stage 3 内嵌「设计-开发协调循环」--开发过程中遇设计阻塞时返回 design_block_report JSON(code_complete+design_block_issues),主会话协调 des-xxx patch_mode 修补后重启本 Agent + - 🔄 第0.6步响应码预检查泛化为多 category 设计可开发性检测(response_code/api_endpoint/data_model/business_logic/config) + - 🛡️ 废止原第0.6步「询问用户补充响应码定义」模式(subagent 无法与用户交互),统一走 design_block_issues 返回供主会话协调 + - 🛡️ 新增末尾 design_block_report JSON 返回规范(复用 go-code-review 末尾 JSON 块模式,供主会话解析) + - 🛡️ 强化已有产物覆盖继续模式(收到【已有产物路径】时用 Edit 覆盖已生成代码,不从头重建) v4.9 - 2026-07-16 - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则 + signals 基于职责正向设计) v4.8 - 2026-07-15 @@ -519,53 +527,115 @@ git pull --- -### 第0.6步:设计文档响应码预检查 ⭐v3.5新增 +### 第0.6步:设计文档可开发性预检查 ⭐v4.9 重构(原响应码预检查泛化) + +**目的**:在开始生成代码前,检测设计文档是否存在影响开发的设计缺失,产出 `design_block_issues` 供 dev-flow 主会话协调 des-xxx patch_mode 修补。**废止原 v3.5「询问用户补充」模式**(本 Agent 作为 subagent 无法与用户交互)。 + +**检查维度(多 category)**: -**目的**:在开始生成代码前,验证设计文档是否包含必要的响应码定义 +| category | 检查内容 | 缺失判定 | +|---|---|---| +| response_code | 接口响应码定义(设计文档章节/api-spec.yaml) | 含 API 接口但无响应码定义 | +| api_endpoint | API 端点定义(路径/方法/参数) | 含 API 功能但端点未定义 | +| data_model | 数据模型/表结构 | 涉及数据持久化但无表结构 | +| business_logic | 核心业务规则/流程 | 关键业务流程未描述 | +| config | 配置项/环境变量 | 涉及外部依赖但配置未定义 | **检查逻辑**: ``` -IF 设计文档包含"接口设计"或"响应码规范"章节 THEN - 提取响应码定义(优先YAML格式,其次表格格式) - 记录到上下文变量 RESPONSE_CODES_DEFINED - 输出:"✅ 检测到响应码定义:[列出定义]" -ELSE IF 存在 api-spec.yaml THEN - 读取api-spec.yaml中的响应码定义 - 记录到上下文变量 RESPONSE_CODES_DEFINED - 输出:"✅ 从api-spec.yaml读取响应码定义:[列出定义]" -ELSE - 输出:"⚠️ 未检测到响应码定义" - 询问用户:"设计文档中未找到响应码定义。请确认: - 1. 本功能是否需要API接口? - 2. 如果需要,响应码如何定义? - - 使用项目默认(0=成功,其他=失败) - - 或提供具体响应码定义" - - 等待用户确认后,记录到 RESPONSE_CODES_DEFINED - - IF 用户选择跳过 OR 非API场景 THEN - 设置上下文变量 SKIP_RESPONSE_CODE_CHECK = true - END IF +design_block_issues = [] +FOR each category IN [response_code, api_endpoint, data_model, business_logic, config]: + IF 本功能涉及该 category AND 设计文档缺失该 category 的必要定义 THEN + design_block_issues.append({ + id: "DB-{序号}", + category: category, + location: "设计文档 §{对应章节}", + description: "{缺失内容描述}", + suggestion: "{修补建议}", + severity: "critical" | "high", + touches_api: (category IN [response_code, api_endpoint]) + }) +END FOR + +# response_code 兼容旧逻辑:优先设计文档章节,次选 api-spec.yaml +IF design_block_issues 无 response_code 类 AND (设计文档章节 OR api-spec.yaml) 含响应码定义 THEN + 记录到 RESPONSE_CODES_DEFINED(供第1步生成代码使用,原逻辑不变) +END IF +``` + +**决策**: +``` +IF design_block_issues 含 critical: + -> 不强行生成代码,置 code_complete=false,返回 design_block_issues + -> 主会话将调 des-xxx patch_mode 修补后重启本 Agent(注入【已有产物路径】覆盖继续) +ELIF design_block_issues 仅有 high: + -> 可降级处理:按现有降级逻辑生成代码,code_complete 视生成完成情况置 true,high 项记入 design_block_issues 供主会话知会 +ELSE: + -> 正常生成代码,完成后置 code_complete=true,design_block_issues=[] END IF ``` **输出格式**: ```markdown -## 响应码预检查报告 +## 设计可开发性预检查报告 -| 检查项 | 结果 | 定义内容 | -|:------:|:----:|---------| -| 设计文档章节 | ✅/❌ | - | -| api-spec.yaml | ✅/❌ | - | -| 用户确认 | ✅/❌ | - | +| category | 结果 | 说明 | +|:---:|:---:|---| +| response_code | ✅/❌ | - | +| api_endpoint | ✅/❌ | - | +| data_model | ✅/❌ | - | +| business_logic | ✅/❌ | - | +| config | ✅/❌ | - | -**响应码定义**: -- 成功:code=0 -- 失败:code=404,500 +**预检查结论**:通过 / 降级继续 / 阻塞(critical 项 N 个) -**预检查结论**:通过/跳过/失败 +**design_block_issues**:见末尾 design_block_report JSON 块 ``` +> ⚠️ 本步骤不再「询问用户」。所有设计缺失统一记入 design_block_issues,由主会话协调 des-xxx 修补或用户介入。code_complete 与 design_block_issues 的最终值在末尾 design_block_report JSON 块统一返回(见文末「design_block_report 返回规范」)。 + +--- + +### 第0.7步:强制搜索开发规范 ⭐新增 + +**目标**:开发前强制从设计文档和项目规范文件搜索开发规范,显式列出供第2步及之后代码生成时参照。本步骤只搜索并输出清单,不做生成后回看验证。 + +**搜索范围**(强制逐项检查存在性并搜索): +1. 设计文档:使用 dev-flow 主会话注入的【设计文档路径】(已按属性感知解析为 `{需求名}_后端设计.md` 或回退 `{需求名}_设计.md`;未注入时按第1步属性感知规则自行检测) +2. 业务项目根 `CLAUDE.md`:路径 = 【项目路径】/CLAUDE.md(【项目路径】由 dev-flow 主会话注入;未注入时用当前工作目录的 CLAUDE.md,不存在则跳过) + +**搜索关键词**(章节名 + 正文匹配,大小写不敏感): +`规范 | 约束 | constraint | standard | 技术约束 | 开发规范 | 技术选型 | 实现要求 | 非功能要求 | 编码规范` + +**输出**(强制,即使为空也输出): + +```markdown +## 开发规范搜索结果 + +**搜索源**: +| 搜索源 | 路径 | 是否存在 | +|---|---|:---:| +| 设计文档 | {路径} | ✅/❌ | +| 项目 CLAUDE.md | {路径} | ✅/❌ | + +**搜到的规范清单**: +| 序号 | 规范内容 | 来源(文件§章节) | 强制级别 | +|:---:|---|---|:---:| +| 1 | {规范内容} | 设计文档§3.2 技术约束 | must | +| ... | ... | ... | ... | +``` + +**若清单为空**:输出 `⚠️ 未搜索到明确开发规范,按项目默认规范生成`,继续第1步(无 DEV-STANDARD 约束可注入,第2-6步按项目默认规范生成)。 + +**约束注入(DEV-STANDARD 约束清单)**: + +将上述"搜到的规范清单"标记为 DEV-STANDARD 约束,每条赋予编号(DS-001, DS-002, ...),作为第2步~第6步所有代码生成步骤的**全局硬约束**(一次性注入,后续每步生成代码时自动适用,无需每步重新回看)。 + +**约束应用规则**: +- 生成本步代码时,逐条检查 DEV-STANDARD 约束是否与本步相关;相关的规范**必须**体现在生成的代码中 + +> ⚠️ 本步骤通过约束注入机制,将规范清单从"可选参照"升级为"生成时强制对照的全局硬约束"(一次性注入,后续自动适用)。仍不做第7步的全局回看验证(规范全局遵守情况不在本机制保障范围,按既定决策保留)。 + --- ### 第1步:分析设计文档 @@ -1027,6 +1097,47 @@ Feature文件:docs/{branch}/features/{name}.feature 如果推断的路径不存在,在"下一步建议"中提示用户手动指定。 +### design_block_report 返回规范(v4.9 新增,配合 dev-flow Stage 3 协调循环) + +本 Agent 作为 dev-flow Stage 3 subagent 运行时,**必须在返回文本末尾追加 design_block_report JSON 块**,供主会话解析决策(是否收敛/是否调 des-xxx 修补/是否上传石墨)。 + +**返回格式**(严格用 ```json 代码块包裹,置于返回文本最末尾): + +```json +{ + "code_complete": true, + "design_block_issues": [], + "progress_note": "代码开发完成,已生成 Entity/Service/Controller" +} +``` + +**字段语义**: + +| 字段 | 类型 | 语义 | +|---|---|---| +| code_complete | bool | true=代码开发完成(主会话进入收敛流程:审查设计修改+上传石墨);false=遇设计阻塞无法继续(主会话调 des-xxx patch_mode 修补后重启本 Agent) | +| design_block_issues | array | 设计阻塞清单(空数组=无阻塞)。每项含 id/category/location/description/suggestion/severity/touches_api | +| progress_note | string | 进度说明(已生成什么、阻塞在哪) | + +**design_block_issues 单项 schema**: +```json +{ + "id": "DB-001", + "category": "response_code|api_endpoint|data_model|business_logic|config", + "location": "设计文档 §2.3 接口设计", + "description": "响应码未定义", + "suggestion": "补充 code=0成功 / code=404未找到", + "severity": "critical|high|medium", + "touches_api": true +} +``` + +**两种返回场景**: +- 代码完成:`code_complete=true`,`design_block_issues=[]`(或含降级处理的 high 项供知会) +- 设计阻塞:`code_complete=false`,`design_block_issues=[critical/high 项]`,不强行生成不完整代码 + +**与已有产物覆盖**:主会话修补设计后重启本 Agent 时,注入【已有产物路径】,本 Agent 用 Edit 覆盖已生成代码继续,不从头重建。 + ### 协议执行 在完成代码开发后,**输出**以下完整格式: diff --git a/.claude/agents/development/typescript-code-developer.md b/.claude/agents/development/typescript-code-developer.md index 19b8b64a444797af3398e5d79fc397339b1adfab..7e1b945061ed8f23a66a610f0569dd8d79890827 100644 --- a/.claude/agents/development/typescript-code-developer.md +++ b/.claude/agents/development/typescript-code-developer.md @@ -2,10 +2,18 @@ name: typescript-code-developer type: development description: TypeScript后端开发专家,专注于NestJS应用开发,生成高质量的TypeScript代码 -version: 4.9 +version: 4.10 author: DevSyncAgent Team -last_updated: 2026-07-16 +last_updated: 2026-07-20 changelog: + v4.10 - 2026-07-20 + - 🆕 新增第0.7步:强制搜索开发规范(设计文档§章节 + 项目CLAUDE.md),输出规范清单;并通过约束注入机制(DEV-STANDARD约束清单+DS编号)将规范清单作为第2-6步全局硬约束一次性注入,生成时逐条对照相关规范。只搜索不回看(不做第7步全局回看验证)。 + v4.9 - 2026-07-16 + - 🆕 配合 dev-flow Stage 3 内嵌「设计-开发协调循环」--开发过程中遇设计阻塞时返回 design_block_report JSON(code_complete+design_block_issues),主会话协调 des-xxx patch_mode 修补后重启本 Agent + - 🔄 第0.6步响应码预检查泛化为多 category 设计可开发性检测(response_code/api_endpoint/data_model/business_logic/config) + - 🛡️ 废止原第0.6步「询问用户补充响应码定义」模式(subagent 无法与用户交互),统一走 design_block_issues 返回供主会话协调 + - 🛡️ 新增末尾 design_block_report JSON 返回规范(复用 go-code-review 末尾 JSON 块模式,供主会话解析) + - 🛡️ 强化已有产物覆盖继续模式(收到【已有产物路径】时用 Edit 覆盖已生成代码,不从头重建) v4.9 - 2026-07-16 - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则 + signals 基于职责正向设计) v4.8 - 2026-07-15 @@ -367,25 +375,115 @@ git pull --- -### 第0.6步:设计文档响应码预检查 +### 第0.6步:设计文档可开发性预检查 ⭐v4.9 重构(原响应码预检查泛化) + +**目的**:在开始生成代码前,检测设计文档是否存在影响开发的设计缺失,产出 `design_block_issues` 供 dev-flow 主会话协调 des-xxx patch_mode 修补。**废止原 v3.5「询问用户补充」模式**(本 Agent 作为 subagent 无法与用户交互)。 + +**检查维度(多 category)**: -**目的**:在开始生成代码前,验证设计文档是否包含必要的响应码定义 +| category | 检查内容 | 缺失判定 | +|---|---|---| +| response_code | 接口响应码定义(设计文档章节/api-spec.yaml) | 含 API 接口但无响应码定义 | +| api_endpoint | API 端点定义(路径/方法/参数) | 含 API 功能但端点未定义 | +| data_model | 数据模型/表结构 | 涉及数据持久化但无表结构 | +| business_logic | 核心业务规则/流程 | 关键业务流程未描述 | +| config | 配置项/环境变量 | 涉及外部依赖但配置未定义 | **检查逻辑**: ``` -IF 设计文档包含"接口设计"或"响应码规范"章节 THEN - 提取响应码定义 - 记录到上下文变量 RESPONSE_CODES_DEFINED - 输出:"✅ 检测到响应码定义:[列出定义]" -ELSE IF 存在 api-spec.yaml THEN - 读取api-spec.yaml中的响应码定义 - 记录到上下文变量 RESPONSE_CODES_DEFINED -ELSE - 输出:"⚠️ 未检测到响应码定义" - 询问用户确认 +design_block_issues = [] +FOR each category IN [response_code, api_endpoint, data_model, business_logic, config]: + IF 本功能涉及该 category AND 设计文档缺失该 category 的必要定义 THEN + design_block_issues.append({ + id: "DB-{序号}", + category: category, + location: "设计文档 §{对应章节}", + description: "{缺失内容描述}", + suggestion: "{修补建议}", + severity: "critical" | "high", + touches_api: (category IN [response_code, api_endpoint]) + }) +END FOR + +# response_code 兼容旧逻辑:优先设计文档章节,次选 api-spec.yaml +IF design_block_issues 无 response_code 类 AND (设计文档章节 OR api-spec.yaml) 含响应码定义 THEN + 记录到 RESPONSE_CODES_DEFINED(供第1步生成代码使用,原逻辑不变) END IF ``` +**决策**: +``` +IF design_block_issues 含 critical: + -> 不强行生成代码,置 code_complete=false,返回 design_block_issues + -> 主会话将调 des-xxx patch_mode 修补后重启本 Agent(注入【已有产物路径】覆盖继续) +ELIF design_block_issues 仅有 high: + -> 可降级处理:按现有降级逻辑生成代码,code_complete 视生成完成情况置 true,high 项记入 design_block_issues 供主会话知会 +ELSE: + -> 正常生成代码,完成后置 code_complete=true,design_block_issues=[] +END IF +``` + +**输出格式**: +```markdown +## 设计可开发性预检查报告 + +| category | 结果 | 说明 | +|:---:|:---:|---| +| response_code | ✅/❌ | - | +| api_endpoint | ✅/❌ | - | +| data_model | ✅/❌ | - | +| business_logic | ✅/❌ | - | +| config | ✅/❌ | - | + +**预检查结论**:通过 / 降级继续 / 阻塞(critical 项 N 个) + +**design_block_issues**:见末尾 design_block_report JSON 块 +``` + +> ⚠️ 本步骤不再「询问用户」。所有设计缺失统一记入 design_block_issues,由主会话协调 des-xxx 修补或用户介入。code_complete 与 design_block_issues 的最终值在末尾 design_block_report JSON 块统一返回(见文末「design_block_report 返回规范」)。 + +--- + +### 第0.7步:强制搜索开发规范 ⭐新增 + +**目标**:开发前强制从设计文档和项目规范文件搜索开发规范,显式列出供第2步及之后代码生成时参照。本步骤只搜索并输出清单,不做生成后回看验证。 + +**搜索范围**(强制逐项检查存在性并搜索): +1. 设计文档:使用 dev-flow 主会话注入的【设计文档路径】(已按属性感知解析为 `{需求名}_后端设计.md` 或回退 `{需求名}_设计.md`;未注入时按第1步属性感知规则自行检测) +2. 业务项目根 `CLAUDE.md`:路径 = 【项目路径】/CLAUDE.md(【项目路径】由 dev-flow 主会话注入;未注入时用当前工作目录的 CLAUDE.md,不存在则跳过) + +**搜索关键词**(章节名 + 正文匹配,大小写不敏感): +`规范 | 约束 | constraint | standard | 技术约束 | 开发规范 | 技术选型 | 实现要求 | 非功能要求 | 编码规范` + +**输出**(强制,即使为空也输出): + +```markdown +## 开发规范搜索结果 + +**搜索源**: +| 搜索源 | 路径 | 是否存在 | +|---|---|:---:| +| 设计文档 | {路径} | ✅/❌ | +| 项目 CLAUDE.md | {路径} | ✅/❌ | + +**搜到的规范清单**: +| 序号 | 规范内容 | 来源(文件§章节) | 强制级别 | +|:---:|---|---|:---:| +| 1 | {规范内容} | 设计文档§3.2 技术约束 | must | +| ... | ... | ... | ... | +``` + +**若清单为空**:输出 `⚠️ 未搜索到明确开发规范,按项目默认规范生成`,继续第1步(无 DEV-STANDARD 约束可注入,第2-6步按项目默认规范生成)。 + +**约束注入(DEV-STANDARD 约束清单)**: + +将上述"搜到的规范清单"标记为 DEV-STANDARD 约束,每条赋予编号(DS-001, DS-002, ...),作为第2步~第6步所有代码生成步骤的**全局硬约束**(一次性注入,后续每步生成代码时自动适用,无需每步重新回看)。 + +**约束应用规则**: +- 生成本步代码时,逐条检查 DEV-STANDARD 约束是否与本步相关;相关的规范**必须**体现在生成的代码中 + +> ⚠️ 本步骤通过约束注入机制,将规范清单从"可选参照"升级为"生成时强制对照的全局硬约束"(一次性注入,后续自动适用)。仍不做第7步的全局回看验证(规范全局遵守情况不在本机制保障范围,按既定决策保留)。 + --- ### 第1步:分析设计文档 @@ -967,6 +1065,49 @@ describe('{EntityName}Controller (e2e)', () => { --- +## design_block_report 返回规范(v4.9 新增,配合 dev-flow Stage 3 协调循环) + +本 Agent 作为 dev-flow Stage 3 subagent 运行时,**必须在返回文本末尾追加 design_block_report JSON 块**,供主会话解析决策(是否收敛/是否调 des-xxx 修补/是否上传石墨)。 + +**返回格式**(严格用 ```json 代码块包裹,置于返回文本最末尾): + +```json +{ + "code_complete": true, + "design_block_issues": [], + "progress_note": "代码开发完成,已生成 Entity/Service/Controller" +} +``` + +**字段语义**: + +| 字段 | 类型 | 语义 | +|---|---|---| +| code_complete | bool | true=代码开发完成(主会话进入收敛流程:审查设计修改+上传石墨);false=遇设计阻塞无法继续(主会话调 des-xxx patch_mode 修补后重启本 Agent) | +| design_block_issues | array | 设计阻塞清单(空数组=无阻塞)。每项含 id/category/location/description/suggestion/severity/touches_api | +| progress_note | string | 进度说明(已生成什么、阻塞在哪) | + +**design_block_issues 单项 schema**: +```json +{ + "id": "DB-001", + "category": "response_code|api_endpoint|data_model|business_logic|config", + "location": "设计文档 §2.3 接口设计", + "description": "响应码未定义", + "suggestion": "补充 code=0成功 / code=404未找到", + "severity": "critical|high|medium", + "touches_api": true +} +``` + +**两种返回场景**: +- 代码完成:`code_complete=true`,`design_block_issues=[]`(或含降级处理的 high 项供知会) +- 设计阻塞:`code_complete=false`,`design_block_issues=[critical/high 项]`,不强行生成不完整代码 + +**与已有产物覆盖**:主会话修补设计后重启本 Agent 时,注入【已有产物路径】,本 Agent 用 Edit 覆盖已生成代码继续,不从头重建。 + +--- + ## 下一步建议 代码开发完成后,建议执行以下测试流程: diff --git a/.claude/agents/development/web-frontend-developer.md b/.claude/agents/development/web-frontend-developer.md index 714981fd2937af8f91f29d6ae283c7aba254aa3d..8cb54bb57d253f08aaebca6e199d6127b809880c 100644 --- a/.claude/agents/development/web-frontend-developer.md +++ b/.claude/agents/development/web-frontend-developer.md @@ -2,10 +2,18 @@ name: web-frontend-developer type: development description: 前端项目开发专家,支持React/Vue项目的本地代码生成,遵循现有代码规范 -version: 4.7 +version: 4.8 author: DevSyncAgent Team -last_updated: 2026-07-16 +last_updated: 2026-07-20 changelog: + v4.8 - 2026-07-20 + - 🆕 新增第0.7步:强制搜索开发规范(设计文档§章节 + 项目CLAUDE.md),输出规范清单;并通过约束注入机制(DEV-STANDARD约束清单+DS编号)将规范清单作为第2-6步全局硬约束一次性注入,生成时逐条对照相关规范。只搜索不回看(不做第7步全局回看验证)。 + v4.7 - 2026-07-16 + - 🆕 配合 dev-flow Stage 3 内嵌「设计-开发协调循环」--开发过程中遇设计阻塞时返回 design_block_report JSON(code_complete+design_block_issues),主会话协调 des-xxx patch_mode 修补后重启本 Agent + - 🆕 新增第0.6步「设计文档可开发性预检查」(前端 category:api_endpoint/component_design/state_management/interaction/config),检测设计缺失产出 design_block_issues + - 🛡️ 本 Agent 作为 subagent 无法与用户交互,设计缺失统一走 design_block_issues 返回供主会话协调 + - 🛡️ 新增末尾 design_block_report JSON 返回规范(复用 go-code-review 末尾 JSON 块模式,供主会话解析) + - 🛡️ 强化已有产物覆盖继续模式(收到【已有产物路径】时用 Edit 覆盖已生成代码,不从头重建) v4.7 - 2026-07-16 - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则 + signals 基于职责正向设计) v4.6 - 2026-06-01 @@ -192,6 +200,113 @@ echo "✅ 框架检测完成: $FRAMEWORK, UI库: $UI_LIBRARY, 状态管理: $STA --- +### 第0.6步:设计文档可开发性预检查 ⭐v4.7 新增(前端 category) + +**目的**:在开始生成代码前,检测设计文档是否存在影响开发的设计缺失,产出 `design_block_issues` 供 dev-flow 主会话协调 des-xxx patch_mode 修补。**本 Agent 作为 subagent 无法与用户交互**,所有缺失统一记入 design_block_issues 返回。 + +**检查维度(多 category,前端关注项)**: + +| category | 检查内容 | 缺失判定 | +|---|---|---| +| api_endpoint | Web API 端点定义(路径/方法/请求响应结构) | 含接口调用但端点未定义 | +| component_design | 组件结构/页面布局/组件拆分 | 涉及页面渲染但无组件设计 | +| state_management | 状态管理/数据流(Redux/Pinia/Context) | 涉及跨组件状态但无状态设计 | +| interaction | 交互流程/事件处理/表单校验 | 关键交互未描述 | +| config | 配置项/环境变量/构建配置 | 涉及外部依赖但配置未定义 | + +**检查逻辑**: +``` +design_block_issues = [] +FOR each category IN [api_endpoint, component_design, state_management, interaction, config]: + IF 本功能涉及该 category AND 设计文档缺失该 category 的必要定义 THEN + design_block_issues.append({ + id: "DB-{序号}", + category: category, + location: "设计文档 §{对应章节}", + description: "{缺失内容描述}", + suggestion: "{修补建议}", + severity: "critical" | "high", + touches_api: (category IN [api_endpoint]) + }) +END FOR + +``` + +**决策**: +``` +IF design_block_issues 含 critical: + -> 不强行生成代码,置 code_complete=false,返回 design_block_issues + -> 主会话将调 des-xxx patch_mode 修补后重启本 Agent(注入【已有产物路径】覆盖继续) +ELIF design_block_issues 仅有 high: + -> 可降级处理:按现有降级逻辑生成代码,code_complete 视生成完成情况置 true,high 项记入 design_block_issues 供主会话知会 +ELSE: + -> 正常生成代码,完成后置 code_complete=true,design_block_issues=[] +END IF +``` + +**输出格式**: +```markdown +## 设计可开发性预检查报告 + +| category | 结果 | 说明 | +|:---:|:---:|---| +| api_endpoint | ✅/❌ | - | +| component_design | ✅/❌ | - | +| state_management | ✅/❌ | - | +| interaction | ✅/❌ | - | +| config | ✅/❌ | - | + +**预检查结论**:通过 / 降级继续 / 阻塞(critical 项 N 个) + +**design_block_issues**:见末尾 design_block_report JSON 块 +``` + +> ⚠️ 本步骤不「询问用户」。所有设计缺失统一记入 design_block_issues,由主会话协调 des-xxx 修补或用户介入。code_complete 与 design_block_issues 的最终值在末尾 design_block_report JSON 块统一返回(见文末「design_block_report 返回规范」)。 + +--- + +### 第0.7步:强制搜索开发规范 ⭐新增 + +**目标**:开发前强制从设计文档和项目规范文件搜索开发规范,显式列出供第2步及之后代码生成时参照。本步骤只搜索并输出清单,不做生成后回看验证。 + +**搜索范围**(强制逐项检查存在性并搜索): +1. 设计文档:使用 dev-flow 主会话注入的【设计文档路径】(已按属性感知解析为 `{需求名}_前端设计.md` 或回退 `{需求名}_设计.md`;未注入时按第1步属性感知规则自行检测) +2. 业务项目根 `CLAUDE.md`:路径 = 【项目路径】/CLAUDE.md(【项目路径】由 dev-flow 主会话注入;未注入时用当前工作目录的 CLAUDE.md,不存在则跳过) + +**搜索关键词**(章节名 + 正文匹配,大小写不敏感): +`规范 | 约束 | constraint | standard | 技术约束 | 开发规范 | 技术选型 | 实现要求 | 非功能要求 | 编码规范` + +**输出**(强制,即使为空也输出): + +```markdown +## 开发规范搜索结果 + +**搜索源**: +| 搜索源 | 路径 | 是否存在 | +|---|---|:---:| +| 设计文档 | {路径} | ✅/❌ | +| 项目 CLAUDE.md | {路径} | ✅/❌ | + +**搜到的规范清单**: +| 序号 | 规范内容 | 来源(文件§章节) | 强制级别 | +|:---:|---|---|:---:| +| 1 | {规范内容} | 设计文档§3.2 技术约束 | must | +| ... | ... | ... | ... | +``` + +**若清单为空**:输出 `⚠️ 未搜索到明确开发规范,按项目默认规范生成`,继续第1步(无 DEV-STANDARD 约束可注入,第2-6步按项目默认规范生成)。 + +**约束注入(DEV-STANDARD 约束清单)**: + +将上述"搜到的规范清单"标记为 DEV-STANDARD 约束,每条赋予编号(DS-001, DS-002, ...),作为第2步~第6步所有代码生成步骤的**全局硬约束**(一次性注入,后续每步生成代码时自动适用,无需每步重新回看)。 + +**约束应用规则**: +- 生成本步代码时,逐条检查 DEV-STANDARD 约束是否与本步相关;相关的规范**必须**体现在生成的代码中 + +> ⚠️ 本步骤通过约束注入机制,将规范清单从"可选参照"升级为"生成时强制对照的全局硬约束"(一次性注入,后续自动适用)。仍不做第7步的全局回看验证(规范全局遵守情况不在本机制保障范围,按既定决策保留)。 + +--- + ### 第1步:读取设计文档 **目标**:从设计文档中提取前端开发所需的信息 @@ -645,6 +760,47 @@ fi **默认行为**:代码生成完成且编译验证通过后执行 +### design_block_report 返回规范(v4.7 新增,配合 dev-flow Stage 3 协调循环) + +本 Agent 作为 dev-flow Stage 3 subagent 运行时,**必须在返回文本末尾追加 design_block_report JSON 块**,供主会话解析决策(是否收敛/是否调 des-xxx 修补/是否上传石墨)。 + +**返回格式**(严格用 ```json 代码块包裹,置于返回文本最末尾): + +```json +{ + "code_complete": true, + "design_block_issues": [], + "progress_note": "代码开发完成,已生成 Component/Service/Store" +} +``` + +**字段语义**: + +| 字段 | 类型 | 语义 | +|---|---|---| +| code_complete | bool | true=代码开发完成(主会话进入收敛流程:审查设计修改+上传石墨);false=遇设计阻塞无法继续(主会话调 des-xxx patch_mode 修补后重启本 Agent) | +| design_block_issues | array | 设计阻塞清单(空数组=无阻塞)。每项含 id/category/location/description/suggestion/severity/touches_api | +| progress_note | string | 进度说明(已生成什么、阻塞在哪) | + +**design_block_issues 单项 schema**: +```json +{ + "id": "DB-001", + "category": "api_endpoint|component_design|state_management|interaction|config", + "location": "设计文档 §3.2 组件设计", + "description": "组件结构未定义", + "suggestion": "补充页面组件拆分与布局", + "severity": "critical|high|medium", + "touches_api": true +} +``` + +**两种返回场景**: +- 代码完成:`code_complete=true`,`design_block_issues=[]`(或含降级处理的 high 项供知会) +- 设计阻塞:`code_complete=false`,`design_block_issues=[critical/high 项]`,不强行生成不完整代码 + +**与已有产物覆盖**:主会话修补设计后重启本 Agent 时,注入【已有产物路径】,本 Agent 用 Edit 覆盖已生成代码继续,不从头重建。 + ### 协议执行 ```markdown diff --git a/.claude/commands/dev-flow.md b/.claude/commands/dev-flow.md index fa7ad4b3fc2be27331df91160badfcdbaee28e3c..a5288eb89ef811050b757596ae7e1b0bc8803718 100644 --- a/.claude/commands/dev-flow.md +++ b/.claude/commands/dev-flow.md @@ -2,10 +2,14 @@ name: dev-flow type: command description: 开发工作流编排命令,启动完整的开发工作流,从需求分析到测试报告生成,支持版本粒度管理 -version: 4.9 +version: 4.10 author: DevSyncAgent Team -last_updated: 2026-07-21 +last_updated: 2026-07-23 changelog: + v4.10 - 2026-07-22 + - 🆕 需求名称格式规范升级为5段全角中括号:【xx风险】【用户体验优化/运维优化/需求部门】【组件名】【一级模块-二级模块】【前后端需求】需求名称(如 【低风险】【运维优化】【Exchangis】【告警管理-IMS告警】【前后端需求】IMS告警增加ecc_receiver ECC通知人字段) + - 🔄 正则升级为 ^【(高风险|中风险|低风险)】【(.+?)】【(.+?)】【(.+?)】【(.+?)】(.+)$(5段全角中括号;第1段风险枚举,第2/3/4/5段自由文本);name 取第6段需求名称,rawFullName 仍为完整格式串 + - 🔗 配套修改:stage-hooks.md(versions.json schema 示例 rawFullName 同步新格式) v4.9 - 2026-07-23 - 🆕 阶段3 S6:多git编排(多项目多仓库,S12纵向增量)。核心:工作目录模型从单一pwd扩展为多仓库localPath映射。4处新增交互:G1第3.8轮"是否多git"询问+G2每子系统git仓库收集(SSH+localPath)+G3 Stage4需求级跨仓库提交确认+G4 complete-version版本级跨仓库归档确认。数据模型:versions.json contextSchemaVersion 2.0→2.1+isMultiGit+subsystems[].gitUrl/localPath+repositories[]去重仓库列表+requirements[].repositoryId+migrate_v2_to_v2_1向后兼容。8改动点:dev-flow第3.8轮+create-version schema+Stage4需求级跨仓库提交(H1修正:用req.repositoryId非遍历所有仓库)+步骤11版本级跨仓库归档+A6 gitUrl用sub.gitUrl+阶段Prompt【代码工作目录】注入localPath+context.md加repositoryId+add-story仓库归属+context-contract字段。H1修正(Stage4需求级vs步骤11版本级层次)。5决策点(G-D1工作目录模型/G-D2 Stage3 Agent非pwd工作/G-D3跨仓库原子性PendingItem/G-D4每仓库分支/G-D5多project-context)。P5单分支在多git下自然延伸为每仓库一分支(不同仓库同名分支不冲突)。E7技术栈多git下变真实(G-D5多project-context处理) - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目 @@ -22,6 +26,12 @@ changelog: - 🐛 修复 636c1008 hide 提交不彻底:dev-flow.md "### 生成变更单""### 回滚到指定阶段"章节本体保留但无隐藏标注,机器人模式 LLM 读完整 dev-flow.md 生成菜单时误将其当主菜单项→出现 8 项菜单(含变更单/回滚入口)。修复:两章节标题加"⛔已从主菜单隐藏"标注 + 章节开头加明确禁止列入主菜单的约束说明;STARTED 段补"主菜单仅以下6项,禁止把后续章节当菜单项"双保险。能力保留不变(变更单 skill 手动渠道、回滚 execute_rollback 内部调用) - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目 v4.9 - 2026-07-20 + - 🆕 版本轨添加需求支持需求名称格式规范:[风险等级][一级模块名][二级模块名][前后端]需求描述(如 [中风险][文件上传][作业管理-数据源][前后端需求]文件数据集导入功能) + - 🆕 add-story/add-stories 录入时内联格式校验+允许跳过降级(正则 ^\[(高风险|中风险|低风险)\]\[(.+?)\]\[(.+?)\]\[(.+?)\](.+)$);A3 调用 add-system-story 的 name=rawFullName(完整格式串;降级=纯文本 name) + - 🆕 versions.json requirements[] 只新增 rawFullName 字段;name 取末尾需求描述(文档命名用);riskLevel/moduleL1/moduleL2/frontendBackend 仅作确认展示不持久化 + - ⚠️ 风险等级仅作名称前缀和本地展示,不映射 DPMS priority(A3 维持原状不传 priority,DPMS 默认 2=中;P1 priority 维持原逻辑由 req-type-classifier 识别写回) + - 🔗 配套修改:dev-flow.md(添加单个/批量版本需求章节内联格式校验+A3调用4处 name=rawFullName)、stage-hooks.md(versions.json schema 新增 rawFullName) + - ⚠️ 适用范围:仅版本轨添加需求(单需求轨不与 DPMS 交互,不做格式校验) - 🐛 修复创建版本灰度发布场景双重缺口:①收集侧 dev-flow.md 第4轮补"灰度发布日期"询问(选"是"后追加,含 YYYY-MM-DD 格式校验+版本周期范围校验,IF/ELSE双分支同步);②传递侧 create-version.md A2b 补全 MCP 必填 isNeedGrayRelease 与条件必填 expectGrayReleaseDate(对齐 dpms-requirements-sync SKILL.md:418-472 权威定义);versions.json + version-context.md 新增 isNeedGrayRelease/grayReleaseDate 字段持久化 - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目 v4.9 - 2026-07-20 @@ -882,7 +892,7 @@ END IF > 📄 `.claude/config/dev-flow-checklists/complete-version.md` > ⛔ 禁止跳过Read直接执行。每个步骤执行完毕后必须逐项验证。 -**概要**:12步流程(状态检查→A6系列操作→DPMS版本状态更新→Business API Version状态更新→总结报告→归档→Git提交+推送)。A6系列含关联子系统版本分支、流水线封板、测试报告汇总、新增测试报告、发布测试报告。步骤11将版本文档(docs/)、归档目录(dev/completed/)、版本配置(versions.json)和待补录记录统一提交到git并可选推送。 +**概要**:状态检查→用户确认→A5.2前置检查→A6系列操作(关联子系统版本分支+流水线封板+测试报告汇总/新增/发布)→Business API Version状态更新→总结报告→归档→生成变更单询问→Git提交+推送。A6系列含关联子系统版本分支、流水线封板、测试报告汇总、新增测试报告、发布测试报告。步骤11将版本文档(docs/)、归档目录(dev/completed/)、版本配置(versions.json)和待补录记录统一提交到git并可选推送。 > 📋 **A5.2 已迁移至 Stage 10.3(v4.9)**:dpms 回归用例同步在 Stage 10 版本级回归测试中执行(所有需求 Stage 9 通过后触发)。complete-version 步骤2.5 改为前置检查(stage10Completed 已执行则跳过,未执行则提示补执行或跳过)。详见 `.claude/config/dev-flow-checklists/stage-10-version-regression.md`。 @@ -1233,10 +1243,26 @@ execute_rollback(requirement=target_requirement, mode="interactive", reason="主 1. 验证版本存在(读取 `dev/versions/versions.json`) 2. 验证版本未关联(`assigned == false`),若已关联则输出 "❌ 版本已关联版本计划,不允许新增需求!" 3. 验证版本未启动(`started == false`),若已启动则警告并询问是否继续 -4. 从 `story-desc` 智能提取需求名称 -5. 展示确认信息:需求名称、描述 -6. **始终执行**:创建本地记录,更新 `dev/versions/versions.json`(type/priority 留空,由后续 `version start` 时前置步骤P1自动识别填充) +4. 🆕 **需求名称格式校验与提取**(内联,无独立 checklist) + - 展示录入提示文字: + ``` + 请输入需求名称,格式要求:【xx风险】【用户体验优化/运维优化/需求部门】【组件名】【一级模块-二级模块】【前后端需求】需求名称 + - xx风险:高风险 / 中风险 / 低风险 + - 用户体验优化/运维优化/需求部门:需求来源/类型,如 运维优化("需求部门"填具体部门名) + - 组件名:如 Exchangis + - 一级模块-二级模块:如 告警管理-IMS告警 + - 前后端需求:前端需求 / 后端需求 / 前后端需求 + - 需求名称:如 IMS告警增加ecc_receiver ECC通知人字段 + 示例:【低风险】【运维优化】【Exchangis】【告警管理-IMS告警】【前后端需求】IMS告警增加ecc_receiver ECC通知人字段 + ⚠️ 完整格式串将作为系统需求名称上传 DPMS,末尾"需求名称"作为本地文档名称。 + ``` + - 读取用户输入 raw_input,按正则 `^【(高风险|中风险|低风险)】【(.+?)】【(.+?)】【(.+?)】【(.+?)】(.+)$` 校验: + - **格式化模式**(匹配成功):`name`=第6段(末尾需求名称,作文档名),`rawFullName`=raw_input(完整格式串,作 DPMS name);风险/来源类型/组件/模块/前后端仅作确认展示,不持久化、不映射 priority + - **降级模式**(匹配失败):AskUserQuestion [重新输入 / 跳过格式按纯文本录入 / 取消];跳过时 `name`=raw_input,`rawFullName`=raw_input +5. 展示确认信息:需求名称(name)、rawFullName、风险、来源/类型、组件名、一级模块-二级模块、前后端 +6. **始终执行**:创建本地记录,更新 `dev/versions/versions.json`(type/priority 留空由后续 P1 自动识别;🆕 新增 `rawFullName` 字段) - **分配需求编号**:读取当前版本的 `nextReqIndex`,分配 `reqIndex = nextReqIndex`,然后 `nextReqIndex += 1`。`reqPrefix = "REQ-" + str(reqIndex).zfill(2)`(如 REQ-01、REQ-02)。写入 requirements 数组。 + - 🆕 requirements 数组新增 `rawFullName` 字段(完整格式串;降级模式=纯文本=name)。risk/sourceType/component/module/frontendBackend 仅作确认展示不持久化;priority 维持原逻辑(P1 识别写回,不映射风险等级)。 - **分配需求-子系统归属**(⭐阶段1 S5 D12):若版本为多子系统(`len(subsystems) > 1`),AskUserQuestion 询问"需求[{需求名}]归属哪个子系统"(从 subsystems[] 选),写入该需求的 `reqSubsystemId`;若单子系统,`reqSubsystemId = subsystems[0].subsystemId`(自动归属,无需询问)。 - **分配需求-仓库归属**(⭐阶段3 S6):若多git,从需求的 reqSubsystemId 反查 subsystems[] 取 sub.gitUrl 作为 repositoryId;若单git,repositoryId=null。 7. 询问远程操作策略(使用 AskUserQuestion,A3/A4可独立跳过): @@ -1244,8 +1270,8 @@ execute_rollback(requirement=target_requirement, mode="interactive", reason="主 - 选项2: "**仅DPMS创建系统需求 → 创建本地记录 + DPMS创建系统需求,跳过关联子系统版本**" - 选项3: "**全部跳过 → 仅创建本地记录(需求类型由后续启动开发时自动识别)**" 8. 根据用户选择执行远程操作: - - 选项1: 调用 `mcp__sdp__add-system-story`(A3),参数 `enableAiMode` = 1(⚠ 必须显式传入),成功后:① 调用 `mcp__sdp__get-storys(id=storyId)` 查询 `productName` 并回填 versions.json 该需求的 `dpmsStoryId` 和 `productName` 字段;② 自动调用 `mcp__sdp__associate-subsystem-version`(A4);A3或A4失败时按容错机制写入PendingItem - - 选项2: 调用 `mcp__sdp__add-system-story`(A3),参数 `enableAiMode` = 1(⚠ 必须显式传入),成功后:① 调用 `mcp__sdp__get-storys(id=storyId)` 查询 `productName` 并回填 versions.json 该需求的 `dpmsStoryId` 和 `productName` 字段;② A4写入PendingItem + - 选项1: 调用 `mcp__sdp__add-system-story`(A3),参数 `enableAiMode` = 1(⚠ 必须显式传入),🆕 `name` = rawFullName(完整格式串;降级模式=纯文本 name),成功后:① 调用 `mcp__sdp__get-storys(id=storyId)` 查询 `productName` 并回填 versions.json 该需求的 `dpmsStoryId` 和 `productName` 字段;② 自动调用 `mcp__sdp__associate-subsystem-version`(A4);A3或A4失败时按容错机制写入PendingItem + - 选项2: 调用 `mcp__sdp__add-system-story`(A3),参数 `enableAiMode` = 1(⚠ 必须显式传入),🆕 `name` = rawFullName(完整格式串;降级模式=纯文本 name),成功后:① 调用 `mcp__sdp__get-storys(id=storyId)` 查询 `productName` 并回填 versions.json 该需求的 `dpmsStoryId` 和 `productName` 字段;② A4写入PendingItem - 选项3: A3和A4分别写入PendingItem,productName保持null 9. 输出结果摘要(含A3/A4各步骤状态) 10. **下一步引导**(使用 AskUserQuestion): @@ -1256,16 +1282,18 @@ execute_rollback(requirement=target_requirement, mode="interactive", reason="主 ### 批量添加版本需求 **在指定版本下批量添加多个系统需求。版本名从当前活跃版本自动获取。** -2. **解析需求列表**:支持以下分隔格式: +2. 🆕 展示录入提示文字(格式 `【xx风险】【用户体验优化/运维优化/需求部门】【组件名】【一级模块-二级模块】【前后端需求】需求名称` + 字段说明 + 示例,同添加单个需求),并解析需求列表(支持以下分隔格式): - `1. xxx; 2. yyy; 3. zzz` - `1、xxx 2、yyy 3、zzz` - `1) xxx 2) yyy 3) zzz` + - 🆕 对每条按正则 `^【(高风险|中风险|低风险)】【(.+?)】【(.+?)】【(.+?)】【(.+?)】(.+)$` 校验:✅ 符合(name=第6段doc_name, rawFullName=完整串)/ ❌ 不符(标记降级:name=raw_input, rawFullName=raw_input) 3. **确认识别结果**(关键步骤,使用 AskUserQuestion): - - 展示解析到的需求列表(表格形式) - - 选项:"**识别正确,继续**" / "**识别有误,重新输入**" -4. 展示完整确认信息(所有需求列表) -5. **始终执行**:创建本地记录,更新 `dev/versions/versions.json`(type/priority 留空,由后续 `version start` 时前置步骤P1自动识别填充) + - 展示解析结果表(序号 | 用户输入 | 格式校验 | doc_name | 风险 | 来源/类型 | 组件名 | 一级模块-二级模块 | 前后端) + - 选项:"**全部正确,继续(不符条目自动降级为纯文本)**" / "**识别有误,重新输入**" +4. 展示完整确认信息(所有需求列表,含 rawFullName 与风险/来源类型/组件/模块/前后端) +5. **始终执行**:创建本地记录,更新 `dev/versions/versions.json`(type/priority 留空由后续 P1 自动识别;🆕 新增 `rawFullName` 字段) - **分配需求编号**:对每个需求按添加顺序分配递增的 `reqIndex`(从 `nextReqIndex` 开始,每个需求 +1),计算 `reqPrefix = "REQ-" + str(reqIndex).zfill(2)`。写入 requirements 数组并更新 `nextReqIndex`。 + - 🆕 每条需求写入 `rawFullName`(格式化=完整串;降级=纯文本=name)。risk/sourceType/component/module/frontendBackend 仅作确认展示不持久化;priority 维持原逻辑(P1 识别写回,不映射风险等级)。 - **分配需求-子系统归属**(⭐阶段1 S5 D12):对每个需求,若版本为多子系统(`len(subsystems) > 1`),AskUserQuestion 询问该需求归属哪个子系统(可批量询问,从 subsystems[] 选),写入各需求的 `reqSubsystemId`;若单子系统,所有需求 `reqSubsystemId = subsystems[0].subsystemId`(自动归属)。 - **分配需求-仓库归属**(⭐阶段3 S6):对每个需求,若多git,从需求的 reqSubsystemId 反查 subsystems[] 取 sub.gitUrl 作为 repositoryId;若单git,repositoryId=null。 6. 询问远程操作策略(使用 AskUserQuestion,A3/A4可独立跳过): @@ -1273,8 +1301,8 @@ execute_rollback(requirement=target_requirement, mode="interactive", reason="主 - 选项2: "**仅DPMS创建系统需求 → 创建本地记录 + DPMS创建系统需求,跳过关联子系统版本**" - 选项3: "**全部跳过 → 仅创建本地记录(需求类型由后续启动开发时自动识别)**" 7. 根据用户选择,对每个需求独立执行远程操作(单个失败不影响其余): - - 选项1: 调用 `mcp__sdp__add-system-story`(A3),参数 `enableAiMode` = 1(⚠ 必须显式传入),成功后:① 调用 `mcp__sdp__get-storys(id=storyId)` 查询 `productName` 并回填 versions.json 该需求的 `dpmsStoryId` 和 `productName` 字段;② 自动调用 `mcp__sdp__associate-subsystem-version`(A4);A3或A4失败时按容错机制写入PendingItem - - 选项2: 调用 `mcp__sdp__add-system-story`(A3),参数 `enableAiMode` = 1(⚠ 必须显式传入),成功后:① 调用 `mcp__sdp__get-storys(id=storyId)` 查询 `productName` 并回填 versions.json 该需求的 `dpmsStoryId` 和 `productName` 字段;② A4写入PendingItem + - 选项1: 调用 `mcp__sdp__add-system-story`(A3),参数 `enableAiMode` = 1(⚠ 必须显式传入),🆕 `name` = rawFullName(完整格式串;降级模式=纯文本 name),成功后:① 调用 `mcp__sdp__get-storys(id=storyId)` 查询 `productName` 并回填 versions.json 该需求的 `dpmsStoryId` 和 `productName` 字段;② 自动调用 `mcp__sdp__associate-subsystem-version`(A4);A3或A4失败时按容错机制写入PendingItem + - 选项2: 调用 `mcp__sdp__add-system-story`(A3),参数 `enableAiMode` = 1(⚠ 必须显式传入),🆕 `name` = rawFullName(完整格式串;降级模式=纯文本 name),成功后:① 调用 `mcp__sdp__get-storys(id=storyId)` 查询 `productName` 并回填 versions.json 该需求的 `dpmsStoryId` 和 `productName` 字段;② A4写入PendingItem - 选项3: A3和A4分别写入PendingItem,productName保持null 8. 输出结果摘要:本地创建 N 条 + A3成功 M 条 + A4成功 K 条 + 失败进待补录 L 条 9. **下一步引导**(使用 AskUserQuestion): diff --git a/.claude/config/dev-flow-checklists/complete-version.md b/.claude/config/dev-flow-checklists/complete-version.md index 3046bfcd491e2d4def966c907799897e25f83ae1..d10278ad99fd7b5d059397bff6555ff03c561b25 100644 --- a/.claude/config/dev-flow-checklists/complete-version.md +++ b/.claude/config/dev-flow-checklists/complete-version.md @@ -407,6 +407,42 @@ - 将 requirementContextIndex 中每个 contextPath 原子改写为 completed 路径,并再次校验文件存在 - 更新版本配置状态为 `completed` +10.5. **生成变更单询问**(🆕 在步骤10归档+版本状态置completed之后、步骤11 Git提交之前触发;衔接A6-Step3写入的testReportId): + ```python + # 前置:版本状态已置 completed(步骤10),testReportId 已在步骤6(A6-Step3)写入 versions.json + testReportId = 版本配置.testReportId + versionPlanId = 版本配置.dpms.versionPlanId OR 版本配置.dpms.releasePlanId + + # 条件:testReportId 非空才询问(A6-Step3 成功创建报告的标志;跳过A6系列或Step3失败时为空) + IF testReportId 为空 THEN + OUTPUT: "ℹ️ testReportId 为空(A6系列跳过或新增测试报告失败),跳过生成变更单询问,继续步骤11" + ELIF versionPlanId 为空 THEN + OUTPUT: "⚠️ versionPlanId 缺失,无法生成变更单,继续步骤11(可稍后手动 /version-change-order-generator 调用)" + ELSE + change_order_ans = AskUserQuestion({ + "questions": [{ + "question": "版本已完成并归档,测试报告已生成(testReportId 已写入)。是否现在生成版本发布变更单?", + "header": "生成变更单", + "options": [ + {"label": "生成变更单", "description": "调用 version-change-order-generator skill,按模板生成版本发布变更单文档"}, + {"label": "暂不生成,继续", "description": "跳过本次生成,继续步骤11 Git提交;可稍后手动 /version-change-order-generator 调用"} + ] + }] + }) + IF change_order_ans == "生成变更单" THEN + # 直接调用 skill(当前版本唯一,不走 dev-flow.md "生成变更单" 章节的多版本候选选择) + # skill 步骤1校验 subsystemVersionId/testReportId 非空 + 版本 status==completed(步骤10已满足) + Skill(version-change-order-generator, args={"versionPlanId": versionPlanId}) + OUTPUT: "ℹ️ 变更单生成流程结束(无论成功或终止),继续步骤11 Git提交" + END IF + END IF + # 无论生成与否,继续步骤11 + ``` + + ⚠️ **执行时机**:本步骤在步骤10(归档+版本状态置completed)之后、步骤11(Git提交)之前。版本 status 已为 completed,version-change-order-generator skill 步骤1的 `status==completed` 校验可自然通过(时序冲突已解决)。 + ⚠️ **与主菜单"生成变更单"的关系**:dev-flow.md 主菜单的"生成变更单"章节是多版本候选选择场景(当前 dev-flow-menus.json 未配置该入口);本步骤是完成版本流程内的单版本直接调用,不走候选选择,直接传当前版本 versionPlanId。 + ⚠️ **skill 执行后不回主菜单**:与 dev-flow.md "生成变更单"章节末尾"重新展示主菜单"不同,本步骤在 complete-version 流程内,skill 执行后继续步骤11 Git提交。 + 11. **版本归档Git提交**: ```python # 11a. 扫描版本相关文件变更 @@ -566,6 +602,7 @@ FOR operation IN [ - [ ] 步骤9: 总结报告已生成 = ? - [ ] 步骤10: 归档完成 = ? - [ ] 步骤10: versionContextPath/requirementContextIndex 已切换到 completed 路径 = ? +- [ ] 步骤10.5: 生成变更单询问 = ? (生成+skill调用/跳过testReportId空/跳过versionPlanId空/用户选暂不生成) - [ ] 步骤11: 版本归档Git提交 = ? (提交成功/跳过无变更) - [ ] 步骤11: `.agents/` 未修改、未暂存、未提交 = ? - [ ] 步骤11d: git commit = ? diff --git a/.claude/config/dev-flow-checklists/stage-hooks.md b/.claude/config/dev-flow-checklists/stage-hooks.md index 4e5b11a6fc8ee07eca69783ce5139313aa78d482..92f44918165797fd5407167d34db9c1c75d6adf6 100644 --- a/.claude/config/dev-flow-checklists/stage-hooks.md +++ b/.claude/config/dev-flow-checklists/stage-hooks.md @@ -3,6 +3,7 @@ > 来源:dev-flow.md "21阶段有序推进规则" + "逐阶段执行流程" + "阶段Prompt构造规则" + "阶段后置动作映射表" + "阶段后置动作执行指引"章节 > v4.9 G4 新增:Stage 3.5 插件开发迭代评估循环(仅 dev_target=Agent/Skill/Command 触发) > v4.9 上下文优化:统一版本/需求上下文契约、阶段结果协议与两阶段 checkpoint +> v4.10 同步:versions.json schema 示例 rawFullName 升级为5段全角中括号格式 > 用途:执行版本模式逐阶段推进时必须Read本文件,按步骤逐项执行 ## 21阶段有序推进规则 @@ -841,31 +842,102 @@ WHILE cycle_count < MAX_CYCLES: 输出 "ℹ️ 已跳过Stage {stage}检视Agent,继续执行该阶段后置Hook" → 跳到步骤8(不启动检视Agent,不执行本阶段优化交互) - ELIF stage == 3 AND len(selected_agents) >= 1 THEN - IF len(selected_agents) == 1 THEN - 标准串行执行:Agent(subagent_type: selected_agents[0], prompt: 构造的Prompt) - ELSE - 【多Agent串行执行】 - stage3_completed = [] - stage3_failed = [] - FOR each agent IN selected_agents: - 构造Agent专属Prompt: - - 后端Agent: 【设计文档路径】:{后端设计.md或设计.md},【开发范围】:后端(Controller/Service/Entity等) - - 前端Agent: 【设计文档路径】:{前端设计.md},【开发范围】:前端(页面/组件/API封装等) - Agent(subagent_type: agent, prompt: 构造的Prompt) - IF 成功 → stage3_completed.append(agent) - IF 失败 → stage3_failed.append(agent),继续下一个Agent(不中止) - END FOR - 【Stage 3多Agent完成判定规则】 - IF len(stage3_failed) == 0 THEN - → Stage 3全部完成,推进到Stage 3.1 - ELIF len(stage3_completed) > 0 THEN - → 部分完成 - AskUserQuestion("Stage 3部分完成:✅{stage3_completed} ❌{stage3_failed},如何处理?", - ["继续下一阶段(忽略失败Agent)", "重试失败Agent", "中止流程"]) + # ⭐设计-开发协调循环(修复循环断链):开发Agent返回 design_block_report -> 主会话解析 -> 调 des-xxx patch_mode 修补设计文档 -> 重启开发Agent -> 循环到 code_complete=true + cycle = 0; MAX_CYCLES = 3; user_intervene = 0; MAX_USER_INTERVENE = 3; aborted = false + des_agent = 按需求类型(requirement_type)从映射表(第43-48行)取 des-xxx(NEW->des-new-feature / ENHANCE->des-enhance-feature / FIX->des-fix-bug / OPTIMIZE->des-optimize / REFACTOR->des-refactor / INTEGRATE->des-integrate) + raw_design_doc_path = 从 versions.json 该需求 design_doc_path 字段读取(Stage 2 产物路径) + IF raw_design_doc_path 含 ";" THEN # split多文档(后端设计.md;前端设计.md) + backend_design_path, frontend_design_path = raw_design_doc_path 按 ";" 拆分 + ELSE # 单文档(纯后端项目或未拆分) + backend_design_path = frontend_design_path = raw_design_doc_path + END IF + blocked_agent = None # 记录本轮阻塞的Agent,供6.C选对应设计文档路径 + + WHILE True: + # 6.A 启动/重启开发 Agent(prompt含【已有产物路径】,已生成的代码用 Edit 覆盖继续,不从头重建) + IF len(selected_agents) == 1 THEN + blocked_agent = selected_agents[0] # 单Agent,若阻塞就是它 + result = Agent(subagent_type: selected_agents[0], prompt: 构造的Prompt) ELSE - → 全部失败,按现有容错模式处理 + 【多Agent串行执行,任一 code_complete=false 即中断全部】 + stage3_completed = []; stage3_failed = []; blocked_result = None + FOR each agent IN selected_agents: + 构造Agent专属Prompt: + - 后端Agent: 【设计文档路径】:{后端设计.md或设计.md},【开发范围】:后端(Controller/Service/Entity等) + - 前端Agent: 【设计文档路径】:{前端设计.md},【开发范围】:前端(页面/组件/API封装等) + r = Agent(subagent_type: agent, prompt: 构造的Prompt) + p = parse_design_block_report(r) # 解析末尾 ```json 块,schema见6.B + IF p.code_complete == false: + blocked_result = r # 设计阻塞(critical缺失),中断后续Agent,走6.C patch循环 + blocked_agent = agent # 记录阻塞的Agent,供6.C选对应设计文档路径 + BREAK FOR + IF Agent执行报错/异常退出 -> stage3_failed.append(agent),继续下一个Agent(不中止,与code_complete=false区分) + stage3_completed.append(agent) + END FOR + IF blocked_result != None THEN + result = blocked_result # 有设计阻塞,走6.C调 des-xxx patch + ELIF len(stage3_failed) == 0 THEN + result = 最后一个Agent的result # 全部成功,6.C判定 code_complete=true -> BREAK + ELIF len(stage3_completed) > 0 THEN + -> 部分完成(有报错但无阻塞) + AskUserQuestion("Stage 3部分完成:✅{stage3_completed} ❌{stage3_failed},如何处理?", + ["继续下一阶段(忽略失败Agent)", "重试失败Agent", "中止流程"]) + IF "继续下一阶段" -> result = 最后一个完成Agent的result(6.C判定 code_complete=true -> BREAK) + IF "重试失败Agent" -> CONTINUE(重启6.A,已完成的Agent注入已有产物覆盖继续) + IF "中止流程" -> aborted = true; BREAK + ELSE + -> 全部失败,按现有容错模式处理 + END IF + END IF + + # 6.B 解析 design_block_report(仿步骤8.4 的 JSON 块解析,解析返回文本末尾 ```json ... ``` 代码块) + parsed = parse_design_block_report(result) + # schema: {code_complete:bool, design_block_issues:[{id,category,location,description,suggestion,severity,touches_api}], progress_note:string} + IF JSON 解析失败 THEN + OUTPUT "⚠️ design_block_report 解析失败,fail-open 按 code_complete=true 放行" + parsed = {code_complete: true, design_block_issues: [], progress_note: "解析失败fail-open"} END IF + + # 6.C 循环决策 + IF parsed.code_complete == true THEN + OUTPUT "✅ Stage 3 代码开发完成(cycle={cycle})" + BREAK # 退出循环 -> 步骤8.1 B4 转提测 -> Stage 3.1 + ELIF parsed.design_block_issues 非空 AND cycle < MAX_CYCLES THEN + # 根据阻塞Agent选对应设计文档路径(修复:前端Agent阻塞修补前端设计.md,后端Agent阻塞修补后端设计.md) + IF blocked_agent IN [frontend-code-developer, web-frontend-developer] THEN + target_design_path = frontend_design_path + ELSE + target_design_path = backend_design_path + END IF + OUTPUT "🔄 第{cycle+1}轮检测到设计阻塞(critical {count(severity==critical)} 个,阻塞Agent: {blocked_agent}),调 {des_agent} patch_mode 修补设计文档:{target_design_path}" + patch_result = Agent(subagent_type: des_agent, + prompt: 【patch_mode】:true + 【design_doc_path】:target_design_path + 【design_block_issues】:parsed.design_block_issues) + # des-xxx 直接改设计文档,不询问用户、不输出修改清单审查(石墨上传移至整个dev-flow流程末尾,防止反复上传) + OUTPUT "✅ {des_agent} 已修补设计文档:{patch_result.summary}" + cycle += 1 + CONTINUE # 重启 6.A(已完成的Agent注入已有产物覆盖继续) + ELIF cycle >= MAX_CYCLES THEN + # 超限:输出阻塞清单,用户介入 + IF user_intervene >= MAX_USER_INTERVENE THEN + OUTPUT "⚠️ 用户介入已达上限{MAX_USER_INTERVENE}次,强制中止" + aborted = true; BREAK + END IF + OUTPUT "❌ 自动协调已达上限{MAX_CYCLES}次,仍有设计阻塞:" + FOR each issue IN parsed.design_block_issues: + OUTPUT "- [{issue.severity}] {issue.location}: {issue.description}(建议:{issue.suggestion})" + END FOR + AskUserQuestion("已输出阻塞清单。请手动修改设计文档后选择", + ["我已修改设计文档,继续代码开发", "中止流程"]) + IF "中止流程" -> aborted = true; BREAK + IF "继续代码开发" -> user_intervene += 1; cycle = 0; CONTINUE + END IF + END WHILE + IF aborted THEN + 更新 currentStage="3" + OUTPUT "⚠️ Stage 3 已中止,不执行 B4 转提测" + EXIT WHILE # 退出外层 WHILE cycle_count,中止整个流程 END IF + # 循环 BREAK 后 -> 步骤8.1 B4 转提测(在循环外,只执行一次,避免重复转提测) - ELSE(其他阶段): IF stage == 7 AND stage7_skill_sequence 已计算(前置步骤4.8) THEN # ⭐v4.10 前端流程测试自动触发 FOR each skill IN stage7_skill_sequence: @@ -1243,6 +1315,14 @@ WHILE cycle_count < MAX_CYCLES: ELSE 调用 `commit_stage_transition(stage_result)`,统一更新 versions.json/context.md/version-context.md;禁止直接单写 stageHistory END IF + 10.5 ⚠️ 阶段执行记录(仅 stage ∈ {0,1,1.1,2,2.1})⭐v4.12: + 在 context.md 的 `## 📊 阶段执行记录(需求/设计相位)` 表格写入/替换当前 stage 一行(仅记终态,不记待执行/执行中): + - 替换语义:若该 stage 已有行,先移除旧行(保持每 stage 至多一行,兼容回滚后重跑/失败后重试) + - 状态:IF skipDecisions[{stage}] 含 "skipped" THEN "跳过" ELSE "成功" + - 产出物:从本阶段已知路径填——Stage0=澄清纪要路径(若 subagent 落盘了纪要,否则"-");Stage1=requirement_doc_path;Stage1.1="-"(不产新文件,仅检视并可能 Edit 修改 Stage1 的需求文档,优化情况记备注);Stage2=design_doc_path(split 多文档用";"分隔);Stage2.1=接口文档路径(api_md_path,若 Stage2-Hook 生成了接口文档则填路径否则"-";设计文档优化记备注不记产出物)。注:Stage0/1/2 版本模式不可跳过必执行;1.1/2.1 跳过时 Stage1/2-Hook 仍会执行,故 2.1 跳过仍可能产出接口文档,产出物按"是否生成接口文档"判定,不按"是否跳过"判定 + - 完成时间:当前 ISO 8601 + - 备注:IF stage IN {1.1,2.1} THEN:IF skipDecisions[{stage}] 含 "skipped" THEN "阶段跳过" ELIF rechckDecisions[{stage}]="applied" THEN "已应用N项优化,{需求/设计}文档已更新" ELIF rechckDecisions[{stage}]="skipped" THEN "检视完成,未采纳优化" ELSE "-";若同时有 Hook 子动作失败转待补录,追加失败摘要;ELIF 本阶段 Hook(Stage1-Hook/Stage2-Hook)有子动作失败转待补录(DPMS同步/石墨上传/SDL/接口文档生成等),填失败摘要(如"DPMS同步失败已转待补录");若中间步骤失败被判定为阶段失败,状态改"失败"且备注填失败步骤;ELSE "-" + - 原子写入:Read context.md -> 更新表格 -> Write 整文件(单次 Write 即原子,与 frontmatter 状态保持一致) 11. 推进到 REQUIREMENT_STAGE_ORDER 下一项 END FOR @@ -1629,37 +1709,50 @@ IF "执行SDL安全设计同步" THEN # Step 2: 轮询SDL生成结果(每10秒一次,最多3次) sdl_completed = false + sdl_resp = null FOR i IN 1..3: 等待10秒 - 调用 mcp__sdp__get-story-sdl-detail({ + sdl_resp = 调用 mcp__sdp__get-story-sdl-detail({ "storyId": story_id, "userName": "{当前用户}" }) - → 获取 sdlStatus 和 requirementList - IF sdlStatus == 2(已完成)THEN + # get-story-sdl-detail 返回字段:sdl_status / requirement_list / use_sdl / no_sdl_reason / no_sdl_detail 等 + # sdl_status 枚举:2=不涉及安全设计(generate完成,requirement_list为空), 3=涉及安全设计(generate完成,requirement_list非空,待update), 4=生成中 + # 2 或 3 均代表 generate 完成;4 仍在生成中继续轮询 + IF sdl_resp.sdl_status == 2 OR sdl_resp.sdl_status == 3 THEN sdl_completed = true BREAK END IF END FOR IF sdl_completed THEN - # Step 3: 更新安全设计内容到DPMS - # 从requirementList提取storyReqDtoList,用设计文档安全设计章节内容填充htmlDesignContent - 调用 mcp__sdp__update-story-sec-design({ - "storyId": story_id, - "useSdl": 1, - "storyReqDtoList": requirementList.map(item => { + # Step 3: 根据 sdl_status 分支处理 + IF sdl_resp.sdl_status == 3 THEN + # status=3(设计中):根据 generate 实际返回填充 update 报文(generate 返回什么就填什么,不做 if-else 判断) + # - 涉及(use_sdl=1, requirement_list非空):storyReqDtoList 有内容,noSdlReason/noSdlDetail 为空 + # - 不涉及(use_sdl=0, requirement_list空, no_sdl_reason有值):storyReqDtoList 空,noSdlReason/noSdlDetail 有值 + # 按 generate 返回的 requirement_list 字段填充 update 的 storyReqDtoList;noSdlReason/noSdlDetail 取自 no_sdl_reason/no_sdl_detail;useSdl 取自 use_sdl + 调用 mcp__sdp__update-story-sec-design({ "storyId": story_id, - "reqSeq": item.reqSeq, - "isEffective": item.isEffective, - "htmlDesignContent": 从设计文档安全设计章节提取对应reqSeq的内容, - "remoteId": item.remoteId, - "isUpdate": true - }), - "userName": "{当前用户}" - }) - IF 成功 → 输出 "✅ 安全设计已同步到DPMS(Story ID: {story_id},SDL状态:已完成)" - IF 失败 → 按容错模式处理 + "useSdl": sdl_resp.use_sdl, + "storyReqDtoList": sdl_resp.requirement_list.map(item => { + "storyId": story_id, + "reqSeq": item.req_seq, + "isEffective": item.is_effective, + "htmlDesignContent": item.html_design_content, + "remoteId": item.remote_id, + "isUpdate": true + }), + "noSdlReason": sdl_resp.no_sdl_reason, + "noSdlDetail": sdl_resp.no_sdl_detail, + "userName": "{当前用户}" + }) + IF 成功 → 输出 "✅ 安全设计已同步到DPMS(Story ID: {story_id},useSdl: {sdl_resp.use_sdl})" + IF 失败 → 按容错模式处理 + ELIF sdl_resp.sdl_status == 2 THEN + # 不涉及安全设计:SDL系统已判定(requirement_list为空,use_sdl=0),无需 update 内容 + 输出 "ℹ️ SDL系统判定不涉及安全设计(sdl_status=2,requirement_list为空),无需同步安全设计内容" + END IF ELSE 输出 "⚠️ SDL安全设计生成未完成(3次轮询后仍为生成中),建议稍后手动检查" mcp__biz-sync__save_pending_item( @@ -2116,6 +2209,15 @@ END IF **强制恢复流程**: 1. **不回退产物**:保留已生成的文档(stageHistory记录哪些阶段已完成) 2. **更新状态**:将 currentStage 和 stageHistory 保持不变(记录失败位置) +2.5 ⚠️ 阶段执行记录(仅 stage ∈ {0,1,1.1,2,2.1})⭐v4.12: + 在 context.md `## 📊 阶段执行记录(需求/设计相位)` 表格写入/替换当前 stage 一行: + - 状态:"失败" + - 产出物:已生成的填路径,未生成填"-" + - 完成时间:当前 ISO 8601 + - 备注:失败原因(如"subagent执行失败:{错误摘要}"或中间步骤失败"DPMS同步失败/接口文档生成失败"等) + - 替换语义:若该 stage 已有行先移除旧行 + - 原子写入:Read context.md -> 更新表格 -> Write 整文件 + - 注:若用户随后选"重试"并成功,步骤10.5 会以"成功"行替换本"失败"行,表格只留终态 3. **重试决策**: IF 该阶段连续失败 < 3次 THEN AskUserQuestion("Stage {stage}执行失败,如何处理?", @@ -2136,6 +2238,7 @@ END IF "nextReqIndex": 3, "requirements": [{ "name": "xxx", + "rawFullName": "【低风险】【运维优化】【Exchangis】【告警管理-IMS告警】【前后端需求】IMS告警增加ecc_receiver ECC通知人字段", # 🆕 完整格式串(DPMS name 用;降级模式=纯文本=name;旧数据可能不存在) "reqIndex": 1, "type": "ENHANCE", "currentStage": "1.1", diff --git a/.claude/config/dev-flow-checklists/standalone-mode.md b/.claude/config/dev-flow-checklists/standalone-mode.md index 78612826215847eb91c32ccb1016acf869005841..99dbeb4066c5cd8cf685cf58598049738f79757a 100644 --- a/.claude/config/dev-flow-checklists/standalone-mode.md +++ b/.claude/config/dev-flow-checklists/standalone-mode.md @@ -346,7 +346,7 @@ P7. 知识库构建(可跳过): #### STAGE_ORDER逐阶段控制 -与版本模式相同(STAGE_ORDER = [0, 1, 1.1, 1.2, 1.6, 2, 2.1, 2.2, 3, 3.1, 3.2, 3.5, 4, 5, 5.5, 6, 6.1, 7, 8, 9]),差异如下: +需求级阶段与版本模式相同(STAGE_ORDER = [0, 1, 1.1, 1.2, 1.6, 2, 2.1, 2.2, 3, 3.1, 3.2, 3.5, 4, 5, 5.5, 6, 6.1, 7, 8, 9],共 20 项);版本模式额外含版本级 stage 10(版本级回归测试,Stage 9 通过后 GOTO 触发,共 21 项),单需求模式无 stage 10。差异如下: | 项目 | 版本模式 | 单需求模式 | |------|---------|----------| @@ -667,31 +667,102 @@ WHILE cycle_count < MAX_CYCLES: 输出 "ℹ️ 已跳过Stage {stage}检视Agent,继续执行该阶段本地后置动作" → 跳到步骤7(不启动检视Agent,不执行本阶段优化交互) - ELIF stage == 3 AND len(selected_agents) >= 1 THEN - IF len(selected_agents) == 1 THEN - 标准串行执行:Agent(subagent_type: selected_agents[0], prompt: 构造的Prompt) - ELSE - 【多Agent串行执行】(同版本模式逻辑) - stage3_completed = [] - stage3_failed = [] - FOR each agent IN selected_agents: - 构造Agent专属Prompt: - - 后端Agent: 【设计文档路径】:{后端设计.md或设计.md},【开发范围】:后端(Controller/Service/Entity等) - - 前端Agent: 【设计文档路径】:{前端设计.md},【开发范围】:前端(页面/组件/API封装等) - Agent(subagent_type: agent, prompt: 构造的Prompt) - IF 成功 → stage3_completed.append(agent) - IF 失败 → stage3_failed.append(agent),继续下一个Agent(不中止) - END FOR - 【Stage 3多Agent完成判定规则】 - IF len(stage3_failed) == 0 THEN - → Stage 3全部完成,推进到Stage 3.1 - ELIF len(stage3_completed) > 0 THEN - → 部分完成 - AskUserQuestion("Stage 3部分完成:✅{stage3_completed} ❌{stage3_failed},如何处理?", - ["继续下一阶段(忽略失败Agent)", "重试失败Agent", "中止流程"]) + # ⭐设计-开发协调循环(修复循环断链):开发Agent返回 design_block_report -> 主会话解析 -> 调 des-xxx patch_mode 修补设计文档 -> 重启开发Agent -> 循环到 code_complete=true + cycle = 0; MAX_CYCLES = 3; user_intervene = 0; MAX_USER_INTERVENE = 3; aborted = false + des_agent = 按需求类型(requirement_type)从映射表(stage-hooks.md第43-48行)取 des-xxx(NEW->des-new-feature / ENHANCE->des-enhance-feature / FIX->des-fix-bug / OPTIMIZE->des-optimize / REFACTOR->des-refactor / INTEGRATE->des-integrate) + raw_design_doc_path = 从 context.md 的 design_doc_path 字段读取(Stage 2 产物路径) + IF raw_design_doc_path 含 ";" THEN # split多文档(后端设计.md;前端设计.md) + backend_design_path, frontend_design_path = raw_design_doc_path 按 ";" 拆分 + ELSE # 单文档(纯后端项目或未拆分) + backend_design_path = frontend_design_path = raw_design_doc_path + END IF + blocked_agent = None # 记录本轮阻塞的Agent,供6.C选对应设计文档路径 + + WHILE True: + # 6.A 启动/重启开发 Agent(prompt含【已有产物路径】,已生成的代码用 Edit 覆盖继续,不从头重建) + IF len(selected_agents) == 1 THEN + blocked_agent = selected_agents[0] # 单Agent,若阻塞就是它 + result = Agent(subagent_type: selected_agents[0], prompt: 构造的Prompt) ELSE - → 全部失败,按现有容错模式处理 + 【多Agent串行执行,任一 code_complete=false 即中断全部】(同版本模式逻辑) + stage3_completed = []; stage3_failed = []; blocked_result = None + FOR each agent IN selected_agents: + 构造Agent专属Prompt: + - 后端Agent: 【设计文档路径】:{后端设计.md或设计.md},【开发范围】:后端(Controller/Service/Entity等) + - 前端Agent: 【设计文档路径】:{前端设计.md},【开发范围】:前端(页面/组件/API封装等) + r = Agent(subagent_type: agent, prompt: 构造的Prompt) + p = parse_design_block_report(r) # 解析末尾 ```json 块,schema见6.B + IF p.code_complete == false: + blocked_result = r # 设计阻塞(critical缺失),中断后续Agent,走6.C patch循环 + blocked_agent = agent # 记录阻塞的Agent,供6.C选对应设计文档路径 + BREAK FOR + IF Agent执行报错/异常退出 -> stage3_failed.append(agent),继续下一个Agent(不中止,与code_complete=false区分) + stage3_completed.append(agent) + END FOR + IF blocked_result != None THEN + result = blocked_result # 有设计阻塞,走6.C调 des-xxx patch + ELIF len(stage3_failed) == 0 THEN + result = 最后一个Agent的result # 全部成功,6.C判定 code_complete=true -> BREAK + ELIF len(stage3_completed) > 0 THEN + -> 部分完成(有报错但无阻塞) + AskUserQuestion("Stage 3部分完成:✅{stage3_completed} ❌{stage3_failed},如何处理?", + ["继续下一阶段(忽略失败Agent)", "重试失败Agent", "中止流程"]) + IF "继续下一阶段" -> result = 最后一个完成Agent的result(6.C判定 code_complete=true -> BREAK) + IF "重试失败Agent" -> CONTINUE(重启6.A,已完成的Agent注入已有产物覆盖继续) + IF "中止流程" -> aborted = true; BREAK + ELSE + -> 全部失败,按现有容错模式处理 + END IF + END IF + + # 6.B 解析 design_block_report(仿步骤8.4 的 JSON 块解析,解析返回文本末尾 ```json ... ``` 代码块) + parsed = parse_design_block_report(result) + # schema: {code_complete:bool, design_block_issues:[{id,category,location,description,suggestion,severity,touches_api}], progress_note:string} + IF JSON 解析失败 THEN + OUTPUT "⚠️ design_block_report 解析失败,fail-open 按 code_complete=true 放行" + parsed = {code_complete: true, design_block_issues: [], progress_note: "解析失败fail-open"} + END IF + + # 6.C 循环决策 + IF parsed.code_complete == true THEN + OUTPUT "✅ Stage 3 代码开发完成(cycle={cycle})" + BREAK # 退出循环 -> 推进 Stage 3.1(单需求模式无DPMS,B4转提测本就跳过) + ELIF parsed.design_block_issues 非空 AND cycle < MAX_CYCLES THEN + # 根据阻塞Agent选对应设计文档路径(修复:前端Agent阻塞修补前端设计.md,后端Agent阻塞修补后端设计.md) + IF blocked_agent IN [frontend-code-developer, web-frontend-developer] THEN + target_design_path = frontend_design_path + ELSE + target_design_path = backend_design_path + END IF + OUTPUT "🔄 第{cycle+1}轮检测到设计阻塞(critical {count(severity==critical)} 个,阻塞Agent: {blocked_agent}),调 {des_agent} patch_mode 修补设计文档:{target_design_path}" + patch_result = Agent(subagent_type: des_agent, + prompt: 【patch_mode】:true + 【design_doc_path】:target_design_path + 【design_block_issues】:parsed.design_block_issues) + # des-xxx 直接改设计文档,不询问用户、不输出修改清单审查(石墨上传移至整个dev-flow流程末尾,防止反复上传) + OUTPUT "✅ {des_agent} 已修补设计文档:{patch_result.summary}" + cycle += 1 + CONTINUE # 重启 6.A(已完成的Agent注入已有产物覆盖继续) + ELIF cycle >= MAX_CYCLES THEN + # 超限:输出阻塞清单,用户介入 + IF user_intervene >= MAX_USER_INTERVENE THEN + OUTPUT "⚠️ 用户介入已达上限{MAX_USER_INTERVENE}次,强制中止" + aborted = true; BREAK + END IF + OUTPUT "❌ 自动协调已达上限{MAX_CYCLES}次,仍有设计阻塞:" + FOR each issue IN parsed.design_block_issues: + OUTPUT "- [{issue.severity}] {issue.location}: {issue.description}(建议:{issue.suggestion})" + END FOR + AskUserQuestion("已输出阻塞清单。请手动修改设计文档后选择", + ["我已修改设计文档,继续代码开发", "中止流程"]) + IF "中止流程" -> aborted = true; BREAK + IF "继续代码开发" -> user_intervene += 1; cycle = 0; CONTINUE END IF + END WHILE + IF aborted THEN + 更新 context.md 的 currentStage="3" + OUTPUT "⚠️ Stage 3 已中止" + EXIT WHILE # 退出外层 WHILE cycle_count,中止整个流程 END IF + # 循环 BREAK 后 -> 推进 Stage 3.1(单需求模式无DPMS,B4转提测本就跳过,不重复触发) - ELSE(其他阶段): IF stage == 7 AND stage7_skill_sequence 已计算 THEN # ⭐v4.10 前端流程测试自动触发 FOR each skill IN stage7_skill_sequence: diff --git a/.claude/config/dev-flow-checklists/start-development.md b/.claude/config/dev-flow-checklists/start-development.md index ef9bc669e0e0e94b00e07435edd493f998bb2258..bef66169927450c46b54ca9f0b107f71ed2f9c7e 100644 --- a/.claude/config/dev-flow-checklists/start-development.md +++ b/.claude/config/dev-flow-checklists/start-development.md @@ -474,6 +474,15 @@ updatedAt: "{ISO 8601时间}" # 任务上下文 +## 📊 阶段执行记录(需求/设计相位) + +> 仅记录需求相位(Stage 0/1/1.1)与设计相位(Stage 2/2.1)的终态(成功/跳过/失败),其余阶段不记。 +> 每 stage 至多一行;写入前若该 stage 已有行则先替换旧行(兼容"失败后重试成功")。 +> 写入规则与点位见 `stage-hooks.md` 步骤10.5(成功/跳过)与强制恢复流程步骤2.5(失败)。 + +| 阶段 | 名称 | 状态 | 产出物 | 完成时间 | 备注 | +|------|------|------|--------|----------|------| + ## 📋 任务基本信息 **任务名称**: {task_name} diff --git a/.claude/skills/dpms-design-sync/SKILL.md b/.claude/skills/dpms-design-sync/SKILL.md index 930098490eb9759a5026454fe923459d38a95dc2..d6fe8c7c4088843937ce6fb29bbb6118a9d6b809 100644 --- a/.claude/skills/dpms-design-sync/SKILL.md +++ b/.claude/skills/dpms-design-sync/SKILL.md @@ -2,11 +2,17 @@ name: dpms-design-sync type: skill description: SDP设计同步Skill,负责设计阶段与SDP系统的数据同步(含安全设计) -version: 1.3 +version: 1.4 author: DevSyncAgent Team -last_updated: 2026-05-28 +last_updated: 2026-07-21 --- changelog: + v1.4 - 2026-07-21 + - 修复SDL响应字段映射:update-story-sec-design 入参按 get-story-sdl-detail 返回报文填充(storyReqDtoList 按 requirement_list 填充,noSdlReason/noSdlDetail 取自 no_sdl_reason/no_sdl_detail) + - 修复htmlDesignContent来源:直接复用SDL返回的html_design_content(SDL自动生成内容),非从设计文档安全设计章节提取 + - 修复sdl_status完成判断:2或3均代表generate完成(2=不涉及,3=待update确认),4=生成中; 完成判断改为 sdl_status IN (2,3) + - 补全get_sdl_detail输出字段表:requirement_list[]新增content/sec_design_demo/case_list/test_case_id/remote_id/llm_reason/source + - 修正status==3分支:根据generate实际返回统一填充update报文(不做if-else判断),补noSdlReason/noSdlDetail(取自no_sdl_reason/no_sdl_detail);status==2保持不调update v1.3 - 2026-05-28 - 新增 get_sdl_detail action(查询系统需求安全设计详情) - 新增 generate_sdl action(生成安全设计) @@ -130,8 +136,15 @@ changelog: **执行流程:** ``` 1. 调用 mcp__sdp__generate-sdl-requirement 触发生成安全设计任务 -2. 调用 mcp__sdp__get-story-sdl-detail 获取任务结果(每10秒轮询一次,最多3次;若3次后仍为生成中,提示用户稍后手动检查) -3. 根据任务结果,调用 mcp__sdp__update-story-sec-design 更新安全设计内容 +2. 调用 mcp__sdp__get-story-sdl-detail 获取任务结果(每10秒轮询一次,最多3次) + - 完成判断:sdl_status IN (2,3)(2或3均代表generate完成);4=生成中继续轮询 + - 若3次后仍为生成中(sdl_status==4),提示用户稍后手动检查 +3. 根据 sdl_status 分支处理: + - sdl_status==3(设计中):调用 mcp__sdp__update-story-sec-design,根据 generate 实际返回填充报文(generate返回什么就填什么,不做if-else判断) + - 涉及(use_sdl=1, requirement_list非空):传 storyReqDtoList + - 不涉及(use_sdl=0, requirement_list空, no_sdl_reason有值):传 noSdlReason/noSdlDetail + - 按 generate 返回报文中 requirement_list 下的字段填充 update 的 storyReqDtoList;noSdlReason/noSdlDetail 取自 no_sdl_reason/no_sdl_detail;useSdl 取自 use_sdl + - sdl_status==2(已完成终态):不调 update,输出"无需update" 4. 记录安全设计完成时间 5. 返回完成结果 ``` @@ -141,12 +154,12 @@ changelog: { "success": true, "status": "updated", - "sdlStatus": 2, - "completedAt": "2026-05-28T15:30:00Z" + "sdl_status": 3, + "completedAt": "2026-07-21T15:30:00Z" } ``` -**注意:** 安全设计是可选的,只有在有安全要求时才需要调用此 Action。SDL状态枚举:0=不涉及, 1=未完成, 2=已完成, 3=设计中, 4=生成中。 +**注意:** 安全设计是可选的,只有在有安全要求时才需要调用此 Action。SDL状态枚举:2或3均代表generate完成(2=不涉及/requirement_list通常为空, 3=待update确认/requirement_list可能非空也可能空); 4=生成中。 --- @@ -270,27 +283,34 @@ changelog: | 字段名 | 类型 | 说明 | |--------|------|------| -| `storyId` | number | 系统需求ID | -| `useSdl` | number | 是否执行SDL | -| `noSdlReason` | string | 不执行SDL原因 | -| `noSdlDetail` | string | 不执行SDL详情 | -| `sdlStatus` | number | 安全设计状态: 0=不涉及, 1=未完成, 2=已完成, 3=设计中, 4=生成中 | -| `secDesignTempStatus` | number | 安全设计暂存状态 | +| `story_id` | number | 系统需求ID | +| `use_sdl` | number | 是否执行SDL | +| `no_sdl_reason` | string | 不执行SDL原因 | +| `no_sdl_detail` | string | 不执行SDL详情 | +| `sdl_status` | number | 安全设计状态: 2或3均代表generate完成(2=不涉及/requirement_list通常为空, 3=待update确认/requirement_list可能非空也可能空); 4=生成中 | +| `sec_design_temp_status` | number | 安全设计暂存状态 | | `reviewer` | string | 安全设计审核人 | -| `enableSecDesignReview` | boolean | 是否开启安全设计审核 | -| `secTestCaseFinished` | boolean | 安全测试用例是否已完成 | -| `storyEnableNewSdl` | boolean | 是否启用智能化SDL流程 | -| `newSdlException` | string | 智能化SDL流程执行异常信息 | -| `requirementList` | array | 安全需求列表 | +| `enable_sec_design_review` | boolean | 是否开启安全设计审核 | +| `sec_test_case_finished` | boolean | 安全测试用例是否已完成 | +| `story_enable_new_sdl` | boolean | 是否启用智能化SDL流程 | +| `new_sdl_exception` | string | 智能化SDL流程执行异常信息 | +| `requirement_list` | array | 安全需求列表 | -**requirementList Item:** +**requirement_list Item:** | 字段名 | 类型 | 说明 | |--------|------|------| -| `reqSeq` | string | 安全需求ID | +| `req_seq` | string | 安全需求ID | | `title` | string | 安全需求标题 | -| `isEffective` | number | 是否涉及 | -| `htmlDesignContent` | string | 安全设计内容(HTML) | +| `content` | string | 安全需求内容(SDL规则说明) | +| `sec_design_demo` | string | 安全设计示例 | +| `is_effective` | number | 是否涉及 | +| `html_design_content` | string | 安全设计内容(HTML,SDL自动生成,update时直接复用) | +| `case_list` | array | 涉及案例类型列表(如["接口","数据库操作"]) | +| `test_case_id` | number | 关联测试用例ID | +| `remote_id` | number | 运营平台子系统安全需求记录ID(update时映射为remoteId) | +| `llm_reason` | string | LLM判定依据说明 | +| `source` | string | 判定来源(如"tag") | **执行流程:** ``` @@ -302,15 +322,22 @@ changelog: ```json { "success": true, - "storyId": 1001, - "useSdl": 1, - "sdlStatus": 3, - "requirementList": [ + "story_id": 533363, + "use_sdl": 1, + "sdl_status": 3, + "requirement_list": [ { - "reqSeq": "10", - "title": "输入校验", - "isEffective": 1, - "htmlDesignContent": "

对所有用户输入进行校验...

" + "req_seq": "21", + "title": "未授权访问", + "content": "1.应对用户的身份...2.鉴权逻辑应放在后台...", + "sec_design_demo": "1.除了公开的资源...2.使用XX框架进行鉴权...", + "is_effective": 1, + "html_design_content": "本次需求...无新增未授权访问面。", + "case_list": ["接口"], + "test_case_id": 0, + "remote_id": 37572, + "llm_reason": "判断来源:新增批量导出接口。判断依据:涉及接口。", + "source": "tag" } ] } @@ -362,7 +389,7 @@ changelog: } ``` -**注意:** 安全设计生成是异步过程,生成后需调用 get_sdl_detail 检查 sdlStatus 是否变为2(已完成)。 +**注意:** 安全设计生成是异步过程,生成后需调用 get_sdl_detail 检查 sdl_status 是否变为2或3(均代表generate完成;2=不涉及,3=待update确认)。 --- @@ -425,6 +452,8 @@ changelog: | `isUpdate` | boolean | Yes | 是否推送到运营平台更新(可为null) | | `subSystemId` | string | No | 子系统ID | +⚠️ status==3 时按 generate 返回报文填充:storyReqDtoList 按 requirement_list 下的字段填充,noSdlReason/noSdlDetail 取自 no_sdl_reason/no_sdl_detail,useSdl 取自 use_sdl。status==2 不调 update。 + **执行流程:** ``` 1. 调用 mcp__sdp__update-story-sec-design 更新安全设计内容 diff --git a/.claude/skills/version-change-order-generator/SKILL.md b/.claude/skills/version-change-order-generator/SKILL.md index 5e20bef7fcba318f8493b285de35667e885ee605..4d0bd9b54107008035b8e926ab69dfa34092375f 100644 --- a/.claude/skills/version-change-order-generator/SKILL.md +++ b/.claude/skills/version-change-order-generator/SKILL.md @@ -1,7 +1,7 @@ --- name: version-change-order-generator type: skill -description: 版本发布变更单生成Skill,既可被dev-flow菜单调起也可手动调用,通过versionPlanId定位版本,读取versions.json和各文档石墨链接,按模板生成版本变更单 +description: 版本发布变更单生成Skill,可被complete-version步骤10.5调起或手动命令调用,通过versionPlanId定位版本,读取versions.json和各文档石墨链接,按模板生成版本变更单 version: 1.3 author: DevSyncAgent Team last_updated: 2026-07-14 @@ -34,7 +34,7 @@ changelog: ## 重要概念 -本 Skill 既可被 dev-flow 主菜单(STARTED + ALL_COMPLETED 状态)的"生成变更单"选项调起,也可通过 `/version-change-order-generator ` 手动独立调用,用于在版本开发完成(或阶段完成)后生成版本发布变更单文档。 +本 Skill 可在完成版本流程中由 complete-version 步骤10.5(版本归档后、testReportId非空时询问)调起,也可通过 `/version-change-order-generator ` 手动独立调用,用于在版本开发完成(或阶段完成)后生成版本发布变更单文档。 ## 调用形式 diff --git a/.version-lock.json b/.version-lock.json index d8b166886ee52fa80e2492133c9831ef5eaba350..64a3d439e7d384fef9aefdf3f47449f827e3c95e 100644 --- a/.version-lock.json +++ b/.version-lock.json @@ -1,7 +1,7 @@ { "schema_version": "3.0", - "current_version": "4.10", - "release_date": "2026-07-30", + "current_version": "4.11", + "release_date": "2026-08-19", "status": "development", "agents": { "requirement": { @@ -68,32 +68,32 @@ "last_modified": "2025-01-12" }, "des-enhance-feature": { - "version": "4.9", - "last_modified": "2026-07-16" + "version": "4.11", + "last_modified": "2026-07-17" }, "des-fix-bug": { - "version": "4.9", - "last_modified": "2026-07-16" + "version": "4.11", + "last_modified": "2026-07-17" }, "des-integrate": { - "version": "4.9", - "last_modified": "2026-07-16" + "version": "4.11", + "last_modified": "2026-07-17" }, "des-new-feature": { - "version": "4.9", + "version": "4.10", "last_modified": "2026-07-16" }, "des-optimize": { - "version": "4.9", - "last_modified": "2026-07-16" + "version": "4.11", + "last_modified": "2026-07-17" }, "des-recheck-orchestrator": { "version": "4.8", "last_modified": "2026-06-23" }, "des-refactor": { - "version": "4.9", - "last_modified": "2026-07-16" + "version": "4.11", + "last_modified": "2026-07-17" } }, "development": { @@ -102,40 +102,40 @@ "last_modified": "2026-07-16" }, "frontend-code-developer": { - "version": "4.7", - "last_modified": "2026-07-16" + "version": "4.8", + "last_modified": "2026-07-20" }, "go-code-developer": { - "version": "4.8", - "last_modified": "2026-07-16" + "version": "4.9", + "last_modified": "2026-07-20" }, "go-code-review": { "version": "1.4", "last_modified": "2026-07-16" }, "java-code-developer": { - "version": "4.9", - "last_modified": "2026-07-16" + "version": "4.10", + "last_modified": "2026-07-20" }, "java-code-review": { "version": "1.3", "last_modified": "2026-07-16" }, "python-code-developer": { - "version": "4.9", - "last_modified": "2026-07-16" + "version": "4.10", + "last_modified": "2026-07-20" }, "python-code-review": { "version": "1.3", "last_modified": "2026-07-16" }, "typescript-code-developer": { - "version": "4.9", - "last_modified": "2026-07-16" + "version": "4.10", + "last_modified": "2026-07-20" }, "web-frontend-developer": { - "version": "4.7", - "last_modified": "2026-07-16" + "version": "4.8", + "last_modified": "2026-07-20" } }, "testing": { @@ -199,8 +199,8 @@ "last_modified": "2026-06-01" }, "dpms-design-sync": { - "version": "1.3", - "last_modified": "2026-05-28" + "version": "1.4", + "last_modified": "2026-07-21" }, "dpms-requirements-sync": { "version": "1.6", @@ -311,8 +311,8 @@ "commands": { "workflow": { "dev-flow": { - "version": "4.9", - "last_modified": "2026-07-21" + "version": "4.10", + "last_modified": "2026-07-23" } }, "git": {}, @@ -369,8 +369,8 @@ "1.0": 16, "1.1": 10, "1.2": 3, - "1.3": 6, - "1.4": 1, + "1.3": 5, + "1.4": 2, "1.5": 1, "1.6": 1, "2.1": 1, @@ -379,12 +379,13 @@ "3.0": 1, "3.1": 2, "3.3": 1, - "4.10": 6, + "4.10": 11, + "4.11": 5, "4.4": 1, "4.6": 2, - "4.7": 4, - "4.8": 4, - "4.9": 20 + "4.7": 2, + "4.8": 5, + "4.9": 11 }, "version_list": [ [ @@ -481,31 +482,31 @@ "agent", "design", "des-enhance-feature", - "4.9" + "4.11" ], [ "agent", "design", "des-fix-bug", - "4.9" + "4.11" ], [ "agent", "design", "des-integrate", - "4.9" + "4.11" ], [ "agent", "design", "des-new-feature", - "4.9" + "4.10" ], [ "agent", "design", "des-optimize", - "4.9" + "4.11" ], [ "agent", @@ -517,7 +518,7 @@ "agent", "design", "des-refactor", - "4.9" + "4.11" ], [ "agent", @@ -529,13 +530,13 @@ "agent", "development", "frontend-code-developer", - "4.7" + "4.8" ], [ "agent", "development", "go-code-developer", - "4.8" + "4.9" ], [ "agent", @@ -547,7 +548,7 @@ "agent", "development", "java-code-developer", - "4.9" + "4.10" ], [ "agent", @@ -559,7 +560,7 @@ "agent", "development", "python-code-developer", - "4.9" + "4.10" ], [ "agent", @@ -571,13 +572,13 @@ "agent", "development", "typescript-code-developer", - "4.9" + "4.10" ], [ "agent", "development", "web-frontend-developer", - "4.7" + "4.8" ], [ "agent", @@ -649,7 +650,7 @@ "skill", "other", "dpms-design-sync", - "1.3" + "1.4" ], [ "skill", @@ -811,7 +812,7 @@ "command", "workflow", "dev-flow", - "4.9" + "4.10" ], [ "command", @@ -880,14 +881,14 @@ "1.0" ] ], - "total_versions": 19 + "total_versions": 20 }, "metadata": { "total_agents": 36, "total_skills": 34, "total_commands": 12, "total_components": 82, - "total_versions": 19, + "total_versions": 20, "last_release": "4.9", "last_release_date": "2026-07-24" }, diff --git a/docs/project-knowledge/sessions/agent_requirement-design_fd4df847/session_detail.md b/docs/project-knowledge/sessions/agent_requirement-design_fd4df847/session_detail.md new file mode 100644 index 0000000000000000000000000000000000000000..6aa30ae9c847b856ef300513218a84509ef6afe9 --- /dev/null +++ b/docs/project-knowledge/sessions/agent_requirement-design_fd4df847/session_detail.md @@ -0,0 +1,615 @@ + +## 交互记录 (2026-07-27T09:22:25.393Z) + +**用户**: +分析下当前agent,用户执行dev-flow version和dev-flow 需求描述,整个流程设计哪些agent或skill,输出一个文档,标出具体的stage,具体的agent\skill名称,用途 + +**AI**: +[思考] 用户要求分析当前agent项目,针对"dev-flow version"和"dev-flow 需求描述"两条流程,梳理涉及的agent或skill,输出一个文档,标出具体的stage、agent/skill名称、用途。 + +让我先回顾上下文(CLAUDE.md要求每次回复前必须做上下文回顾)。 + +## 上下文回顾 + +**本次对话的核心问题**:分析dev-flow version和dev-flow 需求描述两条流程涉及的agent/skill,输出文档说明stage、agent/skill名称、用途。 + +**已识别的缺陷/问题**:暂无(这是第一轮对话) + +**当前处于哪个阶段**:分析任务,需要先探索代码库结构。 + +根据CLAUDE.md规范,这是一个分析任务,我需要: +1. 先实际读取agent/skill内容,不能凭假设(memory: verify-against-actual-agent-content) +2. 不要关注changelog,以当前文件内容为准(memory: analyze-project-ignore-changelog) +3. 多对象分析完整性检查 - 涉及多个agent,需要完整枚举 + +这是一个研究/分析任务,不是实施任务,所以不需要enforce-checklist。但需要全面探索代码库。 + +让我先探索项目结构,理解dev-flow的设计。我应该: +1. 找到dev-flow相关的核心文件 +2. 理解stage定义 +3. 梳理version流程和需求描述流程涉及的agent/skill + +让我并行启动几个探索任务。先看项目结构。 + +实际上,这种跨多文件的探索分析任务,适合用Agent工具委托。但我也可以自己先快速探索关键文件。 + +让我先看dev-flow的核心定义文件。从git status看到有 "dev-flow" 相关的md文件在根目录。让我先探索。 + +我会并行: +1. 找dev-flow.md主文件 +2. 找stage-names.json +3. 列出agents目录 +4. 列出skills目录 + +让我开始。考虑到这是一个需要读跨多文件的分析任务,我可以用Agent委托探索,但我自己先建立全局结构会更准确。让我先并行读取关键索引文件。... + + +## 交互记录 (2026-07-27T09:22:49.104Z) + +**用户**: +[{'tool_use_id': 'call_669d77413543467ca6532cc3', 'type': 'tool_result', 'content': '.claude\\commands\\dev-flow.md'}] + +**AI**: +## 上下文回顾 + +**本次对话的核心问题**:分析 `dev-flow version` 和 `dev-flow 需求描述` 两条流程分别涉及哪些 agent/skill,输出文档说明 stage、agent/skill 名称、用途。 + +**当前阶段**:分析任务,需先探索代码库实际结构(遵循 memory `verify-against-actual-agent-content`:不凭假设标注,以实际文件内容为准;`analyze-project-ignore-changelog`:不看 changelog)。 + +先并行探索关键索引文件,建立全局结构。... + + +## 交互记录 (2026-07-27T09:22:49.540Z) + +**用户**: +[{'tool_use_id': 'call_7a4bcb4b8ee34fcdb86f5e98', 'type': 'tool_result', 'content': '.claude\\config\\dev-flow-checklists\\stage-names.json'}] + +**AI**: +[思考] 现在我有了完整的agent和skill列表。接下来需要读取关键文件: +1. `.claude/commands/dev-flow.md` - dev-flow主入口 +2. `.claude/config/dev-flow-checklists/stage-names.json` - stage定义 + +让我读取这两个核心文件,它们应该能告诉我整个流程的stage设计和agent/skill调用。 + +由于dev-flow.md可能很大,我先读它和stage-names.json。并行读取。... + + +## 交互记录 (2026-07-27T09:22:49.730Z) + +**用户**: +[{'tool_use_id': 'call_aa08ec11801a4230b3b5f76e', 'type': 'tool_result', 'content': '.claude\\agents\\common\\word-generation-module.md\n.claude\\agents\\documentation\\diagram-sync-agent.md\n.claude\\agents\\requirement\\SPLITTING_INTEGRATION_GUIDE.md\n.claude\\agents\\requirement\\_clarification-result-complete-example.md\n.claude\\agents\\requirement\\_clarification-result-enhanced-template.md\n.claude\\agents\\requirement\\_qa-io-identification-interaction-optimization.md\n.claude\\agents\\requirement\\_requirement-splitting-workflow.md\n.claude\\agents\\requirement\\req-template-adapter.md\n.claude\\agents\\requirement\\resources\\gherkin-guide.md\n.claude\\agents\\design\\architecture-reviewer.md\n.claude\\agents\\design\\des-recheck-orchestrator.md\n.claude\\agents\\requirement\\req-recheck-orchestrator.md\n.claude\\agents\\analysis\\project-context-analyzer.md\n.claude\\agents\\requirement\\req-refactor-analyzer.md\n.claude\\agents\\requirement\\req-optimize-analyzer.md\n.claude\\agents\\requirement\\req-fix-bug-analyzer.md\n.claude\\agents\\requirement\\req-type-classifier.md\n.claude\\agents\\requirement\\req-clarification-orchestrator.md\n.claude\\agents\\requirement\\req-enhance-feature-analyzer.md\n.claude\\agents\\requirement\\req-integrate-analyzer.md\n.claude\\agents\\requirement\\req-new-feature-analyzer.md\n.claude\\agents\\development\\claude-code-developer.md\n.claude\\agents\\development\\go-code-review.md\n.claude\\agents\\development\\java-code-review.md\n.claude\\agents\\development\\python-code-review.md\n.claude\\agents\\requirement\\acceptance-criteria-generator.md\n.claude\\agents\\requirement\\competitor-analyzer.md\n.claude\\agents\\requirement\\integrate-security-clarifier.md\n.claude\\agents\\requirement\\version-orchestrator.md\n.claude\\agents\\testing\\test-case-clarification-orchestrator.md\n.claude\\agents\\design\\des-enhance-feature.md\n.claude\\agents\\design\\des-fix-bug.md\n.claude\\agents\\design\\des-integrate.md\n.claude\\agents\\design\\des-new-feature.md\n.claude\\agents\\design\\des-optimize.md\n.claude\\agents\\design\\des-refactor.md\n.claude\\agents\\development\\frontend-code-developer.md\n.claude\\agents\\development\\go-code-developer.md\n.claude\\agents\\development\\java-code-developer.md\n.claude\\agents\\development\\python-code-developer.md\n.claude\\agents\\development\\typescript-code-developer.md\n.claude\\agents\\development\\web-frontend-developer.md\n.claude\\agents\\testing\\functional-test-generator.md'}] + +**AI**: +已获得完整 agent/skill 清单。现在读取 dev-flow 主入口和 stage 定义两个核心文件。... + + +## 交互记录 (2026-07-27T09:22:50.122Z) + +**用户**: +[{'tool_use_id': 'call_d4f15867071947e0a84fa958', 'type': 'tool_result', 'content': '.claude\\skills\\des-doc-validator\\SKILL.md\n.claude\\skills\\diagram-sync\\SKILL.md\n.claude\\skills\\docx\\SKILL.md\n.claude\\skills\\module-design-manager\\SKILL.md\n.claude\\skills\\req-doc-validator\\SKILL.md\n.claude\\skills\\session-persistence-manager\\SKILL.md\n.claude\\skills\\injection-attack-tester\\SKILL.md\n.claude\\skills\\injection-defense-designer\\SKILL.md\n.claude\\skills\\injection-guard-prompter\\SKILL.md\n.claude\\skills\\plugin-trace-collector\\SKILL.md\n.claude\\skills\\api-doc-generator\\SKILL.md\n.claude\\skills\\component-dependency-analyzer-go\\SKILL.md\n.claude\\skills\\component-dependency-analyzer-java\\SKILL.md\n.claude\\skills\\component-dependency-analyzer-python\\SKILL.md\n.claude\\skills\\knowledge-base-builder\\SKILL.md\n.claude\\skills\\module-requirement-manager\\SKILL.md\n.claude\\skills\\project-deployer\\SKILL.md\n.claude\\skills\\shimo-doc\\SKILL.md\n.claude\\skills\\memory-manager\\SKILL.md\n.claude\\skills\\dpms-requirements-sync\\SKILL.md\n.claude\\skills\\dpms-testing-sync\\SKILL.md\n.claude\\skills\\frontend-dynamic-tester\\SKILL.md\n.claude\\skills\\injection-risk-identifier\\SKILL.md\n.claude\\skills\\module-code-manager\\SKILL.md\n.claude\\skills\\module-testing-manager\\SKILL.md\n.claude\\skills\\test-case-document-reviewer\\SKILL.md\n.claude\\skills\\test-code-generator\\SKILL.md\n.claude\\skills\\test-code-reviewer\\SKILL.md\n.claude\\skills\\test-executor\\SKILL.md\n.claude\\skills\\test-report\\SKILL.md\n.claude\\skills\\dpms-design-sync\\SKILL.md\n.claude\\skills\\functional-test-generator\\SKILL.md\n.claude\\skills\\version-change-order-generator\\SKILL.md'}] + +**AI**: +[思考] 这是个大文件,我已读到1058行,还有更多内容。让我继续读dev-flow.md的剩余部分,特别是standalone模式(单需求模式)和stage-hooks部分。 + +让我继续读dev-flow.md剩余内容。同时需要读stage-hooks.md(阶段Agent映射表的核心)和standalone-mode.md(单需求模式)。 + +让我先看dev-flow.md还有多少行,然后并行读取关键文件。 + +实际上,我已经获得了核心信息: +- 两条流程入口: + 1. `/dev-flow version` → 版本轨(版本模式) + 2. `/dev-flow <需求描述>` → 单需求轨(standalone模式) +- STAGE_ORDER: 21个阶段(0,1,1.1,1.2,1.6,2,2.1,2.2,3,3.1,3.2,3.5,4,5,5.5,6,6.1,7,8,9,10) + +现在我需要知道每个stage对应哪个agent/skill。这需要读stage-hooks.md。还需要读standalone-mode.md了解单需求模式。 + +让我并行读取: +1. dev-flow.md 剩余部分(1058行之后) +2. stage-hooks.md +3. standalone-mode.md +4. start-development.md(启动版本需求) + +先找这些文件的位置。stage-hooks和standalone-mode、start-development应该都在dev-flow-checklists目录。... + + +## 交互记录 (2026-07-27T09:22:56.954Z) + +**用户**: +[{'tool_use_id': 'call_c5ccb7048e3e45a0a33a10af', 'type': 'tool_result', 'content': '1\t---\n2\tname: dev-flow\n3\ttype: command\n4\tdescription: 开发工作流编排命令,启动完整的开发工作流,从需求分析到测试报告生成,支持版本粒度管理\n5\tversion: 4.9\n6\tauthor: DevSyncAgent Team\n7\tlast_updated: 2026-07-21\n8\tchangelog:\n9\t v4.9 - 2026-07-23\n10\t - 🆕 阶段3 S6:多git编排(多项目多仓库,S12纵向增量)。核心:工作目录模型从单一pwd扩展为多仓库localPath映射。4处新增交互:G1第3.8轮"是否多git"询问+G2每子系统git仓库收集(SSH+localPath)+G3 Stage4需求级跨仓库提交确认+G4 complete-version版本级跨仓库归档确认。数据模型:versions.json contextSchemaVersion 2.0→2.1+isMultiGit+subsystems[].gitUrl/localPath+repositories[]去重仓库列表+requirements[].repositoryId+migrate_v2_to_v2_1向后兼容。8改动点:dev-flow第3.8轮+create-version schema+Stage4需求级跨仓库提交(H1修正:用req.repositoryId非遍历所有仓库)+步骤11版本级跨仓库归档+A6 gitUrl用sub.gitUrl+阶段Prompt【代码工作目录】注入localPath+context.md加repositoryId+add-story仓库归属+context-contract字段。H1修正(Stage4需求级vs步骤11版本级层次)。5决策点(G-D1工作目录模型/G-D2 Stage3 Agent非pwd工作/G-D3跨仓库原子性PendingItem/G-D4每仓库分支/G-D5多project-context)。P5单分支在多git下自然延伸为每仓库一分支(不同仓库同名分支不冲突)。E7技术栈多git下变真实(G-D5多project-context处理)\n11\t - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目\n12\t v4.9 - 2026-07-21\n13\t - 🆕 阶段2 S11:形态B×多子系统整合(最终目标1)。真实整合点2个+交互强化2个(v1.5反附和:6整合点经源码核验4虚假排除):①E6 Stage5部署确认pipelineId从版本级入口单值改为reqSubsystemId反查(第1阶段遗漏补全,与B7 fixBug同模式);②E4 Stage9失败回滚与段屏障交互(阶段0遗留):D1 execute_segments增加pending_reqs跳过已完成段(支持resume:已完成段跳过/bugfix从P1)+D2 Stage9失败分支改blocked+退出+bugfix子需求纳入(原execute_rollback破坏段屏障)+V段屏障判定含completed/skipped/blocked三态+blocked需求不参与V段版本级回归+wait_segment_barrier含blocked+execute_serial_segment感知D段blocked跳出;③交互强化1 execute_segments提前退出(Stage9失败blocked)的用户引导(AskUserQuestion继续开发/返回主菜单);④交互强化2 继续版本开发步骤5适配形态B段调度(阶段0遗漏补全:原"按STAGE_ORDER逐阶段"改调execute_segments统一编排)。execute_segments增加返回值(completed/exited_with_blocked)。不碰数据模型(第1阶段已处理多子系统)。v1.5循环体改造按强制清单:全分支扫描+残留变量扫描+一次收敛\n14\t - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目\n15\t v4.9 - 2026-07-21\n16\t - 🆕 阶段1 S5:多子系统支持落地(S11/S12最终目标的纵向基础)。核心设计:入口子系统(其版本号=版本计划版本号,版本级保留单值subsystemId/subsystemName/subsystemVersionId/branchName/pipelineId/pipelineVersion供"版本计划版本号语义"下游兼容)+ subsystems[]数组(每子系统独立versionId/pipelineId,isEntry标识)+ requirements[].reqSubsystemId需求归属。dev-flow.md 第3.5轮新增"是否多子系统"询问+第4轮单选改多选+入口+第1.5轮循环多版本号+状态表加subsystems[]清单;create-version.md A2b循环多子系统(非阻塞)/6.5单分支(所有子系统共享,P5修正)/6.6多流水线/subsystems[]+入口单值schema;complete-version.md A6循环多子系统封板(入口优先);start-development.md context.md加reqSubsystemId+add-story归属;functional-test-generator(Agent+SKILL两处)子系统来源反查versions.json(顺带修既有project-context错误);business_api.go Version/Task struct加Subsystems[]/EntrySubsystemID/SubsystemID;version-change-order-generator第一章遍历subsystems[]多行(P1修正);stage-hooks.md B7 fixBug反查reqSubsystemId(H1修正:Bug关联到实际所在子系统版本非入口);associate-requirement.md A4-2按reqSubsystemId分组(H2修正:需求关联到各自子系统版本非入口统一);contextSchemaVersion 1.0→2.0+migrate_v1_to_v2向后兼容。D11红利诚实界定:仅"版本计划版本号语义"成立,P1/H1/H2下游必改。3轮检视修正:缺口G(reqSubsystemId)+H1/H2红利误判+P5多分支架构错误(单项目单git不可多分支)\n17\t - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目\n18\t v4.9 - 2026-07-21\n19\t - 🆕 阶段0 spike:形态B分阶段交错并行编排落地(S11/S12最终目标的并行基础)。start-development.md 步骤E 从"逐需求串行A-E全流程"重构为 SEGMENT_ORDER 段调度(P1/S1/P2/S2/D/V 6段,段间屏障同步);stage-hooks.md 新增"形态B分段交错编排"章节含 SEGMENTS 定义+7个段调度函数(execute_segments/execute_parallel_segment/execute_serial_segment/wait_segment_barrier/batch_ask_recheck_optimization/update_segment_progress/migrate_add_segment_progress)+commit_stage_transition 签名不变+flush_commit_queue(方案C:并行段N需求并发生成文档、结果入局部stage_results_queue、主会话串行commit规避并发写versions.json,现有调用100%兼容);dev-flow-context-contract.json allowed_context_updates 新增 segmentProgress;dev-flow.md 继续版本开发恢复逻辑适配 segmentProgress 优先定位。形态B核心规则:改源码段(S1/S2/V)串行、文档段(P1/P2/D)并行(21阶段二分已源码验证:Stage6文档✅/Stage7代码❌/Stage3.2改码❌/Stage3.5改插件❌)。v4.0废弃教训规避:主会话掌段间屏障+commit、subagent只跑单阶段(不重蹈subagent独立编排丢子阶段覆辙)。阶段0限定happy path(Stage9一次通过),Stage9失败回滚与段屏障交互待阶段2 S11实现\n20\t - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目\n21\t v4.9 - 2026-07-21\n22\t - 🐛 修复 636c1008 hide 提交不彻底:dev-flow.md "### 生成变更单""### 回滚到指定阶段"章节本体保留但无隐藏标注,机器人模式 LLM 读完整 dev-flow.md 生成菜单时误将其当主菜单项→出现 8 项菜单(含变更单/回滚入口)。修复:两章节标题加"⛔已从主菜单隐藏"标注 + 章节开头加明确禁止列入主菜单的约束说明;STARTED 段补"主菜单仅以下6项,禁止把后续章节当菜单项"双保险。能力保留不变(变更单 skill 手动渠道、回滚 execute_rollback 内部调用)\n23\t - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目\n24\t v4.9 - 2026-07-20\n25\t - 🐛 修复创建版本灰度发布场景双重缺口:①收集侧 dev-flow.md 第4轮补"灰度发布日期"询问(选"是"后追加,含 YYYY-MM-DD 格式校验+版本周期范围校验,IF/ELSE双分支同步);②传递侧 create-version.md A2b 补全 MCP 必填 isNeedGrayRelease 与条件必填 expectGrayReleaseDate(对齐 dpms-requirements-sync SKILL.md:418-472 权威定义);versions.json + version-context.md 新增 isNeedGrayRelease/grayReleaseDate 字段持久化\n26\t - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目\n27\t v4.9 - 2026-07-20\n28\t - 🐛 修复 Stage 10 版本级回归用例状态流转缺失:新增 10.6.1 子步骤,test_passed 时将版本级回归用例流转为通过(status=3),对齐 Stage 7 B7.5 语义;复用 stage-hooks.md HTTP POST 容错模式;新增 .regression-case-cache.json transitionedAt 幂等标记\n29\t - 🐛 修复 Stage 10.3 product_name 无空值兜底:对齐 Stage6-Hook B5,productName 为空时优先取 requirements[].productName,降级用 storyId 调 get-storys 实时查询回填\n30\t - 🔧 Stage 10.3 safe_call_mcp 调用补 task_name 参数(addTestCase/linkTestCaseToTestPlan)\n31\t - ⚠️ 已知未修:safe_call_mcp 业务错误分支不写 pending(P1-3,通用包装器缺陷,影响所有 Hook,需独立方案评估)\n32\t - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目\n33\t v4.9 - 2026-07-17\n34\t - 🔁 Stage 9 循环决策改为可配置:新增独立 `loop_decision.mode=auto|ask`,标准/质量模板默认询问,极简模板保持自动;不再复用仅控制阶段进入确认的 `non_skippable.9`\n35\t - ⏸️ `ask` 模式检测到测试失败时通过 AskUserQuestion 询问“进入下一轮修复/暂停保留现场”;暂停保持 currentStage=9 且不完成 Stage 9,恢复后重新询问\n36\t - 🧩 交互模板与运行时配置 schema 升至1.1;兼容1.0旧配置,无配置/解析失败/非法值安全回退为询问\n37\t - 🧭 版本全流程上下文传递优化:新增 `.claude/config/dev-flow-context-contract.json`,为 21 个阶段定义 consume/produce 白名单与统一 stage result 协议\n38\t - 🔄 新增版本级 `version-context.md` + 需求级 `context.md` 双层上下文;阶段 Prompt 每次实时刷新版本快照、上一阶段摘要、产物索引、决策与风险\n39\t - 🛡️ 新增两阶段 checkpoint:所有完成/跳过/自动跳过/降级分支统一提交 stageOutputs + stageHistory,修复提前 CONTINUE 导致上下文和进度未传递\n40\t - ♻️ resume 改为 checkpointId/state 恢复,废弃“只比较 stageHistory 长度”的模糊覆盖;Stage 10/complete-version 消费版本聚合上下文\n41\t - 🔧 `stage-names.json` v1.1 补齐 Stage 10,确保 STAGE_ORDER、中文映射与上下文契约均为21阶段\n42\t - ⛔ Claude Code 边界:Stage 4 和版本归档显式排除根目录 `.agents/`,禁止 `git add .`/`git add -A`\n43\t - 🛡️ 版本全流程进度一致性修复:在原 currentStage 双写基础上升级为 checkpointId/checkpointState 对账,避免仅按 stageHistory 长度推断权威状态\n44\t - 🔗 配套修改:stage-hooks.md 步骤1 改为双写一致(versions.json + context.md currentStage 同步写入)、business_api.go 后端聚合 version 状态、message_dispatcher.py create_task stage 恢复非空、task-viewer 前端 STAGE_PIPELINE 补 key + 启动中显示\n45\t - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目\n46\t v4.9 - 2026-07-14(天花板回退至4.9,原 v4.11/v4.10 changelog 合并)\n47\t - 🔄 6.5.1(关联子系统版本到Git分支)从创建版本后移至完成版本封板前:complete-version 新增 A6-Step0(封板前置),封板时先关联分支再封板\n48\t - 🔄 create-version 6.6(更新PACE流水线)解除与 6.5.1 的 v4.9 原子绑定,改为独立步骤(6.6 必须留创建版本以保障开发期 Stage3.5/Stage5/CI-CD 的 pipelineId 依赖)\n49\t - 🗑️ 删除 dev-flow.md 待补录重试中 6.5.1->6.6 联动块(二者不再原子,各自独立重试)\n50\t - ⚠️ 代价:拆开原子绑定后,开发期存在"流水线已指向分支但分支未在SCM关联"的窗口期,直到封板补关联(CI-CD不受影响)\n51\t - 🔗 配套修改:create-version.md(6.6独立+跳过规则+schema注释+验证清单)、complete-version.md(步骤3.5+跳过PendingItem+验证清单)\n52\t - 🔧 Stage1-Hook(B1) content 从全文 Markdown->HTML 转换改为四章节关键信息提取:按「需求背景/需求描述与设计/后台技术设计/测试关注点」四章节从需求文档语义提取(LLM 提取,容忍标题变体),固化 HTML 模板组装(只用

/

/

  • ,规避 DPMS 对 /
    /
    /class 的过滤);后台技术设计与测试关注点限 1-3 句概述,提取不到填占位文本不留空;去掉「五、人力分配情况」章节;配套修改 stage-hooks.md 第 835-854 行伪代码\n53\t    - 🆕 新增 stage 级统一回滚机制:主菜单 STARTED 新增"回滚到指定阶段"选项 + 通用 stage 失败决策新增"回滚到指定阶段"第四选项;用户自由选择回退到已执行的任意阶段(展示中文阶段列表,默认回退上一步)\n54\t    - 🔄 收口原有零散回退逻辑为统一 execute_rollback 函数:Stage5部署失败(->stage3)、Stage3.2自检阻断返回修复(->stage3)、Stage9测试失败循环(->stage1) 全部改调统一函数;修复 Stage5 原未清 stageHistory 遗漏;Stage9 自动语义+MAX_CYCLES=10 保留不变\n55\t    - 🛡️ 回滚原子写入(临时文件+rename):currentStage+stageHistory+skipDecisions+rollbackHistory 一次性更新;防死循环(连续回滚同一 stage ≥3 次提示人工介入)\n56\t    - 📋 新建配置:stage-names.json(stage 中文映射+STAGE_ORDER 单一真相源)、rollback.md(execute_rollback 完整伪代码清单)\n57\t    - 📁 配套修改:stage-hooks.md(统一回滚章节+各回滚点改调+失败决策加选项)、dev-flow-menus.json(STARTED 菜单加回滚项)、standalone-mode.md(单需求模式同步)、create-version.md(schema 补 rollbackHistory)\n58\t    - ⚠️ 远程副作用取舍:已转提测Story/已同步测试用例/已 push commit 不清理(静默接受),仅回滚本地 currentStage+产物\n59\t    - 🆕 主菜单"生成变更单"章节版本选择环节改用 AskUserQuestion(原为自由文本输入 choice=等待用户输入),新增"返回主菜单"出口:用户可在选择版本前取消并返回主菜单,无需被动进入 skill;修复原非数字输入被当作 versionPlanId 传给 skill 的隐患;候选版本 >3 时仅展示前 3 个(活跃优先),其余通过 AskUserQuestion 自带 Other 自定义输入 versionPlanId\n60\t    - 🔄 同步 version-change-order-generator skill v1.3 校验逻辑变更(版本 status==completed):生成变更单章节 candidates 筛选增加 status==completed 条件、default_id 改为取首个 completed 版本、无候选提示与 969 说明文字同步更新\n61\t    - 🔄 生成变更单章节 candidates 按 completedAt 倒序排序(最近完成的版本在前、优先推荐);candidates 记录新增 completedAt 字段,选项 description 展示 completedAt 便于区分\n62\t    - ⚠️ 版本号天花板约束:天花板回退至 v4.9,原 v4.11/v4.10 changelog 合并至 v4.9(保持天花板=4.9 不突破)\n63\t  v4.9 - 2026-07-09\n64\t    - 🆕 新增项目级交互特性配置(P4.5 步骤):版本启动时强制询问用户是否设置/调整版本全流程交互特性(即便存在配置也强制询问)\n65\t    - 🆕 新增模板库 `.claude/config/dev-flow-interaction-templates.json`(3 个预定义模板:标准开发模式/极简高效模式/质量优先模式 + 自定义模式 6 组向导)\n66\t    - 🆕 新增运行时配置 `.claude/config/dev-flow-interaction-config.json`(项目级个性化,install.bat --core exclude 不覆盖)\n67\t    - 🔄 stage-hooks.md Step 3(判断可跳过):优先读取项目级配置 skippable 决策(skip/execute/ask),无配置时沿用原有询问逻辑(向后兼容)\n68\t    - 🔄 stage-hooks.md Step 4.5(分步模式确认):优先读取项目级配置 non_skippable 决策(auto_execute/ask),无配置时沿用原有询问逻辑\n69\t    - 🔄 standalone-mode.md 同步 P4.5 + 步骤2 + 步骤3.5 变更(单需求模式读取同一份项目级配置)\n70\t    - 🔗 配套修改:start-development.md P4 与 P5 之间新增 P4.5 + 步骤D参数块新增 {interaction_config}、install.bat exclude 列表新增 \\config\\dev-flow-interaction-config.json、output/.claude/config 镜像同步\n71\t    - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目\n72\t  v4.9 - 2026-07-08\n73\t    - 🆕 主菜单(STARTED + ALL_COMPLETED)新增"提交变更单"选项:列出 versions.json 所有 versionPlanId(默认推荐当前活跃版本),用户选择后调用 version-change-order-generator skill 生成版本发布变更单\n74\t    - 🆕 模块识别能力优化:identifier.py 新增自动模块发现(common 池目录聚类 + 增量注册 + 幂等性),module-identification-rules.json 新增 auto_discovery 配置段,knowledge-base-builder 阶段0新增自动发现模块确认步骤\n75\t    - 🆕 新增 Stage 10 版本级回归测试:所有需求 Stage 9 通过后触发,含模块选择(全量/手动/跳过)+ dpms 回归用例同步 + 版本级回归测试循环(MAX_CYCLES=3)+ 版本级报告\n76\t    - 🔄 A5.2 从 complete-version 步骤2.5 迁移至 Stage 10.3:触发时机从"完成版本"前移到"测试阶段末尾",complete-version 步骤2.5 改为前置检查(stage10Completed 判断)\n77\t    - 🔗 配套修改:stage-hooks.md STAGE_ORDER +10 + Stage 9 通过后 GOTO Stage 10、complete-version.md 步骤2.5 改为前置检查、stage-10-version-regression.md 新增、test-code-generator/test-executor 新增 --modules 参数(向后兼容)\n78\t    - ⚠️ 版本号天花板约束:保持 v4.9(天花板=4.9),仅追加 changelog 条目\n79\t    - 🔒 版本初始化步骤6.5.1+6.6 合并为原子操作 + 3 个强化措施:通过 IF control dependency 建立硬约束,~95% 阻止模型并行调用两个 MCP(剩余 ~5% 风险来自模型忽视 IF、长伪代码迷失、AskUserQuestion 降级场景)\n80\t    - 🔄 原6.5.1(关联子系统版本到Git分支)和6.6(更新PACE流水线版本及Git分支)合并为一个原子操作块,共享4选项决策入口(执行两个/仅关联/仅流水线/全部跳过)\n81\t    - 🛡️ 强化措施1:6.5.1 和 6.6 之间增加显式串行屏障声明,强化模型对 control dependency 的认知\n82\t    - 🛡️ 强化措施2:6.5.1 返回后显式 OUTPUT "🔒 串行节点:6.5.1 已完成,准备进入 6.6",强化模型对串行节点的认知\n83\t    - 🛡️ 强化措施3:AskUserQuestion 降级场景明确要求"等待用户回答后才继续",禁止在用户回复前发起后续 MCP 调用\n84\t    - 🛡️ 失败策略:6.5.1失败时6.6不执行(原子中止),6.6写入PendingItem(PREREQUISITE_FAILED);6.5.1成功后6.6失败,6.5.1结果保留,6.6单独写入PendingItem\n85\t    - 📋 配套修改:create-version.md 合并6.5.1+6.6章节 + 跳过规则同步 + 完成验证清单更新、complete-version.md 步骤引用同步、dev-flow.md PendingItem重试流程补充6.5.1成功后提示补执行6.6\n86\t    - ⚠️ 诚实声明:本方案为 Prompt 驱动下最可靠的串行保证(~95%),非绝对100%。绝对100%需要方案E(SDP MCP服务端新增合并方法 associate-branch-and-update-pipeline),依赖外部团队开发\n87\t    - ⚠️ 版本号天花板约束:升级到 v4.9(天花板=4.9),与 .version-lock.json current_version 对齐\n88\t  v4.9 - 2026-07-09\n89\t    - 🆕 Stage 5 部署确认增加流水线真实状态校验:用户选"已部署,继续"后调用 mcp__sdp__get-pipeline,判断 data.lastestTrigger.status(大小写不敏感)是否为 SUCCESS;SUCCESS 则推进测试,RUNNING 提示"正在部署"并回退重新询问,其他非 SUCCESS 提示"未成功"并回退重新询问;pipelineId 缺失或 MCP 工具调用异常时 AskUserQuestion 让用户决策(信任继续/跳过校验/回退Stage3);"部署失败"分支与其他逻辑不变\n90\t    - 📦 配套修改:stage-hooks.md 步骤4.6(版本模式,pipelineId 从 versions.json 读取)、standalone-mode.md 步骤3.6(单需求模式,pipelineId 询问用户输入)同步更新\n91\t    - ⚠️ 版本号天花板约束:保持 v4.9(≤ current_version 4.9 合规),仅追加 changelog\n92\t  v4.8 - 2026-07-07\n93\t    - 🆕 新增石墨上传回链 + DPMS资源ID持久化(3项):\n94\t      ① Stage2-Hook 接口文档生成后新增上传 markdown 到石墨(shimo-config.json 新增 api_doc 配置项 v2.1)\n95\t      ② 需求/设计/接口文档上传石墨后捕获 guid,拼 http://docs.weoa.com/docs/{guid} 回写到文档开头(幂等:已有链接行则替换,否则在 frontmatter 后插入)\n96\t      ③ complete-version A6-Step3 成功后将 reportId 持久化到 versions.json testReportId 字段(测试集 testSetId/regressionTestSetId 已由 A5/A5.1 记录)\n97\t    - 📁 仅版本模式生效(单需求模式保持无 shimo/DPMS);链接回写失败不阻塞主流程(转 pending)\n98\t    - 🔗 配套修改:shimo-config.json v2.1、stage-hooks.md(Stage1/2-Hook 回链 + 接口文档上传 + 映射表)、complete-version.md(A6-Step3 持久化 testReportId)、create-version.md(schema 补 testReportId)、dev-flow.md(版本状态表格新增测试报告ID行)\n99\t    - ⚠️ 版本号天花板约束:保持 v4.8(≤ current_version 4.9 合规),仅追加 changelog\n100\t  v4.8 - 2026-07-01\n101\t    - 🆕 新增 Stage 2.1 接口文档生成能力:涉及新增/变更 Web API 接口时,Stage2-Hook 调用新增 Skill `api-doc-generator`,从设计文档接口章节抽取,同时生成 OpenAPI yaml + Markdown 接口文档(同源原子,要么都生成要么都不生成)\n102\t    - 📁 输出路径:yaml 与 markdown 同目录;版本模式 `docs/{versionName}/api/{reqPrefix}_{需求名}_api-spec.yaml` + `_接口文档.md`;单需求模式 `docs/{branch}/api/{需求名}_api-spec.yaml` + `_接口文档.md`\n103\t    - ✅ 双产出同源原子:yaml 符合 OpenAPI 3.0.3 规范,与 markdown 同源生成严格对齐;6 个设计 Agent 删除内嵌 yaml 生成逻辑(v4.8),统一由本 Skill 生成;开发 Agent 读取路径不变\n104\t    - 🛡️ 触发判定:读取设计文档 2.2 API规范设计下的 API端点列表子章节(兼容 ### 2.2.1 API端点列表 和 ### API端点列表 两种格式),为空/N/A 则跳过;NEW/INTEGRATE 类端点视为新增直接生成,仅变更接口时 AskUserQuestion 兜底;随 stage2HookDone 幂等\n105\t    - 🔗 配套修改:新建 .claude/skills/api-doc-generator/SKILL.md(v1.3 双产出同源原子)、6 个设计 Agent 删 yaml 生成逻辑(v4.8)、skill-rules.json 注册、stage-hooks.md(Stage2-Hook 子步骤 + 映射表 2.1 行)、standalone-mode.md(步骤7 Stage 2.1 后置动作 + 幂等兜底描述 + 后置动作摘要)\n106\t    - ⚠️ 版本号天花板约束:保持 current_version 4.8(6 个 des-* 保持 v4.8 删 yaml 生成逻辑),dev-flow 保持 v4.8(追加 changelog,4.8 ≤ 天花板 4.8 合规)\n107\t  v4.8 - 2026-06-30\n108\t    - 🔧 Stage1-Hook(B1) `mcp__sdp__update-story` 的 `content` 参数强制 HTML 格式:调用前先判定输入是否已是 HTML;若为 Markdown/纯文本则执行 Markdown→HTML 转换(含标题/段落/列表/表格/代码围栏;Mermaid/PlantUML 保留为 language-* 代码块;转换失败降级为 `
    ` 包裹)。避免 DPMS 富文本字段直接吃 Markdown 导致展示异常\n109\t  v4.8 - 2026-06-30\n110\t    - 🛡️ 新增 Hook 幂等布尔标记(stage1HookDone/stage2HookDone)+ 下游入口"确认并补执行",防止用户手动改进度/恢复误判/跳阶段绕过 Stage 1.1/2.1 导致 Stage1/2-Hook 漏执行\n111\t    - 🔒 布尔语义定为"Hook 被执行过一次即为 true(失败已由容错框架转待补录,不影响置位)",与 pending-sync 互补不冲突(布尔管本体只跑一次,pending 管重试失败调用)\n112\t    - 🔗 Stage 2 入口查 stage1HookDone 补执行;Stage 3 入口查 stage2HookDone 补执行;两个兜底相互独立,Stage 2 Hook 本体不再前置补 Stage 1 Hook(正常前进流程中 Stage 2 入口先于 Stage 3 执行,stage1HookDone 已在 Stage 2 入口被保证)\n113\t    - 📦 配套修改:stage-hooks.md(布尔说明 + Stage2/3 前置确认 + 1.1/2.1 置位 + 映射表/触发说明)、standalone-mode.md(context.md 布尔字段 + Stage2/3 前置确认 + 步骤7 置位,仅本地动作不含 DPMS/shimo)\n114\t    - ⚠️ 版本号天花板约束:保持 current_version 4.8,dev-flow 保持 v4.8(追加 changelog,4.8 ≤ 天花板 4.8 合规)\n115\t  v4.8 - 2026-06-30\n116\t    - 🗑️ 删除Stage 3代码开发前置缺陷信息收集入口:代码开发前不再询问DPMS缺陷信息、不再向Stage 3 prompt注入defect_info\n117\t    - ✅ 保留开发Agent内部缺陷获取与修复逻辑不变:若外部显式传入defect_info且skip!=true,java/python/typescript开发Agent仍按原逻辑处理\n118\t    - 📦 配套修改:stage-hooks.md和standalone-mode.md同步移除Stage 3前置步骤2,避免版本模式/单需求模式行为不一致\n119\t    - ⚠️ 已知边界:stage-flow-rules.json的defectIntegration.enabled=true配置保留(master已有),但其消费者code-developer第-1步在收集入口删除后永远走"defect_info未定义→跳过"分支,配置事实失效。未来若恢复缺陷信息收集入口,该配置自动生效。\n120\t  v4.8 - 2026-06-26\n121\t    - 🆕 新增 Stage 3.2 代码部署前自检(STAGE_ORDER 在 3.1 与 4 之间插入 3.2,BIZ API stage=development,progress=58,版本模式可跳过)\n122\t    - 🆕 Stage 3.2 多语言动态分发(v4.8):按 project-context.json.techStack 选择对应 Agent\n123\t        - Java/Kotlin/Spring Boot → java-code-review v1.2(@Value/@ConfigurationProperties/@ConditionalOnProperty/System.getenv/classpath resource/Profile 漂移/启动期反模式)\n124\t        - Python → python-code-review v1.2(os.environ 直读/pydantic-settings 必填/decouple/environs/模块顶层 import-time bomb/类型转换陷阱/open() 资源)\n125\t        - Go → go-code-review v1.2(os.Getenv 裸用/init() 内 log.Fatal/包级 var 读 env/_丢 strconv 错误/viper 静默零值/envconfig required/godotenv/flag.Parse/bool 严格匹配)\n126\t        - 其他技术栈 → 自动跳过(auto_skipped_unsupported_tech)\n127\t    - 🔄 设计调整:原 pre-deploy-config-check / -go / -python 三个 Skill 全部改造为同名 -code-review Agent,位于 .claude/agents/development/ 与对应 -code-developer 同级配对,调用方式由 Skill 工具改为 Agent 工具\n128\t    - 🛡️ Stage 3.2 前置步骤1:技术栈分发 + 硬守卫(resolve subagent_type_3_2,不支持的技术栈自动跳过)\n129\t    - 🛡️ Stage 3.2 前置步骤2:AskUserQuestion 收集 target_env(prod/fat/dev/不指定)\n130\t    - 🛡️ Stage 3.2 后置步骤8.4:解析所选 Agent 返回文本末尾的 JSON 块,should_block_deploy=true 时 AskUserQuestion 三选项(返回修复 currentStage="3" / 强制进入部署 / 中止流程)\n131\t    - 📦 配套修改:stage-hooks.md STAGE_ORDER 更新、阶段映射表新增 3.2 行 `{lang}-code-review` 通配符、Agent 通配符解析规则表(Stage 3.2)、FOR 循环步骤4 ELIF 分支动态分发 + 步骤6 通配符调度 + 步骤8.4 + 阶段后置动作映射表\n132\t    - 📦 单需求模式同步集成(standalone-mode.md):STAGE_ORDER 加入 3.2、ELIF stage == 3.2 前置块(技术栈分发 + target_env 收集)、步骤5 通配符调度补 `{lang}-code-review`、新增步骤7.5 Stage 3.2 自检结果决策(写 context.md 而非 versions.json;不调 BIZ API)\n133\t    - 🔄 Stage 2.1 新增设计检视用户优化决策交互:同Stage 1.1五选项,支持执行全部/必要/必须/跳过/查看详细,优化仅修改本地设计文档,不同步DPMS\n134\t    - 🔄 Stage2-Hook执行时机调整:从Stage 2后移至Stage 2.1节点结束后;即使用户跳过Stage 2.1,也仍执行SDL同步、转开发、石墨上传、图表同步、提示词安全设计,且避免重复执行\n135\t    - 📦 单需求模式同步适配:Stage 2.1新增用户优化决策,图表同步和提示词安全设计调整至Stage 2.1节点结束后执行,跳过Stage 2.1时仍保留本地后置动作\n136\t    - 🔄 Stage 1 Hook执行时机调整:从Stage 1后移至Stage 1.1节点结束后,统一对最终需求文档执行update-story、shimo上传、图表同步和提示词注入风险识别;跳过Stage 1.1时仍执行一次\n137\t    - 🗑️ 删除Stage1.1-Hook(B1-Recheck)二次同步入口,避免Stage 1初版同步与Stage 1.1优化后同步重复执行\n138\t    - 📦 单需求模式同步适配:Stage 1图表同步和提示词注入风险识别调整至Stage 1.1节点结束后执行,跳过Stage 1.1时仍保留本地后置动作\n139\t    - ⚠️ 版本号天花板约束:升级到 v4.8(天花板=4.8),与 .version-lock.json current_version 对齐\n140\t  v4.7 - 2026-06-25\n141\t    - 🆕 创建版本新增步骤6.5.1:基于步骤6.5创建的Git分支调用 mcp__sdp__associate-subsystem-version-branch 关联子系统版本与分支(AskUserQuestion 询问 DEV/RELEASE,失败写入 PendingItem 不阻塞)\n142\t    - 🔧 完成版本 A6-Step1 流水线封板 version 参数取值修正:从 版本配置.pipelineVersion(步骤6.6收集,可能为"BDP-XXX_2.0.23"拼装格式)改为 版本配置.subsystemVersionId(第1.5轮收集,纯版本号"2.0.23"),符合 mcp__tctp-dpms-set__freezePipeline 平台契约要求\n143\t    - 🔧 同步修正 complete-version.md A6-Step1 用户补录提示中"BDP-UDES_1.1.16"误导示例为"2.0.23"\n144\t    - 🔗 配套修改:create-version.md 步骤6.5.1新增 + 完成验证清单同步、complete-version.md A6-Step1 version 参数源修正\n145\t    - ⚠️ 版本号天花板约束:保持v4.7(天花板=4.7),仅追加changelog条目\n146\t  v4.7 - 2026-06-22\n147\t    - 🆕 创建版本流程新增A5.1:创建版本回归测试集(createTestPlanSet testStep=2,regressionTestSetId写入versions.json)\n148\t    - 🆕 完成版本流程新增A5.2:填充版本回归用例集(必选=涉及模块回归案例,可选=非涉及模块,AskUserQuestion确认)\n149\t    - 🔗 配套修改:create-version.md步骤5.1、complete-version.md步骤2.5、functional-test-generator v4.7 第6.5步回写moduleId\n150\t    - 🔗 version-orchestrator v4.2 MCP表补充:createTestPlanSet(testStep=2)、addTestCase、linkTestCaseToTestPlan\n151\t    - 📋 详见方案文档:docs/回归测试用例集方案.md\n152\t    - ⚠️ 版本号天花板约束:保持v4.7(天花板=4.7),仅追加changelog条目\n153\t  v4.7 - 2026-06-10\n154\t    - 🔧 biz_api_url确定性保障:server.py读取BIZ_API_BASE环境变量fallback,stage-hooks.md/standalone-mode.md/start-development.md补全biz_api_url参数传递,versions.json新增biz_api_url持久化字段,req-type-classifier补全4处biz_sync_stage缺失参数\n155\t  v4.7 - 2026-06-09\n156\t    - 🆕 新增 P3.5 价值收益评估前置步骤(支持跳过),并与 Stage 0 (req-clarification-orchestrator) 价值量化门控豁免打通\n157\t  v4.6 - 2026-06-08\n158\t    - 🆕 start-development/standalone-mode新增P0步骤:需求描述四要素规范化检查(对齐旧版req-type-classifier Step 0,可跳过)\n159\t    - 🆕 P1步骤1:project-context.json不存在时提供生成选项(对齐旧版Step 6.5自动触发机制,用户可选择生成或跳过)\n160\t    - 🆕 P1步骤2:传入req-type-classifier的分类上下文扩展tech_stack_summary(对齐旧版Step 7项目上下文结合分类)\n161\t    - 🆕 P4项目上下文确认:不存在时提供完整影响展示+修正路径(对齐旧版Step 6.6展示模板+选择选项)\n162\t    - 🆕 Stage 0完成后主会话提取function_attributes/frontend_type更新context.md(修复逐阶段控制下功能属性数据链断裂)\n163\t    - 🆕 阶段Prompt构造规则条件性注入【功能属性】和【前端类型】(对齐旧版subagent内部自动传递)\n164\t    - 🆕 Stage 3前置步骤1增加function_attributes来源三级兜底(context.md>需求文档解析>手动指定,保障3D决策输入)\n165\t  v4.6 - 2026-06-04\n166\t    - 🛡️ 数据属性阻断回退:Stage 0检测到ETL数据开发属性时,回退到需求描述环节重新输入(暂不支持数据开发Agent)\n167\t    - 🔄 P3竞品分析改为可跳过(原P0级强制→默认执行+AskUserQuestion确认,解决耗时过长问题)\n168\t    - 🔄 Stage 9循环决策新增skipDecisions重置(重置"1"及之后条目,保留"0"及之前,让用户在循环中重新选择可跳过环节)\n169\t    - 🔄 P4项目上下文确认兼容P3跳过(若P3已跳过则不融入竞品分析结果)\n170\t    - 🔄 前置步骤结果传递规则/Prompt参数块补充P3跳过时的默认值说明\n171\t    - 🔄 Stage2-Hook(B2)安全设计同步从update-story改为SDL三步流程(generate-sdl-requirement→get-story-sdl-detail→update-story-sec-design)+三选项交互(执行/跳过记录待补录/不涉及SDL);安全设计改为必经环节(不依赖设计文档是否包含安全设计章节)\n172\t    - 🆕 版本初始化步骤6.6:更新PACE流水线版本及Git分支(mcp__sdp__update-version-build-branch),支持执行/跳过+safe_call_mcp容错,版本配置新增pipelineId/pipelineVersion字段\n173\t  v4.6 - 2026-06-01\n174\t    - 🆕 版本模式文档命名新增REQ-NN前缀(如REQ-01_用户注册_需求.md),单需求模式不变\n175\t    - 🆕 versions.json新增nextReqIndex计数器和requirements[].reqIndex字段\n176\t    - 🆕 add-story/add-stories流程自动分配递增需求编号\n177\t    - 🆕 版本模式Prompt新增【需求编号】参数,各Agent识别后为文件名加前缀\n178\t    - 🆕 context.md新增reqIndex和reqPrefix字段\n179\t    - 🆕 查看版本状态/需求列表表格新增"需求编号"列\n180\t    - 🆕 创建版本新增步骤6.5:基于子系统版本号创建Git分支(AskUserQuestion交互,建议名称dev-{subsystemVersionId},幂等处理)\n181\t  v4.6 - 2026-05-28\n182\t    - 🏗️ 架构变更:Step E从subagent独立编排改为主会话按STAGE_ORDER逐阶段控制(修复16阶段子阶段丢失问题)\n183\t    - 🆕 新增16阶段有序推进规则(STAGE_ORDER)和阶段Agent映射表\n184\t    - 🆕 新增版本配置持久化格式(currentStage/stageHistory/skipDecisions)\n185\t    - 🆕 新增错误恢复协议(禁止回退后跳过编排层)\n186\t    - 🔧 Stage 4在版本模式下标记为不可跳过(git-commit+push必须执行)\n187\t    - 🔧 继续版本开发:从currentStage读取恢复起点,按STAGE_ORDER逐阶段恢复\n188\t    - 🆕 前置步骤补全:P1分类三步保障(传入项目上下文+4步决策树+用户确认)、P2模板适配、P3竞品分析(P0强制)、P4项目上下文确认、P6工作区初始化\n189\t    - 🆕 阶段内特殊步骤补全:Stage 3前置缺陷信息收集、Stage 1.5图表同步检查\n190\t    - 🆕 阶段后置动作补全:图表同步检查(Stage 1/2)、BIZ API终态同步(Stage 9)\n191\t    - 🔄 单需求模式迁移:语法1/1A/1B/2/4均改为前置步骤+STAGE_ORDER逐阶段控制,不再启动req-type-classifier做全流程编排\n192\t    - 🔄 清理7处过期引用:req-type-classifier负责BIZ API/全流程编排 → 主会话逐阶段控制\n193\t    - 🔄 req-type-classifier角色重新定义:从"全流程编排"改为"分类+模板适配",Step 9标记为已弃用\n194\t    - 🆕 新增5个Hook执行指引(B1-B7.5指令式伪代码+MCP容错模式),从req-type-classifier.md迁移到主会话执行\n195\t    - 🆕 新增单需求模式完整FOR循环伪代码(9步,与版本模式对齐)\n196\t    - 🆕 context.md格式改为YAML frontmatter+Markdown,新增currentStage/stageHistory/skipDecisions结构化字段\n197\t  v4.6 - 2026-05-19\n198\t    - 🔧 问题1:查看版本状态补充完整输出格式模板和productId缺失处理逻辑(缺失时提示用户输入并保存)\n199\t  v4.6 - 2026-05-18\n200\t    - 🔧 A6创建测试评审从版本初始化阶段移至Stage6-Hook B5.5(测试用例关联系统需求完成后才执行)\n201\t    - 🔄 回滚单需求模式快速模式屏蔽,所有模式统一提供执行模式选择\n202\t    - 🔧 问题1:A6从预留改为正式执行,MCP方法从占位改为savaTestCaseReview,关联成功后自动创建测试评审\n203\t    - 🔧 问题2:步骤D Prompt新增【版本测试集ID】和【发布计划ID】,供subagent Stage1-Hook和Stage6-Hook使用\n204\t    - 🔧 问题3:A5创建测试集后testSetId写入versions.json,Stage6-Hook可获取测试集ID关联测试用例\n205\t    - 🔄 启动开发情形3关联成功后增加A6执行步骤\n206\t  v4.5 - 2026-05-15\n207\t    - 🔗 BIZ API状态同步执行主体从主对话改为req-type-classifier subagent\n208\t    - 🆕 步骤D/继续开发Prompt追加STAGE_SYNC_MAP,传入subagent自行同步阶段状态\n209\t    - 🆕 删除"不传递给req-type-classifier",BIZ_API_INFO和STAGE_SYNC_MAP必须传入subagent\n210\t    - 🆕 补全映射表4个缺失环节:1.2需求知识同步/1.6组件依赖分析/2.2设计知识同步/9循环决策\n211\t    - 🔧 可跳过环节映射表同步更新(1.1/1.2/2.1/4共4处修正)\n212\t  v4.3 - 2026-05-05\n213\t    - 🔧 问题1:步骤2A第3-4轮改为调用list-user-subsystem-role获取子系统列表供用户选择\n214\t    - 🔧 问题2:步骤2A拆分"发布计划名称"和"子系统版本号"输入,新增版本号格式校验\n215\t    - 🛡️ 问题3:A2a前新增参数来源约束声明,禁止多余MCP调用\n216\t    - 🔧 问题4:关联需求到版本计划拆分为两步(update-story设releasePlanId + associate-subsystem-version用正确版本号)\n217\t    - 🆕 问题5:启动开发增加执行模式选择(快速模式/分步模式)\n218\t    - 🔄 问题6:Stage2-Hook修正为同步完整设计文档内容(含安全设计),避免覆盖Stage1需求内容\n219\t  v4.2 - 2026-04-27\n220\t    - 🔧 版本模式subagent_type从general-purpose改为req-type-classifier(修复16阶段流程和DPMS Hook丢失)\n221\t    - 🆕 版本模式prompt模板增加执行模式、工作目录、输出目录字段\n222\t    - 🆕 "继续开发"prompt增加恢复起点阶段和已有产物路径字段\n223\t    - 🔧 "继续开发"阶段判定规则修正:阶段1完成后下一步为阶段1.1需求检视(非设计阶段)\n224\t  v4.2 - 2026-04-26\n225\t    - 🔄 "关联需求到版本计划"从主菜单移除,内嵌到"启动开发"前置步骤中\n226\t    - 🔄 状态机简化:assigned不再影响菜单路由,仅started决定菜单分支(NOT_STARTED/STARTED)\n227\t    - 🆕 需求管理子菜单新增"启动开发"选项(仅 started==false 时显示)\n228\t    - 🆕 添加需求后的"下一步引导"新增"启动开发"选项(仅 started==false 时显示)\n229\t    - 🛡️ 启动开发前置步骤支持三种情形:versionPlanId为空/需求缺StoryId/可执行关联\n230\t    - ⚠️ 所有关联操作均支持跳过,跳过时自动写入PendingItem并标记assigned=true\n231\t    - 🔄 新增AskUserQuestion降级策略:非交互环境自动回退为编号文本选项输出\n232\t  v4.2 - 2026-04-25\n233\t    - 🆕 "完成版本"流程新增A6系列操作(流水线封板→测试报告汇总→新增测试报告→发布测试报告)\n234\t    - 🔄 A6整体前置跳过机制,与其他Hook交互保持一致\n235\t    - 🛡️ A6子步骤失败不阻塞归档流程,统一接入safe_call_mcp容错框架\n236\t  v4.2 - 2026-04-24\n237\t    - 🔄 **版本初始化流程重构**:A2拆分为A2a(产品线)+A2b(子系统),新增A5(测试集)+A6(测试评审预留)\n238\t    - 📤 所有MCP调用补全真实方法名(mcp__sdp__add-release-plan/add-business-version/add-subsystem-version等)\n239\t    - 📤 A3 MCP修正:mcp__dpms__add_story → mcp__sdp__add-system-story\n240\t    - 📤 PendingItem模板补全真实mcpMethod名称(含A5测试集、A6测试评审)\n241\t    - 🔄 步骤2A参数收集从4轮扩展为5轮(新增提测日期/测试负责人/运维人/子系统/灰度发布)\n242\t    - 🕒 新增”创建测试评审(A6)”章节(预留,MCP服务尚未ready)\n243\t    - 🔄 v4.6:A6从预留改为正式执行,MCP方法从占位改为mcp__tctp-dpms-set__savaTestCaseReview\n244\t    - 🔄 **入口收数**:删除所有 version 子命令,统一由 /dev-flow version 引导式入口触发\n245\t    - 🔄 版本管理业务逻辑 100% 收数到 dev-flow.md,WeChat 和 CLI 执行完全相同的代码路径\n246\t    - 🛡️ 启动开发步骤A-F新增错误处理(Task创建失败不影响其他需求)\n247\t  v4.1 - 2026-04-22\n248\t    - 🗑️ 删除 version start --story 参数(语义歧义,单需求启动请用 /dev-flow)\n249\t    - 📝 完善 version 入口引导式全流程交互(3种状态感知 + 需求管理子菜单)\n250\t  v4.0 - 2026-04-18\n251\t    - 🔄 **双轨管理体系**:明确版本轨(dev/versions/)和单需求轨(dev/active/)的隔离规则\n252\t    - 🔄 统一版本号传参格式为 `--version xxx`(语法0.1/0.3/0.4/0.5)\n253\t    - 🆕 新增语法0.7:`version start --version <版本>` 启动版本全流程(含幂等性)\n254\t    - 🆕 新增语法0.8:`version add-story --version <版本> --story-desc "<描述>"` 添加单个需求\n255\t    - 🆕 新增语法0.9:`version add-stories --version <版本> --stories-desc "<列表>"` 批量添加需求\n256\t    - 🆕 新增语法0.10:`version list-stories --version <版本>` 查看版本需求列表\n257\t    - 🆕 新增语法0.11:`version remove-story --version <版本> --story-desc "<描述>"` 删除需求(关联保护)\n258\t    - 🔄 语法0.4 assign 新增幂等性(跳过已关联需求)\n259\t    - 🔄 语法0.2 list 输出追加命令提示(分区展示版本轨+单需求轨)\n260\t    - 🗑️ 删除旧语法5.1(start命令收敛到 version 子命令下)\n261\t    - 🗑️ 删除 version start --story 参数(语义歧义,单需求启动请用 /dev-flow)\n262\t    - 📝 resume/status/completed 扫描逻辑显式限定为单需求轨\n263\t  v4.0 - 2026-04-17\n264\t    - 🛡️ 入口MCP调用(--story/--business-story)新增网络容错\n265\t    - 📝 新增语法0.6:version pending-sync 待补录管理(list/retry/clean)\n266\t    - 📝 待补录记录按项目版本粒度组织,收敛到version子命令下\n267\t  v4.0 - 2026-04-15\n268\t    - 🆕 **新增版本粒度管理**:支持外部项目版本的多需求并行管理\n269\t    - 🆕 新增语法0:`/dev-flow version` 版本管理入口(引导式全流程)\n270\t    - 🆕 新增语法0.1-0.5:版本创建、查看、关联、完成等子命令\n271\t    - 🆕 新增语法5.1:`/dev-flow start --version` 版本模式启动需求\n272\t    - ⚠️ 重要概念澄清:版本指外部项目版本,非 dev-sync-agent 工具版本\n273\t    - 📊 DPMS/SCM 系统集成:满足合规性要求\n274\t  v3.9 - 2026-04-10\n275\t    - 🆕 新增语法8:`/dev-flow completed` 查看已完成任务\n276\t    - 🔧 兼容任务归档机制:同时扫描 dev/active/ 和 dev/completed/\n277\t    - 📊 支持查看已完成任务列表,可按完成时间排序\n278\t    - 🔧 优化版本管理:同步 v3.10 版本启动\n279\t  v3.8 - 2026-03-19\n280\t    - 🔄 **重大变更**:移除语法8(需求变更检测与回退)\n281\t    - 🔄 需求一致性检测移入各环节recheck中处理\n282\t    - 📝 设计recheck新增需求一致性检测,不一致时询问用户是否回退\n283\t    - 📝 测试用例生成新增需求一致性检测,不一致时询问用户是否回退\n284\t    - 🆕 新增环节跳过机制:在各环节开始时主动询问用户是否执行\n285\t    - 🆕 可跳过环节:第1.1/1.2/1.6/2.1/2.2/3.1/4/6.1阶段\n286\t    - 🔧 简化流程:用户主导决策,不自动判断跳过条件\n287\t  v3.6 - 2026-03-04\n288\t    - 🆕 新增第1.1阶段:需求文档质量检视(集成req-recheck-orchestrator)\n289\t    - 🆕 新增第1.2阶段:需求知识同步(集成module-requirement-manager)\n290\t    - 🆕 新增第2.1阶段:设计文档质量检视(集成des-recheck-orchestrator)\n291\t    - 🆕 新增第2.2阶段:设计知识同步(集成module-design-manager)\n292\t    - 🆕 新增第3.1阶段:代码知识同步(集成module-code-manager)\n293\t    - 🆕 新增第6.1阶段:回归测试知识同步(集成module-testing-manager)\n294\t    - 🆕 新增第1.6阶段:组件依赖分析(可选)(2026-02-28)\n295\t    - 🔄 移除第1.5阶段:图表同步检查(从自动流程中移除)(2026-03-02)\n296\t    - 🆕 新增 git-push 命令,专门负责推送代码到远程仓库(2026-02-02)\n297\t    - 📊 完整流程从10阶段扩展到16阶段(含质量检视+知识同步)\n298\t    - 🎯 实现需求/设计/代码/回归测试的全流程知识增量管理\n299\t    - 🔧 提升文档质量保障能力,自动检视并提示改进建议\n300\t  v3.5 - 2026-02-02\n301\t    - 🆕 DevOps自动循环支持:新增循环决策机制\n302\t    - 🆕 新增第4阶段:自动部署(auto-deploy)\n303\t    - 🆕 新增第5阶段:部署确认(用户手动确认)\n304\t    - 🆕 支持根据测试报告决策继续循环或结束流程\n305\t    - 🆕 循环时返回第1阶段调用req-fix-bug-analyzer生成bug fix子需求\n306\t    - 🆕 子需求模式:测试阶段基于父需求测试用例修改/新增\n307\t    - 🆕 支持父子需求关联:cycle-state.json记录parentRequirementId\n308\t    - 🆕 集成git-commit触发CI/CD\n309\t    - 🆕 完整DevOps循环:需求→设计→开发→部署→确认→测试→报告→决策→(循环时)bug修复需求\n310\t  v3.4 - 2026-01-29\n311\t    - 新增阶段5:测试报告生成(test-report)\n312\t    - 完整流程从6个阶段扩展到7个阶段,再到10个阶段(支持DevOps自动循环)\n313\t    - 集成test-report Skill到工作流\n314\t  v3.3 - 2026-01-27\n315\t    - 新增MCP集成:支持从DPMS系统获取需求\n316\t    - 新增语法5:从系统需求启动(--story参数)\n317\t    - 新增语法6:从业务需求启动(--business-story参数)\n318\t    - 新增Hook机制:需求文档确认后自动同步到DPMS\n319\t    - 业务需求流程:update_business_story → add_story\n320\t    - 系统需求流程:update_story\n321\t    - 手动输入流程:add_story\n322\t  v3.2 - 2026-01-16\n323\t    - 初始版本\n324\t    - 支持启动新的开发任务\n325\t    - 支持恢复未完成的任务\n326\t    - 支持查看任务状态和列表\n327\t    - 全流程编排(需求→设计→开发→测试)\n328\t    - 集成Auto-Git功能\n329\t---\n330\t\n331\t## ⚠️ Business API 调用规范\n332\t\n333\t**优先使用MCP工具**:所有写入待补录操作**必须使用 `mcp__biz-sync__save_pending_item`**,所有状态同步操作**必须使用 `mcp__biz-sync__biz_sync_stage/session`**。禁止使用 HTTP 直接调用 biz API 写入待补录或同步状态。\n334\t\n335\t**MCP工具映射**:\n336\t| 操作 | MCP工具 | 禁止使用 |\n337\t|------|---------|---------|\n338\t| 写入待补录 | `mcp__biz-sync__save_pending_item` | ❌ `POST /api/pending` |\n339\t| 标记已同步 | `mcp__biz-sync__mark_pending_synced` | ❌ `POST /api/pending/{id}/complete` |\n340\t| 读取待补录 | `mcp__biz-sync__load_pending_items` | ❌ `GET /api/pending` |\n341\t| 同步阶段状态 | `mcp__biz-sync__biz_sync_stage` | ❌ `PATCH /api/task/{id}/status` |\n342\t| 同步交互记录 | `mcp__biz-sync__biz_sync_session` | ❌ `POST /api/session` |\n343\t| 创建Task | 无MCP工具 | ✅ `POST /api/task`(urllib,无替代) |\n344\t| 创建Session | 无MCP工具 | ✅ `POST /api/session`(urllib,无替代) |\n345\t| 创建/更新Version | 无MCP工具 | ✅ `PATCH /api/version/{id}/status`(urllib,无替代) |\n346\t\n347\t⚠️ **urllib仅用于无MCP工具替代的操作**(创建Task/Session/Version)。所有待补录和状态同步操作必须走MCP工具。\n348\t\n349\t**模板变量 `{projectName}`**:\n350\t- `{projectName}` = 当前项目工作目录的 basename\n351\t- 获取方式:执行 `basename $(pwd)` 或从 `CLAUDE.md` / `pyproject.toml` / `package.json` 中读取项目名\n352\t- ⚠️ 这是动态值,禁止硬编码为任何固定字符串。部署到不同项目时自动适配。\n353\t\n354\t**模板变量 `{project_path}`**(v2.4 GEP 自进化核心关联点):\n355\t- `{project_path}` = 当前项目工作目录的绝对路径(`pwd` 结果)\n356\t- 获取方式:执行 `pwd` 获取绝对路径\n357\t- 用途:stage-hooks 阶段Prompt参数块【项目路径】注入;skill 调 gep_recall/record_outcome 的 project_path 取此值(project_name 取 basename)\n358\t- ⚠️ 这是动态值,禁止硬编码。机器人模式下由"切换项目 "指令切换 cwd 后自动适配。\n359\t\n360\t**关键规则**:\n361\t- ❌ 禁止用 `curl -d` 发送含中文的 JSON(Windows 终端会损坏 UTF-8)\n362\t- ✅ 用 `python3 -c` + `json.dumps().encode(\'utf-8\')` 确保编码正确\n363\t- ✅ 创建Task/Session/Version时走 Python urllib(无MCP工具替代),写入待补录/状态同步时走MCP工具\n364\t- ✅ `{projectId}` 已统一改为 `{projectName}`(项目目录名,非 DPMS 产品 ID)\n365\t\n366\t---\n367\t\n368\t# 开发工作流命令\n369\t\n370\t你的任务是启动完整的开发工作流,帮助用户从需求分析到测试报告生成的全流程开发。\n371\t\n372\t## ⛔ 命令身份声明(最高优先级)\n373\t\n374\t本命令是 `/dev-flow`,负责开发工作流编排。\n375\t\n376\t**当收到 `/dev-flow version` 时**:\n377\t1. 你**必须**执行下方"语法0"的完整步骤0→步骤1流程\n378\t2. 你**必须**使用 `AskUserQuestion` 工具展示交互菜单\n379\t3. **禁止**只输出状态文本就结束\n380\t4. **禁止**读取或执行任何其他命令文件(如 dev-sync-agent-version.md,该文件已废弃删除)\n381\t\n382\t## ⚠️ AskUserQuestion 降级策略\n383\t\n384\t当 `AskUserQuestion` 工具被拒绝或不可用时(常见于通过 API/脚本调用的非交互环境,如企业微信 bot),你必须**立即降级**为编号文本选项输出:\n385\t\n386\t1. 将选项以编号列表形式输出(格式:`序号. 标签 — 说明`)\n387\t2. 明确提示用户"请回复序号或选项名称"\n388\t3. 等待用户下一条文本消息作为选择,继续当前流程\n389\t\n390\t**示例输出**:\n391\t```\n392\t请选择操作:\n393\t1. 创建版本计划 — 创建第一个外部项目版本\n394\t2. 查看帮助 — 了解版本管理流程和命令用法\n395\t\n396\t请回复序号或选项名称。\n397\t```\n398\t\n399\t**重要**:不要因为 AskUserQuestion 被拒绝而停止或重复尝试,必须立即降级并继续交互。\n400\t\n401\t## ⚠️ 重要概念\n402\t\n403\t**版本管理**:此命令支持的是**外部项目版本**(如大数据平台 v3.10),而非 dev-sync-agent 工具本身的版本。\n404\t\n405\t## 双轨管理体系\n406\t\n407\t版本模式和单需求模式是两套**独立的管理体系**,工作目录、生命周期、可视化管理均互相隔离。\n408\t\n409\t### 版本轨(version-track)\n410\t\n411\t| 维度 | 说明 |\n412\t|------|------|\n413\t| 入口命令 | `/dev-flow version`(引导式全流程,根据版本状态自动展示操作菜单) |\n414\t| 工作目录 | `dev/versions/{版本}/active/{task}/` 和 `dev/versions/{版本}/completed/{task}/` |\n415\t| 管理工具 | task-viewer 可视化管理(通过 Business API 写入) |\n416\t| 状态文件 | `dev/versions/{版本}/active/{task}/context.md` |\n417\t| 需求创建 | 引导式菜单中"管理需求"操作 |\n418\t| DPMS关联 | 自动写入 task-viewer 数据源 |\n419\t| task-viewer可见 | 是 |\n420\t\n421\t### 单需求轨(standalone-track)\n422\t\n423\t| 维度 | 说明 |\n424\t|------|------|\n425\t| 入口命令 | `/dev-flow <需求描述>` 或 `/dev-flow --story ` 或 `/dev-flow --business-story ` |\n426\t| 工作目录 | `dev/active/{task}/` 和 `dev/completed/{task}/` |\n427\t| 管理工具 | CLI 命令行管理(无可视化) |\n428\t| 状态文件 | `dev/active/{task}/context.md` |\n429\t| 需求创建 | `/dev-flow <需求描述>` 自动触发 |\n430\t| DPMS关联 | 需求文档确认后 Hook 调用 add_story |\n431\t| task-viewer可见 | 否 |\n432\t\n433\t### 隔离规则\n434\t\n435\t1. 两轨的工作目录完全独立,互不干扰\n436\t2. `/dev-flow resume` 仅恢复**单需求轨**的任务(扫描 `dev/active/`)\n437\t3. `/dev-flow version` 引导菜单中的"启动开发"选项仅启动**版本轨**的任务(扫描 `dev/versions/{版本}/`)\n438\t4. `/dev-flow status` 仅展示**单需求轨**的任务状态\n439\t5. `/dev-flow completed` 仅展示**单需求轨**的已完成任务\n440\t6. task-viewer 仅展示**版本轨**的任务,不展示 `dev/active/` 下的单需求任务\n441\t7. 两轨的状态文件格式一致(context.md),但路径不同\n442\t\n443\t## 📋 命令用法\n444\t\n445\t### 语法0:版本管理入口(引导式全流程)🆕\n446\t```\n447\t/dev-flow version\n448\t```\n449\t\n450\t**进入版本管理引导式全流程,通过交互式对话完成版本管理的完整流程**。\n451\t\n452\t**适用场景**:\n453\t- 第一次使用版本管理功能\n454\t- 不确定下一步该做什么\n455\t- 需要完整的版本管理流程引导\n456\t\n457\t**触发条件**:命令仅包含 `version`,不包含任何子命令或参数。\n458\t\n459\t**执行流程**:\n460\t\n461\t#### 步骤0:前置检查 — 检测已有版本状态\n462\t\n463\t读取 `dev/versions/versions.json`,判断当前版本管理状态:\n464\t\n465\t```python\n466\tversions = load_versions_json()\n467\t\n468\tIF versions IS EMPTY OR versions["list"] IS EMPTY THEN\n469\t    version_state = "NO_VERSION"\n470\tELSE\n471\t    active_versions = [v for v in versions["list"] if v["status"] != "completed"]\n472\t    IF active_versions IS EMPTY THEN\n473\t        version_state = "ALL_COMPLETED"\n474\t    ELSE\n475\t        # 找到最早创建的活跃版本\n476\t        version_state = "HAS_ACTIVE"\n477\t        latest_active = active_versions[0]\n478\t        # 仅按 started 判断子状态(assigned 由"启动开发"内部处理,不影响菜单)\n479\t        IF latest_active.get("started", False) == True THEN\n480\t            version_sub_state = "STARTED"\n481\t        ELSE\n482\t            version_sub_state = "NOT_STARTED"\n483\t        END IF\n484\t    END IF\n485\tEND IF\n486\t```\n487\t\n488\t#### 步骤1:根据状态展示不同的引导菜单\n489\t\n490\t##### 状态A:`NO_VERSION` — 从未创建过版本\n491\t\n492\t读取 `.claude/config/dev-flow-menus.json` 中 `menus.NO_VERSION.items` 获取菜单项。\n493\t\n494\t使用编号文本输出(按JSON中定义的 label 和 description 输出,格式:`编号. **{label}** — {description}`)。\n495\t\n496\t- 选择"创建版本计划" → 跳转到**创建版本引导**(步骤2A)\n497\t- 选择"查看帮助" → 输出单需求模式命令速查,然后重新展示菜单\n498\t\n499\t##### 状态B:`HAS_ACTIVE` — 存在进行中的版本\n500\t\n501\t根据版本子状态展示不同菜单:\n502\t\n503\t###### 状态B-1:`NOT_STARTED` — 版本未启动(started=false)\n504\t\n505\t> `assigned` 字段不影响菜单路由。"关联需求到版本计划"在用户选择"启动开发"后由内部流程处理。\n506\t\n507\t读取 `.claude/config/dev-flow-menus.json` 中 `menus.NOT_STARTED.items` 获取菜单项。\n508\t\n509\t⚠️ 该菜单 5 项,超过 AskUserQuestion 4 选项上限。使用编号文本输出(格式:`编号. **{label}** — {description}`),需动态填充版本信息。\n510\t所有 inline 类型选项执行完成后必须立即重新展示主菜单。\n511\t\n512\t- 选择"查看版本状态" → **内联执行版本状态查看**(读取版本配置,输出状态报告)\n513\t- 选择"管理需求" → 跳转到**需求管理子菜单**(步骤2B,内部含"启动开发"选项)\n514\t- 选择"创建新版本" → 跳转到**创建版本引导**(步骤2A)\n515\t- 选择"查看所有版本" → **内联执行版本列表输出**(读取所有版本配置,输出列表)\n516\t- 选择"管理待补录" → **内联执行待补录管理**(见下方"待补录管理"章节)\n517\t\n518\t###### 状态B-2:`STARTED` — 已启动(started=true)\n519\t\n520\t读取 `.claude/config/dev-flow-menus.json` 中 `menus.STARTED.items` 获取菜单项。\n521\t\n522\t⚠️ 该菜单 6 项,超过 AskUserQuestion 4 选项上限。使用编号文本输出(格式:`编号. **{label}** — {description}`),需动态填充版本信息。\n523\t⛔ 主菜单**仅以下 6 项**,禁止把后续"生成变更单""回滚到指定阶段"等章节作为菜单项展示(这两项已从主菜单隐藏,仅保留能力供 skill/自动回滚内部调用)。\n524\t所有 inline 类型选项执行完成后必须立即重新展示主菜单。\n525\t\n526\t- 选择"查看版本状态" → **内联执行版本状态查看**\n527\t- 选择"查看需求列表" → **内联执行需求列表输出**\n528\t- 选择"继续开发" → **内联执行继续开发**(见下方"继续版本开发"章节)\n529\t- 选择"完成版本" → **内联执行完成版本**(见下方"完成版本"章节)\n530\t- 选择"查看所有版本" → **内联执行版本列表输出**\n531\t- 选择"管理待补录" → **内联执行待补录管理**(见下方"待补录管理"章节)\n532\t\n533\t##### 状态C:`ALL_COMPLETED` — 所有版本已完成\n534\t\n535\t读取 `.claude/config/dev-flow-menus.json` 中 `menus.ALL_COMPLETED.items` 获取菜单项。\n536\t\n537\t使用编号文本输出(按JSON中定义的 label 和 description 输出,格式:`编号. **{label}** — {description}`)。\n538\t\n539\t- 选择"创建新版本" → 跳转到**创建版本引导**(步骤2A)\n540\t- 选择"查看历史版本" → 执行 `version list`\n541\t- 选择"管理待补录" → 执行 `version pending-sync list`\n542\t\n543\t#### 步骤2A:创建版本引导\n544\t\n545\t交互式引导用户完成版本创建,分步收集参数:\n546\t\n547\t**第1轮 — 收集发布计划名称**:\n548\t```\n549\t请输入发布计划名称(如"大数据平台V3.10"):\n550\t```\n551\t\n552\t**第3.5轮 — 是否涉及多个子系统**(⭐阶段1 S5):\n553\t```\n554\tmulti_sub_ans = AskUserQuestion("本次版本是否涉及多个子系统?",\n555\t  ["单子系统(现有流程)— 仅1个子系统",\n556\t   "多子系统 — 涉及2+子系统,每子系统独立版本号,需设定入口子系统(其版本号作为版本计划版本号)"])\n557\tis_multi_subsystem = (用户选择"多子系统")\n558\t```\n559\t\n560\t**第3.8轮 — 是否多git**(⭐阶段3 S6:多项目多仓库):\n561\t```\n562\tmulti_git_ans = AskUserQuestion("本次版本是否涉及多个git仓库(多项目)?",\n563\t  ["单git(现有流程)— 所有子系统在同一git仓库",\n564\t   "多git — 不同子系统在不同git仓库,需收集每仓库SSH地址+本地路径"])\n565\tis_multi_git = (用户选择"多git")\n566\t\n567\tIF is_multi_git THEN\n568\t    # G2:为每子系统收集git仓库信息\n569\t    FOR each sub IN selected_subsystems:\n570\t        sub.gitUrl = AskUserQuestion(f"子系统[{sub.subsystemName}]的git仓库SSH地址:")\n571\t        sub.localPath = AskUserQuestion(f"子系统[{sub.subsystemName}]的本地仓库路径:")\n572\t    END FOR\n573\t    # 去重生成 repositories[](按gitUrl去重)\n574\t    repositories = dedup_repositories(selected_subsystems)\n575\tEND IF\n576\t````\n577\t\n578\t**第1.5轮 — 收集子系统版本号**(⭐阶段1 S5:多子系统时为每子系统独立收集):\n579\t```\n580\t# 单子系统(is_multi_subsystem=false):收集1个版本号(现有流程)\n581\t# 多子系统(is_multi_subsystem=true):为 selected_subsystems 中每子系统独立收集版本号\n582\tFOR each sub IN selected_subsystems:\n583\t    请输入子系统 [{sub.subsystemName}] 版本号,格式要求:X.Y.Z(如 12.23.34):\n584\t    ⚠️ 该版本号将用于SCM子系统版本创建,必须为纯数字点分格式\n585\t```\n586\t\n587\t**版本号校验(强制执行,不符合则循环要求重新输入)**:\n588\t```\n589\tWHILE True:\n590\t    version_input = 用户输入\n591\t    IF version_input 匹配正则 ^\\d+\\.\\d+\\.\\d+$ THEN\n592\t        subsystemVersionId = version_input\n593\t        BREAK\n594\t    ELSE\n595\t        OUTPUT: "❌ 版本号格式不符合规范!要求格式为 X.Y.Z(纯数字+点号),例如 12.23.34"\n596\t        OUTPUT: "您输入的是:{version_input},请重新输入:"\n597\t    END IF\n598\tEND WHILE\n599\t```\n600\t\n601\t**第2轮 — 收集日期信息**:\n602\t```\n603\t请输入计划开始日期(YYYY-MM-DD):\n604\t请输入计划结束日期(YYYY-MM-DD):\n605\t请输入提测日期(YYYY-MM-DD):\n606\t```\n607\t\n608\t**第3轮 — 收集产品信息 + 获取子系统列表**:\n609\t```\n610\t请输入产品ID(DPMS中的产品ID):\n611\t请输入测试负责人英文名:\n612\t请输入运维人英文名:\n613\t```\n614\t\n615\t收集完上述信息后,**立即调用** MCP获取用户关联的子系统列表:\n616\t```\n617\tresult = safe_call_mcp("mcp__sdp__list-user-subsystem-role", {"userId": 当前用户英文名})\n618\tIF result["success"] THEN\n619\t    subsystem_list = result["result"]["list"]\n620\t    缓存 subsystem_list 供第4轮使用\n621\tELSE\n622\t    OUTPUT: "⚠️ 无法获取子系统列表,将在下一步手动输入"\n623\t    subsystem_list = null\n624\tEND IF\n625\t```\n626\t\n627\t**第4轮 — 选择子系统信息**(⭐阶段1 S5:单选→多选+入口子系统):\n628\t\n629\tIF subsystem_list 非空 THEN\n630\t```\n631\t检测到您关联的子系统:\n632\t| 序号 | 子系统名称 | 子系统ID | 角色 |\n633\t|:----:|-----------|---------|------|\n634\t| 1 | {subsystem} | {subsysId} | {userGroup} |\n635\t| 2 | {subsystem} | {subsysId} | {userGroup} |\n636\t\n637\tIF is_multi_subsystem == false THEN\n638\t    请选择子系统(输入序号):\n639\t    selected_subsystems = [单选结果]\n640\t    entry_subsystem = selected_subsystems[0]\n641\tELSE  # 多子系统\n642\t    # 多选(≤4个单批,>4个分批,参考 stage-10:10.2 分批模式)\n643\t    请选择本次版本涉及的多个子系统(可多选):\n644\t    selected_subsystems = multi_select_subsystems(subsystem_list)\n645\t    # 设定入口子系统(其版本号=版本计划版本号,D11)\n646\t    请设定入口子系统(其版本号将作为版本计划版本号):\n647\t    entry_subsystem = 用户从 selected_subsystems 中选定\n648\tEND IF\n649\t是否灰度发布?(是/否)\n650\t\n651\t# 🆕 灰度发布日期收集(决策点1:第4轮内条件询问,选"是"后追加)\n652\tIF 用户选择"是"(灰度发布)THEN\n653\t    OUTPUT: f"请输入预计灰度发布日期(YYYY-MM-DD,须在 {计划开始日期} ~ {计划结束日期} 之间):"\n654\t    OUTPUT: "💡 灰度通常在全量投产前几天先放小流量验证,建议采用全量投产前3天"\n655\t    WHILE True:\n656\t        gray_date_input = 用户输入\n657\t        IF gray_date_input 匹配正则 ^\\d{4}-\\d{2}-\\d{2}$ AND\n658\t           gray_date_input 在 [计划开始日期, 计划结束日期] 区间内 THEN\n659\t            grayReleaseDate = gray_date_input\n660\t            isNeedGrayRelease = 1\n661\t            BREAK\n662\t        ELSE\n663\t            OUTPUT: "❌ 灰度日期格式不符或不在版本周期内,要求 YYYY-MM-DD 且在版本周期内"\n664\t            OUTPUT: f"您输入的是:{gray_date_input},请重新输入:"\n665\t        END IF\n666\t    END WHILE\n667\tELSE  # 用户选择"否"\n668\t    isNeedGrayRelease = 0\n669\t    grayReleaseDate = null\n670\tEND IF\n671\t\n672\t→ 记录选中的 subsystemId、subsystemName、isNeedGrayRelease、grayReleaseDate\n673\t```\n674\t\n675\tELSE(降级为手动输入):\n676\t```\n677\t请输入子系统英文名:\n678\t请输入子系统ID:\n679\t是否灰度发布?(是/否)\n680\t\n681\t# 🆕 灰度发布日期收集(同 IF 分支逻辑)\n682\tIF 用户选择"是"(灰度发布)THEN\n683\t    OUTPUT: f"请输入预计灰度发布日期(YYYY-MM-DD,须在 {计划开始日期} ~ {计划结束日期} 之间):"\n684\t    WHILE True:\n685\t        gray_date_input = 用户输入\n686\t        IF gray_date_input 匹配正则 ^\\d{4}-\\d{2}-\\d{2}$ AND\n687\t           gray_date_input 在 [计划开始日期, 计划结束日期] 区间内 THEN\n688\t            grayReleaseDate = gray_date_input\n689\t            isNeedGrayRelease = 1\n690\t            BREAK\n691\t        ELSE\n692\t            OUTPUT: "❌ 灰度日期格式不符或不在版本周期内,要求 YYYY-MM-DD 且在版本周期内"\n693\t            OUTPUT: f"您输入的是:{gray_date_input},请重新输入:"\n694\t        END IF\n695\t    END WHILE\n696\tELSE\n697\t    isNeedGrayRelease = 0\n698\t    grayReleaseDate = null\n699\tEND IF\n700\t```\n701\t\n702\t**第5轮 — 确认并执行**:\n703\t\n704\t使用编号文本输出确认信息(共5项,超过 AskUserQuestion 4选项上限):\n705\t\n706\t灰度发布:{isNeedGrayRelease==1 ? "是,预计 " + grayReleaseDate : "否"}  🆕\n707\t\n708\t| 选项 | 说明 |\n709\t|------|------|\n710\t| **全部执行(推荐)→ A1版本计划 + A2a产品线 + A2b子系统 + A5 SIT测试集 + A5.1回归测试集** | 执行A1+A2a+A2b+A5+A5.1+本地配置+Business API |\n711\t| **仅DPMS创建版本计划,跳过SCM** | 执行A1+本地配置+Business API,A2a+A2b+A5+A5.1+流水线进待补录 |\n712\t| **仅SCM创建版本,跳过DPMS创建版本计划** | 执行A2a+A2b+本地配置+Business API,A1+A5+A5.1+流水线进待补录 |\n713\t| **全部跳过,仅创建本地配置** | 仅本地配置+Business API,A1+A2a+A2b+A5+A5.1+流水线进待补录 |\n714\t| **取消** | 返回主菜单 |\n715\t\n716\t确认后按照**创建版本执行流程**(见下方"创建版本"章节),并根据用户选择传递同步策略。\n717\t\n718\t创建成功后,自动进入**需求管理子菜单**(步骤2B)。\n719\t\n720\t#### 步骤2B:需求管理子菜单\n721\t\n722\t> **AskUserQuestion 工具限制最多 4 个选项,所有菜单不得超过 4 项。**\n723\t\n724\t**前置检查**:读取版本配置,检查 `assigned` 标志:\n725\t- 若 `assigned == true`:\n726\t  - 输出 "⚠️ 版本 {versionName} 已关联版本计划(assigned=true),不允许新增或删除需求!"\n727\t  - 读取 `.claude/config/dev-flow-menus.json` 中 `sub_menus.管理需求.assigned_true.items` 获取菜单项\n728\t  - 使用 AskUserQuestion 展示\n729\t  - 结束,不展示完整菜单\n730\t- 若 `assigned == false`:展示完整需求管理菜单(见下方)\n731\t\n732\t在用户选择"管理需求"且 `assigned == false` 时展示(需动态填充版本名和需求数量):\n733\t\n734\t读取 `.claude/config/dev-flow-menus.json` 中 `sub_menus.管理需求.assigned_false.items` 获取菜单项。\n735\t\n736\t使用 AskUserQuestion 展示(按JSON中定义的 label 和 description 输出,**严格不超过JSON定义的数量**)。\n737\t\n738\t- 选择"添加需求" → 使用 AskUserQuestion 追问「**添加单个需求**」或「**批量添加需求**」→ 执行对应流程\n739\t- 选择"查看需求列表" → **内联执行需求列表输出**,列表后使用 AskUserQuestion 展示操作:「**删除需求**」/「**启动开发**」(started==false时)/「**返回子菜单**」\n740\t- 选择"启动开发" → **内联执行启动开发**(见下方"启动版本需求"章节,仅 `started == false` 时可选)\n741\t- 选择"返回主菜单" → 重新展示对应状态的引导菜单(步骤1)\n742\t\n743\t#### 循环机制\n744\t\n745\t每次子命令执行完成后,自动回到步骤1重新展示引导菜单,直到用户主动选择"退出"或离开对话。\n746\t\n747\t#### 完整交互示例\n748\t\n749\t```\n750\t👤 用户:\n751\t/dev-flow version\n752\t\n753\t🤖 Agent:\n754\t检测到当前有活跃版本:v3.10(大数据平台),请选择操作:\n755\t(AskUserQuestion 展示5个选项:查看版本状态/管理需求/创建新版本/查看所有版本/管理待补录)\n756\t\n757\t👤 用户:选择"管理需求"\n758\t\n759\t🤖 Agent:\n760\t版本 v3.10 下当前有 3 条需求,请选择需求管理操作:\n761\t(AskUserQuestion 展示6个选项:添加单个需求/批量添加需求/查看需求列表/删除需求/启动开发/返回主菜单)\n762\t\n763\t👤 用户:选择"添加单个需求"\n764\t\n765\t🤖 Agent:\n766\t请输入需求描述:\n767\t\n768\t👤 用户:实现用户数据导出Excel功能\n769\t\n770\t🤖 Agent:\n771\t✅ 需求创建成功!版本 v3.10 下当前有 4 条需求。\n772\t是否继续管理需求?\n773\t(AskUserQuestion: 继续添加需求 / 启动开发 / 返回主菜单)\n774\t\n775\t👤 用户:选择"返回主菜单"\n776\t\n777\t🤖 Agent:\n778\t检测到当前有活跃版本:v3.10(大数据平台),请选择操作:\n779\t(AskUserQuestion 展示6个选项,循环继续)\n780\t```\n781\t\n782\t### 创建版本\n783\t\n784\t> ⚠️ **详细执行流程已外置,禁止凭记忆执行!**\n785\t> 执行此操作前,**必须** Read 以下清单文件后按步骤执行:\n786\t> 📄 `.claude/config/dev-flow-checklists/create-version.md`\n787\t> ⛔ 禁止跳过Read直接执行。每个步骤执行完毕后必须逐项验证。\n788\t\n789\t**概要**:执行流程包括A1版本计划→A2a产品线→A2b子系统→A5 SIT测试集→A5.1 回归测试集🆕→本地配置→Git分支→PACE流水线→Business API写入,共9步(A1/A2a/A2b/A5/A5.1可独立跳过,跳过时写入PendingItem)。\n790\t\n791\t> 📋 **回归测试集说明(v4.7新增)**:\n792\t> - **A5.1 创建版本回归测试集**:在A5之后执行,使用 `createTestPlanSet(testStep=2)` 创建空的回归集,testPlanId写入versions.json的regressionTestSetId字段\n793\t> - **A5.2 填充版本回归用例集**:🆕v4.9 已迁移至 Stage 10.3(版本级回归测试阶段),complete-version 步骤2.5 改为前置检查(stage10Completed 判断)\n794\t> - **依赖数据**:各需求Stage 6.5 由 functional-test-generator 回写 moduleId 到 context.md(v4.7)\n795\t> - **详见方案文档**:`docs/回归测试用例集方案.md`\n796\t\n797\t### 查看版本列表\n798\t\n799\t读取 `dev/versions/versions.json`,输出版本列表表格。\n800\t\n801\t### 查看版本状态\n802\t\n803\t读取指定版本配置,输出详细状态和进度。\n804\t\n805\t**执行流程**:\n806\t1. 读取 `dev/versions/versions.json`,获取当前活跃版本配置\n807\t2. 检查 `productId` 字段:\n808\t   - **若 productId 存在且非空**:直接输出\n809\t   - **若 productId 缺失或为空**:输出提示信息,要求用户输入产品ID,写入版本配置后重新输出\n810\t\n811\t**输出格式**(严格遵守,禁止自由发挥):\n812\t```\n813\t📊 版本状态:{versionName}\n814\t\n815\t📌 基本信息:\n816\t| 项目 | 值 |\n817\t|-----|---|\n818\t| 版本名称 | {versionName} |\n819\t| DPMS产品ID | {productId 或 "⚠️ 未设置"} |\n820\t| 入口子系统ID | {entrySubsystemId 或 subsystemId 或 "⚠️ 未设置"} |\n821\t| 入口子系统名称 | {subsystemName 或 "⚠️ 未设置"} |\n822\t| 入口子系统版本号 | {subsystemVersionId 或 "⚠️ 未设置"}(=版本计划版本号) |\n823\t| 发布计划ID | {dpms.versionPlanId 或 "⚠️ 未设置"} |\n824\t| 测试集ID | {testSetId 或 "⚠️ 未设置"} |\n825\t| 回归测试集ID | {regressionTestSetId 或 "⚠️ 未设置"} |\n826\t| 测试报告ID | {testReportId 或 "⚠️ 未设置"} |\n827\t| Git分支 | {branchName 或 "⚠️ 未创建"}(版本级单分支,所有子系统共享) |\n828\t| 流水线ID | {pipelineId 或 "⚠️ 未设置"}(入口子系统) |\n829\t| 流水线版本 | {pipelineVersion 或 "⚠️ 未设置"}(入口子系统) |\n830\t\n831\t📌 子系统清单(⭐阶段1 S5,共 {subsystems.length} 个):\n832\t| # | 子系统名称 | 子系统ID | 版本号 | 流水线ID | 入口 |\n833\t|:--:|-----------|---------|--------|----------|:----:|\n834\t| 1 | {s.subsystemName} | {s.subsystemId} | {s.subsystemVersionId} | {s.pipelineId} | {s.isEntry ? "✅" : ""} |\n835\t\n836\t📌 进度信息:\n837\t| 项目 | 值 |\n838\t|-----|---|\n839\t| 已关联需求 | {assigned == true ? "是" : "否"} |\n840\t| 已启动开发 | {started == true ? "是" : "否"} |\n841\t| 待补录任务 | {pendingItems数量} |\n842\t\n843\t⚠️ 注意:DPMS产品ID为版本流程关键参数,缺失将影响后续A1/A5/A6等MCP调用。\n844\t```\n845\t\n846\t**productId 缺失处理**:\n847\t```\n848\tIF versions.json 中当前版本的 productId 为空或不存在 THEN\n849\t  OUTPUT: "⚠️ 当前版本缺少 DPMS产品ID(productId),以下操作依赖此ID:\n850\t    • A1 创建版本计划\n851\t    • A5 创建SIT测试集\n852\t    • A5.1 创建回归测试集\n853\t    • A5.2 填充回归用例(complete-version阶段)\n854\t    • A6 新增测试报告\n855\t  请输入产品ID(数字):"\n856\t  用户输入 → 写入 versions.json 对应版本的 productId 字段\n857\t  OUTPUT: "✅ 已保存产品ID: {productId}" + 重新输出完整版本状态\n858\tEND IF\n859\t```\n860\t\n861\t### 关联需求到版本计划\n862\t\n863\t> ⚠️ **详细执行流程已外置,禁止凭记忆执行!**\n864\t> 执行此操作前,**必须** Read 以下清单文件后按步骤执行:\n865\t> 📄 `.claude/config/dev-flow-checklists/associate-requirement.md`\n866\t> ⛔ 禁止跳过Read直接执行。每个步骤执行完毕后必须逐项验证。\n867\t\n868\t**概要**:两步操作(A4-1关联发布计划 + A4-2关联子系统版本)。已内嵌到"启动版本需求"前置步骤中,供内部调用参考。\n869\t\n870\t### 创建测试评审(A6)— 已移至Stage6-Hook自动执行\n871\t\n872\t**⚠️ A6不再在版本初始化阶段手动执行。** 创建测试评审必须在测试用例生成并关联系统需求之后才有意义,因此已统一移至 阶段后置动作 Stage6-Hook B5.5 环节自动执行。\n873\t\n874\t**执行时机**:Stage6-Hook(第6阶段测试用例确认后),在 B5(新增测试案例 + 关联测试集 + 关联系统需求)完成后,由 B5.5 自动调用 `mcp__tctp-dpms-set__savaTestCaseReview`。\n875\t\n876\t**前置条件链**:A3(创建需求)→ A4(关联子系统版本)→ 关联需求到版本计划 → 启动开发 → ... → Stage6-Hook B5(测试用例创建+关联)→ Stage6-Hook B5.5(创建测试评审)\n877\t\n878\t### 完成版本\n879\t\n880\t> ⚠️ **详细执行流程已外置,禁止凭记忆执行!**\n881\t> 执行此操作前,**必须** Read 以下清单文件后按步骤执行:\n882\t> 📄 `.claude/config/dev-flow-checklists/complete-version.md`\n883\t> ⛔ 禁止跳过Read直接执行。每个步骤执行完毕后必须逐项验证。\n884\t\n885\t**概要**:12步流程(状态检查→A6系列操作→DPMS版本状态更新→Business API Version状态更新→总结报告→归档→Git提交+推送)。A6系列含关联子系统版本分支、流水线封板、测试报告汇总、新增测试报告、发布测试报告。步骤11将版本文档(docs/)、归档目录(dev/completed/)、版本配置(versions.json)和待补录记录统一提交到git并可选推送。\n886\t\n887\t> 📋 **A5.2 已迁移至 Stage 10.3(v4.9)**:dpms 回归用例同步在 Stage 10 版本级回归测试中执行(所有需求 Stage 9 通过后触发)。complete-version 步骤2.5 改为前置检查(stage10Completed 已执行则跳过,未执行则提示补执行或跳过)。详见 `.claude/config/dev-flow-checklists/stage-10-version-regression.md`。\n888\t\n889\t### 待补录管理\n890\t\n891\t管理因网络问题跳过的DPMS同步任务。\n892\t\n893\t**执行流程**:\n894\t\n895\t#### 查看待补录列表\n896\t\n897\t**执行逻辑**:\n898\t1. 调用 `mcp__biz-sync__load_pending_items(version_id=指定版本, status="pending")` 获取待补录列表\n899\t2. 读取 `dev/pending-sync/pending-sync-log.json`(本地兜底,MCP不可用时使用)\n900\t3. 合并两个来源(以 API 为主,本地文件补充 API 不可用时的遗漏项,按 ID 去重)\n901\t4. 按 `version_id` 分组输出\n902\t\n903\t**输出格式**:\n904\t```markdown\n905\t# 📋 待补录列表\n906\t\n907\t## 版本: v3.10(1条)\n908\t\n909\t| ID | 任务 | 阶段 | MCP方法 | 跳过原因 | 时间 |\n910\t|----|------|------|---------|---------|------|\n911\t| ps-001 | user-export | Stage1 DPMS同步 | update-story | 网络超时 | 2026-04-17 10:30 |\n912\t\n913\t## 版本: none(0条)\n914\t\n915\t| ID | 任务 | 阶段 | MCP方法 | 跳过原因 | 时间 |\n916\t|----|------|------|---------|---------|------|\n917\t\n918\t---\n919\t\n920\t**总计**: 3 条待补录\n921\t**建议**: 网络恢复后通过 `/dev-flow version` 引导菜单中的"管理待补录"选项重试\n922\t```\n923\t\n924\t#### 重试待补录\n925\t\n926\t**执行逻辑**:\n927\t```\n928\tpending_items = load_pending_sync_items(version_id=指定版本)\n929\tsuccess_count = 0\n930\tauto_trigger_count = 0\n931\t\n932\tFOR EACH item IN pending_items:\n933\t    result = call_mcp(item["mcp_method"], item["mcp_params"])\n934\t    IF result["success"] THEN\n935\t        mark_pending_synced(item["id"])\n936\t        mcp__biz-sync__mark_pending_synced(item_id=item["id"])\n937\t        success_count += 1\n938\t\n939\t        # ── 自动触发:A3成功后回填productName + 检查并触发A4 ──\n940\t        IF item.mcp_method == "mcp__sdp__add-system-story" THEN\n941\t            # 回填productName:从A3调用结果获取storyId,调用get-storys查询产品名称\n942\t            a3_story_id = result 中的 storyId(A3调用返回值)\n943\t            IF a3_story_id 非空 THEN\n944\t              story_info = mcp__sdp__get-storys(id=a3_story_id)\n945\t              IF story_info["success"] AND story_info["list"] 非空 THEN\n946\t                  product_name = story_info["list"][0]["productName"]\n947\t                  更新 versions.json 该需求的 dpmsStoryId = a3_story_id, productName = product_name\n948\t              END IF\n949\t            END IF\n950\t            # 查找同一需求的A4待补录项(关联子系统版本)\n951\t            a4_item = find_pending(\n952\t                stage="requirement",\n953\t                mcp_method="mcp__sdp__associate-subsystem-version",\n954\t                related_story=item.mcp_params.storyId\n955\t            )\n956\t            IF a4_item AND version_config.scm.productLineVersionId 非空 THEN\n957\t                a4_result = call_mcp(a4_item["mcp_method"], a4_item["mcp_params"])\n958\t                IF a4_result["success"] THEN\n959\t                    mark_pending_synced(a4_item["id"])\n960\t                    mcp__biz-sync__mark_pending_synced(item_id=a4_item["id"])\n961\t                    auto_trigger_count += 1\n962\t                    OUTPUT: "  → 自动触发:关联子系统版本 → ✅ 成功(→ {productLineVersionId})"\n963\t                END IF\n964\t            END IF\n965\t        END IF\n966\t\n967\t    ELSE\n968\t        # 保持待补录状态(不调用mark_pending_synced,让item保持pending)\n969\t        error_category = classify_mcp_error(error)\n970\t        IF error_category == "NETWORK_UNAVAILABLE" THEN\n971\t            OUTPUT: "❌ {item.id} 仍因网络问题失败,保持待补录状态"\n972\t        ELSE\n973\t            OUTPUT: "❌ {item.id} 失败:{error_message}"\n974\t    END IF\n975\tEND FOR\n976\t\n977\tIF auto_trigger_count > 0 THEN\n978\t    OUTPUT: "✅ {success_count}/{len(pending_items)} 手动补录成功(含 {auto_trigger_count} 项自动触发的关联操作)"\n979\tELSE\n980\t    OUTPUT: f"补录完成:{success_count}/{len(pending_items)} 条成功"\n981\tEND IF\n982\t```\n983\t\n984\t#### 清理已补录记录\n985\t\n986\t**执行逻辑**:\n987\t1. 读取本地 pending-sync-log.json,移除 status == "synced" 的记录\n988\t2. 将指定版本中 `status == "synced"` 的记录从本地列表中移除\n989\t3. 更新 statistics\n990\t4. 如果列表为空,删除整个 `pending-sync-log.json` 文件\n991\t\n992\t---\n993\t\n994\t### 生成变更单(⛔ 已从主菜单隐藏,仅供 version-change-order-generator skill 手动调用,禁止作为主菜单项展示)\n995\t\n996\t> ⛔ **本章节已从主菜单隐藏(commit 636c1008)**。\n997\t> 主菜单(NO_VERSION/NOT_STARTED/STARTED/ALL_COMPLETED)**不含**"生成变更单"入口,禁止将其列入任何主菜单编号选项。\n998\t> 能力保留:仅当通过 skill 手动渠道调用 `version-change-order-generator` 时,按下方流程执行。\n999\t\n1000\t**生成版本发布变更单(调用 version-change-order-generator skill)**。\n1001\t\n1002\t**执行流程**:\n1003\t\n1004\t```python\n1005\t# 1. 读取 versions.json,提取所有有 versionPlanId 且 status==completed 的版本\n1006\tversions = read("dev/versions/versions.json")\n1007\tIF versions 不存在 OR versions.get("list") 为空 THEN\n1008\t  OUTPUT "❌ 无版本可生成变更单"\n1009\t  重新展示主菜单\n1010\tEND IF\n1011\t\n1012\tcandidates = []\n1013\tFOR each v IN versions.get("list", []):\n1014\t  dpms = v.get("dpms", {})\n1015\t  vp_id = dpms.get("versionPlanId") OR dpms.get("releasePlanId")\n1016\t  # ⚠ 仅纳入版本级 status==completed 的版本(skill 步骤1 强制校验版本 status==completed,非 completed 会被 skill 终止)\n1017\t  IF vp_id 非空 AND v.get("status") == "completed" THEN\n1018\t    candidates.append({\n1019\t      "versionName": v.get("versionName"),\n1020\t      "versionPlanId": str(vp_id),\n1021\t      "status": v.get("status", "unknown"),\n1022\t      "completedAt": v.get("completedAt")\n1023\t    })\n1024\t  END IF\n1025\tEND FOR\n1026\t\n1027\tIF candidates 为空 THEN\n1028\t  OUTPUT "❌ 暂无满足条件的版本:需同时具备 versionPlanId 且 版本级 status==completed(skill 步骤1 强制校验)。请先完成版本流程(complete-version 将版本标记为 completed)后再生成变更单"\n1029\t  重新展示主菜单\n1030\tEND IF\n1031\t\n1032\t# 2. 按 completedAt 倒序排序(最近完成的版本在前,优先推荐;completedAt 缺失排末尾),再取首个为推荐\n1033\tcandidates.sort(key=lambda c: c.get("completedAt") or "", reverse=True)\n1034\tdefault_id = candidates[0]["versionPlanId"] IF candidates 非空 ELSE None\n1035\t# 使用 AskUserQuestion 让用户选择(含"返回主菜单"出口)\n1036\t\n1037\t# 构造选项:各候选版本(推荐项标注)+ "返回主菜单"\n1038\t# ⚠ AskUserQuestion 单问题选项上限 4(含自带 Other):候选版本 >3 时仅展示前 3 个,其余版本用户可选 Other 自定义输入 versionPlanId\n1039\toptions = []\n1040\tFOR c IN candidates[:3]:\n1041\t  label = c["versionName"] + ("(推荐)" IF c["versionPlanId"] == default_id ELSE "")\n1042\t  options.append({"label": label, "description": f"versionPlanId={c[\'versionPlanId\']}, completedAt={c.get(\'completedAt\') or \'未知\'}"})\n1043\toptions.append({"label": "返回主菜单", "description": "取消生成变更单,返回主菜单"})\n1044\t\n1045\tuser_choice = AskUserQuestion(\n1046\t  question="请选择要生成变更单的版本",\n1047\t  header="生成变更单",\n1048\t  options=options\n1049\t)\n1050\t\n1051\tIF user_choice.label == "返回主菜单" THEN\n1052\t  重新展示主菜单\n1053\t  RETURN          # 不进入 skill,结束本次"生成变更单"流程\n1054\tEND IF\n1055\tselected_id = user_choice 对应候选版本的 versionPlanId\n1056\t\n1057\t# 3. 调用 version-change-order-generator skill\n1058\tSkill(version-change-order-generator, args={"versionPlanId": selected_id})'}]
    +
    +**AI**:
    +已读 dev-flow 主入口前半部分。继续读剩余部分,并并行读取 stage-hooks(阶段Agent映射表核心)、standalone-mode(单需求模式)、start-development(启动版本需求)三个清单文件。...
    +
    +
    +## 交互记录 (2026-07-27T09:22:57.156Z)
    +
    +**用户**:
    +[{'tool_use_id': 'call_e2879b735d2b43b0964d8bb0', 'type': 'tool_result', 'content': '1\t{\n2\t  "version": "1.1",\n3\t  "description": "dev-flow stage 中文映射 + STAGE_ORDER 单一真相源。回滚展示与查看版本状态复用,避免中文名散落维护。数据源对齐 stage-hooks.md 阶段Agent映射表。",\n4\t  "stage_order": [0, 1, 1.1, 1.2, 1.6, 2, 2.1, 2.2, 3, 3.1, 3.2, 3.5, 4, 5, 5.5, 6, 6.1, 7, 8, 9, 10],\n5\t  "stage_names": {\n6\t    "0": "需求澄清",\n7\t    "1": "需求分析",\n8\t    "1.1": "需求检视",\n9\t    "1.2": "需求知识同步",\n10\t    "1.6": "组件依赖分析",\n11\t    "2": "设计方案",\n12\t    "2.1": "设计检视",\n13\t    "2.2": "设计知识同步",\n14\t    "3": "代码开发",\n15\t    "3.1": "代码知识同步",\n16\t    "3.2": "代码部署前自检",\n17\t    "3.5": "插件开发迭代评估循环",\n18\t    "4": "自动部署",\n19\t    "5": "部署确认",\n20\t    "5.5": "测试用例澄清",\n21\t    "6": "测试验证",\n22\t    "6.1": "回归测试同步",\n23\t    "7": "测试执行",\n24\t    "8": "测试报告",\n25\t    "9": "循环决策",\n26\t    "10": "版本级回归测试"\n27\t  }\n28\t}\n29\t'}]
    +
    +**AI**:
    +[思考] dev-flow.md读完了。现在我对两条流程有了清晰认识:
    +
    +**流程1: `/dev-flow version`** (版本轨/版本模式)
    +- 步骤0-1: 检测状态、展示菜单
    +- 步骤2A: 创建版本引导 (调用 create-version.md)
    +- 步骤2B: 需求管理子菜单
    +- 启动版本需求 (调用 start-development.md -> stage-hooks.md 21阶段)
    +- 继续版本开发、完成版本、待补录管理、生成变更单、回滚等
    +
    +**流程2: `/dev-flow <需求描述>`** (单需求轨/standalone模式)
    +- 调用 standalone-mode.md (语法1-8 + 5种情况)
    +- 也使用 STAGE_ORDER 21阶段
    +
    +两者共用 stage-hooks.md 的 21阶段。关键是要读 stage-hooks.md 的"阶段Agent映射表"——它定义了每个stage调用哪个agent。
    +
    +现在并行读取最关键的文件:
    +1. stage-hooks.md - 阶段Agent映射表(核心!)
    +2. standalone-mode.md - 单需求模式
    +3. start-development.md - 启动版本需求(P0-P7前置 + 步骤A-F)
    +
    +stage-hooks.md 可能很大,先读它。由于这是核心,我需要完整读取。让我并行读取这三个文件。但担心stage-hooks.md太大,先读它和standalone,start-development。
    +
    +考虑到这些文件可能都很大,我用Agent委托来高效提取"stage→agent/skill映射"会比较合适。但其实我自己读更准确(遵循memory: verify-against-actual-agent-content)。
    +
    +让我并行读取这三个文件。如果太大再分段。...
    +
    +
    +## 交互记录 (2026-07-27T09:23:14.218Z)
    +
    +**用户**:
    +[{'tool_use_id': 'call_1f1e7357283b49c4b94dc45b', 'type': 'tool_result', 'content': '1058\tSkill(version-change-order-generator, args={"versionPlanId": selected_id})\n1059\t```\n1060\t\n1061\t⚠️ **版本完成度校验由 skill 内部执行**:skill 步骤1会校验 `subsystemVersionId` 非空、`testReportId` 非空 且 版本 `status==completed`(target_version.status,字段不存在视为未完成),不符合则输出"版本未完成"并终止。用户需先完成版本流程(complete-version 将版本标记为 completed 并生成 testReportId)再生成本变更单。\n1062\t\n1063\t4. skill 执行完成后(无论成功或终止),重新展示主菜单。\n1064\t\n1065\t---\n1066\t\n1067\t### 启动版本需求\n1068\t\n1069\t> ⚠️ **详细执行流程已外置,禁止凭记忆执行!**\n1070\t> 执行此操作前,**必须** Read 以下清单文件后按步骤执行:\n1071\t> 📄 `.claude/config/dev-flow-checklists/start-development.md`\n1072\t> ⛔ 禁止跳过Read直接执行。每个步骤执行完毕后必须逐项验证。\n1073\t\n1074\t**概要**:幂等性检查→关联需求前置→启动确认→P0-P7前置步骤→并行启动(步骤A-F)→逐阶段Subagent启动(步骤E)。\n1075\t\n1076\t#### 21阶段推进与阶段后置动作\n1077\t\n1078\t> ⚠️ **详细执行流程已外置,禁止凭记忆执行!**\n1079\t> 执行此操作前,**必须** Read 以下清单文件后按步骤执行:\n1080\t> 📄 `.claude/config/dev-flow-checklists/stage-hooks.md`\n1081\t> ⛔ 禁止跳过Read直接执行。每个步骤执行完毕后必须逐项验证。\n1082\t\n1083\t**概要**:包含21阶段 STAGE_ORDER、统一上下文契约、stage result/checkpoint、阶段Prompt构造规则、Stage1-10后置动作、safe_call_mcp容错机制和BIZ API同步规则。\n1084\t### 继续版本开发\n1085\t\n1086\t**恢复已启动版本中各需求的后续阶段。版本名从当前活跃版本自动获取。**\n1087\t\n1088\t**适用场景**:版本已启动(`started=true`),用户返回主菜单后选择"继续开发",需要恢复各需求的全流程。\n1089\t\n1090\t**执行流程**:\n1091\t\n1092\t#### 步骤1:读取版本配置\n1093\t读取 `dev/versions/versions.json`,获取需求列表和版本信息。\n1094\t\n1095\t#### 步骤2:读取各需求的当前阶段\n1096\t对每个需求,**优先从 versions.json 的 currentStage 字段读取**;若该字段不存在,回退到产物扫描判定。\n1097\t\n1098\t⭐阶段0 形态B段调度适配:恢复时**优先读 version-context.md 的 segmentProgress 定位当前段**,再读 currentStage 定位段内断点 stage。若 segmentProgress 不存在(旧版本),调 `migrate_add_segment_progress(req)`(详见 stage-hooks.md "形态B分段交错编排"章节)按 stageHistory 推断段进度后恢复。恢复后仍按 SEGMENT_ORDER 段调度,已完成段跳过,从 (current_segment, current_stage) 继续。\n1099\t\n1100\t⚠️ **三层上下文与 checkpoint 恢复校验**(⭐v4.9):\n1101\t版本模式使用 versions.json(控制权威源)+ context.md(需求执行上下文)+ version-context.md(版本聚合上下文)。恢复前必须 Read `.claude/config/dev-flow-context-contract.json` 并执行:\n1102\t```\n1103\t校验 immutable_identity_fields(versionName/taskName/reqIndex/reqPrefix)\n1104\tIF 任一冲突 THEN 中止恢复并输出冲突字段,禁止静默覆盖\n1105\t\n1106\tv_checkpoint = versions.json 该需求 checkpointId\n1107\tc_checkpoint = context.md.checkpointId\n1108\tIF context.md.checkpointState == "pending" AND c_checkpoint == v_checkpoint THEN\n1109\t    # 权威控制面已提交,只缺镜像 finalize\n1110\t    按 versions.json 回写 context.md stageHistory/currentStage/lastCompletedStage/contextRevision\n1111\t    更新 version-context.md requirementContextIndex\n1112\t    context.md.checkpointState = "clean"\n1113\tELIF context.md.checkpointState == "pending" AND c_checkpoint != v_checkpoint THEN\n1114\t    # 阶段结果已prepare但控制面未提交\n1115\t    不推进;保留候选 stageOutputs,重新执行当前阶段或由用户确认后调用 commit_stage_transition\n1116\tELIF versions.json 已推进但 context.md 缺对应checkpoint THEN\n1117\t    从 versions.json + 实际产物扫描重建最小 stageOutputs,标记 recovered_from_artifacts,再finalize\n1118\tEND IF\n1119\t\n1120\t最后刷新 version-context.md 的版本快照和 requirementContextIndex;禁止使用“stageHistory 较长者覆盖另一处”的旧策略。\n1121\t```\n1122\t\n1123\t```\n1124\t阶段判定规则(优先级:currentStage > 产物扫描):\n1125\t1. 若 versions.json 中有 currentStage 字段 → 直接使用该值 → 下一步: STAGE_ORDER中该值的下一项\n1126\t2. 若无 currentStage,按产物扫描(回退逻辑):\n1127\t   a. 若 docs/{versionName}/testing/ 下有测试报告 → 阶段8 → 下一步: 阶段9\n1128\t   b. 若 docs/{versionName}/testing/ 下有测试执行结果 → 阶段7 → 下一步: 阶段8\n1129\t   c. 若 docs/{versionName}/testing/ 下有测试用例 → 阶段6 → 下一步: 阶段6.1\n1130\t   c.5 若 docs/{versionName}/testing/ 下有测试澄清纪要(*_测试澄清.md)且无测试用例 → 阶段5.5(已完成) → 下一步: 阶段6\n1131\t   d. 若有代码文件且 dev/versions/{versionName}/active/{task}/ 有内容 → 阶段3-5 → 按实际进度判断\n1132\t   e. 若 docs/{versionName}/design/ 下有设计文档 → 阶段2 → 下一步: 阶段2.1\n1133\t   f. 若 docs/{versionName}/requirements/ 下有需求文档 → 阶段1 → 下一步: 阶段1.1\n1134\t   g. 无任何产物 → 阶段0 → 下一步: 阶段0\n1135\t```\n1136\t\n1137\t#### 步骤3:输出需求状态表\n1138\t\n1139\t```\n1140\t📊 版本 {versionName} 各需求当前状态\n1141\t\n1142\t| # | 需求名称 | 已有产物 | 当前阶段 | 下一步 |\n1143\t|---|---------|---------|---------|-------|\n1144\t| 1 | {name1} | 需求文档 | 阶段1: 需求分析完成 | 阶段1.1: 需求检视 |\n1145\t| 2 | {name2} | 需求文档 | 阶段1: 需求分析完成 | 阶段1.1: 需求检视 |\n1146\t```\n1147\t\n1148\t#### 步骤4:输出选项(使用 AskUserQuestion 或文本编号)\n1149\t\n1150\t- **继续全部需求** — 并行启动所有未完成需求的全流程\n1151\t- **继续特定需求** — 选择单个需求继续\n1152\t- **返回主菜单**\n1153\t\n1154\t#### 步骤5:启动 subagent\n1155\t\n1156\t用户选择后,为每个要继续的需求:\n1157\t\n1158\t1. **创建/复用 Business API Task**:\n1159\t   - biz_api_url:从versions.json该需求的biz_api_url字段读取;若为空则从环境变量BIZ_API_BASE获取;若仍为空则使用默认值http://localhost:50009\n1160\t   - 若已有 biz task(`GET {biz_api_url}/api/task?versionId={versionName}`),复用其 task_id\n1161\t   - 若无 biz task,创建新的(同"启动版本需求"步骤A)\n1162\t\n1163\t2. **创建/复用 Session**:\n1164\t   - 若已有 session,复用\n1165\t   - 若无,创建新的(同"启动版本需求"步骤B)\n1166\t\n1167\t3. **调用 execute_segments 恢复(形态B段调度,⭐阶段2 S11 交互强化2:阶段0遗漏补全)**:\n1168\t   - 与"启动版本需求"步骤E使用**同一 execute_segments 入口**(统一编排,非逐需求逐阶段)\n1169\t   - execute_segments 内含 migrate_add_segment_progress + pending_reqs 跳过已完成段(E4 D1)\n1170\t   - 已完成段的需求跳过,未完成段从断点继续,bugfix子需求(若有)从P1开始\n1171\t   - 先完成 checkpoint 恢复(步骤2的segmentProgress对账),再调 execute_segments\n1172\t   - 可跳过环节沿用skipDecisions历史决策或项目级配置\n1173\t   - Stage 4 在版本模式下不可跳过\n1174\t\n1175\t4. **⚠️ 禁止**:恢复时禁止启动 req-type-classifier 做全流程编排(与"启动版本需求"Step E相同规则)\n1176\t\n1177\t**注意**:\n1178\t- 恢复与首次启动必须共用 stage-hooks.md 的 stage_context 构造逻辑,每阶段重新读取三层上下文\n1179\t- 每个阶段prompt必须包含契约允许的上一阶段摘要、已有产物、已确认决策和未关闭风险,避免只恢复进度不恢复语义\n1180\t- 每次恢复都会创建新的 biz session,记录本次交互历史\n1181\t- 每个阶段完成/跳过后调用 commit_stage_transition,禁止直接单写 currentStage/stageHistory\n1182\t\n1183\t### 回滚到指定阶段(⛔ 已从主菜单隐藏,仅供 Stage5/3.2/9 自动回滚内部调用,禁止作为主菜单项展示)\n1184\t\n1185\t> ⛔ **本章节已从主菜单隐藏(commit 636c1008)**。\n1186\t> 主菜单(NO_VERSION/NOT_STARTED/STARTED/ALL_COMPLETED)**不含**"回滚到指定阶段"入口,禁止将其列入任何主菜单编号选项。\n1187\t> 流程异常决策(Stage5部署失败"需修复"/Stage3.2"返回修复"/Stage9失败循环)**不展示独立"回滚"选项**,统一通过下方 `execute_rollback` 内部能力自动执行。\n1188\t> 能力保留:仅 Stage5/3.2/9 自动回滚点调用 `execute_rollback` 时,按下方流程执行。\n1189\t\n1190\t> ⚠️ **详细执行流程已外置,禁止凭记忆执行!**\n1191\t> 执行此操作前,**必须** Read 以下清单文件后按步骤执行:\n1192\t> 📄 `.claude/config/dev-flow-checklists/rollback.md`\n1193\t> 📄 `.claude/config/dev-flow-checklists/stage-names.json`(stage 中文映射)\n1194\t> ⛔ 禁止跳过 Read 直接执行。\n1195\t\n1196\t**概要**:stage 级回滚——用户选择要回退到的已执行阶段,修改 currentStage + 清空目标及之后的 stageHistory/skipDecisions + 记录 rollbackHistory,然后按新 currentStage 继续 dev-flow 流程。默认回退到上一步(stageHistory 最后一项)。\n1197\t\n1198\t**执行流程**:\n1199\t\n1200\t```python\n1201\t# 1. 读取版本配置,获取需求列表\n1202\tversions = read("dev/versions/versions.json")\n1203\tactive_version = 当前活跃版本\n1204\t\n1205\t# 2. 询问用户选择要回滚的需求(若版本下有多个已启动需求)\n1206\tIF active_version 下仅有1个已启动需求 THEN\n1207\t    target_requirement = 该需求\n1208\tELSE\n1209\t    展示已启动需求列表(需求编号 | 需求名 | 当前阶段),让用户选择\n1210\tEND IF\n1211\t\n1212\t# 3. 调用统一回滚函数(interactive 模式)\n1213\tRead .claude/config/dev-flow-checklists/rollback.md\n1214\tRead .claude/config/dev-flow-checklists/stage-names.json\n1215\texecute_rollback(requirement=target_requirement, mode="interactive", reason="主菜单用户主动回滚")\n1216\t# rollback.md 内部:展示中文阶段列表(默认上一步)-> 用户选 -> 原子写入 -> 从目标 stage 恢复\n1217\t```\n1218\t\n1219\t**关键约束**:\n1220\t- 只能回退到 `stageHistory` 中已执行过的阶段(展示列表只含已执行步骤)\n1221\t- 回滚原子写入:currentStage + stageHistory + skipDecisions + rollbackHistory 一次性更新(临时文件+rename)\n1222\t- 防死循环:连续回滚到同一 stage ≥3 次提示人工介入\n1223\t- 回滚后从目标 stage 重新推进,prompt 注入【已有产物路径】避免重复生成\n1224\t- 远程副作用(已转提测/已同步测试用例/已 push)不清理,作为已知取舍\n1225\t\n1226\t4. 回滚执行完成后,重新展示 STARTED 主菜单。\n1227\t\n1228\t### 添加单个版本需求\n1229\t\n1230\t**在指定版本下添加单个系统需求。版本名从当前活跃版本自动获取。**\n1231\t\n1232\t**执行流程**:\n1233\t1. 验证版本存在(读取 `dev/versions/versions.json`)\n1234\t2. 验证版本未关联(`assigned == false`),若已关联则输出 "❌ 版本已关联版本计划,不允许新增需求!"\n1235\t3. 验证版本未启动(`started == false`),若已启动则警告并询问是否继续\n1236\t4. 从 `story-desc` 智能提取需求名称\n1237\t5. 展示确认信息:需求名称、描述\n1238\t6. **始终执行**:创建本地记录,更新 `dev/versions/versions.json`(type/priority 留空,由后续 `version start` 时前置步骤P1自动识别填充)\n1239\t   - **分配需求编号**:读取当前版本的 `nextReqIndex`,分配 `reqIndex = nextReqIndex`,然后 `nextReqIndex += 1`。`reqPrefix = "REQ-" + str(reqIndex).zfill(2)`(如 REQ-01、REQ-02)。写入 requirements 数组。\n1240\t   - **分配需求-子系统归属**(⭐阶段1 S5 D12):若版本为多子系统(`len(subsystems) > 1`),AskUserQuestion 询问"需求[{需求名}]归属哪个子系统"(从 subsystems[] 选),写入该需求的 `reqSubsystemId`;若单子系统,`reqSubsystemId = subsystems[0].subsystemId`(自动归属,无需询问)。\n1241\t   - **分配需求-仓库归属**(⭐阶段3 S6):若多git,从需求的 reqSubsystemId 反查 subsystems[] 取 sub.gitUrl 作为 repositoryId;若单git,repositoryId=null。\n1242\t7. 询问远程操作策略(使用 AskUserQuestion,A3/A4可独立跳过):\n1243\t   - 选项1: "**全部执行(推荐)→ 创建本地记录 + DPMS创建系统需求 + 关联子系统版本**"\n1244\t   - 选项2: "**仅DPMS创建系统需求 → 创建本地记录 + DPMS创建系统需求,跳过关联子系统版本**"\n1245\t   - 选项3: "**全部跳过 → 仅创建本地记录(需求类型由后续启动开发时自动识别)**"\n1246\t8. 根据用户选择执行远程操作:\n1247\t   - 选项1: 调用 `mcp__sdp__add-system-story`(A3),参数 `enableAiMode` = 1(⚠ 必须显式传入),成功后:① 调用 `mcp__sdp__get-storys(id=storyId)` 查询 `productName` 并回填 versions.json 该需求的 `dpmsStoryId` 和 `productName` 字段;② 自动调用 `mcp__sdp__associate-subsystem-version`(A4);A3或A4失败时按容错机制写入PendingItem\n1248\t   - 选项2: 调用 `mcp__sdp__add-system-story`(A3),参数 `enableAiMode` = 1(⚠ 必须显式传入),成功后:① 调用 `mcp__sdp__get-storys(id=storyId)` 查询 `productName` 并回填 versions.json 该需求的 `dpmsStoryId` 和 `productName` 字段;② A4写入PendingItem\n1249\t   - 选项3: A3和A4分别写入PendingItem,productName保持null\n1250\t9. 输出结果摘要(含A3/A4各步骤状态)\n1251\t10. **下一步引导**(使用 AskUserQuestion):\n1252\t   - 选项1:"**继续添加需求**" — 重新执行 add-story 流程(同一版本)\n1253\t   - 选项2:"**启动开发**" — **内联执行启动开发**(见下方"启动版本需求"章节,仅 `started == false` 时显示;`started == true` 时不显示此选项)\n1254\t   - 选项3:"**返回主菜单**"\n1255\t\n1256\t### 批量添加版本需求\n1257\t\n1258\t**在指定版本下批量添加多个系统需求。版本名从当前活跃版本自动获取。**\n1259\t2. **解析需求列表**:支持以下分隔格式:\n1260\t   - `1. xxx; 2. yyy; 3. zzz`\n1261\t   - `1、xxx 2、yyy 3、zzz`\n1262\t   - `1) xxx 2) yyy 3) zzz`\n1263\t3. **确认识别结果**(关键步骤,使用 AskUserQuestion):\n1264\t   - 展示解析到的需求列表(表格形式)\n1265\t   - 选项:"**识别正确,继续**" / "**识别有误,重新输入**"\n1266\t4. 展示完整确认信息(所有需求列表)\n1267\t5. **始终执行**:创建本地记录,更新 `dev/versions/versions.json`(type/priority 留空,由后续 `version start` 时前置步骤P1自动识别填充)\n1268\t   - **分配需求编号**:对每个需求按添加顺序分配递增的 `reqIndex`(从 `nextReqIndex` 开始,每个需求 +1),计算 `reqPrefix = "REQ-" + str(reqIndex).zfill(2)`。写入 requirements 数组并更新 `nextReqIndex`。\n1269\t   - **分配需求-子系统归属**(⭐阶段1 S5 D12):对每个需求,若版本为多子系统(`len(subsystems) > 1`),AskUserQuestion 询问该需求归属哪个子系统(可批量询问,从 subsystems[] 选),写入各需求的 `reqSubsystemId`;若单子系统,所有需求 `reqSubsystemId = subsystems[0].subsystemId`(自动归属)。\n1270\t   - **分配需求-仓库归属**(⭐阶段3 S6):对每个需求,若多git,从需求的 reqSubsystemId 反查 subsystems[] 取 sub.gitUrl 作为 repositoryId;若单git,repositoryId=null。\n1271\t6. 询问远程操作策略(使用 AskUserQuestion,A3/A4可独立跳过):\n1272\t   - 选项1: "**全部执行(推荐)→ 创建本地记录 + DPMS创建系统需求 + 关联子系统版本**"\n1273\t   - 选项2: "**仅DPMS创建系统需求 → 创建本地记录 + DPMS创建系统需求,跳过关联子系统版本**"\n1274\t   - 选项3: "**全部跳过 → 仅创建本地记录(需求类型由后续启动开发时自动识别)**"\n1275\t7. 根据用户选择,对每个需求独立执行远程操作(单个失败不影响其余):\n1276\t   - 选项1: 调用 `mcp__sdp__add-system-story`(A3),参数 `enableAiMode` = 1(⚠ 必须显式传入),成功后:① 调用 `mcp__sdp__get-storys(id=storyId)` 查询 `productName` 并回填 versions.json 该需求的 `dpmsStoryId` 和 `productName` 字段;② 自动调用 `mcp__sdp__associate-subsystem-version`(A4);A3或A4失败时按容错机制写入PendingItem\n1277\t   - 选项2: 调用 `mcp__sdp__add-system-story`(A3),参数 `enableAiMode` = 1(⚠ 必须显式传入),成功后:① 调用 `mcp__sdp__get-storys(id=storyId)` 查询 `productName` 并回填 versions.json 该需求的 `dpmsStoryId` 和 `productName` 字段;② A4写入PendingItem\n1278\t   - 选项3: A3和A4分别写入PendingItem,productName保持null\n1279\t8. 输出结果摘要:本地创建 N 条 + A3成功 M 条 + A4成功 K 条 + 失败进待补录 L 条\n1280\t9. **下一步引导**(使用 AskUserQuestion):\n1281\t   - 选项1:"**继续添加需求**" — 重新执行 add-stories 流程(同一版本)\n1282\t   - 选项2:"**启动开发**" — **内联执行启动开发**(见下方"启动版本需求"章节,仅 `started == false` 时显示;`started == true` 时不显示此选项)\n1283\t   - 选项3:"**返回主菜单**"\n1284\t\n1285\t### 查看版本需求列表\n1286\t\n1287\t**查看指定版本下的所有需求。版本名从当前活跃版本自动获取。**\n1288\t\n1289\t**执行流程**:\n1290\t1. 读取 `dev/versions/versions.json` 中对应版本的 requirements 数组\n1291\t2. 若版本不存在:输出 "❌ 版本 {versionName} 不存在",结束\n1292\t3. 若需求列表为空:输出 "📋 版本 {versionName} 下暂无需求",结束\n1293\t4. 输出需求列表表格:\n1294\t\n1295\t```markdown\n1296\t# 📋 版本 v3.10 需求列表(共N条)\n1297\t\n1298\t| 序号 | 需求编号 | 需求名称 | Story ID | 优先级 | 状态 | 已关联 |\n1299\t|:----:|:-------:|---------|---------|:------:|------|:-----:|\n1300\t| 1 | REQ-01 | 用户数据导出 | 12345 | P1 | pending | 否 |\n1301\t| 2 | REQ-02 | 登录接口修复 | 12346 | P0 | development | 是 |\n1302\t| 3 | REQ-03 | 列表查询优化 | 12347 | P2 | completed | 是 |\n1303\t\n1304\t**统计**:待启动 1 | 开发中 1 | 已完成 1\n1305\t```\n1306\t\n1307\t### 删除版本需求\n1308\t\n1309\t**从版本中移除未关联的系统需求。版本名从当前活跃版本自动获取。**\n1310\t\n1311\t**执行流程**:\n1312\t1. 根据 story-desc 模糊匹配需求(匹配 name 或 description 字段)\n1313\t2. 若未找到:输出 "❌ 未找到匹配的需求",结束\n1314\t3. **状态检查**:\n1315\t   - 若版本已启动(`started == true`):输出 "❌ 版本已启动开发,不支持删除需求!",结束\n1316\t   - 若需求已关联(`assigned == true`):输出 "❌ 需求 [{name}] (Story ID: {id}) 已关联版本计划,不支持删除!",结束\n1317\t4. 展示待删除需求信息并确认(使用 AskUserQuestion)\n1318\t5. 用户确认后,从 requirements 数组中移除该需求\n1319\t6. 更新 `dev/versions/versions.json`\n1320\t7. 输出 "✅ 需求 [{name}] 已从版本中移除"\n1321\t\n1322\t**约束规则**:\n1323\t- 已启动版本(started=true)**不支持删除需求**\n1324\t- 已关联版本(assigned=true)的需求**不支持删除**\n1325\t- 删除仅移除本地配置中的记录,不调用 DPMS 删除接口\n1326\t- **已分配的 reqIndex 不会回收**,允许编号间隙(如删除REQ-02后,后续需求继续从nextReqIndex分配,不会重用02)\n1327\t\n1328\t---\n1329\t\n1330\t### 单需求模式(语法1-8 + 情况1-5)\n1331\t\n1332\t> ⚠️ **详细执行流程已外置,禁止凭记忆执行!**\n1333\t> 执行此操作前,**必须** Read 以下清单文件后按步骤执行:\n1334\t> 📄 `.claude/config/dev-flow-checklists/standalone-mode.md`\n1335\t> ⛔ 禁止跳过Read直接执行。每个步骤执行完毕后必须逐项验证。\n1336\t\n1337\t**概要**:包含语法1-8定义(启动任务、恢复任务、查看状态、修改阶段、查看完成、指定Story、查看帮助、版本模式)和5种执行情况(手动输入、resume、view、modify、completed)的完整步骤。\n1338\t\n1339\t---\n1340\t\n1341\t## ⚠️ 注意事项\n1342\t\n1343\t1. **需求描述要清晰**:包含足够的信息帮助识别需求类型\n1344\t2. **首次使用**:会先分析项目上下文(约1-2分钟)\n1345\t3. **中断恢复**:随时可以输入"暂停"中断,下次用 `resume` 继续\n1346\t4. **多任务管理**:可以同时处理多个任务,每个任务有独立的工作目录\n1347\t5. **模板适配**:支持自然语言描述,系统会自动提取信息并引导补全\n1348\t6. **DevOps 自动部署配置**🆕:\n1349\t   - 本项目通过 `project-deployer` Skill 自动化管理编译与部署流程。\n1350\t   - 自动部署流程:开发完成 → 调用 `project-deployer` Skill(本地编译校验(可跳过)、git-commit、git-push 推送触发云端 CI/CD)→ 用户人工交互式确认部署就绪。\n1351\t   - 配置文件:`.claude/config/deployment-config.json`(仅用于配置相关凭据或地址)\n1352\t\n1353\t---\n1354\t\n1355\t## 📚 更多帮助\n1356\t\n1357\t- **流程主控Agent**:`.claude/agents/requirement/req-type-classifier.md`\n1358\t- **使用指南**:`docs/AGENTS_WORKFLOW_GUIDE.md`\n1359\t- **Agents列表**:`.claude/agents/README.md`\n1360\t\n1361\t---\n1362\t\n1363\t**提示**:这是DevSyncAgent的核心命令,建议收藏使用! ⭐\n1364\t'}]
    +
    +**AI**:
    +dev-flow.md 主入口已读完。两条流程已清晰:`/dev-flow version`(版本轨)和 `/dev-flow <需求描述>`(单需求轨),两者共用 stage-hooks.md 的 21 阶段。现在读取最核心的阶段Agent映射表文件。...
    +
    +
    +## 交互记录 (2026-07-27T09:23:15.069Z)
    +
    +**用户**:
    +[{'tool_use_id': 'call_16a3b27c8cd3410a9b9ee4d7', 'type': 'tool_result', 'content': '.claude\\config\\dev-flow-checklists\\rollback.md\n.claude\\config\\dev-flow-checklists\\associate-requirement.md\n.claude\\config\\dev-flow-checklists\\complete-version.md\n.claude\\config\\dev-flow-checklists\\create-version.md\n.claude\\config\\dev-flow-checklists\\stage-10-version-regression.md\n.claude\\config\\dev-flow-checklists\\stage-hooks.md\n.claude\\config\\dev-flow-checklists\\standalone-mode.md\n.claude\\config\\dev-flow-checklists\\start-development.md'}]
    +
    +**AI**:
    +[思考] 这是核心文件,我已经获得了"阶段Agent映射表"(331-355行)和形态B段调度、逐阶段执行流程、阶段后置动作映射表(1187-1202行)。这是最关键的信息。
    +
    +现在我需要读取剩余的关键内容:
    +1. standalone-mode.md - 单需求模式(`/dev-flow <需求描述>`)的核心,看它和版本模式在stage上的差异
    +2. start-development.md - 启动版本需求的P0-P7前置步骤和步骤A-F
    +
    +另外stage-hooks.md还有Stage10的内容和Stage6/7-Hook的详细伪代码我没读完,但映射表已经够了。让我读standalone-mode.md和start-development.md,以及stage-10-version-regression.md(Stage10用)。
    +
    +为了高效,我用Agent委托读取standalone-mode.md和start-development.md的关键部分,提取"P0-P7前置步骤用什么agent/skill"和"单需求模式的stage差异"。
    +
    +但考虑到memory要求verify-against-actual-agent-content,我自己读更准确。让我并行读取这两个文件 + stage-10。
    +
    +standalone-mode.md和start-development.md可能较大,我直接读。同时读stage-10-version-regression.md。
    +
    +实际上,我已经有足够信息来构建文档了。但为了完整准确(特别是单需求模式的前置步骤和两条流程的差异),我需要读standalone-mode.md和start-development.md。让我并行读取。...
    +
    +
    +## 交互记录 (2026-07-27T09:23:34.680Z)
    +
    +**用户**:
    +[{'tool_use_id': 'call_f64e5063d9584d6fbb2fde72', 'type': 'tool_result', 'content': '1\t# 21阶段推进与后置动作指引\n2\t\n3\t> 来源:dev-flow.md "21阶段有序推进规则" + "逐阶段执行流程" + "阶段Prompt构造规则" + "阶段后置动作映射表" + "阶段后置动作执行指引"章节\n4\t> v4.9 G4 新增:Stage 3.5 插件开发迭代评估循环(仅 dev_target=Agent/Skill/Command 触发)\n5\t> v4.9 上下文优化:统一版本/需求上下文契约、阶段结果协议与两阶段 checkpoint\n6\t> 用途:执行版本模式逐阶段推进时必须Read本文件,按步骤逐项执行\n7\t\n8\t## 21阶段有序推进规则\n9\t\n10\t```\n11\tSTAGE_ORDER = [0, 1, 1.1, 1.2, 1.6, 2, 2.1, 2.2, 3, 3.1, 3.2, 3.5, 4, 5, 5.5, 6, 6.1, 7, 8, 9, 10]\n12\tREQUIREMENT_STAGE_ORDER = STAGE_ORDER[0:-1]  # Stage 10 是版本级阶段,不进入单需求 FOR 循环\n13\t```\n14\t\n15\t## 形态B分段交错编排(⭐阶段0 spike v4.9+)\n16\t\n17\t> 形态B核心规则(用户2026-07-21确认):涉及修改源码的环节(开发/测试代码生成等)不能并行,文档生成环节(需求/设计/测试案例等)可并行。\n18\t> 21阶段按产物类型二分(已源码验证:Stage6生成测试用例文档=文档✅ / Stage7生成测试代码=代码❌ / Stage3.2 auto_fix=改码❌ / Stage3.5插件迭代=改插件❌)。\n19\t> v4.0废弃教训规避:主会话掌段间屏障+commit,subagent只跑单阶段(不重蹈subagent独立编排丢子阶段覆辙)。\n20\t> 阶段0 spike 限定 happy path(所有需求Stage9一次通过);Stage9失败回滚与段屏障交互待阶段2 S11实现。\n21\t\n22\t```\n23\tSEGMENTS = {\n24\t  "P1": {"stages": ["0","1","1.1","1.2","1.6","2","2.1","2.2"], "parallel": True,  "nature": "文档生成"},\n25\t  "S1": {"stages": ["3","3.1","3.2","3.5","4","5"],              "parallel": False, "nature": "改源码"},\n26\t  "P2": {"stages": ["5.5","6","6.1"],                            "parallel": True,  "nature": "文档生成"},\n27\t  "S2": {"stages": ["7","8"],                                    "parallel": False, "nature": "测试执行"},\n28\t  "D":  {"stages": ["9"],                                        "parallel": False, "nature": "循环决策(含失败blocked,需逐需求串行处理,⭐阶段2 F2修正)"},\n29\t  "V":  {"stages": ["10"],                                       "parallel": False, "nature": "版本级回归"}\n30\t}\n31\tSEGMENT_ORDER = ["P1","S1","P2","S2","D","V"]\n32\t```\n33\t\n34\t### 段调度函数\n35\t\n36\t```python\n37\t# 段调度入口(替代原"对每个需求按STAGE_ORDER逐阶段"的外层循环)\n38\tFUNCTION execute_segments(all_requirements):\n39\t  # 0. 迁移:为每个需求补 segmentProgress(向后兼容旧 versions.json/context.md)\n40\t  FOR each req IN all_requirements:\n41\t    migrate_add_segment_progress(req)\n42\t  END FOR\n43\t  FOR each segment IN SEGMENT_ORDER:\n44\t    # ⭐阶段2 S11 E4 D1修正:跳过所有需求已完成的段(支持resume场景:已完成段跳过,bugfix子需求从P1)\n45\t    pending_reqs = [req FOR req IN all_requirements IF req.segmentProgress[segment].status NOT IN ["completed","skipped","blocked"]]\n46\t    IF len(pending_reqs) == 0 THEN CONTINUE  # 该段所有需求已完成/跳过/blocked,跳过该段\n47\t    IF segment == "V" THEN\n48\t      wait_segment_barrier("D", all_requirements)  # 所有需求D段 completed/skipped/blocked 才触发版本级回归\n49\t      # ⭐阶段2 E4:blocked需求不参与V段版本级回归(其bugfix子需求下一轮修复后重新Stage9)\n50\t      active_reqs = [req FOR req IN all_requirements IF req.segmentProgress["D"].status != "blocked"]\n51\t      IF len(active_reqs) > 0 THEN\n52\t          execute_stage_10(active_reqs)  # 复用 stage-10-version-regression.md\n53\t      ELSE\n54\t          OUTPUT: "⚠️ 所有需求Stage9均blocked,V段跳过,等待bugfix子需求下一轮修复"\n55\t      END IF\n56\t      # ⭐阶段2 E4 F1修正:V段后检查是否有blocked需求,有则返回exited_with_blocked触发交互强化1引导\n57\t      blocked_reqs = [req FOR req IN all_requirements IF req.segmentProgress["D"].status == "blocked"]\n58\t      IF len(blocked_reqs) > 0 THEN\n59\t          RETURN "exited_with_blocked"  # 有需求Stage9失败blocked,触发start-development步骤E退出引导\n60\t      END IF\n61\t      RETURN "completed"\n62\t    END IF\n63\t    IF SEGMENTS[segment].parallel == True THEN\n64\t      execute_parallel_segment(segment, pending_reqs)\n65\t    ELSE\n66\t      execute_serial_segment(segment, pending_reqs)\n67\t    END IF\n68\t    wait_segment_barrier(segment, all_requirements)\n69\t  END FOR\n70\t  RETURN "completed"\n71\tEND FUNCTION\n72\t\n73\t# 并行段(P1/P2/D):N需求并发生成文档,方案C队列化commit\n74\tFUNCTION execute_parallel_segment(segment, requirements):\n75\t  stages = SEGMENTS[segment].stages\n76\t  FOR each stage IN stages:\n77\t    stage_results_queue = []\n78\t    IF stage == "0" THEN\n79\t      # 澄清流水线式(逐个澄清,澄清完即进Stage1,不阻塞其他需求)\n80\t      FOR each req IN requirements:\n81\t        Agent(req-clarification-orchestrator, prompt=构造(req,"0"))\n82\t        # 复用步骤7.3提取 function_attributes(已有逻辑)\n83\t        ENQUEUE(stage_results_queue, (req,"0",result))\n84\t      END FOR\n85\t    ELIF stage IN ["1.1","2.1"] THEN\n86\t      # 检视批量决策(交互复用,1次AskUserQuestion覆盖N需求,非N次)\n87\t      batch_decision = batch_ask_recheck_optimization(requirements, stage)\n88\t      FOR each req IN requirements:\n89\t        Agent/des-recheck-orchestrator(prompt=构造(req,stage))\n90\t        apply_batch_decision(req, stage, batch_decision)\n91\t        ENQUEUE(stage_results_queue, (req,stage,result))\n92\t      END FOR\n93\t    ELSE\n94\t      # 文档stage真并发(无交互冲突)—— ⭐阶段0完善:可跳过环节(1.2/1.6/2.2/5.5/6.1等)在ask模式下批量决策\n95\t      # 步骤3"判断可跳过"读项目级配置(skip/execute/ask),多需求并行ask模式时统一批量询问(交互复用)\n96\t      IF stage IN 可跳过环节 AND 项目级配置[stage]=="ask" THEN\n97\t          batch_skip_decision = batch_ask_skippable(requirements, stage)  # 1次问N需求统一执行/跳过\n98\t          IF batch_skip_decision == "skip_all" THEN\n99\t              FOR each req IN requirements:\n100\t                  记录 skipDecisions[{stage}] = "skipped" 到 versions.json 该需求\n101\t                  ENQUEUE(stage_results_queue, (req,stage,{status:"skipped"}))\n102\t              END FOR\n103\t              flush_commit_queue(stage_results_queue)  # 跳过也需commit(skipped状态)\n104\t              CONTINUE  # 跳过该stage的Agent启动,推进下一stage\n105\t          ELIF batch_skip_decision == "ask_individual" THEN\n106\t              # 逐个确认降级:逐需求询问执行/跳过\n107\t              FOR each req IN requirements:\n108\t                  individual_ans = AskUserQuestion(question=f"需求[{req.name}]的Stage {stage}是否执行?",\n109\t                      options=[{label:"执行"},{label:"跳过"}])\n110\t                  IF individual_ans == "跳过" THEN\n111\t                      记录 skipDecisions[{stage}] = "skipped"\n112\t                      ENQUEUE(stage_results_queue, (req,stage,{status:"skipped"}))\n113\t                      CONTINUE\n114\t                  END IF\n115\t                  Agent/Skill(映射表对应agent, prompt=构造(req,stage))\n116\t                  ENQUEUE(stage_results_queue, (req,stage,result))\n117\t              END FOR\n118\t              flush_commit_queue(stage_results_queue)\n119\t              CONTINUE  # 逐个确认已处理完,推进下一stage\n120\t          END IF\n121\t          # batch_skip_decision == "execute_all" 时落到下方并发启动\n122\t      END IF\n123\t      FOR each req IN requirements (并发启动):\n124\t        Agent/Skill(映射表对应agent, prompt=构造(req,stage))\n125\t        ENQUEUE(stage_results_queue, (req,stage,result))\n126\t      END FOR\n127\t    END IF\n128\t    # 方案C:该stage所有需求完成后,主会话串行commit(规避并发写versions.json)\n129\t    flush_commit_queue(stage_results_queue)\n130\t    # 更新各需求段进度\n131\t    FOR each req IN requirements:\n132\t      update_segment_progress(req, segment, "running")\n133\t    END FOR\n134\t  END FOR\n135\tEND FUNCTION\n136\t\n137\t# 串行段(S1/S2):N需求排队改源码(形态B核心规则)\n138\tFUNCTION execute_serial_segment(segment, requirements):\n139\t  FOR each req IN requirements (顺序):\n140\t    FOR each stage IN SEGMENTS[segment].stages:\n141\t      execute_single_stage(req, stage)  # 复用下方 WHILE+FOR 体内的单阶段11步逻辑(步骤0-11)\n142\t      commit_stage_transition(result)  # 串行段直接commit\n143\t      # ⭐阶段2 E4:若该需求Stage9失败blocked(execute_single_stage内EXIT WHILE),跳出该需求后续stage\n144\t      IF stage == "9" AND req.segmentProgress["D"].status == "blocked" THEN BREAK\n145\t    END FOR\n146\t    IF req.segmentProgress[segment].status != "blocked" THEN\n147\t        update_segment_progress(req, segment, "completed")\n148\t    END IF\n149\t  END FOR\n150\tEND FUNCTION\n151\t\n152\t# 段间屏障:本段所有需求 completed/skipped/blocked 才进下一段(⭐阶段2 E4:含blocked三态)\n153\tFUNCTION wait_segment_barrier(segment, requirements):\n154\t  FOR each req IN requirements:\n155\t    WHILE req.segmentProgress[segment].status NOT IN ["completed","skipped","blocked"]:\n156\t      WAIT\n157\t    END WHILE\n158\t  END FOR\n159\tEND FUNCTION\n160\t\n161\t# 检视批量决策(交互复用)\n162\tFUNCTION batch_ask_recheck_optimization(requirements, stage):\n163\t  names = [req.name FOR req IN requirements]\n164\t  AskUserQuestion(question=f"Stage {stage}检视完成,{len(names)}个需求统一应用优化范围?\\n需求:{names}",\n165\t    header="批量检视决策",\n166\t    options=[{label:"全部执行必要优化(推荐)",description:"N个需求统一应用critical+recommended"},\n167\t             {label:"仅必须修改",description:"N个需求统一应用critical"},\n168\t             {label:"跳过优化",description:"N个需求保持原文档"},\n169\t             {label:"逐个确认",description:"退化为逐需求询问(降级)"}])\n170\t  RETURN decision\n171\tEND FUNCTION\n172\t\n173\t# 可跳过环节批量决策(⭐阶段0完善:补全并行段可跳过交互,多需求ask模式统一询问)\n174\tFUNCTION batch_ask_skippable(requirements, stage):\n175\t  names = [req.name FOR req IN requirements]\n176\t  AskUserQuestion(question=f"Stage {stage}(可跳过环节),{len(names)}个需求统一处理?\\n需求:{names}",\n177\t    header="批量跳过决策",\n178\t    options=[{label:"全部执行(推荐)",description:"N个需求都执行此环节"},\n179\t             {label:"全部跳过",description:"N个需求都跳过此环节(记录skipDecisions)"},\n180\t             {label:"逐个确认",description:"退化为逐需求询问(降级)"}])\n181\t  RETURN decision  # "execute_all" / "skip_all" / "ask_individual"\n182\tEND FUNCTION\n183\t\n184\t# 更新段进度(写入 version-context.md requirementContextIndex.{reqPrefix}.segmentProgress)\n185\tFUNCTION update_segment_progress(req, segment, status):\n186\t  req.segmentProgress[segment].status = status\n187\t  IF status == "completed" THEN req.segmentProgress[segment].endAt = now\n188\t  ELIF status == "running" THEN req.segmentProgress[segment].startAt = now\n189\t  END IF\n190\t  原子写 version-context.md requirementContextIndex.{reqPrefix}.segmentProgress\n191\tEND FUNCTION\n192\t\n193\t# 向后兼容迁移:旧 versions.json/context.md 无 segmentProgress 字段时,按 stageHistory 推断段进度\n194\tFUNCTION migrate_add_segment_progress(req):\n195\t  IF req.segmentProgress 不存在 THEN\n196\t    req.segmentProgress = {P1:{status:"pending"},S1:{status:"pending"},P2:{status:"pending"},S2:{status:"pending"},D:{status:"pending"},V:{status:"pending"}}\n197\t    FOR each s IN req.stageHistory:\n198\t      seg = find_segment_by_stage(s)  # 按 SEGMENTS 反查 stage 属于哪个段\n199\t      IF seg THEN req.segmentProgress[seg].status = "completed"\n200\t    END FOR\n201\t    IF req.currentStage 存在 THEN\n202\t      current_seg = find_segment_by_stage(req.currentStage)\n203\t      IF current_seg THEN req.segmentProgress[current_seg].status = "running"\n204\t    END IF\n205\t  END IF\n206\tEND FUNCTION\n207\t```\n208\t\n209\t⚠️ **阶段0 spike 边界**:\n210\t- 限定 happy path(所有需求Stage9一次通过),Stage9失败回滚与段屏障交互待阶段2 S11实现\n211\t- Stage9通过分支:单需求直接GOTO Stage10;多需求形态B标记D段完成交外层V段屏障统一触发(本WHILE+FOR内不直接GOTO,防绕屏障)\n212\t- 单需求时段调度退化为串行(1需求时各段仅1需求,等价现有串行,向后兼容)\n213\t- commit_stage_transition 签名不变,并行段通过局部 stage_results_queue + flush_commit_queue 实现方案C(串行commit规避并发写),现有调用100%不受影响\n214\t- V段(Stage10)复用现有 stage-10-version-regression.md,不改\n215\t\n216\t## 上下文契约(P0)\n217\t\n218\t每次进入本清单必须先 Read `.claude/config/dev-flow-context-contract.json`,并验证:\n219\t\n220\t1. contract version 与 context.md 的 `contextSchemaVersion` 一致;旧 context 缺字段时先原地迁移到 1.0,保留未知字段。\n221\t2. `versions.json` 是生命周期、currentStage、stageHistory、skipDecisions、rollbackHistory 的权威源。\n222\t3. 需求 `context.md` 保存 stageOutputs、artifactIndex、openRisks、decisionLog 等执行上下文。\n223\t4. `version-context.md` 保存版本快照与各需求上下文索引,供 Stage 10/complete-version 聚合消费。\n224\t5. Agent/Skill 只能通过 stage result 的 `context_updates` 建议更新白名单字段,禁止修改 contract 中 `controller_only_fields`。\n225\t\n226\t**来源刷新顺序**:versions.json → context.md → version-context.md → docs 产物扫描 → project-context.json。除不可变身份外,禁止跨 stage 使用主会话旧缓存。\n227\t\n228\t### 统一阶段提交函数 `commit_stage_transition`(P0)\n229\t\n230\t所有完成、跳过、自动跳过、降级成功分支必须调用本函数;任何 `CONTINUE/BREAK/GOTO` 若代表当前 stage 已结束,必须先提交,禁止绕过:\n231\t\n232\t```python\n233\tFUNCTION commit_stage_transition(stage_result):\n234\t  # 0. 校验/归一化\n235\t  VALIDATE stage_result AGAINST contract.stage_result_schema\n236\t  IF Agent/Skill 未返回结构化结果 THEN\n237\t      主会话从返回文本与实际产物扫描合成 stage_result\n238\t  END IF\n239\t  DROP stage_result.context_updates 中不在 allowed_context_updates 的字段\n240\t  checkpoint_id = "{versionName}:{reqPrefix}:{stage}:{ISO时间}"\n241\t\n242\t  # 1. prepare:先保存不可丢失的阶段结果,但不推进控制面\n243\t  原子写 context.md(临时文件 + rename):\n244\t    checkpointId = checkpoint_id\n245\t    checkpointState = "pending"\n246\t    stageOutputs[stage] = {status,summary,artifacts,decisions,risks,contextUpdates,completedAt}\n247\t    artifactIndex = merge_and_dedupe(artifactIndex, stage_result.artifacts)\n248\t    decisionLog = append_dedupe(decisionLog, stage_result.decisions)\n249\t    openRisks = reconcile(openRisks, stage_result.risks)\n250\t    updatedAt = now\n251\t\n252\t  # 2. commit:推进权威控制面\n253\t  原子写 versions.json(临时文件 + rename):\n254\t    currentStage = stage\n255\t    lastCompletedStage = stage\n256\t    stageHistory = append_once(stageHistory, stage)\n257\t    contextPath = context_path\n258\t    contextRevision = context.contextRevision + 1\n259\t    checkpointId = checkpoint_id\n260\t  # skipped/auto_skipped 也必须 append_once(stageHistory, stage),并保留 skipDecisions\n261\t\n262\t  # 3. finalize:完成镜像与版本聚合\n263\t  原子写 context.md:\n264\t    lastCompletedStage = stage\n265\t    stageHistory = versions.json.stageHistory\n266\t    skipDecisions = versions.json.skipDecisions\n267\t    rollbackHistory = versions.json.rollbackHistory\n268\t    contextRevision = versions.json.contextRevision\n269\t    checkpointState = "clean"\n270\t  原子写 version-context.md:\n271\t    requirementContextIndex[reqPrefix] = {taskName,contextPath,currentStage,lastCompletedStage,contextRevision,status,checkpointId}\n272\t    contextRevision += 1\n273\t    updatedAt = now\n274\tEND FUNCTION\n275\t\n276\t# ⭐阶段0:并行段 flush 队列,主会话串行 commit(方案C,规避并发写 versions.json)\n277\tFUNCTION flush_commit_queue(stage_results_queue):\n278\t  FOR each (req, stage, result) IN stage_results_queue:\n279\t    commit_stage_transition(result)  # 串行提交,复用上方 prepare→commit→finalize\n280\t  END FOR\n281\t  CLEAR(stage_results_queue)\n282\tEND FUNCTION\n283\t```\n284\t\n285\t### Stage 9 循环策略解析与暂停持久化(P0)\n286\t\n287\t`step_mode.non_skippable["9"]` 只控制进入 Stage 9 前是否确认;测试失败后是否自动进入修复循环必须使用独立的 `loop_decision.mode`:\n288\t\n289\t```python\n290\tFUNCTION resolve_loop_decision_mode():\n291\t  config = LOAD_JSON_IF_EXISTS(".claude/config/dev-flow-interaction-config.json")\n292\t  IF config != null AND config.loop_decision.mode IN ["auto", "ask"] THEN\n293\t    RETURN config.loop_decision.mode\n294\t  END IF\n295\t  IF config != null AND config.step_mode.non_skippable["9"] == "auto_execute" THEN\n296\t    RETURN "auto"  # schema 1.0 兼容:保留旧配置的显式自动倾向\n297\t  END IF\n298\t  RETURN "ask"     # 无配置、解析失败、非法值均安全回退为询问\n299\tEND FUNCTION\n300\t\n301\tFUNCTION persist_stage_pause(stage_result):\n302\t  VALIDATE stage_result AGAINST contract.stage_result_schema\n303\t  # 只保存阻断现场,不将 Stage 9 标记为完成,也不推进 Stage 10\n304\t  原子写 context.md:\n305\t    stageOutputs["9"] = {status:"blocked",summary,artifacts,decisions,risks,contextUpdates,completedAt}\n306\t    decisionLog = append_dedupe(decisionLog, stage_result.decisions)\n307\t    openRisks = reconcile(openRisks, stage_result.risks)\n308\t    APPLY stage_result.context_updates 中通过白名单校验的字段\n309\t    loopDecisionMode = "ask"\n310\t    currentStage = "9"\n311\t    checkpointState = "clean"\n312\t    updatedAt = now\n313\t  原子写 versions.json:\n314\t    currentStage = "9"\n315\t    # lastCompletedStage/stageHistory 保持 Stage 8 及之前的值,不 append Stage 9\n316\t  原子写 version-context.md:\n317\t    requirementContextIndex[reqPrefix].currentStage = "9"\n318\t    requirementContextIndex[reqPrefix].status = "paused"\n319\t    requirementContextIndex[reqPrefix].lastCompletedStage = versions.json.lastCompletedStage\n320\t  # resume 后重新读取测试报告和 loop_decision.mode,再次进入 Stage 9 循环决策\n321\tEND FUNCTION\n322\t```\n323\t\n324\t**pending 恢复规则**:\n325\t\n326\t- context.checkpointId == versions.checkpointId:说明步骤2已提交,补执行 finalize。\n327\t- context 为 pending 且 versions.checkpointId 不同:权威控制面未提交,不推进阶段;保留 stageOutputs 候选结果,重新执行当前 stage 或由用户确认后重提交流转。\n328\t- versions 已推进但 context 缺 checkpoint:从 versions.json + 实际产物重建最小 stageOutputs,标记 `summary="recovered_from_artifacts"`,再 finalize。\n329\t- 禁止继续使用“仅比较 stageHistory 长度,较长者覆盖另一处”的旧规则。\n330\t\n331\t**阶段Agent映射表**:\n332\t\n333\t| 阶段 | 名称 | Agent/Skill | 版本模式可跳过 | BIZ API stage | progress |\n334\t|-----|------|------------|:------:|--------------|----------|\n335\t| 0 | 需求澄清 | req-clarification-orchestrator | ❌ | clarification | 3 |\n336\t| 1 | 需求分析 | req-xxx-analyzer | ❌ | requirement | 12 |\n337\t| 1.1 | 需求检视 | req-recheck-orchestrator | ✅ | requirement_review | 18 |\n338\t| 1.2 | 需求知识同步 | module-requirement-manager(Skill) | ✅ | requirement_review | 20 |\n339\t| 1.6 | 组件依赖分析 | component-dependency-analyzer-{lang}(Skill) | ✅ | requirement_review | 25 |\n340\t| 2 | 设计方案 | des-xxx | ❌ | design | 30 |\n341\t| 2.1 | 设计检视 | des-recheck-orchestrator | ✅ | design_review | 36 |\n342\t| 2.2 | 设计知识同步 | module-design-manager(Skill) | ✅ | design_review | 38 |\n343\t| 3 | 代码开发 | xxx-code-developer | ❌ | development | 50 |\n344\t| 3.1 | 代码知识同步 | module-code-manager(Skill) | ✅ | development | 55 |\n345\t| 3.2 | 代码部署前自检 ⭐v4.8 | {lang}-code-review | ✅ | development | 58 |\n346\t| 3.5 | 插件开发迭代评估循环 ⭐v4.9 G4 | plugin-dev-eval-loop(命令) | ✅(仅 dev_target=Agent/Skill/Command 触发,其他 dev_target 自动跳过) | development | 60 |\n347\t| 4 | 自动部署 | 编译验证(可跳过)+git-commit+git-push | ❌(版本模式) | deployment | 65 |\n348\t| 5 | 部署确认 | 用户手动确认 | ❌ | deployment_confirm | 70 |\n349\t| 5.5 | 测试用例澄清 | test-case-clarification-orchestrator | ❌ | testing | 75 |\n350\t| 6 | 测试验证 | functional-test-generator | ❌ | testing | 80 |\n351\t| 6.1 | 回归测试同步 | module-testing-manager(Skill) | ✅ | testing | 85 |\n352\t| 7 | 测试执行 | test-code-generator(Skill)→test-executor(Skill) | ❌ | test_execution | 90 |\n353\t| 8 | 测试报告 | test-report(Skill) | ❌ | test_report | 95 |\n354\t| 9 | 循环决策 | 动态选择:通过时退出/失败时req-fix-bug-analyzer | ❌ | test_report | 98 |\n355\t| 10 | 版本级回归测试 | 主会话内联执行(Read stage-10-version-regression.md) | ❌ | version_regression | 99 |\n356\t\n357\t**Agent通配符解析规则**(根据需求类型确定具体Agent名):\n358\t\n359\t| 需求类型 | Stage 1 需求分析Agent | Stage 2 设计Agent | Stage 3 开发Agent |\n360\t|---------|----------------------|-------------------|-------------------|\n361\t| NEW | req-new-feature-analyzer | des-new-feature | 动态选择(见下方Stage 3 Agent选择规则) |\n362\t| ENHANCE | req-enhance-feature-analyzer | des-enhance-feature | 同上 |\n363\t| FIX | req-fix-bug-analyzer | des-fix-bug | 同上 |\n364\t| OPTIMIZE | req-optimize-analyzer | des-optimize | 同上 |\n365\t| REFACTOR | req-refactor-analyzer | des-refactor | 同上 |\n366\t| INTEGRATE | req-integrate-analyzer | des-integrate | 同上 |\n367\t\n368\t**Agent通配符解析规则(Stage 3.2 代码部署前自检)**⭐v4.8:\n369\t\n370\t| techStack 包含 | subagent_type 解析为 |\n371\t|---------------|---------------------|\n372\t| Java / Kotlin / Spring Boot | `java-code-review` |\n373\t| Python | `python-code-review` |\n374\t| Go | `go-code-review` |\n375\t| 其他 | 自动跳过(auto_skipped_unsupported_tech) |\n376\t\n377\t**Skill通配符解析规则**(根据项目技术栈确定具体Skill名):\n378\t\n379\t| 阶段 | 通配符 | 解析规则 |\n380\t|-----|--------|---------|\n381\t| 1.6 | component-dependency-analyzer-{lang} | 读取project-context.json的techStack字段 → 映射:Java→-java, Python→-python, Go→-go;无法判定时AskUserQuestion让用户选择 |\n382\t\n383\t**Stage 3 Agent选择规则**(🆕 替代原有"开发语言判定"单一逻辑):\n384\t\n385\tStep 1: 确定后端Agent(基于项目语言)\n386\t  读取project-context.json的techStack字段,或AskUserQuestion询问用户\n387\t  → 映射:Java→java-code-developer | Python→python-code-developer | Go→go-code-developer | TypeScript/NestJS→typescript-code-developer\n388\t  → backend_agent = 映射结果\n389\t  ⚠️ 纯前端项目(无后端文件pom.xml/go.mod/requirements.txt/pyproject.toml/nest-cli.json)→ backend_agent = null\n390\t\n391\tStep 2: 判断是否需要前端Agent\n392\t  2a. 读取 function_attributes、frontend_type 以及在 Stage 2 中用户选择的前端开发方式 frontendDevMode\n393\t    来源优先级(🆕 三级兜底,兑现行461"需求文档解析回退"承诺):\n394\t    1. context.md YAML frontmatter(主来源)\n395\t       - functionAttributes: context.md中的functionAttributes字段\n396\t       - frontendDevMode: context.md中的frontendDevMode字段(值为 "local_generation" 或 "remote_platform")\n397\t    2. 🆕 若 context.md functionAttributes 为空 → 解析需求文档提取"功能属性"字段\n398\t       路径:版本模式 docs/{versionName}/requirements/REQ-{NN}_{需求名}_需求.md;单需求模式 docs/{branch}/requirements/{需求名}_需求.md\n399\t       提取规则:读取需求文档"功能属性"表格行(模板格式 `| 功能属性 | [前端] [后端] [数据] |`),按勾选项填充 functionAttributes\n400\t    3. 🆕 若仍空 → 触发下方 2b 空值硬守卫(AskUserQuestion 强制确认)\n401\t  2b. 🆕 IF function_attributes 为空([]或不存在)→ 硬守卫(防线2):\n402\t    AskUserQuestion("功能属性为空,无法决策前端Agent,请确认本需求是否涉及前端",\n403\t      options: ["仅后端(不触发前端Agent)", "含前端(触发前端Agent)"])\n404\t    → 根据用户选择写入 context.md functionAttributes("仅后端"→["后端"],"含前端"→["前端","后端"])\n405\t    → 按新值继续走 2c/2d 分支\n406\t    → ⚠️ 禁止以空值进入 Agent 选择决策(防空值误判纯后端、漏选前端 Agent)\n407\t  2c. IF function_attributes不包含"前端" →\n408\t    IF backend_agent != null → selected_agents = [backend_agent]\n409\t    ELSE → OUTPUT: "❌ 纯前端项目但function_attributes不含\'前端\',请检查需求属性" → 中止\n410\t    END IF\n411\t    → 跳到Step 3\n412\t  2d. IF function_attributes包含"前端" → 优先根据上一阶段(Stage 2)用户确认的前端开发方式选择执行的 Agent:\n413\t    - IF frontendDevMode == "remote_platform" (远程平台API代理方式) → \n414\t      frontend_agent = "frontend-code-developer"\n415\t      IF backend_agent != null → selected_agents = [backend_agent, frontend_agent]\n416\t      ELSE → selected_agents = [frontend_agent]\n417\t      END IF\n418\t    - IF frontendDevMode == "local_generation" (本地代码生成模式) → \n419\t      frontend_agent = "web-frontend-developer"\n420\t      IF backend_agent != null → selected_agents = [backend_agent, frontend_agent]\n421\t      ELSE → selected_agents = [frontend_agent]\n422\t      END IF\n423\t    - IF frontendDevMode 为空或无法获取(降级兼容逻辑) → 执行项目前端代码检测:\n424\t      - 检测package.json是否存在且包含react/vue/angular/svelte依赖\n425\t      - 检测前端源码目录是否存在(src/main/frontend/、frontend/、web/、client/等)\n426\t      → has_frontend_code = 检测结果\n427\t      - IF has_frontend_code == false →\n428\t        selected_agents = [backend_agent]\n429\t        IF frontend_type == "前端+后台web API" →\n430\t          OUTPUT: "⚠️ 需求含前端属性但项目无前端代码。仅执行后端开发。"\n431\t        END IF\n432\t      - IF has_frontend_code == true →\n433\t        IF 纯前端项目(有前端依赖 + 无后端文件pom.xml/go.mod等)→ frontend_agent = "web-frontend-developer"\n434\t        ELSE → frontend_agent = "frontend-code-developer"\n435\t        END IF\n436\t        IF backend_agent != null → selected_agents = [backend_agent, frontend_agent]\n437\t        ELSE → selected_agents = [frontend_agent]\n438\t        END IF\n439\t      END IF\n440\t  END IF\n441\t\n442\tStep 3: 确定执行顺序和完成判定\n443\t  - selected_agents仅1个 → 标准串行执行(当前逻辑不变)\n444\t  - selected_agents有2个 → 串行执行:先启动后端Agent,完成后启动前端Agent\n445\t  - 完成判定(见下方Stage 3多Agent完成判定规则)\n446\t\n447\t⚠️ claude-code-developer的P0互斥规则不变:\n448\t  IF dev_target包含Agent/Skill/Command → selected_agents = ["claude-code-developer"] → 跳过Step 1-3\n449\t\n450\t**⚠️ Stage 4 版本模式不可跳过**:git-commit+git-push是代码入库必须环节,版本模式下必须执行。\n451\t\n452\t**⛔ Claude Code 仓库边界(P0)**:Stage 4 提交前必须执行 `git status --short` 并显式排除根目录 `.agents/`。禁止使用会把未跟踪文件整体纳入的 `git add .`/`git add -A`;只允许按本需求实际变更路径逐项 `git add -- `。若 `.agents/` 已被意外暂存,必须先从暂存区移除再提交,且不得修改其内容。\n453\t\n454\t**⭐阶段3 多git(H1修正:需求级仓库提交)**:Stage4在S1段execute_serial_segment每需求各自执行。多git下每需求提交**该需求所属仓库**(非遍历所有仓库):\n455\t```\n456\tIF 版本配置.isMultiGit THEN\n457\t    # 需求级:该需求所属仓库(H1修正:用req.repositoryId,非FOR each repo遍历)\n458\t    repo = FIND 版本配置.repositories WHERE gitUrl == req.repositoryId\n459\t    IF repo 存在 THEN\n460\t        bash(f"cd {repo.localPath}")  # 切换到该需求仓库目录\n461\t        bash("git status --short")    # 仓库边界(排除.agents/)\n462\t        bash(f\'git add -- {该需求变更路径}\')\n463\t        bash(f\'git commit -m "#AI commit# 需求{req.name}仓库{repo.gitUrl}提交"\')\n464\t        bash(f"git push origin {repo.branchName}")\n465\t    ELSE\n466\t        save_pending_item(skip_reason="REPOSITORY_NOT_FOUND", context_description=f"需求{req.name}仓库{req.repositoryId}未找到")\n467\t    END IF\n468\tELSE\n469\t    # 单git:现有流程(git add/commit/push origin,上述仓库边界约束)\n470\tEND IF\n471\t```\n472\t\n473\t## 逐阶段执行流程\n474\t\n475\t> ⭐阶段0 形态B:本节 WHILE+FOR 是**单需求执行单元**,被 execute_serial_segment 的 execute_single_stage 调用(串行段内单需求单阶段11步)。形态B段调度(execute_segments)是外层编排,本节循环体(步骤0-11)不变。单需求版本(非多需求)时,execute_segments 退化为直接进入本节 WHILE+FOR(向后兼容)。\n476\t\n477\t对每个需求,按STAGE_ORDER顺序逐阶段执行:\n478\t\n479\t```\n480\tcycle_count = 0\n481\tMAX_CYCLES = 10\n482\t\n483\tWHILE cycle_count < MAX_CYCLES:\n484\t  FOR each stage IN REQUIREMENT_STAGE_ORDER:\n485\t    stageExecutionSkipped = false  # 仅用于Stage 1.1/2.1:跳过检视Agent但仍执行后置Hook\n486\t    0. 构造 stage_context(每阶段实时刷新,首次启动与resume共用):\n487\t       - 读取 versions.json 当前版本与需求对象\n488\t       - 读取 context.md YAML frontmatter\n489\t       - 读取 version-context.md 版本快照与 requirementContextIndex\n490\t       - 扫描 docs/{versionName}/ 下属于当前 reqPrefix/任务名的已存在产物\n491\t       - 按 dev-flow-context-contract.json 的 stage_contracts[{stage}].consumes 选取字段\n492\t       - 校验 immutable_identity_fields;任一冲突立即中止,不得静默覆盖\n493\t       - 若 context.md.checkpointState == "pending",先执行下方 checkpoint 恢复规则,完成前禁止启动新阶段\n494\t    1. 状态持久化(双写一致)⭐v4.9:将 currentStage={stage} **同时写入两处**,保持原子同步:\n495\t       - versions.json 该需求的 currentStage 字段(恢复读取的权威源)\n496\t       - context.md YAML frontmatter 的 currentStage 字段(保持与 versions.json 一致)\n497\t       ⚠️ 两处必须同步写入,禁止只写一处。双写保证研发流程层(dev-flow 本地状态)进度严格一致,\n498\t          消除 versions.json/context.md 双存储点漂移(历史问题:单写 versions.json 导致 context.md currentStage 悬空)。\n499\t\n500\t       **context.md 写回方式**(参照 functional-test-generator,保留其他字段不变):\n501\t       ```\n502\t       context_path = dev/versions/{versionName}/active/{task_name}/context.md\n503\t       IF context_path 存在 THEN\n504\t           读取 context_path 的 YAML frontmatter(--- 与 --- 之间的部分)\n505\t           新增/更新字段:currentStage: "{stage}"\n506\t           写回 context_path(保留 YAML 其他字段 + Markdown 正文不变)\n507\t       ELSE\n508\t           跳过 context.md 写入(仅写 versions.json,context.md 将由后续阶段创建)\n509\t       END IF\n510\t       ```\n511\t       **versions.json 写回方式**:更新该需求对象的 currentStage 字段,保留其他字段不变。\n512\t       **version-context.md 写回方式**:刷新 requirementContextIndex.{reqPrefix}.currentStage/contextRevision/status="running"。\n513\t    2. 🛡️ BIZ API同步(版本模式):\n514\t       biz_api_url = 从versions.json该需求的biz_api_url字段读取;若为空则从环境变量BIZ_API_BASE获取\n515\t       biz_task_id = 从versions.json该需求的biz_task_id字段读取\n516\t       调用 mcp__biz-sync__biz_sync_stage(biz_api_url=biz_api_url, biz_task_id=biz_task_id, stage={stage_name}, progress={progress})\n517\t       ⚠️ 使用safe_biz_sync包装器(失败时自动记录save_pending_item,不打扰用户)。详见req-type-classifier.md"safe_biz_sync"定义\n518\t    3. 判断可跳过:\n519\t       IF 该阶段"版本模式可跳过" == ✅ THEN\n520\t         # ⭐项目级交互配置:从项目级配置文件读取(来源:P4.5写入的 .claude/config/dev-flow-interaction-config.json;版本模式/单需求模式统一从文件读取,保证恢复场景一致)\n521\t         interaction_config = LOAD_JSON_IF_EXISTS(".claude/config/dev-flow-interaction-config.json")  # 文件不存在或JSON解析失败时返回null(向后兼容)\n522\t         stage_decision = null\n523\t         IF interaction_config != null THEN\n524\t           IF execution_mode == "分步模式" THEN\n525\t             stage_decision = interaction_config.step_mode.skippable.get({stage})\n526\t           ELSE  # 快速模式\n527\t             stage_decision = interaction_config.fast_mode.skippable.get({stage})\n528\t           END IF\n529\t         END IF\n530\t\n531\t         IF stage_decision == "skip" THEN\n532\t           # 按项目级配置自动跳过(不询问用户)\n533\t           记录 skipDecisions[{stage}] = "skipped_by_config" 到 versions.json\n534\t           🛡️ 调用 mcp__biz-sync__biz_sync_session(biz_api_url=biz_api_url, biz_task_id=biz_task_id, content="{stage_name}按配置跳过", stage={stage_name}, progress={progress})\n535\t              ⚠️ 使用safe_biz_sync包装器(失败时自动记录save_pending_item,不打扰用户)\n536\t           IF stage IN [1.1, 2.1] THEN\n537\t             stageExecutionSkipped = true\n538\t             输出 "ℹ️ Stage {stage}按项目级配置跳过检视,仅跳过检视Agent和本地优化交互;继续执行该阶段后置Hook"\n539\t           ELSE\n540\t             commit_stage_transition({stage,status:"skipped",summary:"按项目级配置跳过",artifacts:[],decisions:["skipped_by_config"],risks:[],context_updates:{}})\n541\t             CONTINUE(推进到下一阶段)\n542\t           END IF\n543\t         ELIF stage_decision == "execute" THEN\n544\t           # 按项目级配置自动执行(不询问用户)\n545\t           记录 skipDecisions[{stage}] = "executed_by_config" 到 versions.json\n546\t         ELSE\n547\t           # stage_decision == "ask" 或 interaction_config == null(无配置):沿用原有询问逻辑(向后兼容)\n548\t           使用 AskUserQuestion 询问用户是否执行(默认沿用skipDecisions历史决策)\n549\t           IF 用户选择跳过 THEN\n550\t             记录 skipDecisions[{stage}] = "skipped" 到 versions.json\n551\t             🛡️ 调用 mcp__biz-sync__biz_sync_session(biz_api_url=biz_api_url, biz_task_id=biz_task_id, content="{stage_name}已跳过", stage={stage_name}, progress={progress})\n552\t                ⚠️ 使用safe_biz_sync包装器(失败时自动记录save_pending_item,不打扰用户)\n553\t             IF stage IN [1.1, 2.1] THEN\n554\t               stageExecutionSkipped = true\n555\t               输出 "ℹ️ 用户选择跳过Stage {stage}检视,仅跳过检视Agent和本地优化交互;继续执行该阶段后置Hook"\n556\t             ELSE\n557\t               commit_stage_transition({stage,status:"skipped",summary:"用户选择跳过",artifacts:[],decisions:["skipped"],risks:[],context_updates:{}})\n558\t               CONTINUE(推进到下一阶段)\n559\t             END IF\n560\t           ELSE\n561\t             记录 skipDecisions[{stage}] = "executed" 到 versions.json\n562\t           END IF\n563\t         END IF\n564\t       END IF\n565\t    4. 阶段前置特殊步骤:\n566\t       IF stage == 2 THEN\n567\t         【前置步骤0:Stage1-Hook 幂等确认】⭐v4.8\n568\t         IF stage1HookDone != true THEN\n569\t           补执行 Stage1-Hook(B1)(沿用既有容错,失败转 pending)\n570\t           执行后置 versions.json 该需求 stage1HookDone = true\n571\t         ELSE\n572\t           输出 "ℹ️ Stage1-Hook 已执行过(stage1HookDone=true),跳过"\n573\t         END IF\n574\t       END IF\n575\t       IF stage == 3 THEN\n576\t         【前置步骤0:Stage2-Hook 幂等确认】⭐v4.8\n577\t         IF stage2HookDone != true THEN\n578\t           补执行 Stage2-Hook(B2/B3)(沿用既有容错,失败转 pending)\n579\t           执行后置 versions.json 该需求 stage2HookDone = true\n580\t         ELSE\n581\t           输出 "ℹ️ Stage2-Hook 已执行过(stage2HookDone=true),跳过"\n582\t         END IF\n583\t         【前置步骤1:Agent选择决策(🆕)】\n584\t         执行上方"Stage 3 Agent选择规则"Step 1-3\n585\t         → 确定:selected_agents(有序列表,如["java-code-developer"]、["java-code-developer","frontend-code-developer"]、["web-frontend-developer"])\n586\t         → 将selected_agents写入context.md的selectedDevAgents字段\n587\t       ELIF stage == 1.6 THEN\n588\t         【前置步骤:组件依赖分析器语言选择】\n589\t         执行上方"Skill通配符解析规则"中阶段1.6的解析逻辑\n590\t         → 读取project-context.json的techStack字段\n591\t         → IF techStack包含"Java" → skill_name = "component-dependency-analyzer-java"\n592\t         → ELIF techStack包含"Python" → skill_name = "component-dependency-analyzer-python"\n593\t         → ELIF techStack包含"Go" → skill_name = "component-dependency-analyzer-go"\n594\t         → ELSE AskUserQuestion("无法自动判定项目语言,请选择组件依赖分析器",\n595\t             ["Java项目", "Python项目", "Go项目"])\n596\t             → 根据选择确定skill_name\n597\t         END IF\n598\t       ELIF stage == 3.2 THEN\n599\t         【前置步骤1:技术栈分发 + 硬守卫】⭐v4.8\n600\t         读取project-context.json的techStack字段\n601\t         IF techStack 包含 ("Java" OR "Kotlin" OR "Spring Boot") THEN\n602\t           subagent_type_3_2 = "java-code-review"\n603\t         ELIF techStack 包含 "Python" THEN\n604\t           subagent_type_3_2 = "python-code-review"\n605\t         ELIF techStack 包含 "Go" THEN\n606\t           subagent_type_3_2 = "go-code-review"\n607\t         ELSE\n608\t           OUTPUT: "ℹ️ 当前项目技术栈({techStack})暂不支持代码部署前自检(仅支持 Java/Kotlin/Python/Go),自动跳过 Stage 3.2"\n609\t           记录 skipDecisions["3.2"] = "auto_skipped_unsupported_tech" 到 versions.json\n610\t           🛡️ 调用 safe_biz_sync(content="Stage 3.2 自动跳过(技术栈不支持)", stage="development", progress=58)\n611\t           commit_stage_transition({stage:"3.2",status:"skipped",summary:"技术栈不支持代码部署前自检",artifacts:[],decisions:["auto_skipped_unsupported_tech"],risks:[],context_updates:{}})\n612\t           CONTINUE(推进到下一阶段)\n613\t         END IF\n614\t\n615\t         【前置步骤2:target_env 收集】\n616\t         AskUserQuestion(\n617\t           question: "Stage 3.2 代码部署前自检({subagent_type_3_2})的重点环境是?(影响多环境配置一致性检查)",\n618\t           header: "目标环境",\n619\t           options: [\n620\t             { label: "prod(生产)", description: "重点关注 prod 环境的配置完整性" },\n621\t             { label: "fat(联调)", description: "重点关注 fat 环境的配置完整性" },\n622\t             { label: "dev(开发)", description: "重点关注 dev 环境的配置完整性" },\n623\t             { label: "不指定(推荐)", description: "对比所有环境的配置,仅在所有环境都未声明且代码无默认值时报 critical" }\n624\t           ]\n625\t         )\n626\t         → 将选择追加到 Agent 调用 prompt:target_env=<用户选择,"不指定"时不传该参数>\n627\t\n628\t         【前置步骤3:Agent 调用参数构造】\n629\t         agent_prompt_extra = "【from_dev_flow】:true"\n630\t         IF target_env != "不指定" THEN agent_prompt_extra += "\\n【target_env】:" + target_env\n631\t         → 后续步骤6 Agent 调用(subagent_type=subagent_type_3_2)使用此 prompt 片段附加到标准 Prompt\n632\t       ELIF stage == 3.5 THEN\n633\t         【前置步骤1:dev_target 守卫】⭐v4.9 G4\n634\t         读取 context.md 的 dev_target 字段(来源:Stage 0 澄清 result)\n635\t         IF dev_target NOT IN ["Agent", "Skill", "Command"] THEN\n636\t           OUTPUT: "ℹ️ 当前需求 dev_target={dev_target},不触发 Stage 3.5 插件开发迭代评估循环,自动跳过"\n637\t           记录 skipDecisions["3.5"] = "auto_skipped_non_plugin_target" 到 versions.json\n638\t           🛡️ 调用 safe_biz_sync(content="Stage 3.5 自动跳过(非插件开发需求)", stage="development", progress=60)\n639\t           commit_stage_transition({stage:"3.5",status:"skipped",summary:"非插件开发需求",artifacts:[],decisions:["auto_skipped_non_plugin_target"],risks:[],context_updates:{}})\n640\t           CONTINUE(推进到下一阶段 Stage 4)\n641\t         END IF\n642\t\n643\t         【前置步骤2:插件路径与评估参数解析】\n644\t         plugin_path = Stage 3 claude-code-developer subagent 返回的插件生成路径\n645\t         target_type = LOWER(context.md.dev_target)(agent / skill / command)\n646\t         dataset_dir = plugin_path + "/evals"(默认)或 context.md.evals_dir(可选覆盖)\n647\t         max_iterations = 3(默认,可由 .claude/config/plugin-dev/plugin-dev-flow-rules.json 覆盖)\n648\t         pass_threshold = 0.8(默认,同上)\n649\t         → 后续步骤6 调用 /plugin-dev-eval-loop 命令,参数:\n650\t           /plugin-dev-eval-loop {plugin_path} --target-type {target_type} --dataset {dataset_dir} --max-iterations {max_iterations} --threshold {pass_threshold}\n651\t       END IF\n652\t    4.5 分步模式确认:IF execution_mode == "分步模式" AND stageExecutionSkipped != true THEN\n653\t         # ⭐项目级交互配置:从项目级配置文件读取 non_skippable 决策(仅分步模式生效;快速模式定义即auto_execute)\n654\t         interaction_config = LOAD_JSON_IF_EXISTS(".claude/config/dev-flow-interaction-config.json")  # 文件不存在或JSON解析失败时返回null(向后兼容)\n655\t         non_skip_decision = null\n656\t         IF interaction_config != null THEN\n657\t           non_skip_decision = interaction_config.step_mode.non_skippable.get({stage})\n658\t         END IF\n659\t\n660\t         IF non_skip_decision == "auto_execute" THEN\n661\t           # 按项目级配置自动执行(不询问)\n662\t           输出 "ℹ️ Stage {stage}按项目级配置自动执行"\n663\t         ELSE\n664\t           # non_skip_decision == "ask" 或 interaction_config == null(无配置):沿用原有询问逻辑(向后兼容)\n665\t           AskUserQuestion("即将执行Stage {stage}: {stage_name},是否继续?",\n666\t             ["继续执行", "跳过此阶段", "中止流程"])\n667\t           IF "跳过" →\n668\t             记录skipDecisions[{stage}]="skipped"\n669\t             IF stage IN [1.1, 2.1] THEN\n670\t               stageExecutionSkipped = true\n671\t               输出 "ℹ️ 分步模式选择跳过Stage {stage}检视,仅跳过检视Agent和本地优化交互;继续执行该阶段后置Hook"\n672\t             ELSE\n673\t               CONTINUE\n674\t             END IF\n675\t           IF "中止" → 更新currentStage为当前阶段 → EXIT WHILE\n676\t         END IF\n677\t       END IF\n678\t    4.6 Stage 5部署确认:IF stage == 5 THEN\n679\t         # 部署确认循环:用户选"已部署"时调用 mcp__sdp__get-pipeline 校验真实部署状态,\n680\t         # 校验未通过则回退重新询问;"部署失败"分支保持原逻辑不变 ⭐v4.9\n681\t         deploy_confirmed = false\n682\t         WHILE deploy_confirmed == false:\n683\t           AskUserQuestion("部署确认:代码已推送到远程仓库,请确认CI/CD部署状态",\n684\t             ["已部署,继续", "部署失败,需修复"])\n685\t           IF "部署失败,需修复" THEN\n686\t             # ⭐v4.10:改走统一回滚函数(修复原未清 stageHistory 的遗漏),保留"部署失败回代码开发"语义\n687\t             Read .claude/config/dev-flow-checklists/rollback.md\n688\t             execute_rollback(mode="auto", target_stage="3", reason="Stage5部署失败")\n689\t             BREAK FOR(回退到Stage 3重新开发,原语义不变)\n690\t           END IF\n691\t\n692\t           # ── 用户选"已部署,继续":获取 pipelineId(⭐阶段2 S11 E6:多子系统下用需求所属子系统pipelineId)──\n693\t           pipeline_id = None\n694\t           req_subsystem_id = req.reqSubsystemId  # 该需求所属子系统(第1阶段D12)\n695\t           IF req_subsystem_id 非空 AND 版本配置.subsystems 存在 THEN\n696\t               sub = FIND 版本配置.subsystems WHERE subsystemId == req_subsystem_id\n697\t               IF sub THEN pipeline_id = sub.pipelineId\n698\t           END IF\n699\t           IF pipeline_id 为空 THEN pipeline_id = 版本配置.pipelineId  # 入口兜底(D11)\n700\t\n701\t           IF pipeline_id 为空 THEN\n702\t             # 决策1:无法校验,让用户决策\n703\t             AskUserQuestion("⚠️ 无法获取流水线ID(versions.json 的 pipelineId 为空),无法自动校验部署状态。如何处理?",\n704\t               ["信任用户判断,继续推进到测试", "回退到Stage 3重新开发"])\n705\t             IF "信任继续" THEN\n706\t               OUTPUT "ℹ️ 跳过流水线状态校验,按用户判断继续"\n707\t               deploy_confirmed = true\n708\t             ELIF "回退Stage 3" THEN\n709\t               重置 currentStage="3" -> BREAK FOR\n710\t             END IF\n711\t           ELSE\n712\t             # 决策2:调用 mcp__sdp__get-pipeline 校验(含工具异常重试,内层循环)\n713\t             mcp_done = false\n714\t             WHILE mcp_done == false:\n715\t               mcp_result = safe_call_mcp("mcp__sdp__get-pipeline", {"id": pipeline_id})\n716\t               IF mcp_result["success"] == false THEN\n717\t                 # MCP 工具调用异常(网络/认证/502,非部署状态判断)\n718\t                 AskUserQuestion("❌ 流水线状态查询工具调用失败:{mcp_result.error}(工具异常,非部署状态判断)。如何处理?",\n719\t                   ["重试调用", "跳过校验,继续推进到测试", "回退到Stage 3重新开发"])\n720\t                 IF "重试调用" THEN\n721\t                   CONTINUE(内层 WHILE,重新调用 mcp__sdp__get-pipeline)\n722\t                 ELIF "跳过校验继续" THEN\n723\t                   OUTPUT "ℹ️ 跳过流水线状态校验(工具异常),按用户判断继续"\n724\t                   deploy_confirmed = true\n725\t                   mcp_done = true\n726\t                 ELIF "回退Stage 3" THEN\n727\t                   重置 currentStage="3" -> BREAK FOR\n728\t                 END IF\n729\t               ELSE\n730\t                 mcp_done = true\n731\t                 # 判断 data.lastestTrigger.status(大小写不敏感,实际返回大写 SUCCESS)\n732\t                 status = UPPER(mcp_result["result"]["data"]["lastestTrigger"]["status"])\n733\t                 IF status == "SUCCESS" THEN\n734\t                   OUTPUT "✅ 流水线部署校验通过(lastestTrigger.status=SUCCESS)"\n735\t                   deploy_confirmed = true\n736\t                 ELIF status == "RUNNING" THEN\n737\t                   # 决策3:流水线仍在执行中\n738\t                   OUTPUT "⏳ 流水线正在部署中(lastestTrigger.status=RUNNING),尚未完成,请稍后再次确认"\n739\t                   CONTINUE(外层 WHILE,重新询问用户是否部署成功)\n740\t                 ELSE\n741\t                   # FAILURE 等其他非 SUCCESS 状态\n742\t                   OUTPUT "❌ 流水线部署未成功(lastestTrigger.status={status}),请确认后再次选择"\n743\t                   CONTINUE(外层 WHILE,重新询问用户是否部署成功)\n744\t                 END IF\n745\t               END IF\n746\t             END WHILE\n747\t           END IF\n748\t         END WHILE\n749\t         # deploy_confirmed == true -> 推进到 Stage 5.5\n750\t       END IF\n751\t    4.7 Stage 5.5测试用例澄清前置:IF stage == 5.5 THEN\n752\t         【前置步骤:澄清上下文准备】\n753\t         - 确保【已有产物路径】包含需求文档 + 设计文档(此阶段测试用例尚未生成)\n754\t         - 确保【context.md路径】可读(含 functionAttributes/frontendType,供澄清Agent复用,不重新识别)\n755\t         - 将【测试用例生成输入摘要】注入 prompt:代码变更/接口定义/Feature文件/需求文档/project-context 的路径\n756\t         ⚠️ Stage 5.5 不可跳过(不进 skipDecisions 询问),由 test-case-clarification-orchestrator 在主对话执行多轮澄清\n757\t       END IF\n758\t    5. 构造阶段Prompt(见下方"阶段Prompt构造规则")\n759\t       IF stageExecutionSkipped == true THEN\n760\t         跳过Prompt构造(仅Stage 1.1/2.1跳过检视时使用;后续仍执行对应后置Hook)\n761\t       END IF\n762\t    6. 启动Subagent:\n763\t       - IF stageExecutionSkipped == true THEN\n764\t         输出 "ℹ️ 已跳过Stage {stage}检视Agent,继续执行该阶段后置Hook"\n765\t         → 跳到步骤8(不启动检视Agent,不执行本阶段优化交互)\n766\t       - ELIF stage == 3 AND len(selected_agents) >= 1 THEN\n767\t         IF len(selected_agents) == 1 THEN\n768\t           标准串行执行:Agent(subagent_type: selected_agents[0], prompt: 构造的Prompt)\n769\t         ELSE\n770\t           【多Agent串行执行】\n771\t           stage3_completed = []\n772\t           stage3_failed = []\n773\t           FOR each agent IN selected_agents:\n774\t             构造Agent专属Prompt:\n775\t               - 后端Agent: 【设计文档路径】:{后端设计.md或设计.md},【开发范围】:后端(Controller/Service/Entity等)\n776\t               - 前端Agent: 【设计文档路径】:{前端设计.md},【开发范围】:前端(页面/组件/API封装等)\n777\t             Agent(subagent_type: agent, prompt: 构造的Prompt)\n778\t             IF 成功 → stage3_completed.append(agent)\n779\t             IF 失败 → stage3_failed.append(agent),继续下一个Agent(不中止)\n780\t           END FOR\n781\t           【Stage 3多Agent完成判定规则】\n782\t           IF len(stage3_failed) == 0 THEN\n783\t             → Stage 3全部完成,推进到Stage 3.1\n784\t           ELIF len(stage3_completed) > 0 THEN\n785\t             → 部分完成\n786\t             AskUserQuestion("Stage 3部分完成:✅{stage3_completed} ❌{stage3_failed},如何处理?",\n787\t               ["继续下一阶段(忽略失败Agent)", "重试失败Agent", "中止流程"])\n788\t           ELSE\n789\t             → 全部失败,按现有容错模式处理\n790\t           END IF\n791\t         END IF\n792\t       - ELSE(其他阶段):\n793\t         从映射表获取该阶段的Agent/Skill列值\n794\t         IF 映射值包含"(命令)"后缀 THEN  ⭐v4.9 G4 新增\n795\t           命令类型阶段:通过 Skill 工具调用(Claude Code 中 slash 命令本质上是 Skill)\n796\t           去除"(命令)"后缀,获取实际命令名(如 plugin-dev-eval-loop)\n797\t           Skill(skill: 命令名, args: 构造的Prompt + 步骤4前置步骤2已解析的参数)\n798\t         ELIF 映射值包含"(Skill)"后缀 THEN\n799\t           Skill类型阶段:使用 Skill 工具\n800\t           IF 映射值包含"{lang}"(Skill通配符)THEN\n801\t             使用步骤4中已解析的skill_name(如component-dependency-analyzer-java)\n802\t             Skill(skill: skill_name, args: 构造的Prompt)\n803\t           ELIF 映射值包含"→"(多个Skill串行)THEN\n804\t             按"→"拆分为有序Skill列表\n805\t             FOR each skill IN 有序Skill列表:\n806\t               去除"(Skill)"后缀,获取实际skill名\n807\t               Skill(skill: skill名, args: 构造的Prompt)\n808\t             END FOR\n809\t           ELSE\n810\t             去除"(Skill)"后缀,获取实际skill名\n811\t             Skill(skill: skill名, args: 构造的Prompt)\n812\t           END IF\n813\t         ELSE\n814\t           Agent类型阶段:使用 Agent 工具\n815\t           IF 映射值 == "{lang}-code-review"(Stage 3.2 通配符)⭐v4.8 THEN\n816\t             使用步骤4中已解析的 subagent_type_3_2(java-code-review / python-code-review / go-code-review)\n817\t             Agent(subagent_type: subagent_type_3_2, prompt: 构造的Prompt + agent_prompt_extra)\n818\t           ELSE\n819\t             使用映射表静态值(subagent_type 从映射表获取,解析规则见映射表后"Agent通配符解析规则")\n820\t           END IF\n821\t         END IF\n822\t    7. 等待Subagent完成(stageExecutionSkipped == true 时无Subagent可等待)\n823\t    7.1 归一化阶段结果(所有 Agent/Skill/主会话内联阶段):\n824\t       - 优先解析返回文本中的 `dev_flow_stage_result` JSON 代码块\n825\t       - 校验 stage/status/summary/artifacts/decisions/risks/context_updates\n826\t       - stage 与当前阶段不一致 → 标记 failed,禁止推进\n827\t       - artifacts 中每个路径必须实际存在;不存在的路径移入 risks,不写 artifactIndex\n828\t       - summary 超过1000字时由主会话压缩,保留结论、变更和未决风险\n829\t       - 无结构化结果时,主会话从返回文本、git diff 与 docs 扫描合成,不因旧 Agent 不支持协议而中断\n830\t       - controller_only_fields 出现在 context_updates 时丢弃并输出警告\n831\t    7.3 ⚠️ 功能属性提取(仅Stage 0):\n832\t       IF stage == 0 THEN\n833\t         从subagent返回的澄清结果中提取function_attributes和frontend_type\n834\t         → 更新context.md YAML frontmatter:\n835\t           functionAttributes: {提取值,如["前端","后端"]或["后端"]}\n836\t           frontendType: {提取值,如"纯前端"或"前端+后台web API",无前端属性则""}\n837\t         → 提取方法(优先级从高到低):\n838\t           1. subagent输出中的结构化字段(JSON/表格中"功能属性"行)\n839\t           2. subagent输出文本中的关键词匹配("功能属性"后跟"前端/后端/数据")\n840\t           3. 若以上均失败:functionAttributes留空 → 🆕 防线1 强制兜底(禁止留空进入 Stage 1):\n841\t              AskUserQuestion("Stage 0 未能从澄清结果提取功能属性,请显式确认本需求涉及的功能属性",\n842\t                options: ["前端", "后端", "前端+后端", "前端+后端+数据"])\n843\t              → 根据用户选择写入 context.md functionAttributes(如"前端+后端"→["前端","后端"])\n844\t              → ⚠️ 禁止留空,必须写入非空值\n845\t              → Stage 3 前置步骤1 的 2a 三级兜底(context.md→需求文档解析→2b硬守卫)作为二级保障\n846\t       END IF\n847\t    7.5 ⚠️ 数据属性阻断回退检查(仅Stage 0):\n848\t       IF stage == 0 AND subagent返回包含 {action: "restart_from_requirement_input", reason: "data_attribute_detected"}:\n849\t         → OUTPUT: "🚫 检测到数据开发属性(ETL场景),当前暂不支持数据开发Agent,回退到需求描述环节"\n850\t         → 清除当前需求的澄清结果(versions.json中重置该需求的currentStage和stageHistory)\n851\t         → BREAK FOR(退出当前STAGE_ORDER循环)\n852\t         → 回退到前置步骤之前,提示用户重新输入需求描述(重新执行P1-P7 + STAGE_ORDER)\n853\t       END IF\n854\t    7.6 ⚠️ Stage 1.1 用户优化决策处理(仅Stage 1.1):\n855\t       IF stage == 1.1 AND stageExecutionSkipped != true AND subagent返回的recheckReport存在 THEN\n856\t         主对话向用户展示报告摘要(综合评分/结构检查/优化建议数量)\n857\t         AskUserQuestion 五选项:\n858\t           1 ✅ 执行全部优化(critical + recommended + optional)\n859\t           2 🔶 执行必要优化(critical + recommended)\n860\t           3 🔸 仅执行必须修改(critical)\n861\t           4 ❌ 跳过优化,保持原文档\n862\t           5 📋 查看详细检视报告\n863\t         WHILE 用户选择 == 5(查看详细报告):\n864\t           showDetailedReport(recheckReport)\n865\t           重新 AskUserQuestion 五选项\n866\t         END WHILE\n867\t         IF 用户选择 ∈ [1, 2, 3] THEN\n868\t           根据选择确定优化范围 → optimizationsToExecute\n869\t           FOR each opt IN optimizationsToExecute:\n870\t             使用 Edit 工具按 opt.location 和 opt.suggestion 修改需求文档\n871\t           END FOR\n872\t           写入 versions.json: tasks[i].rechckDecisions["1.1"] = "applied"\n873\t           输出 "✅ 优化执行完成({N}项)"\n874\t         ELIF 用户选择 == 4 THEN\n875\t           保持原文档\n876\t           写入 versions.json: tasks[i].rechckDecisions["1.1"] = "skipped"\n877\t           输出 "ℹ️ 用户选择跳过优化,保持原需求文档"\n878\t         END IF\n879\t       END IF\n880\t    7.7 ⚠️ Stage 2.1 用户优化决策处理(仅Stage 2.1):\n881\t       IF stage == 2.1 AND stageExecutionSkipped != true AND subagent返回的recheckReport存在 THEN\n882\t         主对话向用户展示报告摘要(综合评分/质量维度/优化建议数量)\n883\t         AskUserQuestion 五选项:\n884\t           1 ✅ 执行全部优化(critical + recommended + optional)\n885\t           2 🔶 执行必要优化(critical + recommended)\n886\t           3 🔸 仅执行必须修改(critical)\n887\t           4 ❌ 跳过优化,保持原设计文档\n888\t           5 📋 查看详细检视报告\n889\t         WHILE 用户选择 == 5(查看详细报告):\n890\t           showDetailedReport(recheckReport)\n891\t           重新 AskUserQuestion 五选项\n892\t         END WHILE\n893\t         IF 用户选择 ∈ [1, 2, 3] THEN\n894\t           根据选择确定优化范围 → optimizationsToExecute\n895\t           FOR each opt IN optimizationsToExecute:\n896\t             使用 Edit 工具按 opt.location 和 opt.suggestion 修改设计文档\n897\t           END FOR\n898\t           写入 versions.json: tasks[i].rechckDecisions["2.1"] = "applied"\n899\t           输出 "✅ 设计文档优化执行完成({N}项)"\n900\t         ELIF 用户选择 == 4 THEN\n901\t           保持原设计文档\n902\t           写入 versions.json: tasks[i].rechckDecisions["2.1"] = "skipped"\n903\t           输出 "ℹ️ 用户选择跳过优化,保持原设计文档"\n904\t         END IF\n905\t       END IF\n906\t    7.8 ⚠️ 提取subagent结构化输出(仅Stage 7):\n907\t       IF stage == 7 THEN\n908\t         从subagent返回结果中提取 event_type 字段\n909\t         event_type提取规则(按优先级):\n910\t           1. 优先读取subagent返回的结构化字段 event_type(test-executor v4.7+提供)\n911\t           2. 若无结构化字段,从测试验证结果报告解析:\n912\t              - 全部通过(0失败)→ event_type = "test_passed"\n913\t              - 存在失败用例 → event_type = "test_failed"\n914\t              - Bug已修复验证通过 → event_type = "bug_fixed"\n915\t           3. 若仍无法判定 → AskUserQuestion("无法自动判定测试结果,请选择",\n916\t              ["test_passed(全部通过)", "test_failed(存在失败)", "bug_fixed(Bug已修复)"])\n917\t         ⚠️ event_type 提取失败时禁止跳过后续步骤8.3!\n918\t       END IF\n919\t    8. 执行阶段后置动作 — 主队列(详见下方各Stage-Hook伪代码,此处仅列出清单)\n920\t       IF stage == 1 THEN 无主队列动作(Stage1-Hook已后移至Stage 1.1节点结束后,避免需求检视/修复前提前同步)\n921\t       ELIF stage == 1.1 THEN Read下方Stage1-Hook(B1)伪代码 → 逐项执行(无论Stage 1.1检视执行或跳过,均执行一次)→ 执行后置 stage1HookDone=true ⭐v4.8\n922\t       ELIF stage == 2.1 THEN Read下方Stage2-Hook(B2/B3)伪代码 → 逐项执行(无论Stage 2.1检视执行或跳过,均执行一次)→ 执行后置 stage2HookDone=true ⭐v4.8\n923\t       ELIF stage == 3 THEN 无主队列动作(B4已移至独立步骤8.1)\n924\t       ELIF stage == 6 THEN Read下方Stage6-Hook(B5)伪代码 → 逐项执行(⚠️ 仅B5,不含B5.5)\n925\t       ELIF stage == 7 THEN Read下方Stage7-Hook(B6/B7)伪代码 → 逐项执行(⚠️ 仅B6/B7,不含B7.5)\n926\t       ELIF stage == 9 THEN 无主队列动作(终态同步在FOR循环结束后的循环决策中条件执行,见下方"Stage 9循环决策"伪代码)\n927\t       ELSE 无后置动作\n928\t       END IF\n929\t    8.1 ⚠️ 执行 B4:系统需求转提测 + 提示词安全防护(仅Stage 3)— 独立步骤,不可跳过\n930\t       IF stage == 3 THEN Read下方Stage3-Hook(B4)伪代码 → 逐项执行(含DPMS转提测+提示词安全防护)\n931\t         IF story_id 为空 THEN\n932\t           save_pending_item(mcp_method="mcp__sdp__deliver-story", skip_reason="STORY_ID_EMPTY")\n933\t         ELSE\n934\t           调用 mcp__sdp__deliver-story({"storyId": story_id, "optUserName": "{当前用户}", "action": "转提测"})\n935\t           IF 成功 → 输出 "✅ 开发完成已同步到DPMS(Story ID: {story_id},已转提测)"\n936\t           IF 失败 → save_pending_item(skip_reason="MCP_FAILED")\n937\t         END IF\n938\t       END IF\n939\t    8.2 ⚠️ 执行 B5.5:测试用例评审(仅Stage 6)— 独立步骤,不可跳过\n940\t       IF stage == 6 AND product_id AND release_plan_id AND story_id THEN\n941\t         调用 mcp__tctp-dpms-set__savaTestCaseReview({\n942\t           "productId": product_id, "releasePlanId": release_plan_id,\n943\t           "reviewName": "测试用例评审-{task_name}", "storyId": story_id,\n944\t           "createUser": "{当前用户}", "reviewResult": "通过",\n945\t           "reviewOpinion": "测试用例同步后自动评审"\n946\t         })\n947\t         IF 失败 AND 错误码为1003/状态不满足 THEN\n948\t           输出 "⚠️ 测试评审失败(错误码1003),补执行B4转提测..."\n949\t           调用 mcp__sdp__deliver-story({"storyId": story_id, "optUserName": "{当前用户}", "action": "转提测"})\n950\t           IF 补执行成功 THEN\n951\t             重试 mcp__tctp-dpms-set__savaTestCaseReview({...同上参数...})\n952\t             IF 重试失败 → save_pending_item(skip_reason="B4_RECOVERY_RETRY_FAILED")\n953\t           ELSE\n954\t             save_pending_item(skip_reason="B4_RECOVERY_FAILED",\n955\t               context_description="Stage6-Hook(B5.5):补执行B4转提测失败,测试评审无法创建")\n956\t           END IF\n957\t         ELIF 失败 → save_pending_item(skip_reason="MCP_FAILED")\n958\t       ELIF stage == 6 AND NOT (product_id AND release_plan_id AND story_id) THEN\n959\t         missing = []\n960\t         IF NOT product_id THEN missing.append("product_id")\n961\t         IF NOT release_plan_id THEN missing.append("release_plan_id")\n962\t         IF NOT story_id THEN missing.append("story_id")\n963\t         save_pending_item(mcp_method="mcp__tctp-dpms-set__savaTestCaseReview", skip_reason="PARAMS_INCOMPLETE",\n964\t           context_description="Stage6-Hook(B5.5):测试用例评审跳过,缺少参数:{missing}")\n965\t       END IF\n966\t     8.3 ⚠️ 执行 B7.5:测试通过 → 用例流转(仅Stage 7)— 发送 HTTP POST 请求到 `http://10.107.100.21:3000/tctptest/chatbot/updateTestCaseStatus`\n967\t        ⚠️ 失败时按"HTTP POST调用容错模式"处理(见上方容错框架),save_pending_item的mcp_method使用MCP方法名以确保待补录重试可用\n968\t        IF stage == 7 AND event_type == "test_passed" THEN\n969\t          从本地缓存加载 test_case_ids(mcp__biz-sync__load_testcase_id)\n970\t          IF test_case_ids 为空 THEN\n971\t            save_pending_item(mcp_method="mcp__tctp-dpms-set__updateTestCaseStatus", skip_reason="TEST_CASE_IDS_EMPTY")\n972\t          ELIF release_plan_id 为空 OR test_plan_id 为空 THEN\n973\t            save_pending_item(mcp_method="mcp__tctp-dpms-set__updateTestCaseStatus", skip_reason="RELEASE_PLAN_OR_TEST_PLAN_EMPTY")\n974\t          ELSE\n975\t            发送 HTTP POST 到 http://10.107.100.21:3000/tctptest/chatbot/updateTestCaseStatus:\n976\t              {\n977\t                "releasePlanId": release_plan_id,\n978\t                "testPlanId": test_plan_id,\n979\t                "operator": "{当前用户}",\n980\t                "testCaseList": [{"testCaseId": tc_id, "status": 3, "modifier": "{当前用户}", "runUser": "{当前用户}"} FOR tc_id IN test_case_ids]\n981\t              }\n982\t            IF 成功 → 输出 "✅ 测试用例已通过 HTTP 接口流转为通过"\n983\t            IF 失败 → 按"HTTP POST调用容错模式"处理 → save_pending_item(mcp_method="mcp__tctp-dpms-set__updateTestCaseStatus")\n984\t          END IF\n985\t        END IF\n986\t    8.4 ⚠️ 执行 Stage 3.2 自检结果决策(仅Stage 3.2)⭐v4.8 — 独立步骤,不可跳过\n987\t       IF stage == 3.2 THEN\n988\t         从 {subagent_type_3_2} Agent(java-code-review / python-code-review / go-code-review 之一)返回的最终文本中解析 JSON 块(包裹在 ```json ... ``` 代码块中)\n989\t         读取关键字段:review_status / critical_remaining / high_remaining / manual_items / changed_files / should_block_deploy\n990\t\n991\t         IF JSON 解析失败 THEN\n992\t           OUTPUT: "⚠️ Stage 3.2 {subagent_type_3_2} Agent 返回无法解析为 JSON,按容错处理:默认不阻断部署"\n993\t           记录 versions.json[currentVersion].codeReviewResult = { status: "json_parse_failed", agent: subagent_type_3_2, completedAt: "" }\n994\t           commit_stage_transition({stage:"3.2",status:"completed",summary:"自检结果JSON解析失败,按兼容策略不阻断部署",artifacts:[],decisions:["proceed_on_parse_failure"],risks:["code_review_result_unparsed"],context_updates:{codeReviewResult:{status:"json_parse_failed",agent:subagent_type_3_2}}})\n995\t           CONTINUE(推进到 Stage 4)\n996\t         END IF\n997\t\n998\t         IF review_status IN ("skipped_non_java", "skipped_non_python", "skipped_non_go") THEN\n999\t           OUTPUT: "ℹ️ Stage 3.2 已由 {subagent_type_3_2} Agent 内部技术栈守卫跳过"\n1000\t           记录 versions.json[currentVersion].codeReviewResult = JSON返回值\n1001\t           commit_stage_transition({stage:"3.2",status:"skipped",summary:"代码自检Agent技术栈守卫跳过",artifacts:[],decisions:[review_status],risks:[],context_updates:{codeReviewResult:JSON返回值}})\n1002\t           CONTINUE(推进到 Stage 4)\n1003\t         END IF\n1004\t\n1005\t         IF should_block_deploy == true THEN\n1006\t           AskUserQuestion(\n1007\t             question: "Stage 3.2 代码自检({subagent_type_3_2})发现 {critical_remaining} 个 critical 问题未修复,是否仍进入自动部署?",\n1008\t             header: "部署阻断决策",\n1009\t             options: [\n1010\t               { label: "返回修复(推荐)", description: "回退到 Stage 3 让 Agent 重新生成代码,或人工修复后再次执行 Stage 3.2" },\n1011\t               { label: "强制进入部署", description: "已了解风险(启动可能炸),按用户判断继续 git-commit + git-push" },\n1012\t               { label: "中止流程", description: "退出版本开发循环,保留已有产物" }\n1013\t             ]\n1014\t           )\n1015\t           IF "返回修复" THEN\n1016\t             # ⭐v4.10:改走统一回滚函数\n1017\t             Read .claude/config/dev-flow-checklists/rollback.md\n1018\t             execute_rollback(mode="auto", target_stage="3", reason="Stage3.2代码自检阻断")\n1019\t             BREAK FOR\n1020\t           END IF\n1021\t           IF "强制进入部署" → 记录 versions.json[currentVersion].codeReviewResult = { ...JSON返回值, agent: subagent_type_3_2, override: "force_proceed_with_risk", overrideAt: "" } → commit_stage_transition({stage:"3.2",status:"completed",summary:"用户确认带风险进入部署",artifacts:[],decisions:["force_proceed_with_risk"],risks:["code_review_block_overridden"],context_updates:{codeReviewResult:JSON返回值}}) → CONTINUE\n1022\t           IF "中止流程" → 更新currentStage="3.2" → EXIT WHILE\n1023\t         ELSE\n1024\t           记录 versions.json[currentVersion].codeReviewResult = { ...JSON返回值, agent: subagent_type_3_2 }\n1025\t           OUTPUT: "✅ Stage 3.2 自检通过({subagent_type_3_2}):auto_fixed={auto_fixed}, manual_items={manual_items}, changed_files={len(changed_files)}"\n1026\t           commit_stage_transition({stage:"3.2",status:"completed",summary:"代码部署前自检通过",artifacts:changed_files,decisions:[],risks:manual_items,context_updates:{codeReviewResult:JSON返回值}})\n1027\t           CONTINUE(推进到 Stage 4)\n1028\t         END IF\n1029\t       END IF\n1030\t    8.5 ⚠️ 执行 Stage 3.5 插件开发迭代评估循环(仅 Stage 3.5)⭐v4.9 G4 — 独立步骤,dev_target 守卫已在步骤4前置步骤1完成\n1031\t       IF stage == 3.5 THEN\n1032\t         调用 /plugin-dev-eval-loop 命令(参数由步骤4前置步骤2构造)\n1033\t         从命令返回结果解析 exit_code 与 eval_summary:\n1034\t         - exit_code=0(达标)→ 记录 versions.json[currentVersion].pluginEvalResult = { status: "passed", ...eval_summary } → commit_stage_transition({stage:"3.5",status:"completed",summary:"插件迭代评估达标",artifacts:golden_fixture_paths,decisions:[],risks:[],context_updates:{pluginEvalResult:eval_summary}}) → OUTPUT: "✅ Stage 3.5 评估达标(pass_rate={pass_rate}),Golden Fixture 已沉淀" → CONTINUE(推进到 Stage 4)\n1035\t         - exit_code=1(未达标/迭代超限)→ AskUserQuestion("Stage 3.5 评估循环未达标(max_iterations={max_iterations} 已耗尽),如何处理?", 选项=["降级到 Stage 4(推荐)", "中止流程人工介入"]) → IF "降级" → 记录 pluginEvalResult = { status: "fallback_max_iter", ... } → commit_stage_transition({stage:"3.5",status:"completed",summary:"评估未达标,用户确认降级继续",artifacts:[],decisions:["fallback_max_iter"],risks:["plugin_eval_not_passed"],context_updates:{pluginEvalResult:eval_summary}}) → CONTINUE;IF "中止" → 更新currentStage="3.5" → EXIT WHILE\n1036\t         - exit_code=2(评估引擎不可用/数据集不存在)→ OUTPUT: "⚠️ Stage 3.5 评估引擎不可用,自动降级到 Stage 4" → 记录 pluginEvalResult = { status: "engine_unavailable", ... } → commit_stage_transition({stage:"3.5",status:"completed",summary:"评估引擎不可用,按规则降级继续",artifacts:[],decisions:["engine_unavailable_fallback"],risks:["plugin_eval_engine_unavailable"],context_updates:{pluginEvalResult:eval_summary}}) → CONTINUE\n1037\t         - exit_code=3(参数错误)→ OUTPUT: "❌ Stage 3.5 参数错误:{error_msg}" → 更新currentStage="3.5" → EXIT WHILE\n1038\t         END IF\n1039\t       END IF\n1040\t    9. 🛡️ BIZ API同步(版本模式):调用 mcp__biz-sync__biz_sync_session(biz_api_url=biz_api_url, biz_task_id=biz_task_id, content="{stage_name}完成", stage={stage_name}, progress={progress})\n1041\t       ⚠️ 使用safe_biz_sync包装器(失败时自动记录save_pending_item,不打扰用户)\n1042\t    10. IF stage == 9 THEN\n1043\t          stage9_candidate_result = stage_result\n1044\t          # Stage 9 的完成提交延迟到下方循环决策;此处不得 append stageHistory\n1045\t          BREAK FOR\n1046\t        ELSE\n1047\t          调用 `commit_stage_transition(stage_result)`,统一更新 versions.json/context.md/version-context.md;禁止直接单写 stageHistory\n1048\t        END IF\n1049\t    11. 推进到 REQUIREMENT_STAGE_ORDER 下一项\n1050\t  END FOR\n1051\t\n1052\t  # Stage 9循环决策(FOR循环结束后;loop_decision 独立于执行模式)\n1053\t  loop_decision_mode = resolve_loop_decision_mode()\n1054\t  更新 context.md.loopDecisionMode = loop_decision_mode\n1055\t  读取测试报告,判断:\n1056\t  IF 所有测试通过且无缺陷 THEN\n1057\t    commit_stage_transition({stage:"9",status:"completed",summary:"所有测试通过且无缺陷",artifacts:stage9_candidate_result.artifacts,decisions:["tests_passed"],risks:[],context_updates:{cycleDecision:"proceed_to_stage_10",loopDecisionMode:loop_decision_mode}})\n1058\t    🛡️ 调用 mcp__biz-sync__biz_sync_stage(biz_api_url=biz_api_url, biz_task_id=biz_task_id, stage="completed", progress=100, status="completed")\n1059\t    ⚠️ 使用safe_biz_sync包装器(失败时自动记录save_pending_item,不打扰用户)\n1060\t    OUTPUT: "✅ 全流程完成,退出循环"\n1061\t    # 🆕 v4.9 新增:所有需求 Stage 9 通过后,触发 Stage 10 版本级回归测试\n1062\t    # ⭐阶段0 形态B:本 WHILE+FOR 是单需求执行单元。Stage10 触发分两种情况:\n1063\t    #   - 单需求版本(非形态B):本路径直接 GOTO Stage 10\n1064\t    #   - 多需求形态B:本需求 D段完成(update_segment_progress(req,"D","completed")),由外层\n1065\t    #     execute_segments 的 V段 wait_segment_barrier("D") 等所有需求 D段通过后统一触发 Stage10\n1066\t    #     (禁止本路径直接 GOTO Stage10 绕过 V段屏障,否则多需求下会漏屏障)\n1067\t    IF 形态B多需求模式 THEN\n1068\t        update_segment_progress(req, "D", "completed")\n1069\t        EXIT WHILE  # 本需求 D段完成,交外层 execute_segments V段屏障统一触发 Stage10\n1070\t    ELSE\n1071\t        GOTO Stage 10(版本级回归测试,详见 stage-10-version-regression.md)\n1072\t        # Stage 10 完成后才进入 complete-version\n1073\t        BREAK\n1074\t    END IF\n1075\t  ELSE IF 存在失败测试用例或缺陷 THEN\n1076\t    failure_summary = 从测试报告提取失败用例数、缺陷数、关键失败原因和报告路径\n1077\t    OUTPUT: "⚠️ Stage 9 检测到测试失败:{failure_summary}"\n1078\t\n1079\t    IF loop_decision_mode == "ask" THEN\n1080\t      AskUserQuestion(\n1081\t        question: "Stage 9 检测到失败测试或缺陷。是否进入下一轮修复?\\n{failure_summary}",\n1082\t        header: "循环决策",\n1083\t        options: [\n1084\t          {label: "进入下一轮修复(推荐)", description: "生成 bug fix 子需求,回滚到 Stage 1 并重新执行开发测试流程"},\n1085\t          {label: "暂停循环,保留现场", description: "停留在 Stage 9,不生成修复需求;恢复流程时再次询问"}\n1086\t        ]\n1087\t      )\n1088\t      IF 用户选择 "暂停循环,保留现场" THEN\n1089\t        persist_stage_pause({stage:"9",status:"blocked",summary:"测试失败,用户选择暂停循环",artifacts:stage9_candidate_result.artifacts,decisions:["pause_for_manual_intervention"],risks:[failure_summary],context_updates:{cycleDecision:"manual_pause",loopDecisionMode:"ask"}})\n1090\t        🛡️ 调用 safe_biz_sync(content="Stage 9 测试失败,用户暂停修复循环", stage="testing", progress=95)\n1091\t        OUTPUT: "⏸️ 已暂停在 Stage 9 并保留失败现场;恢复 dev-flow 时将重新询问"\n1092\t        EXIT WHILE\n1093\t      END IF\n1094\t      cycle_decision = "user_confirmed_fix_loop"\n1095\t    ELSE\n1096\t      cycle_decision = "auto_fix_loop"\n1097\t      OUTPUT: "🔄 循环策略为 auto,将自动进入下一轮修复"\n1098\t    END IF\n1099\t\n1100\t    cycle_count += 1\n1101\t    OUTPUT: "🔄 开始第{cycle_count}次修复循环"\n1102\t    调用 req-fix-bug-analyzer 生成bug fix子需求\n1103\t    fix_requirement_summary = 提取 bug fix 子需求摘要与产物路径\n1104\t    # ⭐阶段2 S11 E4 D2修正:原需求不回滚(保持Stage9),标记blocked;bugfix子需求纳入下一轮段调度\n1105\t    # 形态B下回滚会破坏段屏障(其他需求可能在D段已通过),改为blocked+退出+resume\n1106\t    commit_stage_transition({stage:"9",status:"blocked",summary:"测试失败,原需求blocked,bugfix子需求纳入下一轮",artifacts:stage9_candidate_result.artifacts + fix_requirement_summary.artifacts,decisions:[cycle_decision,"blocked_for_fix"],risks:[failure_summary],context_updates:{cycleDecision:cycle_decision,fixRequirementSummary:fix_requirement_summary.summary,loopDecisionMode:loop_decision_mode}})\n1107\t    # bugfix子需求加入版本需求列表(currentStage=0,segmentProgress全pending,参与下一轮execute_segments)\n1108\t    版本配置.requirements.append(fix_requirement_summary.子需求对象)\n1109\t    # ⭐D2修正:不再 execute_rollback(target=1)(规避段屏障破坏);标记该需求D段blocked,退出当前WHILE\n1110\t    update_segment_progress(req, "D", "blocked")\n1111\t    OUTPUT: "⚠️ 需求[{req.task_name}]Stage9失败已blocked,bugfix子需求已生成"\n1112\t    OUTPUT: "请执行【继续开发】恢复:已完成需求跳过已完成段,bugfix子需求从P1开始"\n1113\t    EXIT WHILE  # 退出单需求WHILE,交外层execute_segments(V段屏障判定含blocked)\n1114\t  END IF\n1115\tEND WHILE\n1116\t\n1117\tIF cycle_count >= MAX_CYCLES THEN\n1118\t  OUTPUT: "⚠️ 已达最大循环次数({MAX_CYCLES}),强制退出"\n1119\t  AskUserQuestion("已达到最大循环次数,如何处理?",\n1120\t    ["强制退出(保留已有产物)", "继续循环(再给10次机会)"])\n1121\tEND IF\n1122\t```\n1123\t\n1124\t## 阶段Prompt构造规则\n1125\t\n1126\t每个阶段的subagent prompt包含:\n1127\t\n1128\t```\n1129\t{需求描述}\n1130\t【输入来源】:version_mode\n1131\t【上下文契约】:.claude/config/dev-flow-context-contract.json(version=1.0)\n1132\t【上下文修订号】:{contextRevision}\n1133\t【版本ID】:{versionName}\n1134\t【项目路径】:{project_path}                ← v2.4 GEP自进化核心关联点(skill 调 gep_recall/record_outcome 的 project_path 取此值,project_name 取 basename)\n1135\t【项目名】:{projectName}                  ← v2.4 项目路径 basename(= GEP project_name,作 projects/{name}/ 存储目录名)\n1136\t【需求编号】:REQ-{reqIndex的2位零填充}(如REQ-01)\n1137\t【DPMS Story ID】:{dpmsStoryId}\n1138\t【DPMS产品ID】:{productId}\n1139\t【DPMS产品名称】:{productName}\n1140\t【版本测试集ID】:{testSetId}\n1141\t【发布计划ID】:{releasePlanId}\n1142\t【当前阶段】:{stage} - {stage_name}\n1143\t(BIZ API同步由主会话负责,subagent无需处理。biz_api_url从环境变量BIZ_API_BASE获取,biz_task_id={biz_task_id}仅用于错误追踪标识)\n1144\t【执行模式】:{execution_mode}\n1145\t【工作目录】:dev/versions/{versionName}/active/{task_name}/\n1146\t【代码工作目录】:{req_repository_localPath}(⭐阶段3:多git时需求所属仓库localPath;单git时=pwd)\n1147\t【输出目录】:docs/{versionName}/\n1148\t【版本上下文路径】:dev/versions/{versionName}/version-context.md\n1149\t【文档路径变量】:{branch} = {versionName}(版本模式下所有 docs/{branch}/ 路径替换为 docs/{versionName}/,subagent 优先使用此注入值,单需求模式无此注入时回退 git branch --show-current)\n1150\t【已有产物路径】:{该需求已生成的所有文档路径列表}\n1151\t【上一已完成阶段】:{lastCompletedStage}\n1152\t【上一阶段摘要】:{prior_stage_summary}\n1153\t【当前阶段输入】:{按 stage_contracts[stage].consumes 选择并序列化的字段;缺失必填输入必须显式标记}\n1154\t【已确认决策】:{与当前阶段相关的 decisionLog 子集}\n1155\t【未关闭风险】:{与当前阶段相关的 openRisks 子集}\n1156\t【竞品分析摘要】:{competitor_analysis_summary}\n1157\t【价值收益摘要】:{value_benefit_summary}       ← P3.5收集,若用户跳过P3.5,值为"(用户跳过价值收益评估)"\n1158\t【context.md路径】:dev/versions/{versionName}/active/{task_name}/context.md\n1159\t【功能属性】:{functionAttributes}              ← 仅当stage>=1且functionAttributes非空时注入\n1160\t【前端类型】:{frontendType}                    ← 仅当stage>=1且frontendType非空时注入\n1161\t\n1162\t【阶段结果回传协议】:完成后必须返回以下 JSON 代码块;不得直接修改 currentStage/stageHistory 等控制字段。\n1163\t~~~json dev_flow_stage_result\n1164\t{"stage":"{stage}","status":"completed|skipped|blocked|failed","summary":"不超过1000字","artifacts":[{"type":"artifact_type","path":"实际存在的路径"}],"decisions":[],"risks":[],"context_updates":{}}\n1165\t~~~\n1166\t```\n1167\t\n1168\t**文档落盘路径约束(P0)**:\n1169\t- 所有交付文档(需求/设计/接口/测试)落盘必须以【输出目录】`docs/{versionName}/` 为根\n1170\t- 【工作目录】`dev/versions/{versionName}/active/{task_name}/` 仅存放 context.md/cycle-state.json 等状态文件\n1171\t- 禁止在【工作目录】下创建 requirements/design/api/testing 子目录存放交付文档\n1172\t- 构造 subagent prompt 时,文档路径必须用【输出目录】+ 子目录,不得用【工作目录】+ 子目录\n1173\t\n1174\t**已有产物路径**:以 context.md 的 artifactIndex 为主,docs/ 目录扫描为校验与补全;不得仅依据 stageHistory 推断文件存在。\n1175\t\n1176\t**最小披露原则**:主会话只注入 `stage_contracts[stage].consumes` 声明的上下文字段。禁止把 versions.json、完整 context.md 或其他需求上下文整包复制给 subagent;Stage 10 仅接收版本聚合摘要和所选模块。\n1177\t\n1178\t**结果兼容策略**:旧 Agent/Skill 未返回 `dev_flow_stage_result` 时,由主会话合成同结构结果后再 checkpoint;兼容不等于跳过产物存在性和身份校验。\n1179\t\n1180\t**条件性参数**:当context.md的functionAttributes非空时,从Stage 1起注入【功能属性】和【前端类型】。Stage 0不注入(此时尚未产生)。\n1181\t\n1182\t**Stage 5.5 专属说明(测试用例澄清)**:\n1183\t- subagent 为 `test-case-clarification-orchestrator`,在主对话执行多轮澄清后**自行写盘**纪要到 `docs/{versionName}/testing/{需求名}_测试澄清.md`(版本模式加 REQ-NN_ 前缀),并更新 context.md 的 testClarificationPath/testScope/environmentInfo。\n1184\t- ⚠️ Stage 5.5 **不进 DPMS Hook 主队列**(步骤8中无 stage==5.5 分支):测试用例尚不存在,B5(addTestCase/关联测试集/关联系统需求)必须留在 Stage 6。\n1185\t- Stage 6 prompt 构造时,从 context.md 读取 testClarificationPath,作为【测试澄清纪要路径】注入 functional-test-generator(纪要不存在则 functional-test-generator 按降级逻辑处理)。\n1186\t\n1187\t## 阶段后置动作映射表\n1188\t\n1189\t| 阶段 | 后置动作 |\n1190\t|-----|---------|\n1191\t| 1 | 无主队列后置动作(Stage1-Hook已后移至Stage 1.1节点结束后,避免需求检视/修复前提前同步) |\n1192\t| 1.1 | Stage1-Hook(B1):execute_dpms_sync_hook + 图表同步检查 + **提示词注入风险识别**(仅Claude插件需求,调用/injection-risk-identifier,写入context.md的injection_risk字段)⭐v4.8;即使用户跳过Stage 1.1需求检视也必须执行一次;**执行后置 stage1HookDone=true ⭐v4.8** |\n1193\t| 2 | 无主队列后置动作(Stage2-Hook已后移至Stage 2.1节点结束后,避免设计检视/修复前提前同步) |\n1194\t| 2.1 | Stage2-Hook(B2/B3):execute_design_stage_hook(B2:SDL三步流程+三选项交互 + B3:转开发)+ 图表同步检查 + **提示词安全设计**(调用/injection-defense-designer,追加到设计文档末尾)+ **接口文档生成**(涉及新增/变更Web API时,调用/api-doc-generator生成 OpenAPI yaml + Markdown 接口文档到 docs/{versionName}/api/,同源原子(要么都生成要么都不生成))⭐v4.8;即使用户跳过Stage 2.1设计检视也必须执行一次;**执行后置 stage2HookDone=true ⭐v4.8** |\n1195\t| 3 | 步骤8.1(B4):execute_dev_complete_hook — 独立步骤,不在步骤8主队列中 + **提示词安全防护**(调用/injection-guard-prompter,写入Prompt文件安全边界章节)⭐v4.8 |\n1196\t| 3.2 | 步骤8.4:execute_code_review_decision — 根据 techStack 动态分发到 java-code-review / python-code-review / go-code-review,解析 Agent 返回的 JSON,should_block_deploy=true 时 AskUserQuestion 决策(返回修复 / 强制进入部署 / 中止流程);其他技术栈由前置步骤1硬守卫自动跳过 ⭐v4.8 |\n1197\t| 3.5 | 步骤8.5:execute_plugin_dev_eval_loop — 仅 dev_target=Agent/Skill/Command 触发(前置步骤1硬守卫),调用 /plugin-dev-eval-loop 命令执行迭代评估循环(max=3,pass_threshold=0.8),评估达标→CONTINUE Stage 4;评估未达标/迭代超限/评估引擎不可用→降级到 Stage 4(保证主流程不中断)⭐v4.9 G4 |\n1198\t| 4 | git-commit+git-push(已在阶段内执行) |\n1199\t| 6 | Stage6-Hook(B5) + 步骤8.2(B5.5):execute_test_case_hook + save_testcase_id + 独立步骤8.2测试评审 + **注入攻击测试**(调用/injection-attack-tester,生成注入测试报告)⭐v4.8 |\n1200\t| 7 | Stage7-Hook(B6/B7) + 步骤8.3(B7.5):execute_test_execution_hook + load_testcase_id + 独立步骤8.3用例流转 |\n1201\t| 9 | 无步骤8主队列动作(biz_sync_session由步骤9通用流程执行;biz_sync_stage标记completed在循环决策退出路径中条件执行,测试通过时才标记终态) |\n1202\t| 10 | 无步骤8主队列动作(Stage 10 为版本级阶段,在版本级 FOR 循环结束后触发,详见 stage-10-version-regression.md) |\n1203\t\n1204\t## 阶段后置动作执行指引(🚨 主会话必须遵循)\n1205\t\n1206\t⚠️ 以下为版本模式专属的后置动作。单需求模式仅执行图表同步检查和提示词注入防护(⭐v4.8),不执行DPMS Hook。\n1207\t\n1208\t**MCP调用容错模式**(所有Hook统一遵循,三层错误分类):\n1209\t```\n1210\t调用MCP方法 →\n1211\t  IF 成功 → 记录结果,输出成功消息\n1212\t  IF 网络不可用(连接超时/DNS失败/502/503/504)→\n1213\t    AskUserQuestion("MCP服务网络不可用:{描述}", 选项=["跳过并记录(推荐)","再试1次"])\n1214\t    IF "跳过并记录" → mcp__biz-sync__save_pending_item(skip_reason="NETWORK_UNAVAILABLE") → 返回跳过\n1215\t    IF "再试1次" → 重试1次,仍失败 → save_pending_item → 返回跳过\n1216\t  IF 认证/权限错误(401/403/unauthorized/forbidden)→\n1217\t    AskUserQuestion("MCP认证失败:{描述}\\n请检查VPN连接或MCP服务权限配置", 选项=["检查后重试(推荐)","跳过并记录"])\n1218\t    IF "检查后重试" → 重试1次,仍失败 → save_pending_item(skip_reason="AUTH_ERROR") → 返回跳过\n1219\t    IF "跳过并记录" → save_pending_item(skip_reason="AUTH_ERROR") → 返回跳过\n1220\t  IF 业务逻辑错误(参数错误/数据冲突等其他错误)→\n1221\t    AskUserQuestion("MCP调用业务错误:{描述}", 选项=["重试","跳过并记录","中止当前Hook"])\n1222\t    IF "重试" → 重试1次,仍失败 → 返回中止\n1223\t    IF "跳过并记录" → save_pending_item → 返回跳过\n1224\t    IF "中止" → 返回中止\n1225\t```\n1226\t\n1227\t**HTTP POST调用容错模式**(用于B7.5/B7 Step3的用例流转,三层错误分类):\n1228\t```\n1229\t发送HTTP POST请求 →\n1230\t  IF 成功(2xx响应)→ 记录结果,输出成功消息\n1231\t  IF 网络不可用(连接超时/DNS失败/连接拒绝)→\n1232\t    AskUserQuestion("HTTP服务网络不可用:{描述}", 选项=["跳过并记录(推荐)","再试1次"])\n1233\t    IF "跳过并记录" → mcp__biz-sync__save_pending_item(mcp_method="mcp__tctp-dpms-set__updateTestCaseStatus", skip_reason="NETWORK_UNAVAILABLE") → 返回跳过\n1234\t    IF "再试1次" → 重试1次,仍失败 → save_pending_item(mcp_method="mcp__tctp-dpms-set__updateTestCaseStatus") → 返回跳过\n1235\t  IF 认证/权限错误(401/403)→\n1236\t    AskUserQuestion("HTTP认证失败:{描述}\\n请检查VPN连接或服务权限配置", 选项=["检查后重试(推荐)","跳过并记录"])\n1237\t    IF "检查后重试" → 重试1次,仍失败 → save_pending_item(mcp_method="mcp__tctp-dpms-set__updateTestCaseStatus", skip_reason="AUTH_ERROR") → 返回跳过\n1238\t    IF "跳过并记录" → save_pending_item(mcp_method="mcp__tctp-dpms-set__updateTestCaseStatus", skip_reason="AUTH_ERROR") → 返回跳过\n1239\t  IF 业务逻辑错误(4xx/5xx等其他错误)→\n1240\t    AskUserQuestion("HTTP调用业务错误:{描述}", 选项=["重试","跳过并记录","中止当前Hook"])\n1241\t    IF "重试" → 重试1次,仍失败 → 返回中止\n1242\t    IF "跳过并记录" → save_pending_item(mcp_method="mcp__tctp-dpms-set__updateTestCaseStatus") → 返回跳过\n1243\t    IF "中止" → 返回中止\n1244\t```\n1245\t\n1246\t⚠️ HTTP POST容错模式中,save_pending_item的mcp_method统一使用MCP方法名`mcp__tctp-dpms-set__updateTestCaseStatus`(而非HTTP URL),确保待补录重试时可通过MCP工具补录。\n1247\t\n1248\t⚠️ 完整的safe_call_mcp容错框架定义见req-type-classifier.md"🛡️ MCP调用容错框架"章节(本处为精简版,逻辑一致)。\n1249\t\n1250\t---\n1251\t\n1252\t### 🛡️ Hook 幂等布尔标记(stage1HookDone / stage2HookDone)⭐v4.8\n1253\t\n1254\t**背景**:Stage1-Hook 原仅在经过 Stage 1.1 节点时触发,Stage2-Hook 原仅在经过 Stage 2.1 节点时触发。若用户手动改 currentStage、恢复误判或跳阶段(如直接进 Stage 2.1/Stage 3)绕过 1.1/2.1,会导致 Hook 漏执行(update-story / SDL / deliver-story 转开发缺失)。用两个布尔标记 + 下游关键阶段入口"确认并补执行"兜底。\n1255\t\n1256\t**字段(写入 versions.json 该需求对象)**:\n1257\t```json\n1258\t"stage1HookDone": false,\n1259\t"stage2HookDone": false\n1260\t```\n1261\t\n1262\t**布尔语义(P0 — 决定是否与待补录冲突)**:\n1263\t```\n1264\tstageXHookDone = true  当 Hook 被执行过一次(无论内部单个动作成功还是失败)。\n1265\t  - 成功的动作 → 完成\n1266\t  - 失败的动作 → 已由容错框架 save_pending_item 转入待补录\n1267\t  → 两种情况都视为"已执行",置 true\n1268\tstageXHookDone = false  当 Hook 从未被执行过。\n1269\t```\n1270\t\n1271\t**置位时机**:Hook 被调用执行后即置 true,不再判"是否全部成功"或"是否中止"。失败留给待补录重试。\n1272\t\n1273\t**与待补录(pending-sync)的关系(互补不冲突)**:\n1274\t| 机制 | 负责 | 粒度 |\n1275\t|------|------|------|\n1276\t| 布尔幂等 | 保证 Hook 本体只被触发一次 → 不重复调用、不重复写 pending | 整个 Hook |\n1277\t| pending-sync | 独立重试 Hook 内失败的单个 MCP 调用 | 单个动作 |\n1278\t\n1279\t已置 true 的 Hook 不会被补执行,因此不产生重复调用/重复 pending;失败的单个调用交由 pending-sync 重试。\n1280\t\n1281\t**Stage 1 与 Stage 2 兜底相互独立**:Stage 2 入口查 `stage1HookDone`,Stage 3 入口查 `stage2HookDone`,各自独立补执行,Stage2-Hook 本体不再前置补 Stage1-Hook。正常前进流程中 Stage 2 入口必先于 Stage 3 执行,故 stage1HookDone 已在 Stage 2 入口被保证。\n1282\t\n1283\t**调用点**:\n1284\t| 调用点 | 逻辑 |\n1285\t|--------|------|\n1286\t| Stage 1.1 后置动作(步骤8) | 执行 Stage1-Hook → 置 stage1HookDone=true |\n1287\t| Stage 2.1 后置动作(步骤8) | 执行 Stage2-Hook → 置 stage2HookDone=true |\n1288\t| Stage 2 前置(步骤4) | `IF stage1HookDone != true → 补执行 Stage1-Hook → 置 true` |\n1289\t| Stage 3 前置(步骤4,Agent选择前) | `IF stage2HookDone != true → 补执行 Stage2-Hook → 置 true` |\n1290\t\n1291\t---\n1292\t\n1293\t### Stage1-Hook(B1):需求文档最终确认后的DPMS同步 + 图表同步\n1294\t\n1295\t**触发**:Stage 1.1节点结束后(需求检视执行并完成本地优化后,或用户跳过需求检视后);或在 Stage 2 入口 `stage1HookDone != true` 时兜底补执行 ⭐v4.8。Stage 1不再触发本Hook。执行后置 stage1HookDone=true,已为 true 则不重复执行。\n1296\t**参数来源**:\n1297\t- `story_id`:从versions.json该需求的`dpmsStoryId`字段读取\n1298\t- `requirement_doc_path`:从Stage 1产物路径获取(Stage 1.1若采纳优化,则该路径内容已是优化后的最终需求文档)\n1299\t- `version_id`:{versionName}\n1300\t- `task_name`:需求名称\n1301\t\n1302\t**执行逻辑**:\n1303\t```\n1304\tIF story_id 非空 THEN\n1305\t  读取需求文档内容 → requirement_content\n1306\t\n1307\t  # ⭐v4.11 content 改为四章节关键信息提取(替代 v4.8 全文 markdown_to_html 转换)\n1308\t  # 背景:全文转换产出冗长 HTML、DPMS 展示噪声大,且依赖可能被 DPMS 过滤的 
    /
    /
    /class 标签\n1309\t  # 新方案:LLM 按章节映射语义提取关键信息 -> 固化 HTML 模板组装 -> 只用 

    /

    /

    • 规避 DPMS 白名单\n1310\t # 输入无论是 Markdown 还是 HTML,统一走 extract_dpms_sections(LLM 语义提取,容忍章节标题变体如"一、"/"1."/"1. "/纯文字")\n1311\t\n1312\t # Step 1: 按章节映射提取关键信息(LLM 语义提取,非正则切片;提取不到走兜底占位,不留空)\n1313\t extracted = extract_dpms_sections(requirement_content):\n1314\t section_1_需求背景:\n1315\t 来源: 需求文档「一、需求背景」\n1316\t 提取: 业务背景 + 痛点 + 价值 + 需求范围,压缩为 3-5 条要点\n1317\t 兜底: 提取不到 -> "需求背景见原文档"\n1318\t section_2_需求描述与设计:\n1319\t 来源: 「二、核心流程」+「三、功能需求」合并\n1320\t 提取: 核心流程概述(不含 mermaid 源码,只描述流程文字)+ 功能点清单(ID/名称/优先级,每点一行)\n1321\t 兜底: 流程或功能缺一则只填存在的部分;都缺 -> "需求描述见原文档"\n1322\t section_3_后台技术设计:'}] + +**AI**: +已获得核心的"阶段Agent映射表"和"形态B段调度"。现在读取单需求模式、启动版本需求前置、Stage 10 三个清单文件,确认两条流程在 stage 上的差异和前置步骤涉及的 agent/skill。... + + +## 交互记录 (2026-07-27T09:23:53.478Z) + +**用户**: +[{'tool_use_id': 'call_83b32dc0aa8745c18e52d522', 'type': 'tool_result', 'content': '1\t# 单需求模式执行步骤\n2\t\n3\t> 来源:dev-flow.md "语法1-8" + "执行步骤(情况1-5)" + "环节跳过机制" + "循环决策"章节\n4\t> 用途:执行单需求模式操作时必须Read本文件,按步骤逐项执行\n5\t\n6\t### 语法1:启动新的开发任务\n7\t```\n8\t/dev-flow <需求描述>\n9\t```\n10\t\n11\t**示例**:\n12\t```\n13\t/dev-flow 实现SSH操作信息持久化到数据库\n14\t/dev-flow 修复登录接口返回500错误\n15\t/dev-flow 优化用户列表查询性能,响应时间从2s降到500ms\n16\t```\n17\t\n18\t### 语法2:恢复未完成的任务(自动检测最新任务)\n19\t```\n20\t/dev-flow resume\n21\t```\n22\t\n23\t**不指定任务名称,自动恢复最新的未完成任务**。\n24\t\n25\t**适用场景**:\n26\t- 只有一个未完成任务\n27\t- 想快速恢复最近的任务\n28\t\n29\t### 语法3:查看任务状态\n30\t```\n31\t/dev-flow status\n32\t```\n33\t\n34\t列出所有进行中和已暂停的任务。\n35\t\n36\t**示例**:\n37\t```bash\n38\t/dev-flow status\n39\t```\n40\t\n41\t### 语法4:恢复指定的未完成任务\n42\t```\n43\t/dev-flow resume [task-name]\n44\t```\n45\t\n46\t**指定任务名称,精确恢复指定任务**。\n47\t\n48\t**示例**:\n49\t```\n50\t/dev-flow resume ssh-operation-log\n51\t```\n52\t\n53\t**适用场景**:\n54\t- 有多个未完成任务\n55\t- 明确知道要恢复哪个任务\n56\t\n57\t**注意**:如果不指定任务名称(仅使用 `resume`),将自动检测最近的未完成任务。\n58\t\n59\t### 语法5:从DPMS系统需求启动 🆕\n60\t```\n61\t/dev-flow --story --product \n62\t```\n63\t\n64\t**从DPMS系统获取系统需求并启动开发流程**。\n65\t\n66\t**示例**:\n67\t```\n68\t/dev-flow --story 12345 --product 100\n69\t```\n70\t\n71\t**参数说明**:\n72\t- `--story `: 系统需求ID\n73\t- `--product `: 产品ID\n74\t\n75\t**执行流程**:\n76\t1. 调用 `get_story_info_with_content` MCP获取系统需求详情\n77\t2. 将需求内容作为输入进行需求分析\n78\t3. 用户确认需求文档后,调用 `update_story` MCP更新系统需求\n79\t4. 继续后续流程(设计→开发→测试)\n80\t\n81\t### 语法6:从DPMS业务需求启动 🆕\n82\t```\n83\t/dev-flow --business-story --product --department \n84\t```\n85\t\n86\t**从DPMS系统获取业务需求并启动开发流程**。\n87\t\n88\t**示例**:\n89\t```\n90\t/dev-flow --business-story 67890 --product 100 --department 50\n91\t```\n92\t\n93\t**参数说明**:\n94\t- `--business-story `: 业务需求ID\n95\t- `--product `: 产品ID\n96\t- `--department `: 业务部门ID\n97\t\n98\t**执行流程**:\n99\t1. 调用 `get_business_story_info_with_content` MCP获取业务需求详情\n100\t2. 将需求内容作为输入进行需求分析\n101\t3. 用户确认需求文档后:\n102\t - 先调用 `update_business_story` MCP更新业务需求\n103\t - 再调用 `add_story` MCP创建新的系统需求\n104\t4. 继续后续流程(设计→开发→测试)\n105\t\n106\t### 语法7:修改已完成任务的需求/设计 🆕\n107\t```\n108\t/dev-flow modify --task --from --requirement-doc [--design-doc ]\n109\t```\n110\t\n111\t**对已完成需求或设计阶段的任务进行修改,在原有文档基础上更新**。\n112\t\n113\t**示例**:\n114\t```bash\n115\t# 从需求阶段重新开始,修改需求文档和设计文档\n116\t/dev-flow modify --task user-export --from requirement --requirement-doc docs/dev-zhaobincai/requirements/user-export_需求.md\n117\t\n118\t# 从设计阶段重新开始,只修改设计文档(需求文档保持不变)\n119\t/dev-flow modify --task user-export --from design --requirement-doc docs/dev-zhaobincai/requirements/user-export_需求.md --design-doc docs/dev-zhaobincai/design/user-export_设计.md\n120\t```\n121\t\n122\t**参数说明**:\n123\t| 参数 | 必填 | 说明 |\n124\t|-----|:----:|------|\n125\t| `--task ` | ✅ | 要修改的任务名称(已有任务目录名) |\n126\t| `--from ` | ✅ | 从哪个阶段重新开始,可选值:`requirement` 或 `design` |\n127\t| `--requirement-doc ` | ✅ | 已有的需求文档路径(相对于项目根目录) |\n128\t| `--design-doc ` | ⚪ | 已有的设计文档路径(当 `--from design` 时必填) |\n129\t\n130\t**阶段说明**:\n131\t| 阶段值 | 说明 | 必需文档 | 文档处理方式 |\n132\t|-------|------|---------|------------|\n133\t| `requirement` | 从需求澄清开始重新执行 | 需求文档 | 需求文档在原有基础上修改,设计文档后续也会被修改 |\n134\t| `design` | 从设计阶段开始重新执行 | 需求文档 + 设计文档 | 需求文档保持不变,设计文档在原有基础上修改 |\n135\t\n136\t**执行流程**:\n137\t\n138\t#### 流程A:从需求阶段开始(--from requirement)\n139\t1. 验证需求文档路径是否存在\n140\t2. 读取任务上下文(如存在)\n141\t3. 主会话按STAGE_ORDER从Stage 0开始逐阶段控制,subagent prompt增加修改模式参数:\n142\t - `【模式】:modify(修改模式)`\n143\t - `【修改起点】:requirement(需求阶段)`\n144\t - `【已有需求文档路径】:`\n145\t4. Stage 0/1:基于已有需求文档进行澄清和修改(使用Edit工具修改原文件)\n146\t5. Stage 2+:设计阶段修改原有设计文档而非新增,后续阶段正常执行\n147\t\n148\t#### 流程B:从设计阶段开始(--from design)\n149\t1. 验证需求文档和设计文档路径是否都存在\n150\t2. 读取任务上下文(如存在)\n151\t3. 主会话按STAGE_ORDER从Stage 2开始逐阶段控制,subagent prompt增加修改模式参数:\n152\t - `【模式】:modify(修改模式)`\n153\t - `【修改起点】:design(设计阶段)`\n154\t - `【已有需求文档路径】:`\n155\t - `【已有设计文档路径】:`\n156\t4. 需求文档保持不变(直接使用指定文档),设计阶段修改原有设计文档(使用Edit工具修改原文件),后续阶段正常执行\n157\t\n158\t**与 resume 的区别**:\n159\t| 命令 | 场景 | 文档处理 |\n160\t|-----|------|---------| \n161\t| `resume` | 恢复中断的任务 | 继续未完成的工作 |\n162\t| `modify` | 修改已完成的文档 | 在原有文档基础上修改 |\n163\t\n164\t### 语法8:查看已完成任务 🆕\n165\t```\n166\t/dev-flow completed [--limit ]\n167\t```\n168\t\n169\t**查看已完成的任务列表,支持任务归档机制**。\n170\t\n171\t**示例**:\n172\t```bash\n173\t# 查看所有已完成任务\n174\t/dev-flow completed\n175\t\n176\t# 查看最近10个已完成任务\n177\t/dev-flow completed --limit 10\n178\t```\n179\t\n180\t**参数说明**:\n181\t| 参数 | 必填 | 说明 |\n182\t|-----|:----:|------|\n183\t| `--limit ` | ⚪ | 限制返回数量,默认显示全部 |\n184\t\n185\t**实现逻辑**:\n186\t\n187\t```python\n188\tcompleted_tasks = []\n189\t\n190\t# 1. 扫描单需求轨已完成任务(仅 dev/active/,不含 dev/versions/)\n191\tFOR EACH directory IN dev/active/:\n192\t IF context.md EXISTS THEN\n193\t 任务状态 = extract_field(context.md, "任务状态")\n194\t IF 任务状态 == "已完成" THEN\n195\t ADD TO completed_tasks WITH status="未归档"\n196\t END IF\n197\t END IF\n198\tEND FOR\n199\t\n200\t# 2. 扫描 dev/completed/ 中的任务(已归档)\n201\tFOR EACH directory IN dev/completed/:\n202\t IF context.md EXISTS THEN\n203\t ADD TO completed_tasks WITH status="已归档"\n204\t END IF\n205\tEND FOR\n206\t\n207\t# 3. 按完成时间降序排序\n208\tSORT completed_tasks BY 完成时间 DESC\n209\t\n210\t# 4. 限制返回数量\n211\tIF limit EXISTS THEN\n212\t completed_tasks = completed_tasks[:limit]\n213\tEND IF\n214\t```\n215\t\n216\t**输出格式**:\n217\t\n218\t```markdown\n219\t# 📋 已完成任务列表(最近N个)\n220\t\n221\t| 任务名称 | 需求类型 | 完成时间 | 状态 |\n222\t|---------|---------|---------|------|\n223\t| ssh-operation-log | NEW | 2026-04-09 | 已归档 |\n224\t| user-export-excel | ENHANCE | 2026-04-08 | 未归档 |\n225\t| login-500-fix | FIX | 2026-04-07 | 未归档 |\n226\t\n227\t**统计**: 共 3 个已完成任务(已归档 1 个,未归档 2 个)\n228\t\n229\t## 🔄 任务操作\n230\t\n231\t### 查看任务详情\n232\t```bash\n233\t# 查看未归档任务\n234\tcat dev/active/ssh-operation-log/context.md\n235\t\n236\t# 查看已归档任务\n237\tcat dev/completed/ssh-operation-log/context.md\n238\t```\n239\t\n240\t### 修改已完成任务\n241\t使用 `/dev-flow modify` 命令重新执行需求或设计阶段。\n242\t\n243\t---\n244\t\n245\t\n246\t---\n247\t\n248\t## 🔗 Business API 状态同步规范\n249\t\n250\t### 适用范围\n251\t\n252\t本规范适用于**版本轨**(`version start` 启动的需求)。单需求轨暂不接入。\n253\t\n254\t### 执行主体\n255\t\n256\t**阶段级状态同步由主会话在逐阶段控制流程中负责**。主会话在每个阶段开始时调用 mcp__biz-sync__biz_sync_stage 更新 task-viewer,阶段完成时调用 mcp__biz-sync__biz_sync_session 记录进度。\n257\t\n258\t主对话(dev-flow.md 命令层)负责:\n259\t- 步骤A-C:创建 Task、Session、更新 Version 状态\n260\t- 步骤D:准备版本参数块(供步骤E构造阶段Prompt时引用)\n261\t- 步骤E:逐阶段启动subagent,并在每个阶段前后调用BIZ API同步\n262\t- 终态:subagent 完成后由 `_run_with_task_registry` 处理 completed/failed\n263\t\n264\t### 阶段-状态-进度映射表(单一真相源)\n265\t\n266\t本映射表供主会话在逐阶段控制流程中调用 mcp__biz-sync__biz_sync_stage/session 时引用,subagent不执行BIZ API同步。\n267\t\n268\t| 阶段 | stage 值 | progress |\n269\t|:----:|---------|:--------:|\n270\t| 阶段0: 需求澄清 | clarification | 3 |\n271\t| 阶段1: 需求分析 | requirement | 12 |\n272\t| 阶段1.1: 需求检视 | requirement_review | 18 |\n273\t| 阶段1.2: 需求知识同步 | requirement_review | 20 |\n274\t| 阶段1.6: 组件依赖分析 | requirement_review | 25 |\n275\t| 阶段2: 设计方案 | design | 30 |\n276\t| 阶段2.1: 设计检视 | design_review | 36 |\n277\t| 阶段2.2: 设计知识同步 | design_review | 38 |\n278\t| 阶段3: 代码开发 | development | 50 |\n279\t| 阶段3.1: 代码同步 | development | 55 |\n280\t| 阶段4: 自动部署 | deployment | 65 |\n281\t| 阶段5: 部署确认 | deployment_confirm | 70 |\n282\t| 阶段5.5: 测试用例澄清 | testing | 75 |\n283\t| 阶段6: 测试验证 | testing | 80 |\n284\t| 阶段6.1: 回归测试同步 | testing | 85 |\n285\t| 阶段7: 测试执行 | test_execution | 90 |\n286\t| 阶段8: 测试报告 | test_report | 95 |\n287\t| 阶段9: 循环决策 | test_report | 98 |\n288\t\n289\t### 执行约束\n290\t\n291\t1. **仅版本模式生效**:BIZ API同步由主会话在逐阶段控制流程中执行(WHILE+FOR循环step 2/9),非版本模式不执行任何 BIZ API 调用\n292\t2. **静默失败**:Python urllib 调用失败时不阻塞流程,继续执行后续阶段\n293\t3. **幂等性**:同一阶段重复调用无副作用\n294\t\n295\t## 🎯 执行步骤\n296\t\n297\t### 情况1:用户提供了需求描述(手动输入)\n298\t\n299\t**步骤**:主会话执行前置步骤P0-P7,然后按STAGE_ORDER逐阶段控制\n300\t\n301\t#### 前置步骤(与版本模式P0-P7相同)\n302\t\n303\tP0. 需求描述规范化检查:\n304\t 检测需求描述是否包含四要素(背景/目的/输入/输出),≥75分通过\n305\t → IF 通过:继续P1\n306\t → IF 未通过:AskUserQuestion("是否补充缺失信息?", ["补充信息", "跳过检查"])\n307\t IF "补充":等待用户补充 → 重新检测(最多2轮)\n308\t IF "跳过":继续P1\n309\t\n310\tP1. 需求分类:\n311\t 步骤1:读取项目根目录 `project-context.json`\n312\t → 若存在:提取 `existing_modules` + `tech_stack_summary`\n313\t → 若不存在:AskUserQuestion("⚠️ 未检测到项目上下文文件,是否生成?",\n314\t ["生成项目上下文(推荐)— 自动分析技术栈、代码规范和现有模块(约1-2分钟)",\n315\t "跳过 — 按新项目模式处理,使用默认技术栈规范,P4仍可补充生成"])\n316\t IF "生成":Agent(subagent_type: "project-context-analyzer", prompt: "请分析当前项目的完整上下文") → 重新读取\n317\t ELSE:`existing_modules` = [],`tech_stack_summary` = "(未生成项目上下文,使用默认配置)"\n318\t 步骤2:Agent(subagent_type: "req-type-classifier", prompt: "仅分类:{描述}\\n【项目现有模块】:{existing_modules}\\n【项目技术栈】:{tech_stack_summary}\\n请使用4步决策树分类并输出JSON格式")\n319\t 步骤3:用户确认分类结果(置信度<0.8强制确认)\n320\tP2. 模板适配:如果非模板格式,调用req-template-adapter\n321\tP3. 竞品分析:AskUserQuestion确认是否执行(默认执行,可选择跳过)→ IF执行: Agent(competitor-analyzer) → IF跳过: competitor_analysis_summary = "(用户跳过竞品分析)"\n322\tP3.5. 价值收益评估:AskUserQuestion确认是否执行(默认执行,可选择跳过)→ IF执行: 引导填写增效与降本维度的收益并拼接为 value_benefit_summary → IF跳过: value_benefit_summary = "(用户跳过价值收益评估)"\n323\tP4. 项目上下文确认:\n324\t → 若 `project-context.json` 存在:展示摘要 → AskUserQuestion确认\n325\t → 若不存在:\n326\t OUTPUT: "⚠️ 未检测到项目上下文文件" + 影响范围表格(现有模块识别/代码规范继承/Stage 3 Agent选择)\n327\t AskUserQuestion("是否现在生成项目上下文?",\n328\t ["生成项目上下文(推荐)", "继续 — 按默认配置处理"])\n329\t IF "生成":Agent(subagent_type: "project-context-analyzer", prompt: "请分析当前项目的完整上下文") → 展示摘要 → 确认\n330\t IF "继续":标记project_context_confirmed=false → 继续P4.5\n331\tP4.5. 项目级交互特性配置(强制询问)⭐项目级交互配置:\n332\t 完整步骤逻辑同版本模式(详见 start-development.md P4.5 步骤1-5),核心流程:\n333\t - 步骤1:检测 `.claude/config/dev-flow-interaction-config.json` 是否存在\n334\t - 步骤2:不存在→询问"现在设置/使用默认";存在→询问"沿用/重新选择/微调/删除"(即便存在也强制询问)\n335\t - 步骤3:选择模板(标准/极简/质量/自定义,模板库 `.claude/config/dev-flow-interaction-templates.json`)\n336\t - 步骤4:确认并写入(含21环节摘要展示)\n337\t - 步骤5:自定义向导(6组)\n338\t 单需求模式无差异,读取同一份项目级配置。结果写入 context.md 的 interactionConfig 字段,供下方步骤2/3.5读取。\n339\tP5. 执行模式选择:AskUserQuestion(快速/分步)\n340\tP6. 工作区初始化:创建 dev/active/{task_name}/ 目录 + context.md(格式同版本模式P6,但无版本参数:inputSource="manual",无dpmsStoryId/testSetId/releasePlanId/productId。仍需包含functionAttributes/frontendType/selectedDevAgents/knowledgeBaseStatus/moduleIndexPath字段,以及 stage1HookDone/stage2HookDone 布尔字段⭐v4.8,初始均为 false);rollbackHistory 数组字段⭐v4.10 初始为 [])\n341\tP7. 知识库构建(可跳过):\n342\t 与版本模式P7一致,差异:\n343\t - 单需求模式下无版本关联参数(productId/releasePlanId/testSetId),MCP直连DPMS不可用\n344\t - 阶段4 DPMS数据源降级为:Excel文件 > 跳过(无MCP直连选项)\n345\t - 知识库状态写入context.md的knowledgeBaseStatus和moduleIndexPath字段\n346\t\n347\t#### STAGE_ORDER逐阶段控制\n348\t\n349\t与版本模式相同(STAGE_ORDER = [0, 1, 1.1, 1.2, 1.6, 2, 2.1, 2.2, 3, 3.1, 3.2, 3.5, 4, 5, 5.5, 6, 6.1, 7, 8, 9]),差异如下:\n350\t\n351\t| 项目 | 版本模式 | 单需求模式 |\n352\t|------|---------|----------|\n353\t| 工作目录 | dev/versions/{versionName}/{task_name}/ | dev/active/{task_name}/ |\n354\t| 状态持久化 | versions.json | context.md |\n355\t| BIZ API同步 | ✅ 逐阶段调用 | ❌ 不执行 |\n356\t| DPMS Hook(B1-B7.5) | ✅ 阶段后置动作 | ❌ 不执行 |\n357\t| 提示词注入防护 ⭐v4.8 | ✅ 阶段后置动作(仅Claude插件需求) | ✅ 阶段后置动作(仅Claude插件需求) |\n358\t| Stage 4可跳过 | ❌ 版本模式不可跳过 | ✅ 可跳过 |\n359\t| 版本参数 | versionName/dpmsStoryId/testSetId/releasePlanId | ❌ 无 |\n360\t| 文档命名前缀 | ✅ REQ-NN_(由【需求编号】参数传入) | ❌ 无前缀 |\n361\t\n362\t**阶段Prompt构造规则**(单需求模式):\n363\t```\n364\t{需求描述}\n365\t【输入来源】:manual(手动输入)\n366\t【当前阶段】:{stage} - {stage_name}\n367\t【执行模式】:{execution_mode}\n368\t【工作目录】:dev/active/{task_name}/\n369\t【已有产物路径】:{该任务已生成的所有文档路径列表}\n370\t【竞品分析摘要】:{competitor_analysis_summary}\n371\t【价值收益摘要】:{value_benefit_summary} ← P3.5收集,若用户跳过P3.5,值为"(用户跳过价值收益评估)"\n372\t【context.md路径】:dev/active/{task_name}/context.md\n373\t【功能属性】:{functionAttributes} ← 仅当stage>=1且functionAttributes非空时注入\n374\t【前端类型】:{frontendType} ← 仅当stage>=1且frontendType非空时注入\n375\t```\n376\t\n377\t**阶段后置动作**(单需求模式):图表同步检查(Stage 1.1/2.1后检测Mermaid/PlantUML)+ 提示词注入防护(Stage 1.1/2.1/3/6,仅Claude插件开发需求执行)+ 接口文档生成(Stage 2.1后,涉及新增/变更Web API时,生成OpenAPI yaml + Markdown接口文档到 docs/{branch}/api/,同源原子)⭐v4.8,无DPMS Hook/shimo上传。Stage 1.1/2.1被用户跳过时仍执行对应文档图表同步、提示词注入防护和接口文档生成。\n378\t\n379\t**🛡️ Hook 幂等布尔标记(单需求模式)⭐v4.8**:\n380\t- 字段(context.md YAML frontmatter):`stage1HookDone: false` / `stage2HookDone: false`。\n381\t- 语义同版本模式(见 stage-hooks.md):`true` = 对应阶段本地后置动作已被执行过一次(成功或失败均置 true;失败已由容错框架处理,如注入防护 Skill 失败按"输出警告不阻塞"处理)。\n382\t- 单需求模式 Hook 仅本地动作(图表同步 + 提示词注入防护),**不含 DPMS/shimo**。\n383\t- 置位时机:本地后置动作执行后即置 true。\n384\t- 兜底调用点:Stage 2 入口 `IF stage1HookDone != true → 补执行 → 置 true`;Stage 3 入口 `IF stage2HookDone != true → 补执行 → 置 true`。Stage 2 与 Stage 3 兜底相互独立,Stage 2 的本地后置动作本体不再前置补 Stage 1。\n385\t\n386\t#### 单需求模式逐阶段执行流程\n387\t\n388\t对每个任务,按STAGE_ORDER顺序逐阶段执行:\n389\t\n390\t```\n391\tcycle_count = 0\n392\tMAX_CYCLES = 10\n393\t\n394\tWHILE cycle_count < MAX_CYCLES:\n395\t FOR each stage IN STAGE_ORDER:\n396\t stageExecutionSkipped = false # 仅用于Stage 1.1/2.1:跳过检视Agent但仍执行本地后置动作\n397\t 1. 状态持久化:将 currentStage={stage} 写入 context.md 的 YAML frontmatter\n398\t 2. 判断可跳过:\n399\t IF 该阶段"版本模式可跳过" == ✅ THEN\n400\t # ⭐项目级交互配置:从项目级配置文件读取(来源:P4.5写入的 .claude/config/dev-flow-interaction-config.json;与版本模式统一)\n401\t interaction_config = LOAD_JSON_IF_EXISTS(".claude/config/dev-flow-interaction-config.json") # 文件不存在或JSON解析失败时返回null(向后兼容)\n402\t stage_decision = null\n403\t IF interaction_config != null THEN\n404\t IF execution_mode == "分步模式" THEN\n405\t stage_decision = interaction_config.step_mode.skippable.get({stage})\n406\t ELSE # 快速模式\n407\t stage_decision = interaction_config.fast_mode.skippable.get({stage})\n408\t END IF\n409\t END IF\n410\t\n411\t IF stage_decision == "skip" THEN\n412\t 记录 skipDecisions[{stage}] = "skipped_by_config" 到 context.md\n413\t IF stage IN [1.1, 2.1] THEN\n414\t stageExecutionSkipped = true\n415\t 输出 "ℹ️ Stage {stage}按项目级配置跳过检视,仅跳过检视Agent和本地优化交互;继续执行该阶段本地后置动作"\n416\t ELSE\n417\t CONTINUE\n418\t END IF\n419\t ELIF stage_decision == "execute" THEN\n420\t 记录 skipDecisions[{stage}] = "executed_by_config" 到 context.md\n421\t ELSE\n422\t # stage_decision == "ask" 或 interaction_config == null(无配置):沿用原有询问逻辑(向后兼容)\n423\t AskUserQuestion 询问是否执行(默认沿用skipDecisions历史决策)\n424\t IF 用户选择跳过 THEN\n425\t 记录 skipDecisions[{stage}] = "skipped" 到 context.md\n426\t IF stage IN [1.1, 2.1] THEN\n427\t stageExecutionSkipped = true\n428\t 输出 "ℹ️ 用户选择跳过Stage {stage}检视,仅跳过检视Agent和本地优化交互;继续执行该阶段本地后置动作"\n429\t ELSE\n430\t CONTINUE\n431\t END IF\n432\t ELSE\n433\t 记录 skipDecisions[{stage}] = "executed" 到 context.md\n434\t END IF\n435\t END IF\n436\t END IF\n437\t ⚠️ Stage 4 单需求模式可跳过(非版本模式,无git-commit强制要求)\n438\t 3. 阶段前置特殊步骤:\n439\t IF stage == 2 THEN\n440\t 【前置步骤0:Stage1 本地后置动作幂等确认】⭐v4.8\n441\t IF stage1HookDone != true THEN\n442\t 补执行 Stage 1.1 本地后置动作(图表同步 + 提示词注入风险识别;无DPMS/shimo)\n443\t 执行后置 context.md 的 stage1HookDone = true\n444\t ELSE\n445\t 输出 "ℹ️ Stage1 本地后置动作已执行过,跳过"\n446\t END IF\n447\t END IF\n448\t IF stage == 3 THEN\n449\t 【前置步骤0:Stage2 本地后置动作幂等确认】⭐v4.8\n450\t IF stage2HookDone != true THEN\n451\t 补执行 Stage 2.1 本地后置动作(图表同步 + 提示词安全设计 + 接口文档生成;无DPMS/shimo)\n452\t 执行后置 context.md 的 stage2HookDone = true\n453\t ELSE\n454\t 输出 "ℹ️ Stage2 本地后置动作已执行过,跳过"\n455\t END IF\n456\t 【前置步骤1:Agent选择决策(🆕)】\n457\t 执行"Stage 3 Agent选择规则"Step 1-3(规则定义见stage-hooks.md)\n458\t Step 1: 确定后端Agent(基于项目语言)\n459\t Step 2: 判断是否需要前端Agent(function_attributes + frontend_type + has_frontend_code检测)\n460\t Step 3: 确定执行顺序和完成判定\n461\t → 确定:selected_agents(有序列表,如["java-code-developer"]、["java-code-developer","frontend-code-developer"]、["web-frontend-developer"])\n462\t → 将selected_agents写入context.md的selectedDevAgents字段\n463\t ELIF stage == 1.6 THEN\n464\t 【前置步骤:组件依赖分析器语言选择】\n465\t 执行"Skill通配符解析规则"中阶段1.6的解析逻辑(规则定义见stage-hooks.md)\n466\t → 读取project-context.json的techStack字段\n467\t → IF techStack包含"Java" → skill_name = "component-dependency-analyzer-java"\n468\t → ELIF techStack包含"Python" → skill_name = "component-dependency-analyzer-python"\n469\t → ELIF techStack包含"Go" → skill_name = "component-dependency-analyzer-go"\n470\t → ELSE AskUserQuestion("无法自动判定项目语言,请选择组件依赖分析器",\n471\t ["Java项目", "Python项目", "Go项目"])\n472\t → 根据选择确定skill_name\n473\t END IF\n474\t ELIF stage == 3.2 THEN\n475\t 【前置步骤1:技术栈分发 + 硬守卫】⭐v4.8\n476\t 读取project-context.json的techStack字段\n477\t IF techStack 包含 ("Java" OR "Kotlin" OR "Spring Boot") THEN\n478\t subagent_type_3_2 = "java-code-review"\n479\t ELIF techStack 包含 "Python" THEN\n480\t subagent_type_3_2 = "python-code-review"\n481\t ELIF techStack 包含 "Go" THEN\n482\t subagent_type_3_2 = "go-code-review"\n483\t ELSE\n484\t OUTPUT: "ℹ️ 当前项目技术栈({techStack})暂不支持代码部署前自检(仅支持 Java/Kotlin/Python/Go),自动跳过 Stage 3.2"\n485\t 记录 skipDecisions["3.2"] = "auto_skipped_unsupported_tech" 到 context.md\n486\t CONTINUE(推进到下一阶段;单需求模式不调用 BIZ API 同步)\n487\t END IF\n488\t\n489\t 【前置步骤2:target_env 收集】\n490\t AskUserQuestion(\n491\t question: "Stage 3.2 代码部署前自检({subagent_type_3_2})的重点环境是?(影响多环境配置一致性检查)",\n492\t header: "目标环境",\n493\t options: [\n494\t { label: "prod(生产)", description: "重点关注 prod 环境的配置完整性" },\n495\t { label: "fat(联调)", description: "重点关注 fat 环境的配置完整性" },\n496\t { label: "dev(开发)", description: "重点关注 dev 环境的配置完整性" },\n497\t { label: "不指定(推荐)", description: "对比所有环境的配置,仅在所有环境都未声明且代码无默认值时报 critical" }\n498\t ]\n499\t )\n500\t → 将选择追加到 Agent 调用 prompt:target_env=<用户选择,"不指定"时不传该参数>\n501\t\n502\t 【前置步骤3:Agent 调用参数构造】\n503\t agent_prompt_extra = "【from_dev_flow】:true"\n504\t IF target_env != "不指定" THEN agent_prompt_extra += "\\n【target_env】:" + target_env\n505\t → 后续步骤5 Agent 调用(subagent_type=subagent_type_3_2)使用此 prompt 片段附加到标准 Prompt\n506\t ELIF stage == 3.5 THEN\n507\t 【前置步骤1:dev_target 守卫】⭐v4.9 G4\n508\t 读取 context.md 的 dev_target 字段(来源:Stage 0 澄清 result)\n509\t IF dev_target NOT IN ["Agent", "Skill", "Command"] THEN\n510\t OUTPUT: "ℹ️ 当前需求 dev_target={dev_target},不触发 Stage 3.5 插件开发迭代评估循环,自动跳过"\n511\t 记录 skipDecisions["3.5"] = "auto_skipped_non_plugin_target" 到 context.md\n512\t CONTINUE(推进到下一阶段 Stage 4;单需求模式不调用 BIZ API 同步)\n513\t END IF\n514\t\n515\t 【前置步骤2:插件路径与评估参数解析】\n516\t plugin_path = Stage 3 claude-code-developer subagent 返回的插件生成路径\n517\t target_type = LOWER(context.md.dev_target)(agent / skill / command)\n518\t dataset_dir = plugin_path + "/evals"(默认)或 context.md.evals_dir(可选覆盖)\n519\t max_iterations = 3(默认,可由 .claude/config/plugin-dev/plugin-dev-flow-rules.json 覆盖)\n520\t pass_threshold = 0.8(默认,同上)\n521\t → 后续步骤5 调用 /plugin-dev-eval-loop 命令,参数:\n522\t /plugin-dev-eval-loop {plugin_path} --target-type {target_type} --dataset {dataset_dir} --max-iterations {max_iterations} --threshold {pass_threshold}\n523\t ELIF stage == 5.5 THEN\n524\t 【前置步骤:测试用例澄清上下文准备】\n525\t - 确保【已有产物路径】包含需求文档 + 设计文档(此阶段测试用例尚未生成)\n526\t - 确保【context.md路径】可读(含 functionAttributes/frontendType,供澄清Agent复用,不重新识别)\n527\t - 将【测试用例生成输入摘要】注入 prompt:代码变更/接口定义/Feature文件/需求文档/project-context 的路径\n528\t ⚠️ Stage 5.5 不可跳过(不进 skipDecisions 询问),由 test-case-clarification-orchestrator 在主对话执行多轮澄清\n529\t END IF\n530\t 3.5 分步模式确认:IF execution_mode == "分步模式" AND stageExecutionSkipped != true THEN\n531\t # ⭐项目级交互配置:从项目级配置文件读取 non_skippable 决策(仅分步模式生效;快速模式定义即auto_execute)\n532\t interaction_config = LOAD_JSON_IF_EXISTS(".claude/config/dev-flow-interaction-config.json") # 文件不存在或JSON解析失败时返回null(向后兼容)\n533\t non_skip_decision = null\n534\t IF interaction_config != null THEN\n535\t non_skip_decision = interaction_config.step_mode.non_skippable.get({stage})\n536\t END IF\n537\t\n538\t IF non_skip_decision == "auto_execute" THEN\n539\t # 按项目级配置自动执行(不询问)\n540\t 输出 "ℹ️ Stage {stage}按项目级配置自动执行"\n541\t ELSE\n542\t # non_skip_decision == "ask" 或 interaction_config == null(无配置):沿用原有询问逻辑(向后兼容)\n543\t AskUserQuestion("即将执行Stage {stage}: {stage_name},是否继续?",\n544\t ["继续执行", "跳过此阶段", "中止流程"])\n545\t IF "跳过" ->\n546\t 记录skipDecisions[{stage}]="skipped"\n547\t IF stage IN [1.1, 2.1] THEN\n548\t stageExecutionSkipped = true\n549\t 输出 "ℹ️ 分步模式选择跳过Stage {stage}检视,仅跳过检视Agent和本地优化交互;继续执行该阶段本地后置动作"\n550\t ELSE\n551\t CONTINUE\n552\t END IF\n553\t IF "中止" -> 更新currentStage为当前阶段 -> EXIT WHILE\n554\t END IF\n555\t END IF\n556\t 3.6 Stage 5部署确认:IF stage == 5 THEN\n557\t # 部署确认循环:用户选"已部署"时调用 mcp__sdp__get-pipeline 校验真实部署状态,\n558\t # 校验未通过则回退重新询问;"部署失败"分支保持原逻辑不变 ⭐v4.9\n559\t deploy_confirmed = false\n560\t WHILE deploy_confirmed == false:\n561\t AskUserQuestion("部署确认:代码已推送到远程仓库,请确认CI/CD部署状态",\n562\t ["已部署,继续", "部署失败,需修复"])\n563\t IF "部署失败,需修复" THEN\n564\t # ⭐v4.10:改走统一回滚函数(读写 context.md,修复原未清 stageHistory 遗漏)\n565\t Read .claude/config/dev-flow-checklists/rollback.md\n566\t execute_rollback(mode="auto", target_stage="3", reason="Stage5部署失败")\n567\t BREAK FOR(回退到Stage 3重新开发,原语义不变)\n568\t END IF\n569\t\n570\t # ── 用户选"已部署,继续":获取 pipelineId(单需求模式无 versions.json,询问用户)──\n571\t pipeline_id = AskUserQuestion("请输入流水线ID用于校验部署状态(输入空值视为无法校验)")\n572\t\n573\t IF pipeline_id 为空 THEN\n574\t # 决策1:无法校验,让用户决策\n575\t AskUserQuestion("⚠️ 未提供流水线ID,无法自动校验部署状态。如何处理?",\n576\t ["信任用户判断,继续推进到测试", "回退到Stage 3重新开发"])\n577\t IF "信任继续" THEN\n578\t OUTPUT "ℹ️ 跳过流水线状态校验,按用户判断继续"\n579\t deploy_confirmed = true\n580\t ELIF "回退Stage 3" THEN\n581\t 重置 context.md 的 currentStage="3" -> BREAK FOR\n582\t END IF\n583\t ELSE\n584\t # 决策2:调用 mcp__sdp__get-pipeline 校验(含工具异常重试,内层循环)\n585\t mcp_done = false\n586\t WHILE mcp_done == false:\n587\t mcp_result = safe_call_mcp("mcp__sdp__get-pipeline", {"id": pipeline_id})\n588\t IF mcp_result["success"] == false THEN\n589\t # MCP 工具调用异常(网络/认证/502,非部署状态判断)\n590\t AskUserQuestion("❌ 流水线状态查询工具调用失败:{mcp_result.error}(工具异常,非部署状态判断)。如何处理?",\n591\t ["重试调用", "跳过校验,继续推进到测试", "回退到Stage 3重新开发"])\n592\t IF "重试调用" THEN\n593\t CONTINUE(内层 WHILE,重新调用 mcp__sdp__get-pipeline)\n594\t ELIF "跳过校验继续" THEN\n595\t OUTPUT "ℹ️ 跳过流水线状态校验(工具异常),按用户判断继续"\n596\t deploy_confirmed = true\n597\t mcp_done = true\n598\t ELIF "回退Stage 3" THEN\n599\t 重置 context.md 的 currentStage="3" -> BREAK FOR\n600\t END IF\n601\t ELSE\n602\t mcp_done = true\n603\t # 判断 data.lastestTrigger.status(大小写不敏感,实际返回大写 SUCCESS)\n604\t status = UPPER(mcp_result["result"]["data"]["lastestTrigger"]["status"])\n605\t IF status == "SUCCESS" THEN\n606\t OUTPUT "✅ 流水线部署校验通过(lastestTrigger.status=SUCCESS)"\n607\t deploy_confirmed = true\n608\t ELIF status == "RUNNING" THEN\n609\t # 决策3:流水线仍在执行中\n610\t OUTPUT "⏳ 流水线正在部署中(lastestTrigger.status=RUNNING),尚未完成,请稍后再次确认"\n611\t CONTINUE(外层 WHILE,重新询问用户是否部署成功)\n612\t ELSE\n613\t # FAILURE 等其他非 SUCCESS 状态\n614\t OUTPUT "❌ 流水线部署未成功(lastestTrigger.status={status}),请确认后再次选择"\n615\t CONTINUE(外层 WHILE,重新询问用户是否部署成功)\n616\t END IF\n617\t END IF\n618\t END WHILE\n619\t END IF\n620\t END WHILE\n621\t # deploy_confirmed == true -> 推进到 Stage 5.5\n622\t END IF\n623\t 4. 构造阶段Prompt(单需求模式格式,见上方"阶段Prompt构造规则")\n624\t IF stageExecutionSkipped == true THEN\n625\t 跳过Prompt构造(仅Stage 1.1/2.1跳过检视时使用;后续仍执行对应本地后置动作)\n626\t END IF\n627\t 5. 启动Subagent:\n628\t - IF stageExecutionSkipped == true THEN\n629\t 输出 "ℹ️ 已跳过Stage {stage}检视Agent,继续执行该阶段本地后置动作"\n630\t → 跳到步骤7(不启动检视Agent,不执行本阶段优化交互)\n631\t - ELIF stage == 3 AND len(selected_agents) >= 1 THEN\n632\t IF len(selected_agents) == 1 THEN\n633\t 标准串行执行:Agent(subagent_type: selected_agents[0], prompt: 构造的Prompt)\n634\t ELSE\n635\t 【多Agent串行执行】(同版本模式逻辑)\n636\t stage3_completed = []\n637\t stage3_failed = []\n638\t FOR each agent IN selected_agents:\n639\t 构造Agent专属Prompt:\n640\t - 后端Agent: 【设计文档路径】:{后端设计.md或设计.md},【开发范围】:后端(Controller/Service/Entity等)\n641\t - 前端Agent: 【设计文档路径】:{前端设计.md},【开发范围】:前端(页面/组件/API封装等)\n642\t Agent(subagent_type: agent, prompt: 构造的Prompt)\n643\t IF 成功 → stage3_completed.append(agent)\n644\t IF 失败 → stage3_failed.append(agent),继续下一个Agent(不中止)\n645\t END FOR\n646\t 【Stage 3多Agent完成判定规则】\n647\t IF len(stage3_failed) == 0 THEN\n648\t → Stage 3全部完成,推进到Stage 3.1\n649\t ELIF len(stage3_completed) > 0 THEN\n650\t → 部分完成\n651\t AskUserQuestion("Stage 3部分完成:✅{stage3_completed} ❌{stage3_failed},如何处理?",\n652\t ["继续下一阶段(忽略失败Agent)", "重试失败Agent", "中止流程"])\n653\t ELSE\n654\t → 全部失败,按现有容错模式处理\n655\t END IF\n656\t END IF\n657\t - ELSE(其他阶段):\n658\t 从映射表获取该阶段的Agent/Skill列值\n659\t IF 映射值包含"(命令)"后缀 THEN ⭐v4.9 G4 新增\n660\t 命令类型阶段:通过 Skill 工具调用(Claude Code 中 slash 命令本质上是 Skill)\n661\t 去除"(命令)"后缀,获取实际命令名(如 plugin-dev-eval-loop)\n662\t Skill(skill: 命令名, args: 构造的Prompt + 步骤4前置步骤2已解析的参数)\n663\t ELIF 映射值包含"(Skill)"后缀 THEN\n664\t Skill类型阶段:使用 Skill 工具\n665\t IF 映射值包含"{lang}"(Skill通配符)THEN\n666\t 使用步骤3中已解析的skill_name(如component-dependency-analyzer-java)\n667\t Skill(skill: skill_name, args: 构造的Prompt)\n668\t ELIF 映射值包含"→"(多个Skill串行)THEN\n669\t 按"→"拆分为有序Skill列表\n670\t FOR each skill IN 有序Skill列表:\n671\t 去除"(Skill)"后缀,获取实际skill名\n672\t Skill(skill: skill名, args: 构造的Prompt)\n673\t END FOR\n674\t ELSE\n675\t 去除"(Skill)"后缀,获取实际skill名\n676\t Skill(skill: skill名, args: 构造的Prompt)\n677\t END IF\n678\t ELSE\n679\t Agent类型阶段:使用 Agent 工具\n680\t IF 映射值 == "{lang}-code-review"(Stage 3.2 通配符)⭐v4.8 THEN\n681\t 使用步骤3中已解析的 subagent_type_3_2(java-code-review / python-code-review / go-code-review)\n682\t Agent(subagent_type: subagent_type_3_2, prompt: 构造的Prompt + agent_prompt_extra)\n683\t ELSE\n684\t 使用映射表静态值(subagent_type 从映射表获取,解析规则见stage-hooks.md"Agent通配符解析规则")\n685\t END IF\n686\t END IF\n687\t 6. 等待Subagent完成(stageExecutionSkipped == true 时无Subagent可等待)\n688\t 6.3 ⚠️ 功能属性提取(仅Stage 0):\n689\t IF stage == 0 THEN\n690\t 从subagent返回的澄清结果中提取function_attributes和frontend_type\n691\t → 更新context.md YAML frontmatter:\n692\t functionAttributes: {提取值,如["前端","后端"]或["后端"]}\n693\t frontendType: {提取值,如"纯前端"或"前端+后台web API",无前端属性则""}\n694\t → 提取方法(优先级从高到低):\n695\t 1. subagent输出中的结构化字段(JSON/表格中"功能属性"行)\n696\t 2. subagent输出文本中的关键词匹配("功能属性"后跟"前端/后端/数据")\n697\t 3. 若以上均失败:functionAttributes留空 → 🆕 防线1 强制兜底(禁止留空进入后续阶段):\n698\t AskUserQuestion("Stage 0 未能从澄清结果提取功能属性,请显式确认本需求涉及的功能属性",\n699\t options: ["前端", "后端", "前端+后端", "前端+后端+数据"])\n700\t → 根据用户选择写入 context.md functionAttributes(如"前端+后端"→["前端","后端"])\n701\t → ⚠️ 禁止留空,必须写入非空值\n702\t → Stage 3 前置步骤1 的 2a 三级兜底(context.md→需求文档解析→2b硬守卫,规则见stage-hooks.md)作为二级保障\n703\t END IF\n704\t 6.5 ⚠️ 数据属性阻断回退检查(仅Stage 0):\n705\t IF stage == 0 AND subagent返回包含 {action: "restart_from_requirement_input", reason: "data_attribute_detected"}:\n706\t → OUTPUT: "🚫 检测到数据开发属性(ETL场景),当前暂不支持数据开发Agent,回退到需求描述环节"\n707\t → 清除context.md中当前任务的澄清结果(重置currentStage和stageHistory)\n708\t → BREAK FOR(退出当前STAGE_ORDER循环)\n709\t → 回退到前置步骤之前,提示用户重新输入需求描述(重新执行P0-P7 + STAGE_ORDER)\n710\t END IF\n711\t 6.6 ⚠️ Stage 1.1 用户优化决策处理(仅Stage 1.1):\n712\t IF stage == 1.1 AND stageExecutionSkipped != true AND subagent返回的recheckReport存在 THEN\n713\t 主对话向用户展示报告摘要(综合评分/结构检查/优化建议数量)\n714\t AskUserQuestion 五选项:\n715\t 1 ✅ 执行全部优化(critical + recommended + optional)\n716\t 2 🔶 执行必要优化(critical + recommended)\n717\t 3 🔸 仅执行必须修改(critical)\n718\t 4 ❌ 跳过优化,保持原需求文档\n719\t 5 📋 查看详细检视报告\n720\t WHILE 用户选择 == 5(查看详细报告):\n721\t showDetailedReport(recheckReport)\n722\t 重新 AskUserQuestion 五选项\n723\t END WHILE\n724\t IF 用户选择 ∈ [1, 2, 3] THEN\n725\t 根据选择确定优化范围 → optimizationsToExecute\n726\t FOR each opt IN optimizationsToExecute:\n727\t 使用 Edit 工具按 opt.location 和 opt.suggestion 修改需求文档\n728\t END FOR\n729\t 更新 context.md YAML frontmatter: rechckDecisions["1.1"] = "applied"\n730\t 输出 "✅ 需求文档优化执行完成({N}项)"\n731\t ELIF 用户选择 == 4 THEN\n732\t 保持原需求文档\n733\t 更新 context.md YAML frontmatter: rechckDecisions["1.1"] = "skipped"\n734\t 输出 "ℹ️ 用户选择跳过优化,保持原需求文档"\n735\t END IF\n736\t END IF\n737\t 6.7 ⚠️ Stage 2.1 用户优化决策处理(仅Stage 2.1):\n738\t IF stage == 2.1 AND stageExecutionSkipped != true AND subagent返回的recheckReport存在 THEN\n739\t 主对话向用户展示报告摘要(综合评分/质量维度/优化建议数量)\n740\t AskUserQuestion 五选项:\n741\t 1 ✅ 执行全部优化(critical + recommended + optional)\n742\t 2 🔶 执行必要优化(critical + recommended)\n743\t 3 🔸 仅执行必须修改(critical)\n744\t 4 ❌ 跳过优化,保持原设计文档\n745\t 5 📋 查看详细检视报告\n746\t WHILE 用户选择 == 5(查看详细报告):\n747\t showDetailedReport(recheckReport)\n748\t 重新 AskUserQuestion 五选项\n749\t END WHILE\n750\t IF 用户选择 ∈ [1, 2, 3] THEN\n751\t 根据选择确定优化范围 → optimizationsToExecute\n752\t FOR each opt IN optimizationsToExecute:\n753\t 使用 Edit 工具按 opt.location 和 opt.suggestion 修改设计文档\n754\t END FOR\n755\t 更新 context.md YAML frontmatter: rechckDecisions["2.1"] = "applied"\n756\t 输出 "✅ 设计文档优化执行完成({N}项)"\n757\t ELIF 用户选择 == 4 THEN\n758\t 保持原设计文档\n759\t 更新 context.md YAML frontmatter: rechckDecisions["2.1"] = "skipped"\n760\t 输出 "ℹ️ 用户选择跳过优化,保持原设计文档"\n761\t END IF\n762\t END IF\n763\t 7. 执行阶段后置动作(图表同步检查 + 提示词注入防护 ⭐v4.8):\n764\t IF stage IN [1.1, 2.1] THEN\n765\t 读取阶段产物文档,检测 ```mermaid 或 ```plantuml 代码块\n766\t IF 包含 THEN\n767\t Agent(subagent_type: "diagram-sync-agent", prompt: "检查文档中图表一致性:{doc_path}")\n768\t END IF\n769\t END IF\n770\t # 提示词注入防护(仅Claude插件开发需求执行)⭐v4.8\n771\t IF stage == 1.1 THEN\n772\t 检查context.md的injection_risk字段\n773\t IF injection_risk.level == "N/A" THEN\n774\t 输出 "ℹ️ injection_risk.level为N/A(需求不涉及Claude插件开发),跳过注入防护"\n775\t ELIF injection_risk不存在 THEN\n776\t Skill(injection-risk-identifier):评估注入风险 → 写入context.md的injection_risk字段\n777\t ELSE\n778\t 输出 "ℹ️ injection_risk字段已存在,跳过重复识别"\n779\t END IF\n780\t ELIF stage == 2.1 THEN\n781\t 读取context.md的injection_risk字段\n782\t IF injection_risk.level == "N/A" THEN\n783\t 输出 "ℹ️ injection_risk.level为N/A(需求不涉及Claude插件开发),跳过注入防护"\n784\t ELIF injection_risk存在 AND injection_risk.level != "N/A" THEN\n785\t 检查设计文档是否已包含"提示词安全设计"章节\n786\t IF 不包含 THEN\n787\t Skill(injection-defense-designer):根据风险等级生成"提示词安全设计"章节\n788\t → 追加到设计文档末尾\n789\t → 将defense_layers字段写回context.md\n790\t ELSE\n791\t 输出 "ℹ️ 提示词安全设计章节已存在,跳过重复生成"\n792\t END IF\n793\t ELSE\n794\t 输出 "⚠️ injection_risk字段不存在,无法确定注入防护策略,跳过提示词安全设计"\n795\t END IF\n796\t # 接口文档生成 ⭐v4.8(本次涉及新增/变更 Web API 接口时;纯本地动作,无DPMS/shimo)\n797\t # 数据源:设计文档已有的接口章节(2.2/2.5/3.3/1.3)\n798\t # 产出:OpenAPI yaml + Markdown 接口文档(同源生成,严格对齐;要么都生成要么都不生成)\n799\t 读取设计文档 "## 2.2 API规范设计" 下的 "API端点列表" 子章节表格(兼容 "### 2.2.1 API端点列表" 和 "### API端点列表" 两种格式)\n800\t IF 端点列表缺失 / 为空 / 全为模板占位符 / 标注 N/A THEN\n801\t 输出 "ℹ️ 设计文档未包含 Web API 端点,判定本次无接口,跳过接口文档生成"\n802\t ELSE\n803\t IF 需求类型 IN [NEW, INTEGRATE] OR 端点表/变更影响章节含"新增" THEN\n804\t 生成决策 = "生成"\n805\t ELSE\n806\t AskUserQuestion("本次接口为变更(非新增),是否仍生成接口文档?", ["生成(推荐)", "跳过"])\n807\t 生成决策 = 用户选择\n808\t END IF\n809\t IF 生成决策 == "生成" THEN\n810\t output_dir = docs/{branch}/api/ # 不存在则创建;yaml 与 markdown 同目录\n811\t Skill(api-doc-generator, args={\n812\t design_doc_path: {设计文档路径},\n813\t requirement_name: {需求名},\n814\t output_dir: output_dir,\n815\t requirement_type: {需求类型}\n816\t })\n817\t IF 成功 → 输出 "✅ 接口文档已生成:docs/{branch}/api/{需求名}_接口文档.md(+ 同名 _api-spec.yaml)"\n818\t IF 失败 → 输出警告,不阻塞后续流程(单需求模式不写待补录)\n819\t ELSE\n820\t 输出 "ℹ️ 用户选择跳过接口文档生成"\n821\t END IF\n822\t END IF\n823\t ELIF stage == 3 THEN\n824\t 读取context.md的injection_risk和defense_layers字段\n825\t IF injection_risk.level == "N/A" THEN\n826\t 输出 "ℹ️ injection_risk.level为N/A(需求不涉及Claude插件开发),跳过注入防护"\n827\t ELIF injection_risk存在 AND injection_risk.level != "N/A" THEN\n828\t 检查Prompt文件是否已包含"⚠️ 安全边界"章节\n829\t IF 不包含 THEN\n830\t Skill(injection-guard-prompter):根据风险等级生成安全边界章节内容\n831\t → 将"⚠️ 安全边界"章节写入Prompt文件(Agent/Skill/Command .md文件)\n832\t → 在执行流程章节之前插入\n833\t → 安全防护内容深度:L1→~8行, L2→~35行, L3→~45行\n834\t ELSE\n835\t 输出 "ℹ️ 安全边界章节已存在,跳过重复生成"\n836\t END IF\n837\t ELSE\n838\t 输出 "⚠️ injection_risk字段不存在,无法确定注入防护策略,跳过安全边界写入"\n839\t END IF\n840\t ELIF stage == 6 THEN\n841\t 读取context.md的injection_risk字段\n842\t IF injection_risk.level == "N/A" THEN\n843\t 输出 "ℹ️ injection_risk.level为N/A(需求不涉及Claude插件开发),跳过注入攻击测试"\n844\t ELIF injection_risk存在 AND injection_risk.level != "N/A" THEN\n845\t 检查 docs/{branch}/testing/{需求名}_注入测试报告.md 是否已存在\n846\t IF 不存在 THEN\n847\t Skill(injection-attack-tester):执行注入攻击模拟测试\n848\t → 测试深度:按injection_risk.level决定(L1≥5用例, L2≥13用例, L3≥21用例)\n849\t → 输出注入测试报告 → 写入 docs/{branch}/testing/{需求名}_注入测试报告.md\n850\t ELSE\n851\t 输出 "ℹ️ 注入测试报告已存在,跳过重复生成"\n852\t END IF\n853\t ELSE\n854\t 输出 "⚠️ injection_risk字段不存在,无法确定注入防护策略,跳过注入攻击测试"\n855\t END IF\n856\t END IF\n857\t IF 注入防护Skill执行失败 → 输出警告,不阻塞后续流程\n858\t # 幂等置位 ⭐v4.8:本地后置动作执行后置对应布尔(失败已由上方容错处理,不影响置位)\n859\t IF stage == 1.1 THEN 置 context.md 的 stage1HookDone = true\n860\t ELIF stage == 2.1 THEN 置 context.md 的 stage2HookDone = true\n861\t END IF\n862\t 7.5 ⚠️ 执行 Stage 3.2 自检结果决策(仅Stage 3.2)⭐v4.8 — 独立步骤,不可跳过\n863\t IF stage == 3.2 THEN\n864\t 从 {subagent_type_3_2} Agent(java-code-review / python-code-review / go-code-review 之一)返回的最终文本中解析 JSON 块(包裹在 ```json ... ``` 代码块中)\n865\t 读取关键字段:review_status / critical_remaining / high_remaining / manual_items / changed_files / should_block_deploy\n866\t\n867\t IF JSON 解析失败 THEN\n868\t OUTPUT: "⚠️ Stage 3.2 {subagent_type_3_2} Agent 返回无法解析为 JSON,按容错处理:默认不阻断部署"\n869\t 更新 context.md YAML frontmatter:codeReviewResult = { status: "json_parse_failed", agent: subagent_type_3_2, completedAt: "" }\n870\t CONTINUE(推进到 Stage 4)\n871\t END IF\n872\t\n873\t IF review_status IN ("skipped_non_java", "skipped_non_python", "skipped_non_go") THEN\n874\t OUTPUT: "ℹ️ Stage 3.2 已由 {subagent_type_3_2} Agent 内部技术栈守卫跳过"\n875\t 更新 context.md YAML frontmatter:codeReviewResult = JSON返回值\n876\t CONTINUE(推进到 Stage 4)\n877\t END IF\n878\t\n879\t IF should_block_deploy == true THEN\n880\t AskUserQuestion(\n881\t question: "Stage 3.2 代码自检({subagent_type_3_2})发现 {critical_remaining} 个 critical 问题未修复,是否仍进入自动部署?",\n882\t header: "部署阻断决策",\n883\t options: [\n884\t { label: "返回修复(推荐)", description: "回退到 Stage 3 让 Agent 重新生成代码,或人工修复后再次执行 Stage 3.2" },\n885\t { label: "强制进入部署", description: "已了解风险(启动可能炸),按用户判断继续 git-commit + git-push" },\n886\t { label: "中止流程", description: "退出流程,保留已有产物" }\n887\t ]\n888\t )\n889\t IF "返回修复" THEN\n890\t # ⭐v4.10:改走统一回滚函数\n891\t Read .claude/config/dev-flow-checklists/rollback.md\n892\t execute_rollback(mode="auto", target_stage="3", reason="Stage3.2代码自检阻断")\n893\t BREAK FOR\n894\t END IF\n895\t IF "强制进入部署" → 更新 context.md YAML frontmatter:codeReviewResult = { ...JSON返回值, agent: subagent_type_3_2, override: "force_proceed_with_risk", overrideAt: "" } → CONTINUE\n896\t IF "中止流程" → 更新 context.md 的 currentStage="3.2" → EXIT WHILE\n897\t ELSE\n898\t 更新 context.md YAML frontmatter:codeReviewResult = { ...JSON返回值, agent: subagent_type_3_2 }\n899\t OUTPUT: "✅ Stage 3.2 自检通过({subagent_type_3_2}):auto_fixed={auto_fixed}, manual_items={manual_items}, changed_files={len(changed_files)}"\n900\t CONTINUE(推进到 Stage 4)\n901\t END IF\n902\t END IF\n903\t 7.6 ⚠️ 执行 Stage 3.5 插件开发迭代评估循环(仅 Stage 3.5)⭐v4.9 G4 — 独立步骤,dev_target 守卫已在步骤4前置步骤1完成\n904\t IF stage == 3.5 THEN\n905\t 调用 /plugin-dev-eval-loop 命令(参数由步骤4前置步骤2构造)\n906\t 从命令返回结果解析 exit_code 与 eval_summary:\n907\t - exit_code=0(达标)→ 更新 context.md YAML frontmatter:pluginEvalResult = { status: "passed", ...eval_summary } → OUTPUT: "✅ Stage 3.5 评估达标(pass_rate={pass_rate}),Golden Fixture 已沉淀" → CONTINUE(推进到 Stage 4)\n908\t - exit_code=1(未达标/迭代超限)→ AskUserQuestion("Stage 3.5 评估循环未达标(max_iterations={max_iterations} 已耗尽),如何处理?", 选项=["降级到 Stage 4(推荐)", "中止流程人工介入"]) → IF "降级" → 更新 pluginEvalResult = { status: "fallback_max_iter", ... } → CONTINUE;IF "中止" → 更新 context.md 的 currentStage="3.5" → EXIT WHILE\n909\t - exit_code=2(评估引擎不可用/数据集不存在)→ OUTPUT: "⚠️ Stage 3.5 评估引擎不可用,自动降级到 Stage 4" → 更新 pluginEvalResult = { status: "engine_unavailable", ... } → CONTINUE\n910\t - exit_code=3(参数错误)→ OUTPUT: "❌ Stage 3.5 参数错误:{error_msg}" → 更新 context.md 的 currentStage="3.5" → EXIT WHILE\n911\t END IF\n912\t END IF\n913\t 8. 将 stage 追加到 context.md 的 stageHistory 数组\n914\t 9. 推进到 STAGE_ORDER 下一项\n915\t END FOR\n916\t\n917\t # Stage 9循环决策(FOR循环结束后)\n918\t 读取测试报告,判断:\n919\t IF 所有测试通过且无缺陷 THEN\n920\t OUTPUT: "✅ 全流程完成,退出循环"\n921\t BREAK\n922\t ELSE IF 存在失败测试用例或缺陷 THEN\n923\t cycle_count += 1\n924\t OUTPUT: "🔄 检测到失败,第{cycle_count}次循环"\n925\t 调用 req-fix-bug-analyzer 生成bug fix子需求\n926\t # ⭐v4.10:改走统一回滚函数(自动语义不变:强制 stage1 + MAX_CYCLES=10 保留 + 仍生成 bug fix 子需求)\n927\t Read .claude/config/dev-flow-checklists/rollback.md\n928\t execute_rollback(mode="auto", target_stage="1", reason="Stage9测试失败循环")\n929\t CONTINUE(重新进入WHILE循环)\n930\t END IF\n931\tEND WHILE\n932\t\n933\tIF cycle_count >= MAX_CYCLES THEN\n934\t OUTPUT: "⚠️ 已达最大循环次数({MAX_CYCLES}),强制退出"\n935\t AskUserQuestion("已达到最大循环次数,如何处理?",\n936\t ["强制退出(保留已有产物)", "继续循环(再给10次机会)"])\n937\tEND IF\n938\t```\n939\t\n940\t**示例**:\n941\t```\n942\t用户输入: /dev-flow 实现用户导出功能\n943\t↓\n944\tP0: 需求描述规范化检查 → 通过(4要素齐全)\n945\tP1: 读取project-context.json → existing_modules=["User","Order"] → Agent(req-type-classifier) → 分类结果: ENHANCE, 置信度: 0.92\n946\tP2: 跳过(已是模板格式)\n947\tP3: Agent(competitor-analyzer) → 竞品分析结果\n948\tP4: 读取project-context.json → 展示摘要 → 用户确认\n949\tP5: AskUserQuestion → 用户选择"快速模式"\n950\tP6: 创建 dev/active/user-export-function/ + context.md\n951\t↓\n952\tSTAGE_ORDER逐阶段控制:\n953\t Stage 0: Agent(req-clarification-orchestrator)\n954\t Stage 1: Agent(req-new-feature-analyzer)\n955\t Stage 1.1: AskUserQuestion("是否执行需求检视?") → 跳过/执行\n956\t ...后续阶段依次执行\n957\t```\n958\t\n959\t### 情况1A:从DPMS系统需求启动 🆕\n960\t\n961\t**触发条件**:命令包含 `--story` 参数\n962\t\n963\t**步骤**:\n964\t\n965\t#### 步骤1:解析参数\n966\t```\n967\t提取参数:\n968\t storyId = [从命令行提取]\n969\t productId = [从命令行提取]\n970\t```\n971\t\n972\t#### 步骤2:调用MCP获取系统需求(含容错)🛡️\n973\t\n974\t```\n975\t通过 dpms-requirements-sync skill 调用 mcp__sdp__get-story-info-with-content:\n976\t 参数:\n977\t productId: {productId}\n978\t storyId: {storyId}\n979\t isImageParse: false # 默认不解析图片\n980\t\n981\t容错处理(v4.0新增):\n982\tIF 调用成功 THEN\n983\t → 进入步骤3,将需求内容传给Agent\n984\tELSE\n985\t error_category = classify_mcp_error(error)\n986\t IF error_category == "NETWORK_UNAVAILABLE" THEN\n987\t 使用AskUserQuestion询问:\n988\t - "跳过,转为手动输入模式(推荐)" → 进入情况1(手动输入流程)\n989\t - "再试1次" → 重试后仍失败则回到询问\n990\t ELSE IF error_category == "AUTH_ERROR" THEN\n991\t 使用AskUserQuestion询问:\n992\t - "检查VPN/权限后重试(推荐)"\n993\t - "跳过,转为手动输入模式"\n994\t ELSE\n995\t 使用AskUserQuestion询问:\n996\t - "重试"\n997\t - "中止流程"\n998\t END IF\n999\tEND IF\n1000\t\n1001\t返回:\n1002\t {\n1003\t "story": {\n1004\t "id": 12345,\n1005\t "name": "用户导出功能",\n1006\t "type": 1, # 需求类型\n1007\t "priority": 1,\n1008\t ...\n1009\t },\n1010\t "content": "<富文本内容>",\n1011\t "attachments": [...]\n1012\t }\n1013\t```\n1014\t\n1015\t#### 步骤3:格式化需求内容并启动前置步骤+逐阶段控制\n1016\t\n1017\t主会话执行前置步骤P0-P7(与情况1相同),然后按STAGE_ORDER逐阶段控制。\n1018\t\n1019\t**差异**:\n1020\t- P6工作区初始化时,将storyId和productId写入context.md\n1021\t- 阶段Prompt构造规则中增加:\n1022\t ```\n1023\t 【输入来源】:dpms_story(DPMS系统需求)\n1024\t 【DPMS需求ID】:{storyId}\n1025\t 【DPMS产品ID】:{productId}\n1026\t ```\n1027\t- Stage 1后置动作:调用 dpms-requirements-sync skill 更新系统需求内容(非版本模式,不执行B1-B7.5 Hook)\n1028\t\n1029\t**注意**:dpms_story模式下不接入BIZ API同步,不执行版本模式专属的DPMS Hook。\n1030\t\n1031\t### 情况1B:从DPMS业务需求启动 🆕\n1032\t\n1033\t**触发条件**:命令包含 `--business-story` 参数\n1034\t\n1035\t**步骤**:\n1036\t\n1037\t#### 步骤1:解析参数\n1038\t```\n1039\t提取参数:\n1040\t businessStoryId = [从命令行提取]\n1041\t productId = [从命令行提取]\n1042\t departmentId = [从命令行提取]\n1043\t```\n1044\t\n1045\t#### 步骤2:调用MCP获取业务需求(含容错)🛡️\n1046\t```\n1047\t通过 dpms-requirements-sync skill 调用 mcp__sdp__get-business-story-info-with-content:\n1048\t 参数:\n1049\t businessDepartmentId: {departmentId}\n1050\t productId: {productId}\n1051\t businessStoryId: {businessStoryId}\n1052\t isImageParse: false # 默认不解析图片\n1053\t\n1054\t容错处理(v4.0新增,与情况1A步骤2一致):\n1055\tIF 调用成功 THEN\n1056\t → 进入步骤3\n1057\tELSE\n1058\t error_category = classify_mcp_error(error)\n1059\t IF error_category == "NETWORK_UNAVAILABLE" THEN\n1060\t 使用AskUserQuestion询问:\n1061\t - "跳过,转为手动输入模式(推荐)"\n1062\t - "再试1次"\n1063\t ELSE IF error_category == "AUTH_ERROR" THEN\n1064\t 使用AskUserQuestion询问:\n1065\t - "检查VPN/权限后重试(推荐)"\n1066\t - "跳过,转为手动输入模式"\n1067\t ELSE\n1068\t 使用AskUserQuestion询问:\n1069\t - "重试"\n1070\t - "中止流程"\n1071\t END IF\n1072\tEND IF\n1073\t\n1074\t返回:\n1075\t {\n1076\t "businessStory": {\n1077\t "id": 67890,\n1078\t "name": "用户导出功能",\n1079\t "status": 16, # 业务审批中\n1080\t ...\n1081\t },\n1082\t "content": "<富文本内容>",\n1083\t "attachments": [...]\n1084\t }\n1085\t```\n1086\t\n1087\t#### 步骤3:格式化需求内容并启动前置步骤+逐阶段控制\n1088\t\n1089\t主会话执行前置步骤P0-P7(与情况1相同),然后按STAGE_ORDER逐阶段控制。\n1090\t\n1091\t**差异**:\n1092\t- P6工作区初始化时,将businessStoryId、productId、departmentId写入context.md\n1093\t- 阶段Prompt构造规则中增加:\n1094\t ```\n1095\t 【输入来源】:dpms_business_story(DPMS业务需求)\n1096\t 【DPMS业务需求ID】:{businessStoryId}\n1097\t 【DPMS产品ID】:{productId}\n1098\t 【DPMS部门ID】:{departmentId}\n1099\t ```\n1100\t- Stage 1后置动作:调用 dpms-requirements-sync skill 更新业务需求 + 创建系统需求(非版本模式,不执行B1-B7.5 Hook)\n1101\t\n1102\t**注意**:dpms_business_story模式下不接入BIZ API同步,不执行版本模式专属的DPMS Hook。\n1103\t\n1104\t### 情况2:用户请求恢复任务\n1105\t\n1106\t**步骤**:\n1107\t\n1108\t#### 步骤1:识别恢复参数\n1109\t\n1110\t```\n1111\tIF 命令包含 "resume [task-name]" THEN\n1112\t target_task = [task-name]\n1113\t recovery_mode = "specific"\n1114\tELSE IF 命令仅包含 "resume" THEN\n1115\t target_task = null\n1116\t recovery_mode = "auto"\n1117\tEND IF\n1118\t```\n1119\t\n1120\t#### 步骤2:扫描未完成任务\n1121\t\n1122\t**扫描逻辑**:\n1123\t```\n1124\tFOR EACH task_dir IN dev/active/:\n1125\t context_file = dev/active/{task_dir}/context.md\n1126\t\n1127\t IF context_file EXISTS THEN\n1128\t PARSE context.md 提取:\n1129\t - 任务名称 (task_dir)\n1130\t - 需求类型\n1131\t - 当前阶段\n1132\t - 任务状态\n1133\t - 最后更新时间\n1134\t\n1135\t IF 任务状态 IN ["进行中", "已暂停"] THEN\n1136\t ADD TO incomplete_tasks\n1137\t END IF\n1138\t END IF\n1139\tEND FOR\n1140\t\n1141\tSORT incomplete_tasks BY 最后更新时间 DESC\n1142\t```\n1143\t\n1144\t#### 步骤3:确定恢复目标\n1145\t\n1146\t**恢复目标选择逻辑**:\n1147\t\n1148\t```\n1149\tincomplete_tasks = scan_incomplete_tasks()\n1150\t\n1151\tIF incomplete_tasks IS EMPTY THEN\n1152\t # 情况A:没有未完成任务\n1153\t OUTPUT: "✅ 当前没有未完成的任务"\n1154\t RETURN\n1155\t\n1156\tELSE IF recovery_mode == "specific" THEN\n1157\t # 情况B:指定了任务名称\n1158\t target_task = FIND_BY_NAME(incomplete_tasks, target_task_name)\n1159\t\n1160\t IF target_task NOT FOUND THEN\n1161\t OUTPUT: "❌ 未找到任务: {target_task_name}"\n1162\t OUTPUT: "💡 使用 \'/dev-flow status\' 查看所有未完成任务"\n1163\t RETURN\n1164\t END IF\n1165\t\n1166\tELSE IF recovery_mode == "auto" THEN\n1167\t # 情况C:自动恢复\n1168\t\n1169\t IF len(incomplete_tasks) == 1 THEN\n1170\t # 只有一个任务,直接恢复\n1171\t target_task = incomplete_tasks[0]\n1172\t OUTPUT: "🔄 自动恢复唯一未完成任务: {target_task.task_name}"\n1173\t\n1174\t ELSE\n1175\t # 多个任务,显示列表让用户选择\n1176\t OUTPUT: task_selection_list(incomplete_tasks)\n1177\t OUTPUT: "请输入要恢复的任务名称,或按回车恢复最新任务"\n1178\t WAIT_FOR_USER_INPUT\n1179\t RETURN\n1180\t END IF\n1181\tEND IF\n1182\t```\n1183\t\n1184\t#### 步骤4:读取任务上下文\n1185\t\n1186\t```\n1187\tcontext_file = dev/active/{target_task.task_name}/context.md\n1188\tcontext_content = READ_FILE(context_file)\n1189\t\n1190\tEXTRACT FROM context.md:\n1191\t - 任务名称\n1192\t - 需求类型\n1193\t - 当前阶段\n1194\t - 执行模式\n1195\t - 已完成工作\n1196\t - 待完成工作\n1197\t - 输入文件路径\n1198\t - 输出文件路径\n1199\t```\n1200\t\n1201\t#### 步骤5:输出恢复信息并调用Agent\n1202\t\n1203\t**恢复信息输出模板**:\n1204\t```\n1205\t# 🔄 恢复未完成任务\n1206\t\n1207\t**任务名称**: {task_name}\n1208\t**中断位置**: {current_stage}\n1209\t**最后更新**: {last_updated}\n1210\t\n1211\t## 📊 任务进度\n1212\t\n1213\t- ✅ 阶段0: 需求澄清(已完成)\n1214\t- ✅ 阶段1: 需求分析(已完成)\n1215\t- 🔄 阶段2: 设计方案生成(**进行中,已中断**)\n1216\t- ⏸️ 阶段3: 代码开发(未开始)\n1217\t- ⏸️ 阶段4: 测试用例生成(未开始)\n1218\t\n1219\t## 🎯 恢复方式\n1220\t\n1221\t### 方式1:使用 /dev-flow 命令(推荐)\n1222\t```bash\n1223\t/dev-flow resume {task_name}\n1224\t```\n1225\t\n1226\t### 方式2:直接调用Agent\n1227\t通过Task工具调用 **{agent_name}** agent恢复被中断任务:\n1228\t\n1229\t```\n1230\tTask(\n1231\t subagent_type: "{agent_name}",\n1232\t prompt: "请基于需求文档生成设计方案:{input_file}"\n1233\t)\n1234\t```\n1235\t\n1236\t---\n1237\t\n1238\t正在从 {current_stage} 继续执行...\n1239\t```\n1240\t\n1241\t**调用Agent继续执行**:\n1242\t主会话从context.md的YAML frontmatter读取currentStage/stageHistory/skipDecisions,按STAGE_ORDER从currentStage开始逐阶段恢复。\n1243\t\n1244\t```\n1245\t1. 读取 dev/active/{task_name}/context.md 的 YAML frontmatter\n1246\t → 提取 currentStage(如"2")、stageHistory(如["0","1"])、skipDecisions(如{"1.1":"skipped"})\n1247\t → 提取 requirementType、executionMode、inputSource\n1248\t2. 从STAGE_ORDER中定位currentStage的下一个阶段\n1249\t3. 按STAGE_ORDER逐阶段恢复执行(与情况1的逐阶段控制相同)\n1250\t4. 跳过stageHistory中已完成的阶段\n1251\t5. 沿用skipDecisions历史决策(不重复询问已跳过的环节)\n1252\t```\n1253\t\n1254\t**任务选择列表输出模板**(多个任务时):\n1255\t```\n1256\t# 🔄 检测到多个未完成任务\n1257\t\n1258\t请选择要恢复的任务:\n1259\t\n1260\t| 序号 | 任务名称 | 需求类型 | 当前阶段 | 最后更新 |\n1261\t|:----:|---------|---------|---------|----------|\n1262\t| 1 | ssh-operation-log | NEW | 阶段2-设计方案 | 2小时前 |\n1263\t| 2 | user-export-excel | ENHANCE | 阶段1-需求分析 | 1天前 |\n1264\t| 3 | login-500-fix | FIX | 阶段3-代码开发 | 3天前 |\n1265\t\n1266\t## 恢复方式\n1267\t\n1268\t### 方式1:恢复最新任务(推荐)\n1269\t```bash\n1270\t/dev-flow resume ssh-operation-log\n1271\t```\n1272\t\n1273\t### 方式2:恢复指定任务\n1274\t```bash\n1275\t/dev-flow resume <任务名称>\n1276\t```\n1277\t\n1278\t例如:\n1279\t```bash\n1280\t/dev-flow resume login-500-fix\n1281\t```\n1282\t\n1283\t---\n1284\t\n1285\t**提示**:输入任务名称即可恢复对应任务\n1286\t```\n1287\t\n1288\t### 情况3:用户查看状态\n1289\t\n1290\t**步骤**:\n1291\t1. 识别关键词 `status`\n1292\t2. 扫描 `dev/active/` 目录,查找所有任务目录\n1293\t3. 对每个任务目录,检查是否存在 `context.md`\n1294\t4. 读取并解析 `context.md`,提取任务信息:\n1295\t - 任务名称、需求类型、当前阶段\n1296\t - 任务状态(进行中/已暂停/已完成)\n1297\t - 创建时间、最后更新时间\n1298\t5. 过滤出状态为"进行中"或"已暂停"的任务\n1299\t6. 按最后更新时间降序排序(最新的在前)\n1300\t7. 输出任务列表\n1301\t\n1302\t**检测逻辑**:\n1303\t```\n1304\t# 扫描单需求轨未完成任务(仅 dev/active/,不含 dev/versions/)\n1305\tFOR EACH directory IN dev/active/:\n1306\t IF directory/context.md EXISTS THEN\n1307\t PARSE context.md\n1308\t IF 任务状态 IN ["进行中", "已暂停"] THEN\n1309\t ADD TO task_list\n1310\t END IF\n1311\t END IF\n1312\tEND FOR\n1313\t\n1314\tSORT task_list BY 最后更新时间 DESC\n1315\t```\n1316\t\n1317\t**输出格式1:有未完成的任务**:\n1318\t```\n1319\t# 📋 任务状态列表\n1320\t\n1321\t## 进行中或已暂停的任务(N个)\n1322\t\n1323\t| 任务名称 | 需求类型 | 当前阶段 | 状态 | 最后更新 |\n1324\t|---------|---------|---------|------|----------|\n1325\t| ssh-operation-log | NEW | 阶段2-设计方案生成 | 已暂停 | 2小时前 |\n1326\t| user-export-excel | ENHANCE | 阶段1-需求分析 | 进行中 | 1天前 |\n1327\t| login-500-fix | FIX | 阶段3-代码开发 | 已暂停 | 3天前 |\n1328\t\n1329\t## 🔄 恢复任务\n1330\t\n1331\t### 方式1:恢复最新任务(推荐)\n1332\t```bash\n1333\t/dev-flow resume\n1334\t```\n1335\t⚠️ 将自动恢复最新的未完成任务:`ssh-operation-log`\n1336\t\n1337\t### 方式2:恢复指定任务\n1338\t```bash\n1339\t/dev-flow resume ssh-operation-log\n1340\t```\n1341\t\n1342\t### 方式3:交互选择\n1343\t请告诉我您想恢复哪个任务,输入任务名称即可。\n1344\t\n1345\t---\n1346\t\n1347\t**提示**:使用 `/dev-flow resume <任务名称>` 恢复指定任务\n1348\t```\n1349\t\n1350\t**输出格式2:没有未完成的任务**:\n1351\t```\n1352\t# 📋 任务状态列表\n1353\t\n1354\t## ✅ 当前没有未完成的任务\n1355\t\n1356\t**检查范围**: dev/active/ 目录\n1357\t**检查结果**: 未发现进行中或已暂停的任务\n1358\t\n1359\t**开始新任务**:\n1360\t使用以下命令启动新的开发任务:\n1361\t\n1362\t```bash\n1363\t/dev-flow <您的需求描述>\n1364\t```\n1365\t\n1366\t例如:\n1367\t```bash\n1368\t/dev-flow 实现用户导出Excel功能\n1369\t```\n1370\t\n1371\t---\n1372\t```\n1373\t\n1374\t### 情况4:修改已有任务的需求/设计 🆕\n1375\t\n1376\t**触发条件**:命令包含 `modify` 参数\n1377\t\n1378\t**步骤**:\n1379\t\n1380\t#### 步骤1:解析参数\n1381\t\n1382\t```\n1383\t提取参数:\n1384\t task_name = --task 参数值\n1385\t modify_from = --from 参数值(requirement 或 design)\n1386\t requirement_doc = --requirement-doc 参数值\n1387\t design_doc = --design-doc 参数值(当 modify_from = design 时必填)\n1388\t```\n1389\t\n1390\t#### 步骤2:验证文档路径\n1391\t\n1392\t```\n1393\t# 验证需求文档存在性\n1394\tIF NOT FILE_EXISTS(requirement_doc) THEN\n1395\t OUTPUT: "❌ 需求文档不存在: {requirement_doc}"\n1396\t RETURN\n1397\tEND IF\n1398\t\n1399\t# 如果从设计阶段开始,验证设计文档存在性\n1400\tIF modify_from == "design" THEN\n1401\t IF NOT FILE_EXISTS(design_doc) THEN\n1402\t OUTPUT: "❌ 设计文档不存在: {design_doc}"\n1403\t RETURN\n1404\t END IF\n1405\tEND IF\n1406\t\n1407\t# 验证任务目录存在性(可选,用于更新上下文)\n1408\ttask_dir = "dev/active/{task_name}"\n1409\tIF NOT DIR_EXISTS(task_dir) THEN\n1410\t OUTPUT: "⚠️ 任务目录不存在: {task_dir},将创建新目录"\n1411\tEND IF\n1412\t```\n1413\t\n1414\t#### 步骤3:读取已有文档内容\n1415\t\n1416\t```\n1417\trequirement_content = READ_FILE(requirement_doc)\n1418\t\n1419\tIF modify_from == "design" THEN\n1420\t design_content = READ_FILE(design_doc)\n1421\tEND IF\n1422\t```\n1423\t\n1424\t#### 步骤4:启动逐阶段修改流程\n1425\t\n1426\t主会话按STAGE_ORDER逐阶段控制,从modify_from指定的阶段开始。\n1427\t\n1428\t**流程A:从需求阶段开始(modify_from = requirement)**\n1429\t\n1430\t从Stage 0开始,按STAGE_ORDER逐阶段控制。差异:\n1431\t- Stage 0/1的subagent prompt增加:`【模式】:modify(修改模式)\\n【已有需求文档路径】:{requirement_doc}\\n请修改原有需求文档,使用Edit工具而非Write`\n1432\t- Stage 2的subagent prompt增加:`【已有设计文档路径】:{design_doc}\\n请修改或创建设计文档`\n1433\t- 跳过前置步骤P1-P7(已有任务工作区)\n1434\t\n1435\t**流程B:从设计阶段开始(modify_from = design)**\n1436\t\n1437\t从Stage 2开始,按STAGE_ORDER逐阶段控制。差异:\n1438\t- Stage 2的subagent prompt增加:`【模式】:modify(修改模式)\\n【已有需求文档路径】:{requirement_doc}\\n【已有设计文档路径】:{design_doc}\\n请修改原有设计文档,使用Edit工具而非Write`\n1439\t- 跳过Stage 0-1(需求文档保持不变)\n1440\t- 跳过前置步骤P1-P7(已有任务工作区)\n1441\t\n1442\t#### 步骤5:输出修改信息\n1443\t\n1444\t**修改信息输出模板**:\n1445\t```\n1446\t# ✏️ 修改已有任务文档\n1447\t\n1448\t**任务名称**: {task_name}\n1449\t**修改起点**: {modify_from}\n1450\t**需求文档**: {requirement_doc}\n1451\t**设计文档**: {design_doc 或 "后续修改"}\n1452\t\n1453\t## 📊 修改流程\n1454\t\n1455\t- 🔄 阶段0: 需求澄清({从需求开始/跳过})\n1456\t- 🔄 阶段1: 需求分析({修改原有文档/保持不变})\n1457\t- 🔄 阶段2: 设计方案生成(修改原有文档)\n1458\t- ⏸️ 阶段3-9: 后续阶段正常执行\n1459\t\n1460\t## ⚠️ 注意事项\n1461\t\n1462\t- 所有修改将在原有文档基础上进行\n1463\t- 文档路径保持不变,不会创建新文件\n1464\t- 建议在修改前备份原有文档\n1465\t\n1466\t---\n1467\t\n1468\t正在从 {modify_from} 阶段开始执行修改...\n1469\t```\n1470\t\n1471\t---\n1472\t\n1473\t## 💡 关于流程主控\n1474\t\n1475\t该命令由主会话按STAGE_ORDER逐阶段控制流程,各阶段由对应的专业subagent执行。\n1476\t\n1477\t主会话会自动完成以下工作:\n1478\t1. **前置步骤**:需求分类(req-type-classifier)、模板适配、竞品分析、项目上下文确认、执行模式选择、工作区初始化\n1479\t2. **逐阶段编排**:按STAGE_ORDER有序列表逐阶段启动专业subagent\n1480\t3. **进度管理**:跟踪执行状态(持久化到versions.json或context.md),支持中断和恢复\n1481\t4. **BIZ API同步**:每个阶段前后调用biz_sync_stage/session更新task-viewer(版本模式)\n1482\t5. **阶段后置动作**:DPMS Hook执行、图表同步检查等\n1483\t\n1484\t---\n1485\t\n1486\t## 🚀 预期输出\n1487\t\n1488\t成功调用后,agent会输出类似以下内容:\n1489\t\n1490\t```markdown\n1491\t# 📝 需求描述格式检测\n1492\t\n1493\t**检测结果**:⚠️ 非模板格式\n1494\t\n1495\t**判断依据**:\n1496\t- ✗ 未检测到模板章节标记\n1497\t- ✗ 未包含【必填】/【选填】标记\n1498\t\n1499\t**后续处理**:\n1500\t→ 系统将自动从您的描述中提取关键信息\n1501\t→ 对于缺失的必填项,将通过问答引导您补充完善\n1502\t\n1503\t---\n1504\t\n1505\t# 🎯 需求类型识别结果\n1506\t\n1507\t**需求类型**:新增功能(NEW)\n1508\t**置信度**:92%\n1509\t**优先级**:P1\n1510\t\n1511\t## 判断依据\n1512\t- ✓ 包含关键词"实现"\n1513\t- ✓ 描述了明确的业务功能\n1514\t\n1515\t---\n1516\t\n1517\t# 📋 建议处理流程\n1518\t\n1519\t## 第0阶段:需求澄清对话 💬 【必选】\n1520\t## 第1阶段:需求分析与文档生成 📝 【必选】\n1521\t## 第1.1阶段:需求文档质量检视 🔍 🆕 【可跳过】\n1522\t## 第1.2阶段:需求知识同步 📚 🆕 【可跳过】\n1523\t## 第1.6阶段:组件依赖分析(可选)\n1524\t## 第2阶段:设计方案生成 📐 【必选】\n1525\t## 第2.1阶段:设计文档质量检视 🔍 🆕 【可跳过】\n1526\t## 第2.2阶段:设计知识同步 📚 🆕 【可跳过】\n1527\t## 第3阶段:代码开发 💻 【必选】\n1528\t## 第3.1阶段:代码知识同步 📚 🆕 【可跳过】\n1529\t## 第4阶段:自动部署 🚀 【可跳过】\n1530\t## 第5阶段:部署确认 ⏸️ 【依赖第4阶段】\n1531\t## 第6阶段:测试验证 🧪 【必选】\n1532\t## 第6.1阶段:回归测试知识同步 📚 🆕 【可跳过】\n1533\t## 第7阶段:测试执行 ⚡ 【必选】\n1534\t## 第8阶段:测试报告生成 📊 【必选】\n1535\t## 第9阶段:循环决策 🔄 【必选】\n1536\t\n1537\t### ⏭️ 环节跳过机制 🆕\n1538\t\n1539\t**核心原则**:到了可跳过环节 → 询问用户 → 用户决定\n1540\t\n1541\t**可跳过环节**:第1.1、第1.2、第1.6、第2.1、第2.2、第3.1、第4、第6.1阶段\n1542\t\n1543\t**询问方式**:使用AskUserQuestion工具,不使用文本问答\n1544\t\n1545\t**决策记录路径**:\n1546\t- 版本轨:`dev/versions/versions.json` 中该需求的 `skipDecisions` 字段\n1547\t- 单需求轨:`dev/active/{task-name}/context.md` 的 YAML frontmatter `skipDecisions` 字段\n1548\t\n1549\t**跳过时执行以下操作**:\n1550\t\n1551\t```\n1552\t用户选择跳过某环节时:\n1553\t\n1554\t# 1. 本地记录\n1555\tskip_decision = {\n1556\t stage: "{当前环节编号和名称}",\n1557\t skipped_at: "{当前时间}",\n1558\t reason: "用户主动跳过"\n1559\t}\n1560\t更新 versions.json/context.md 中 skipDecisions[{stage}] = "skipped"\n1561\t\n1562\t# 2. 写入 pending(统一使用MCP工具,确保与Hook的pending写入到同一位置)\n1563\tmcp__biz-sync__save_pending_item(\n1564\t version_id="{current_version_id}",\n1565\t task_name="{环节中文名称}",\n1566\t mcp_method="",\n1567\t skip_reason="USER_SKIPPED",\n1568\t context_description="用户跳过:{环节中文名称}(Stage {所属主阶段})"\n1569\t)\n1570\t\n1571\t# 3. 同步 task stage 到下一阶段(让 task-viewer 反映真实进展,仅版本模式)\n1572\tIF biz_task_id 非空 THEN\n1573\t biz_api_url = 从版本配置(versions.json该需求的biz_api_url字段)读取;若为空则从环境变量BIZ_API_BASE获取;若仍为空则使用默认值http://localhost:50009\n1574\t 根据下方的「可跳过环节→下一阶段映射表」确定 next_stage 和 next_progress\n1575\t 🛡️ mcp__biz-sync__biz_sync_stage(\n1576\t biz_api_url=biz_api_url,\n1577\t biz_task_id=biz_task_id,\n1578\t stage=next_stage,\n1579\t progress=next_progress,\n1580\t status="running"\n1581\t )\n1582\t ⚠️ 使用safe_biz_sync包装器(失败时自动记录save_pending_item,不打扰用户)\n1583\tEND IF\n1584\t\n1585\tOUTPUT: "⏭️ 已跳过 {环节名称},继续执行下一阶段"\n1586\t```\n1587\t\n1588\t**可跳过环节→下一阶段映射表**:\n1589\t\n1590\t| 当前环节 | task 描述 | 所属主阶段 | 跳过后推进到的 stage | 跳过后 progress |\n1591\t|---------|----------|-----------|-------------------|:--------------:|\n1592\t| 第1.1 需求检视 | 需求文档质量检视 | requirement | requirement_review | 20 |\n1593\t| 第1.2 需求知识同步 | 需求知识库同步 | requirement | requirement_review | 25 |\n1594\t| 第1.6 组件依赖分析 | 组件依赖关系分析 | requirement | design | 30 |\n1595\t| 第2.1 设计检视 | 设计文档质量检视 | design | design_review | 38 |\n1596\t| 第2.2 设计知识同步 | 设计知识库同步 | design | development | 50 |\n1597\t| 第3.1 代码知识同步 | 代码知识库同步 | development | deployment | 65 |\n1598\t| 第4 自动部署 | 自动部署 | deployment | deployment | 70 |\n1599\t| 第6.1 回归测试同步 | 回归测试知识同步 | testing | test_execution | 90 |\n1600\t\n1601\t**决策逻辑**:根据测试报告决定下一步行动\n1602\t\n1603\t### 决策条件\n1604\t\n1605\t| 条件 | 操作 | 说明 |\n1606\t|-----|------|------|\n1607\t| ✅ 所有测试通过且无缺陷 | **退出循环** | 流程结束 |\n1608\t| 🔄 存在失败测试用例或缺陷 | **继续循环** | 返回第1阶段,调用req-fix-bug-analyzer生成bug fix子需求 |\n1609\t| ⚠️ 达到最大循环次数(10次) | **强制退出** | 停止循环,输出警告 |\n1610\t\n1611\t### 继续循环流程\n1612\t\n1613\t当检测到失败测试用例或缺陷时:\n1614\t\n1615\t1. **读取测试报告**:从test-status.json获取失败信息\n1616\t2. **生成bug fix子需求**:\n1617\t - 调用 `req-fix-bug-analyzer` Agent\n1618\t - 生成类型为FIX的子需求文档\n1619\t - 在cycle-state.json中记录父子关系:\n1620\t ```json\n1621\t {\n1622\t "parentRequirementId": "原需求ID",\n1623\t "subRequirementType": "bug-fix",\n1624\t "relatedTestCases": ["失败的测试用例ID列表"]\n1625\t }\n1626\t ```\n1627\t3. **子需求测试处理**:\n1628\t - 测试用例生成:基于父需求测试用例文档**修改/新增**,不重新生成\n1629\t - 测试代码生成:基于父需求测试代码**修改/新增**,不重新生成\n1630\t - 测试执行:执行修改后的测试用例/代码\n1631\t4. **重复循环**:从第1阶段(需求分析)开始重新执行\n1632\t\n1633\t### 状态文件\n1634\t\n1635\t- **cycle-state.json**:记录循环次数、父子需求关系、失败用例列表\n1636\t- **test-status.json**:记录测试执行状态和结果\n1637\t\n1638\t---\n1639\t\n1640\t### 情况5:用户查看已完成任务 🆕\n1641\t\n1642\t**触发条件**:命令为 `completed` 或包含 `completed` 关键词\n1643\t\n1644\t**步骤**:\n1645\t\n1646\t#### 步骤1:解析参数\n1647\t\n1648\t```\n1649\tIF 命令包含 "--limit" THEN\n1650\t limit = 提取 --limit 参数值\n1651\tELSE\n1652\t limit = null # 显示全部\n1653\tEND IF\n1654\t```\n1655\t\n1656\t#### 步骤2:扫描已完成任务\n1657\t\n1658\t**扫描逻辑**:\n1659\t```\n1660\tcompleted_tasks = []\n1661\t\n1662\t# 扫描单需求轨已完成任务(仅 dev/active/ 和 dev/completed/,不含 dev/versions/)\n1663\tFOR EACH directory IN dev/active/:\n1664\t IF context.md EXISTS THEN\n1665\t PARSE context.md\n1666\t IF 任务状态 == "已完成" THEN\n1667\t ADD TO completed_tasks WITH:\n1668\t - 任务名称\n1669\t - 需求类型\n1670\t - 完成时间\n1671\t - 状态 = "未归档"\n1672\t END IF\n1673\t END IF\n1674\tEND FOR\n1675\t\n1676\t# 扫描 dev/completed/ 中的任务(已归档)\n1677\tFOR EACH directory IN dev/completed/:\n1678\t IF context.md EXISTS THEN\n1679\t PARSE context.md\n1680\t ADD TO completed_tasks WITH:\n1681\t - 任务名称\n1682\t - 需求类型\n1683\t - 完成时间\n1684\t - 状态 = "已归档"\n1685\t END IF\n1686\tEND FOR\n1687\t```\n1688\t\n1689\t#### 步骤3:排序和限制\n1690\t\n1691\t```\n1692\t# 按完成时间降序排序\n1693\tSORT completed_tasks BY 完成时间 DESC\n1694\t\n1695\t# 限制返回数量\n1696\tIF limit EXISTS THEN\n1697\t completed_tasks = completed_tasks[:limit]\n1698\tEND IF\n1699\t```\n1700\t\n1701\t#### 步骤4:输出任务列表\n1702\t\n1703\t**输出格式1:有已完成的任务**:\n1704\t```\n1705\t# 📋 已完成任务列表(最近N个)\n1706\t\n1707\t| 任务名称 | 需求类型 | 完成时间 | 状态 |\n1708\t|---------|---------|---------|------|\n1709\t| ssh-operation-log | NEW | 2026-04-09 | 已归档 |\n1710\t| user-export-excel | ENHANCE | 2026-04-08 | 未归档 |\n1711\t| login-500-fix | FIX | 2026-04-07 | 未归档 |\n1712\t\n1713\t**统计**: 共 3 个已完成任务(已归档 1 个,未归档 2 个)\n1714\t\n1715\t## 🔄 任务操作\n1716\t\n1717\t### 查看任务详情\n1718\t```bash\n1719\t# 查看未归档任务\n1720\tcat dev/active/ssh-operation-log/context.md\n1721\t\n1722\t# 查看已归档任务\n1723\tcat dev/completed/ssh-operation-log/context.md\n1724\t```\n1725\t\n1726\t### 修改已完成任务\n1727\t使用 `/dev-flow modify` 命令重新执行需求或设计阶段。\n1728\t\n1729\t---\n1730\t```\n1731\t\n1732\t**输出格式2:没有已完成的任务**:\n1733\t```\n1734\t# 📋 已完成任务列表\n1735\t\n1736\t## ✅ 当前没有已完成的任务\n1737\t\n1738\t**检查范围**: dev/active/ 和 dev/completed/ 目录\n1739\t**检查结果**: 未发现已完成的任务\n1740\t\n1741\t**开始新任务**:\n1742\t使用以下命令启动新的开发任务:\n1743\t\n1744\t```bash\n1745\t/dev-flow <您的需求描述>\n1746\t```\n1747\t\n1748\t---\n1749\t```\n1750\t\n1751\t---\n1752\t\n1753\t# ⚙️ 执行模式选择\n1754\t\n1755\t请选择:\n1756\t1. 快速模式(自动执行,每阶段完成后按回车继续)\n1757\t2. 分步模式(每阶段完成后等待确认)\n1758\t```\n1759\t\n1760\t---\n1761\t\n1762\t## ⛔ 完成验证\n1763\t\n1764\t- [ ] 语法类型正确识别 = ?\n1765\t- [ ] P0 规范化检查 = ? (通过/跳过)\n1766\t- [ ] P1 步骤1 项目上下文 = ? (读取/生成/跳过)\n1767\t- [ ] P1 分类结果 = ?\n1768\t- [ ] P2 模板适配 = ?\n1769\t- [ ] P3 竞品分析 = ? (执行/跳过)\n1770\t- [ ] P3.5 价值收益评估 = ? (执行/跳过)\n1771\t- [ ] P4 项目上下文确认 = ? (确认/生成/继续默认)\n1772\t- [ ] P4.5 项目级交互配置 = ? (新增/调整/沿用/删除/跳过默认)\n1773\t- [ ] P5 执行模式 = ?\n1774\t- [ ] P6 工作区初始化 = ?\n1775\t- [ ] P7 知识库构建 = ? (built/skipped/部分built)\n1776\t- [ ] STAGE_ORDER逐阶段控制已启动 = ?\n1777\t- [ ] 阶段后置动作(图表同步)已执行 = ?\n1778\t\n1779\t⛔ 流程结束后输出完成摘要\n1780\t'}] + +**AI**: +[思考] 我现在已经有了非常完整的信息。让我梳理两条流程: + +## 流程1: `/dev-flow version` (版本轨) + +### 入口层 (dev-flow.md) +- 步骤0: 检测版本状态 (读 versions.json) +- 步骤1: 根据状态展示菜单 (NO_VERSION / HAS_ACTIVE / ALL_COMPLETED) +- 步骤2A: 创建版本引导 -> 调用 create-version.md (A1版本计划/A2a产品线/A2b子系统/A5 SIT测试集/A5.1回归测试集/本地配置/Git分支/PACE流水线/Business API) +- 步骤2B: 需求管理子菜单 (添加需求/查看/删除/启动开发) +- 添加需求: 调用 mcp__sdp__add-system-story (A3) + mcp__sdp__associate-subsystem-version (A4) +- 启动版本需求: 调用 start-development.md +- 继续开发/完成版本/待补录管理/生成变更单/回滚 + +### 启动版本需求层 (start-development.md) +- 关联需求前置 (associate-requirement.md: A4-1, A4-2) +- P0-P7 前置步骤: + - P0: 需求描述规范化检查 (无agent) + - P1: 需求分类 -> project-context-analyzer (可选) + req-type-classifier + - P2: 模板适配 -> req-template-adapter + - P3: 竞品分析 -> competitor-analyzer + - P3.5: 价值收益评估 (无agent,引导填写) + - P4: 项目上下文确认 -> project-context-analyzer (可选) + - P4.5: 项目级交互特性配置 (无agent,配置文件) + - P5: 执行模式选择 (无agent) + - P6: 工作区初始化 (无agent) + - P7: 知识库构建 -> module-identifier(identifier.py) + knowledge-base-builder (Skill) +- 步骤A: 创建 Business API Task +- 步骤B: 创建 Business API Session +- 步骤C: 更新 Version 状态 +- 步骤D: 版本参数块 +- 步骤E: 形态B分段交错编排 (execute_segments) + +### 21阶段层 (stage-hooks.md) - 版本模式 +STAGE_ORDER = [0, 1, 1.1, 1.2, 1.6, 2, 2.1, 2.2, 3, 3.1, 3.2, 3.5, 4, 5, 5.5, 6, 6.1, 7, 8, 9, 10] + +每个stage的Agent/Skill: +- 0 需求澄清: req-clarification-orchestrator +- 1 需求分析: req-xxx-analyzer (按类型: req-new-feature-analyzer / req-enhance-feature-analyzer / req-fix-bug-analyzer / req-optimize-analyzer / req-refactor-analyzer / req-integrate-analyzer) +- 1.1 需求检视: req-recheck-orchestrator +- 1.2 需求知识同步: module-requirement-manager (Skill) +- 1.6 组件依赖分析: component-dependency-analyzer-{lang} (Skill: -java/-python/-go) +- 2 设计方案: des-xxx (按类型: des-new-feature / des-enhance-feature / des-fix-bug / des-optimize / des-refactor / des-integrate) +- 2.1 设计检视: des-recheck-orchestrator +- 2.2 设计知识同步: module-design-manager (Skill) +- 3 代码开发: xxx-code-developer (java-code-developer / python-code-developer / go-code-developer / typescript-code-developer / frontend-c... + + +## 交互记录 (2026-07-27T09:23:53.774Z) + +**用户**: +[{'tool_use_id': 'call_f4ec5d5dddaa47c09a8d6dc2', 'type': 'tool_result', 'content': '1\t# 启动版本需求步骤清单\n2\t\n3\t> 来源:dev-flow.md "启动版本需求"章节\n4\t> 用途:执行启动版本需求操作时必须Read本文件,按步骤逐项执行\n5\t\n6\t## 幂等性检查\n7\t\n8\t读取 `dev/versions/{versionName}/` 目录和版本配置,检查 `started` 标志:\n9\t- 若 `started == true`:输出 "⚠️ 版本 {versionName} 已启动" + 已启动需求列表,结束\n10\t- 若 `started == false` 或不存在:继续执行\n11\t\n12\t## 前置步骤 — 关联需求到版本计划\n13\t\n14\t读取版本配置,检查 `assigned` 标志:\n15\t- 若 `assigned == true`:已关联,跳过此步骤,直接进入启动确认\n16\t- 若 `assigned == false`:需要先处理"关联需求到版本计划",展示以下选项(使用 AskUserQuestion):\n17\t\n18\t **情形1 — `dpms.versionPlanId` 为空(DPMS 版本计划未创建)**:\n19\t - 选项1: "**跳过关联,直接启动开发**" — 将"关联需求到版本计划"写入 PendingItem,标记 `assigned=true`(跳过),直接进入启动确认\n20\t - 选项2: "**取消**" → 终止流程,返回主菜单\n21\t\n22\t **情形2 — `dpms.versionPlanId` 存在但需求缺少 `dpmsStoryId`**:\n23\t - 选项1: "**跳过关联,直接启动开发**" — 将"关联需求到版本计划"写入 PendingItem,标记 `assigned=true`(跳过),直接进入启动确认\n24\t - 选项2: "**先去待补录管理补录 Story ID**" — 引导跳转到待补录管理,结束当前流程\n25\t - 选项3: "**取消**" → 终止流程,返回主菜单\n26\t\n27\t **情形3 — `dpms.versionPlanId` 存在且所有需求均有 `dpmsStoryId`**:\n28\t - 选项1: "**执行关联(推荐)**" — 调用 DPMS MCP 关联需求到版本计划(见"关联需求到版本计划"checklist步骤2~6),成功后标记 `assigned=true`\n29\t - 选项2: "跳过关联,直接启动开发" — 将"关联需求到版本计划"写入 PendingItem,标记 `assigned=true`(跳过),直接进入启动确认\n30\t - 选项3: "**取消**" → 终止流程,返回主菜单\n31\t\n32\t **注意**:创建测试评审(A6)已移至Stage6-Hook B5.5自动执行,不再在版本初始化阶段手动触发。\n33\t\n34\t 用户选择"跳过关联"时,执行跳过写入规则(需写入所有被跳过的操作):\n35\t ```\n36\t # 1a. 关联需求到发布计划(A4-1)\n37\t mcp__biz-sync__save_pending_item(\n38\t version_id="{versionName}",\n39\t task_name="关联需求到发布计划({需求数量}条)",\n40\t mcp_method="mcp__sdp__update-story",\n41\t mcp_params={ storyIds: "[需求storyId列表]", releasePlanId },\n42\t skip_reason="USER_SKIPPED",\n43\t context_description="启动开发时跳过A4-1:关联需求到发布计划"\n44\t )\n45\t\n46\t # 1b. 关联需求到子系统版本(A4-2)⭐阶段1 S5 H2修正:按 reqSubsystemId 分组记录待补录\n47\t mcp__biz-sync__save_pending_item(\n48\t version_id="{versionName}",\n49\t task_name="关联需求到子系统版本({需求数量}条,按reqSubsystemId分组)",\n50\t mcp_method="mcp__sdp__associate-subsystem-version",\n51\t mcp_params={ "说明": "按reqSubsystemId分组,每组{subSystemId, version:对应子系统subsystemVersionId, storyIds}", storyIds: "[需求storyId列表]" },\n52\t skip_reason="USER_SKIPPED",\n53\t context_description="启动开发时跳过A4-2:关联需求到子系统版本(多子系统时各组独立补录)"\n54\t )\n55\t\n56\t # 注意:创建测试评审(A6)已移至Stage6-Hook B5.5自动执行,不再在版本初始化阶段记录PendingItem\n57\t ```\n58\t 更新本地版本配置:`assigned=true`\n59\t OUTPUT: "⚠️ 已跳过需求关联,已记录到待补录列表。测试评审将在Stage6-Hook中自动执行。"\n60\t\n61\t## 启动确认\n62\t\n63\t1. 从版本配置中读取所有可启动的需求列表(根据上一步用户选择过滤)\n64\t2. 若为空:输出 "❌ 版本 {versionName} 下无可启动的需求",结束\n65\t3. 使用 AskUserQuestion 展示需求列表并确认:\n66\t - "**启动全部 N 个需求**"\n67\t - "**选择特定需求启动**"\n68\t\n69\t## 前置步骤(启动前必做,按顺序执行)\n70\t\n71\t确认启动后,**在执行步骤A之前**,按以下顺序执行前置步骤:\n72\t\n73\t### P0. 需求描述规范化检查\n74\t\n75\t检测需求描述是否包含四要素:背景、目的、输入、输出。\n76\t\n77\t| 要素 | 检测关键词(满足任一即可) | 最低要求 | 权重 |\n78\t|:---:|--------------------------|---------|:----:|\n79\t| 背景 | 痛点/现状/当前/问题/背景/原因/为什么 | ≥1关键词 + ≥10字描述 | 25% |\n80\t| 目的 | 目标/价值/期望/实现/功能/支持/达到 | ≥1关键词 + ≥10字描述 | 25% |\n81\t| 输入 | 输入/填写/选择/上传/参数/条件/操作/步骤 | ≥1关键词 + ≥5字描述 | 25% |\n82\t| 输出 | 输出/生成/返回/显示/导出/结果/文件/数据 | ≥1关键词 + ≥5字描述 | 25% |\n83\t\n84\t**通过标准**:≥75分(至少3要素通过)\n85\t\n86\t→ IF 通过:继续执行P1\n87\t→ IF 未通过:\n88\t OUTPUT: "⚠️ 需求描述缺少关键信息:{缺失要素列表},补充后可提高后续分析精度"\n89\t AskUserQuestion("是否补充缺失信息?",\n90\t ["补充信息 — 我将补充{缺失要素}的描述",\n91\t "跳过检查 — 直接进入需求分类(可能影响分析精度)"])\n92\t IF "补充信息":等待用户补充 → 重新检测(最多2轮)\n93\t IF "跳过":继续执行P1\n94\t\n95\t### P1. 需求分类(三步保障)\n96\t\n97\t**步骤1:主会话读取项目上下文**\n98\t→ 读取项目根目录 `project-context.json`\n99\t→ 若存在:\n100\t 提取现有模块名称列表 → `existing_modules`\n101\t 提取技术栈摘要 → `tech_stack_summary`(如"Java/Spring Boot 3.x/MySQL 8.x")\n102\t→ 若不存在:\n103\t AskUserQuestion("⚠️ 未检测到项目上下文文件,是否生成?",\n104\t ["生成项目上下文(推荐)— 自动分析技术栈、代码规范和现有模块(约1-2分钟)",\n105\t "跳过 — 按新项目模式处理,使用默认技术栈规范,P4仍可补充生成"])\n106\t IF 用户选择"生成":\n107\t Agent(subagent_type: "project-context-analyzer", prompt: "请分析当前项目的完整上下文")\n108\t → 等待完成后重新读取 project-context.json\n109\t → 提取 `existing_modules` + `tech_stack_summary`\n110\t ELSE:\n111\t `existing_modules` = []\n112\t `tech_stack_summary` = "(未生成项目上下文,使用默认配置)"\n113\t\n114\t**步骤2:调用req-type-classifier分类(传入项目上下文)**\n115\t```\n116\tAgent(\n117\t subagent_type: "req-type-classifier",\n118\t description: "需求分类识别",\n119\t prompt: "请按4步分类决策树识别以下需求的类型(只需分类,不要执行后续流程):\n120\t\n121\t需求名称:{name}\n122\t需求描述:{description}\n123\t项目现有模块:{existing_modules}\n124\t项目技术栈:{tech_stack_summary}\n125\t\n126\t4步分类决策树:\n127\t1. 是否涉及第三方系统集成?→ INTEGRATE\n128\t2. 是否是Bug修复?→ FIX\n129\t3. 是否涉及架构变更?→ REFACTOR vs OPTIMIZE\n130\t4. 项目是否已有类似模块?→ NEW vs ENHANCE\n131\t\n132\t输出格式(严格遵守):\n133\t分类结果:{TYPE}\n134\t置信度:{0.0-1.0}\n135\t优先级:P0/P1/P2(P0最高,依据紧急度与业务影响判断)\n136\t理由:{简要理由}\n137\t决策路径:{走了哪几步,如"第2步识别为FIX"}"\n138\t)\n139\t```\n140\t\n141\t**步骤3:用户确认分类结果**\n142\t\n143\t输出分类结果表格后,使用 AskUserQuestion 确认:\n144\t- 如果置信度 **< 0.8**:强制确认(必须用户选择才能继续)\n145\t- 如果置信度 **≥ 0.8**:允许快速确认\n146\t- 选项:"确认正确" / "修改为 NEW" / "修改为 ENHANCE" / "修改为 FIX" / "修改为 OPTIMIZE" / "修改为 REFACTOR" / "修改为 INTEGRATE"\n147\t\n148\t将**确认后**的分类结果写回 `dev/versions/versions.json` 中各需求的 `type` 字段;同时将 req-type-classifier 输出的**优先级**(P0/P1/P2,P0最高)写回该需求的 `priority` 字段(覆盖添加需求时的留空值,用户确认分类时一并接受优先级)。\n149\t\n150\t### P2. 模板适配(如果需求描述是非模板格式)\n151\t→ 检测需求描述是否包含模板章节标记(如【必填】、【背景】等)\n152\t→ 如果是非模板格式:\n153\t ```\n154\t Agent(\n155\t subagent_type: "req-template-adapter",\n156\t prompt: "从以下需求描述中提取关键信息并引导补全必填项:\\n{需求描述}"\n157\t )\n158\t ```\n159\t→ 如果已是模板格式或已提取完成:跳过\n160\t\n161\t### P3. 竞品分析(默认执行,用户可选择跳过)\n162\t```\n163\tAskUserQuestion("竞品分析可能耗时较长(通常2-5分钟),是否执行?",\n164\t ["执行竞品分析(推荐)— 提供行业视角,帮助发现遗漏功能",\n165\t "跳过竞品分析 — 节省时间,但不获取竞品参考信息"])\n166\t\n167\tIF 用户选择"执行竞品分析" THEN\n168\t Agent(\n169\t subagent_type: "competitor-analyzer",\n170\t description: "竞品分析",\n171\t prompt: "{需求描述}"\n172\t )\n173\t → 竞品分析结果存储为 `competitor_analysis_result`\n174\t → 此结果将传递给Stage 0的req-clarification-orchestrator\n175\t → `competitor_analysis_summary` = 竞品分析核心发现摘要(<=500字)\n176\tELSE\n177\t → `competitor_analysis_summary` = "(用户跳过竞品分析)"\n178\t → OUTPUT: "⚠️ 已跳过竞品分析,需求澄清将不包含竞品参考信息"\n179\tEND IF\n180\t```\n181\t\n182\t### P3.5. 价值收益评估(默认执行,用户可选择跳过) 🆕\n183\t\n184\t使用 AskUserQuestion 询问用户是否进行价值收益评估:\n185\t```\n186\tAskUserQuestion("是否执行价值收益评估?",\n187\t ["执行评估 — 提供包含增效与降本维度的具体业务价值",\n188\t "跳过评估 — 节省时间,不单独描述价值收益(收敛于后续澄清流程)"])\n189\t\n190\tIF 用户选择"执行评估" THEN\n191\t 引导用户填写降本与增效两个核心澄清维度的收益:\n192\t 1. 增效维度:请描述该需求的增效收益(如:缩短业务流程、减少人工处理时间、提高吞吐等)\n193\t 2. 降本维度:请描述该需求的降本收益(如:降低人力成本、节省服务器与计算资源、减少授权费用等)\n194\t → 拼接答案存入 `value_benefit_summary`(格式为 "【增效】...;【降本】...")\n195\t → 写入 context.md 的 "价值收益摘要" 字段\n196\tELSE\n197\t → `value_benefit_summary` = "(用户跳过价值收益评估)"\n198\t → 写入 context.md 的 "价值收益摘要" 字段\n199\tEND IF\n200\t```\n201\t\n202\t### P4. 项目上下文确认\n203\t→ 若 `project-context.json` 存在:\n204\t 展示项目上下文摘要(若P3竞品分析已执行,融入竞品分析发现的遗漏功能;若P3已跳过,仅展示项目上下文)\n205\t AskUserQuestion确认:"以上项目上下文信息是否正确?"\n206\t→ 若不存在:\n207\t OUTPUT: "⚠️ 未检测到项目上下文文件"\n208\t | 影响项 | 问题描述 |\n209\t |-------|---------|\n210\t | 现有模块识别 | 无法自动识别现有模块,可能导致功能重复开发 |\n211\t | 代码规范继承 | 无法继承项目代码规范,生成的代码可能不兼容 |\n212\t | Stage 3 Agent选择 | 无法自动确定后端开发语言和前端框架,Stage 3 3D决策(语言+功能属性+前端检测)将缺少关键输入 |\n213\t\n214\t AskUserQuestion("是否现在生成项目上下文?",\n215\t ["生成项目上下文(推荐)— 自动分析技术栈和代码规范",\n216\t "继续 — 按默认配置处理"])\n217\t IF "生成":\n218\t Agent(subagent_type: "project-context-analyzer", prompt: "请分析当前项目的完整上下文")\n219\t → 生成完成后展示摘要 → AskUserQuestion确认:"以上项目上下文信息是否正确?"\n220\t IF "继续":标记project_context_confirmed=false → 继续P4.5\n221\t\n222\t### P4.5. 项目级交互特性配置(强制询问)⭐项目级交互配置\n223\t\n224\t**强制规则**:即便检测到项目级配置已存在,也**必须**询问用户是否需要调整。本步骤在 P4 之后、P5 之前执行。\n225\t\n226\t**配置作用**:版本全流程 21 个环节(12 个不可跳过 + 9 个可跳过)的「跳过询问/自动执行」策略,以及 Stage 9 测试失败后的循环决策策略。每个模板同时包含 step_mode、fast_mode 和独立的 `loop_decision.mode`;`loop_decision` 不受 P5 执行模式影响,也不等同于 `step_mode.non_skippable.9`(后者只控制进入 Stage 9 前是否确认)。\n227\t\n228\t**配置文件路径**:\n229\t- 模板库(系统级,随 install 安装更新):`.claude/config/dev-flow-interaction-templates.json`\n230\t- 运行时配置(项目级,用户个性化;install.bat --core 模式 exclude,不覆盖):`.claude/config/dev-flow-interaction-config.json`\n231\t\n232\t**步骤1:检测现有配置**\n233\t```\n234\tCONFIG_PATH = ".claude/config/dev-flow-interaction-config.json"\n235\tconfig_exists = FILE_EXISTS(CONFIG_PATH)\n236\t\n237\tFUNCTION normalize_loop_decision(config, config_exists):\n238\t IF config == null THEN config = {}\n239\t IF config.loop_decision.mode IN ["auto", "ask"] THEN RETURN config\n240\t # 兼容 schema 1.0:沿用旧配置对 Stage 9 的显式确认倾向;无配置或非法值时安全回退为 ask\n241\t IF config_exists AND config.step_mode.non_skippable["9"] == "auto_execute" THEN\n242\t config.loop_decision.mode = "auto"\n243\t ELSE\n244\t config.loop_decision.mode = "ask"\n245\t END IF\n246\t RETURN config\n247\tEND FUNCTION\n248\t```\n249\t\n250\t**步骤2:根据存在性分流**\n251\t\n252\t```\n253\tIF NOT config_exists THEN\n254\t # 场景1:新增设置\n255\t AskUserQuestion(\n256\t question: "检测到当前项目未配置版本全流程交互特性。是否现在设置?(共21个环节:12个不可跳过 + 9个可跳过)",\n257\t header: "交互配置",\n258\t options: [\n259\t {label: "是,现在设置", description: "选择模板或自定义,配置各环节的跳过/自动执行策略"},\n260\t {label: "否,使用默认", description: "沿用系统默认行为(可跳过环节逐个询问、不可跳过环节自动执行、测试失败时询问是否循环)"}\n261\t ]\n262\t )\n263\t IF "否,使用默认" → interaction_config = null、loopDecisionMode = "ask" → 写入context.md的interactionConfig字段为空 → 进入P5\n264\t IF "是,现在设置" → 执行步骤3(选择模板)→ 执行步骤4(确认写入,is_new=true)\n265\tELSE\n266\t # 场景2:调整设置(即便存在也强制询问)\n267\t 读取 CONFIG_PATH → 调用 normalize_loop_decision(config, true) → 提取 template_name、configured_at 和 loop_decision.mode\n268\t AskUserQuestion(\n269\t question: "检测到当前项目已存在交互特性配置({template_name},配置于{configured_at})。是否需要调整?",\n270\t header: "调整配置",\n271\t options: [\n272\t {label: "沿用现有配置", description: "不修改,直接启动版本"},\n273\t {label: "重新选择模板", description: "覆盖现有配置,重新选择模板"},\n274\t {label: "微调当前配置", description: "在现有基础上逐环节修改"},\n275\t {label: "删除配置", description: "移除项目级配置,恢复系统默认行为"}\n276\t ]\n277\t )\n278\t IF "沿用现有配置" → interaction_config = 读取的现有config → 写入context.md → 进入P5\n279\t IF "重新选择模板" → 执行步骤3 → 执行步骤4(is_new=false,覆盖模式)\n280\t IF "微调当前配置" → 执行步骤5(自定义向导,base=现有config)→ 执行步骤4(is_new=false)\n281\t IF "删除配置" → 删除CONFIG_PATH → interaction_config = null → 写入context.md为空 → 进入P5\n282\tEND IF\n283\t```\n284\t\n285\t**步骤3:选择配置模板**\n286\t\n287\t```\n288\tAskUserQuestion(\n289\t question: "请选择配置模板:",\n290\t header: "配置模板",\n291\t options: [\n292\t {label: "标准开发模式(推荐)", description: "可跳过环节均询问;测试失败时询问是否进入下一轮修复"},\n293\t {label: "极简高效模式", description: "可跳过环节默认跳过(除3.2/3.5询问);不可跳过环节均自动执行"},\n294\t {label: "质量优先模式", description: "检视/自检环节强制执行;分步模式核心环节均询问"},\n295\t {label: "自定义模式", description: "逐环节配置(6组向导,8-10轮)"}\n296\t ]\n297\t)\n298\tIF 选"自定义模式" → 执行步骤5(base=null)→ 返回config对象\n299\tELSE → 从 dev-flow-interaction-templates.json 的 templates.{对应id} 读取 → 深拷贝为config对象\n300\t 模板id映射:标准开发模式→standard_development / 极简高效模式→minimal_efficient / 质量优先模式→quality_first\n301\t```\n302\t\n303\t**步骤4:确认并写入配置(含摘要展示)**\n304\t\n305\t```\n306\t# 渲染配置摘要(含21个环节完整名称,输出step_mode和fast_mode两张Markdown表格,并单列循环决策策略)\n307\tOUTPUT render_config_summary(config)\n308\t # 表格列:序号 | 环节名称 | 跳过支持 | 配置值\n309\t # 环节名称取自 stage-hooks.md 阶段Agent映射表(0=需求澄清 ... 10=版本级回归测试)\n310\t # 循环决策:config.loop_decision.mode(auto=自动进入修复循环;ask=每次失败询问用户)\n311\t\n312\tIF is_new == true THEN\n313\t AskUserQuestion(\n314\t question: "以上为配置摘要({template_name}),是否确认应用?",\n315\t header: "确认配置",\n316\t options: [\n317\t {label: "确认应用", description: "写入配置文件,继续启动版本"},\n318\t {label: "重新选择模板", description: "返回步骤3重新选择"},\n319\t {label: "微调当前模板", description: "在当前模板基础上逐环节修改"}\n320\t ]\n321\t )\n322\t IF "确认应用" → 执行写入(见下方)\n323\t IF "重新选择模板" → 回到步骤3\n324\t IF "微调当前模板" → 执行步骤5(base=当前config)→ 回到步骤4\n325\tELSE # 调整场景(is_new == false)\n326\t AskUserQuestion(\n327\t question: "以上为新配置摘要({template_name}),将覆盖现有配置。是否确认应用?",\n328\t header: "确认覆盖",\n329\t options: [\n330\t {label: "确认覆盖应用", description: "写入新配置,覆盖现有,继续启动版本"},\n331\t {label: "重新选择模板", description: "返回步骤3重新选择"},\n332\t {label: "微调当前模板", description: "在当前模板基础上逐环节修改"},\n333\t {label: "取消,保留原配置", description: "放弃修改,沿用现有配置"}\n334\t ]\n335\t )\n336\t IF "确认覆盖应用" → 执行写入\n337\t IF "重新选择模板" → 回到步骤3\n338\t IF "微调当前模板" → 执行步骤5(base=当前config)→ 回到步骤4\n339\t IF "取消,保留原配置" → interaction_config = 现有config → 进入P5\n340\tEND IF\n341\t\n342\t# 写入操作(原子化:先写临时文件再rename)\n343\t写入 CONFIG_PATH:\n344\t{\n345\t "schema_version": "1.1",\n346\t "template_id": {template_id 或 "custom"},\n347\t "template_name": {template_name 或 "自定义配置"},\n348\t "configured_at": {当前ISO 8601时间},\n349\t "configured_by": {当前用户},\n350\t "step_mode": {config.step_mode},\n351\t "fast_mode": {config.fast_mode},\n352\t "loop_decision": {config.loop_decision}\n353\t}\n354\tinteraction_config = 写入的config对象\n355\tOUTPUT "✅ 交互特性配置已写入:{CONFIG_PATH}(模板:{template_name})"\n356\t```\n357\t\n358\t**步骤5:自定义向导(自定义模式或微调时调用)**\n359\t\n360\t```\n361\t读取 dev-flow-interaction-templates.json 的 custom_mode.groups(6组)\n362\tconfig = normalize_loop_decision(base, base != null)(若base为null则初始化空config,含空step_mode、fast_mode和loop_decision)\n363\tFOR each group IN groups:\n364\t FOR each stage IN group.stages:\n365\t 环节名称 = 从stage-hooks.md映射表查stage对应名称\n366\t IF stage IN non_skippable_stages THEN\n367\t AskUserQuestion(question: "{group.name} - 环节{stage}({环节名称}):执行方式?",\n368\t header: "环节配置",\n369\t options: [\n370\t {label: "自动执行", description: "不询问,直接执行"},\n371\t {label: "询问确认", description: "执行前询问用户"}\n372\t ])\n373\t decision = ("自动执行"→"auto_execute") / ("询问确认"→"ask")\n374\t config.step_mode.non_skippable[{stage}] = decision\n375\t # 不可跳过环节在fast_mode中恒为auto_execute(快速模式定义),fast_mode不存储non_skippable\n376\t ELSE # stage IN skippable_stages\n377\t AskUserQuestion(question: "{group.name} - 环节{stage}({环节名称}):处理方式?",\n378\t header: "环节配置",\n379\t options: [\n380\t {label: "执行", description: "执行该环节,不询问"},\n381\t {label: "跳过", description: "跳过该环节,不询问"},\n382\t {label: "询问", description: "询问用户是否执行/跳过"}\n383\t ])\n384\t decision = ("执行"→"execute") / ("跳过"→"skip") / ("询问"→"ask")\n385\t config.step_mode.skippable[{stage}] = decision\n386\t config.fast_mode.skippable[{stage}] = decision # 自定义模式下两模式默认一致;微调时可分别询问\n387\t END IF\n388\t END FOR\n389\tEND FOR\n390\t\n391\t# Stage 9 测试失败循环是独立决策,不复用 non_skippable["9"]\n392\tAskUserQuestion(\n393\t question: "Stage 9 检测到测试失败或缺陷后,如何决定是否进入下一轮修复?",\n394\t header: "循环决策",\n395\t options: [\n396\t {label: "每次询问我(推荐)", description: "展示失败摘要,由我决定进入下一轮修复或暂停保留现场"},\n397\t {label: "自动进入修复循环", description: "自动生成 bug fix 子需求并回滚到 Stage 1,最多循环 10 次"}\n398\t ]\n399\t)\n400\tconfig.loop_decision.mode = ("每次询问我"→"ask") / ("自动进入修复循环"→"auto")\n401\t→ 返回 config 对象\n402\t```\n403\t\n404\t**结果传递**:\n405\t- 配置持久化:写入 `.claude/config/dev-flow-interaction-config.json`(项目级唯一真相源;step_mode/fast_mode 由 stage-hooks.md 与 standalone-mode.md 统一读取,`loop_decision` 由版本模式 Stage 9 读取,保证恢复场景行为一致)\n406\t- 写入 context.md YAML frontmatter:`interactionConfig: {template_id 或 "custom" 或 ""(无配置时)}` 与 `loopDecisionMode: {auto|ask}`(追溯标记;实际配置数据在上述 json 文件中)。无配置时 `loopDecisionMode=ask`。\n407\t- 步骤D版本参数块新增变量 `{interaction_config}`:P4.5加载的对象(备用缓存;stage-hooks 实际从文件读取)\n408\t\n409\t**容错与回退**:\n410\t- P4.5 任何交互异常/用户取消 → interaction_config = null、loopDecisionMode=ask → 回退系统默认行为,不阻塞版本启动\n411\t- CONFIG_PATH JSON 解析失败 → interaction_config = null、loopDecisionMode=ask → 输出警告 → 进入 P5(安全回退)\n412\t- schema 1.0 配置缺少 `loop_decision` → 按 `step_mode.non_skippable["9"]` 迁移:`auto_execute→auto`,其余值→`ask`;只在用户确认写入时升级磁盘配置,读取阶段不静默改文件\n413\t\n414\t### P5. 执行模式选择(使用 AskUserQuestion):\n415\t - 选项1: "**快速模式(推荐)** — 自动执行所有阶段(需求澄清→需求分析→设计→开发→测试)"\n416\t - 选项2: "**分步模式** — 每个阶段执行前暂停确认"\n417\t\n418\t 将用户选择的执行模式记录为 `execution_mode`,传入步骤D的Prompt。\n419\t\n420\t### P6. 工作区初始化\n421\t→ 创建 `dev/versions/{versionName}/active/{task_name}/` 目录(如不存在)\n422\t→ Read `.claude/config/dev-flow-context-contract.json`,校验 `version == "1.0"`\n423\t→ 读取/刷新 `dev/versions/{versionName}/version-context.md`;不存在时按 create-version.md 步骤6补建\n424\t→ 创建 `context.md`,使用以下结构化格式(YAML frontmatter + Markdown正文):\n425\t\n426\t```markdown\n427\t---\n428\tcontextSchemaVersion: "1.0"\n429\tcontextRevision: 1\n430\tcheckpointId: ""\n431\tcheckpointState: "clean" # clean/pending;pending 表示阶段结果尚未完成控制面提交\n432\tcurrentStage: "0"\n433\tlastCompletedStage: ""\n434\tstageHistory: []\n435\tskipDecisions: {}\n436\trollbackHistory: [] # ⭐v4.10 回滚历史,记录每次 {from,to,reason,time},初始空数组\n437\ttaskName: "{task_name}"\n438\trequirementType: "{确认后的分类类型}"\n439\texecutionMode: "{快速模式/分步模式}"\n440\tinteractionConfig: "{template_id 或 custom 或空字符串}"\n441\tloopDecisionMode: "{normalize_loop_decision 后的 auto|ask;无配置时为 ask}"\n442\tinputSource: "version_mode"\n443\treqIndex: "{2位零填充编号,如01}"\n444\treqPrefix: "REQ-{reqIndex}"\n445\tversionName: "{versionName}"\n446\tversionContextPath: "dev/versions/{versionName}/version-context.md"\n447\tdpmsStoryId: "{dpmsStoryId}"\n448\ttestSetId: "{testSetId}"\n449\tregressionTestSetId: "{regressionTestSetId}"\n450\treleasePlanId: "{releasePlanId}"\n451\tproductId: "{productId}"\n452\tproductName: "{productName}" # 🆕 A3创建需求后通过get-storys回填,初始为null\n453\tsubsystemId: "{subsystemId}" # ⭐阶段1 S5:入口子系统单值(兼容下游,=entrySubsystemId)\n454\tsubsystemName: "{subsystemName}" # ⭐阶段1 S5:入口子系统单值(兼容)\n455\tsubsystemVersionId: "{subsystemVersionId}" # ⭐阶段1 S5:入口子系统版本号=版本计划版本号(兼容)\n456\tbranchName: "{branchName}" # ⭐阶段1 S5:版本级单分支(所有子系统共享)\n457\tpipelineId: "{pipelineId}" # ⭐阶段1 S5:入口子系统流水线(兼容)\n458\tpipelineVersion: "{pipelineVersion}" # ⭐阶段1 S5:入口子系统流水线版本(兼容)\n459\treqSubsystemId: "{reqSubsystemId}" # ⭐阶段1 S5 D12:需求归属子系统ID(单子系统自动归属入口;多子系统add-story时选)\n460\trepositoryId: "{repositoryId}" # ⭐阶段3 S6:需求归属仓库ID(多git时从subsystem.gitUrl映射;单git时null)\n461\tfunctionAttributes: "" # 🆕 需求澄清后填入,如["前端","后端"]\n462\tfrontendType: "" # 🆕 需求澄清后填入,如"纯前端"或"前端+后台web API"\n463\tselectedDevAgents: [] # 🆕 Stage 3前置步骤1填入,如["java-code-developer","frontend-code-developer"]\n464\tknowledgeBaseStatus: "" # P7填入:"built"/"skipped"\n465\tmoduleIndexPath: "" # P7填入:module-index.json路径(若built)\n466\tstageOutputs: {} # stage -> {status,summary,artifacts,decisions,risks,completedAt}\n467\tartifactIndex: {} # artifactType -> path[],由主会话归一化维护\n468\tstaleArtifacts: [] # 回滚失效但物理文件仍存在的产物,默认不注入后续阶段\n469\topenRisks: [] # 尚未关闭的跨阶段风险\n470\tdecisionLog: [] # 不含控制字段的业务/技术决策\n471\tcreatedAt: "{ISO 8601时间}"\n472\tupdatedAt: "{ISO 8601时间}"\n473\t---\n474\t\n475\t# 任务上下文\n476\t\n477\t## 📋 任务基本信息\n478\t\n479\t**任务名称**: {task_name}\n480\t**需求类型**: {type}\n481\t**执行模式**: {execution_mode}\n482\t**竞品分析摘要**: {竞品分析结果摘要} ← 若用户跳过P3,值为"(用户跳过竞品分析)"\n483\t**价值收益摘要**: {value_benefit_summary} ← 若用户跳过P3.5,值为"(用户跳过价值收益评估)"\n484\t\n485\t## 📋 项目上下文确认\n486\t\n487\t**项目上下文状态**: {已确认/已生成/未确认(project_context_confirmed=false)} ← P4确认结果\n488\t**生成时间戳**: {P4生成project-context.json的时间,若P4未生成则为空}\n489\t\n490\t## 📚 知识库状态\n491\t\n492\t**知识库状态**: {已构建/已跳过} ← P7执行结果\n493\t**模块索引**: {module-index.json路径或"未构建"}\n494\t\n495\t## 📝 需求描述\n496\t\n497\t{用户需求描述}\n498\t```\n499\t\n500\t⚠️ **关键**:YAML frontmatter 中的 `currentStage/stageHistory/skipDecisions` 是控制字段镜像,权威值来自 versions.json;`stageOutputs/artifactIndex/openRisks/decisionLog` 是跨阶段执行上下文。每个阶段完成或跳过后必须通过 stage-hooks.md 的统一 checkpoint 更新,禁止 Agent/Skill 直接写控制字段。\n501\t\n502\t**P6 双层索引写回**:\n503\t1. 更新 versions.json 该需求:`contextPath/contextSchemaVersion/contextRevision/lastCompletedStage`。\n504\t2. 更新 version-context.md 的 `requirementContextIndex.{reqPrefix}`:`taskName/contextPath/currentStage/lastCompletedStage/contextRevision/status`。\n505\t3. 任一不可变身份字段(versionName/taskName/reqIndex/reqPrefix)在三处不一致时立即中止启动,禁止静默覆盖。\n506\t\n507\t### P7. 知识库构建(可跳过)\n508\t\n509\t构建项目存量知识库(模块识别→代码解读→需求文档→设计文档→回归测试),产出存档到 `docs/project-knowledge/`,供后续阶段参考。\n510\t\n511\t**⚠️ 层面1约束**:当前仅串联调用,知识库产出不注入任何阶段Prompt,对16阶段流程无影响。\n512\t\n513\t**前置检查**:读取 `docs/project-knowledge/module-index.json`,若存在且 `config_hash` 与当前配置一致 → 跳过阶段0(模块识别),直接使用现有索引。\n514\t\n515\t```\n516\tAskUserQuestion("是否构建项目存量知识库?",\n517\t ["构建知识库(推荐)— 生成模块级代码解读、需求/设计文档、回归测试集(约10-30分钟,取决于项目规模)",\n518\t "跳过 — 直接启动开发,后续可手动执行 /skill knowledge-base-builder"])\n519\t\n520\tIF "构建知识库" THEN\n521\t knowledge_base_status = "building"\n522\t\n523\t # ── 阶段0:模块识别(确定性,<1分钟) ──\n524\t Bash("python .claude/dev-tools/module-identifier/identifier.py --project {project_path}")\n525\t → 读取生成的 docs/project-knowledge/module-index.json\n526\t → 提取模块列表:modules = [{id, name, files_count, avg_confidence}...]\n527\t → OUTPUT: "📦 模块识别完成:{len(modules)}个模块,{total_files}个文件"\n528\t\n529\t # ── 阶段1-3:存量知识构建(按模块逐个执行) ──\n530\t FOR each module IN modules:\n531\t Skill(knowledge-base-builder, args: "--code {project_path} --stages 1,2,3 --modules {module.id}")\n532\t → 产出:\n533\t - docs/project-knowledge/code/{module.id}/代码解读.md\n534\t - docs/project-knowledge/requirements/{module.id}_模块需求.md\n535\t - docs/project-knowledge/design/{module.id}_模块设计.md\n536\t → OUTPUT: "✅ 模块 [{module.name}] 知识构建完成(代码解读+需求+设计)"\n537\t END FOR\n538\t\n539\t # ── 阶段4:存量回归测试(依赖DPMS数据源) ──\n540\t # DPMS数据源优先级:MCP直连 > Excel文件 > 跳过\n541\t dpms_source = None\n542\t IF MCP工具 mcp__tctp-dpms-set__addTestCase 可用 THEN\n543\t dpms_source = "mcp"\n544\t ELSE\n545\t AskUserQuestion("回归测试构建需要DPMS历史案例数据,请选择数据源:",\n546\t ["提供Excel文件 — 输入DPMS历史回归案例文件路径(.xlsx)",\n547\t "跳过回归测试 — 仅基于需求文档生成,不集成DPMS历史案例"])\n548\t IF "提供Excel文件" THEN\n549\t → 追问文件路径 → 验证文件存在性\n550\t dpms_source = "excel:{file_path}"\n551\t ELSE\n552\t dpms_source = "skip"\n553\t END IF\n554\t END IF\n555\t\n556\t IF dpms_source != "skip" THEN\n557\t FOR each module IN modules:\n558\t Skill(knowledge-base-builder, args: "--code {project_path} --stage 4 --modules {module.id} --dpms-source {dpms_source}")\n559\t → 产出:\n560\t - docs/project-knowledge/testing/regression/{module.id}_回归测试集.md\n561\t - docs/project-knowledge/testing/features/{module.id}.feature\n562\t → OUTPUT: "✅ 模块 [{module.name}] 回归测试构建完成"\n563\t END FOR\n564\t ELSE\n565\t OUTPUT: "⚠️ 已跳过回归测试构建(无DPMS数据源)"\n566\t END IF\n567\t\n568\t knowledge_base_status = "built"\n569\t OUTPUT: "✅ 知识库构建完成:{len(modules)}个模块,产出路径 docs/project-knowledge/"\n570\tELSE\n571\t knowledge_base_status = "skipped"\n572\t OUTPUT: "⚠️ 已跳过知识库构建,后续可手动执行 /skill knowledge-base-builder"\n573\tEND IF\n574\t```\n575\t\n576\t**知识库状态写入**:\n577\t- 写入context.md YAML frontmatter:`knowledgeBaseStatus: "{knowledge_base_status}"`\n578\t- 写入context.md Markdown正文:追加"📚 知识库状态"章节\n579\t\n580\t### 前置步骤结果传递规则\n581\t\n582\tP0-P7 的结果必须先归一化,再同时写入需求上下文与阶段 Prompt 变量;禁止仅保存在主会话临时记忆中:\n583\t\n584\t1. **写入context.md Markdown正文**:\n585\t - P2模板适配结果:追加到context.md"需求描述"章节(适配后的模板内容替换原始描述;如未适配则保持原文)\n586\t - P3竞品分析结果:写入context.md"竞品分析摘要"字段(已在上方context.md格式中体现;若用户跳过P3,值为"(用户跳过竞品分析)")\n587\t - P4项目上下文确认结果:写入context.md"项目上下文确认"章节(含project_context_confirmed标记;若P4生成了项目上下文,记录生成时间戳)\n588\t\n589\t2. **写入阶段Prompt构造变量**:\n590\t - `template_adapted_description` = P2适配后的需求描述(如未适配则为原始描述,用于替换阶段Prompt中的`{需求描述}`字段)\n591\t - `competitor_analysis_summary` = P3竞品分析的核心发现摘要(<=500字);若用户跳过P3,值为"(用户跳过竞品分析)"\n592\t - `value_benefit_summary` = P3.5价值收益评估结果摘要;若用户跳过P3.5,值为"(用户跳过价值收益评估)"\n593\t - `knowledge_base_status` = P7执行结果("built"/"skipped")\n594\t - `module_index_path` = "docs/project-knowledge/module-index.json"(若built)或 ""(若skipped)\n595\t - `version_context_path` = `dev/versions/{versionName}/version-context.md`\n596\t - `context_contract_path` = `.claude/config/dev-flow-context-contract.json`\n597\t - `prior_stage_summary/artifact_index/open_risks/decision_log` = 从 context.md 对应字段实时读取,禁止使用启动时缓存\n598\t - `knowledge_base_status/module_index_path` 仅在契约对应阶段的 `consumes` 声明需要时注入\n599\t - 上述变量在步骤E按 context contract 的阶段白名单填入,未声明字段不得整包注入\n600\t\n601\t## 并行启动(核心实现)\n602\t\n603\t确认后,对每个要启动的需求,**按顺序**执行以下操作:\n604\t\n605\t**步骤A — 创建 Business API Task**(确保 task-viewer 可见):\n606\t```bash\n607\tTASK_RESPONSE=$(python3 -c "\n608\timport urllib.request, json\n609\tdata = json.dumps({\'versionId\': \'{versionName}\', \'projectId\': \'{projectName}\', \'stage\': \'requirement\'}).encode(\'utf-8\')\n610\treq = urllib.request.Request(\'{biz_api_url}/api/task\', data=data, headers={\'Content-Type\': \'application/json\'})\n611\tresp = urllib.request.urlopen(req)\n612\tprint(resp.read().decode(\'utf-8\'))\n613\t")\n614\tbiz_task_id=$(echo "$TASK_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)[\'id\'])")\n615\tbiz_api_url = 从环境变量BIZ_API_BASE获取,默认http://localhost:50009\n616\t\n617\t# 将 biz_task_id 和 biz_api_url 写入 versions.json 该需求记录\n618\t更新 versions.json 该需求的 biz_task_id 和 biz_api_url 字段\n619\t\n620\t# 错误处理:Task 创建失败时跳过该需求,不影响其他需求\n621\tif [ -z "$biz_task_id" ] || [ "$biz_task_id" = "null" ]; then\n622\t OUTPUT: "⚠️ 需求 [{name}] Task 创建失败,跳过启动,已记录到待补录"\n623\t mcp__biz-sync__save_pending_item(\n624\t version_id="{versionName}",\n625\t task_name="{name}",\n626\t mcp_method="POST /api/task",\n627\t skip_reason="NETWORK_UNAVAILABLE",\n628\t context_description="步骤A:创建Business API Task失败"\n629\t )\n630\t 跳过该需求的步骤B-F,继续处理下一个需求\n631\tEND IF\n632\t```\n633\t\n634\t**步骤B — 创建 Business API Session**:\n635\t```bash\n636\tSESSION_RESPONSE=$(python3 -c "\n637\timport urllib.request, json\n638\tdata = json.dumps({\'taskId\': \'$biz_task_id\', \'versionId\': \'{versionName}\', \'projectId\': \'{projectName}\'}).encode(\'utf-8\')\n639\treq = urllib.request.Request(\'{biz_api_url}/api/session\', data=data, headers={\'Content-Type\': \'application/json\'})\n640\tresp = urllib.request.urlopen(req)\n641\tprint(resp.read().decode(\'utf-8\'))\n642\t")\n643\tbiz_session_id=$(echo "$SESSION_RESPONSE" | python3 -c "import sys,json; print(json.load(sys.stdin)[\'id\'])")\n644\t\n645\t# 错误处理:Session 创建失败不阻塞启动(主会话仍可在逐阶段控制中同步BIZ API状态)\n646\tif [ -z "$biz_session_id" ] || [ "$biz_session_id" = "null" ]; then\n647\t OUTPUT: "⚠️ 需求 [{name}] Session 创建失败,继续启动(主会话仍可在逐阶段控制中同步BIZ API状态)"\n648\tEND IF\n649\t```\n650\t\n651\t**步骤C — 更新 Version 状态为 running**(仅首次启动时执行):\n652\t```bash\n653\tpython3 -c "\n654\timport urllib.request, json\n655\tdata = json.dumps({\'status\': \'running\', \'progress\': 0}).encode(\'utf-8\')\n656\treq = urllib.request.Request(\'{biz_api_url}/api/version/{versionName}/status\', data=data, headers={\'Content-Type\': \'application/json\'}, method=\'PATCH\')\n657\turllib.request.urlopen(req)\n658\t" 2>/dev/null || true\n659\t```\n660\t\n661\t**步骤D — 版本参数块**(供步骤E"阶段Prompt构造规则"引用的参数来源):\n662\t\n663\t以下参数在步骤E构造每个阶段Prompt时填充:\n664\t- {versionName}:版本名称\n665\t- {dpmsStoryId}:从versions.json该需求的dpmsStoryId读取\n666\t- {productId}:从versions.json该需求的dpms.productId读取\n667\t- {productName}:从versions.json该需求的productName读取(A3创建需求后通过get-storys回填,初始为null)\n668\t- {testSetId}:从versions.json该需求的testSetId读取\n669\t- {releasePlanId}:从versions.json该需求的dpms.releasePlanId或dpms.versionPlanId读取\n670\t- {biz_task_id}:步骤A创建的Business API Task ID\n671\t- {biz_api_url}:从环境变量BIZ_API_BASE获取,默认http://localhost:50009\n672\t- {execution_mode}:用户在P5选择的执行模式\n673\t- {interaction_config}:P4.5加载的项目级交互特性对象(含step_mode/fast_mode/loop_decision,或null)。⚠️ stage-hooks.md Step 3/4.5 与 Stage 9 循环决策实际从 .claude/config/dev-flow-interaction-config.json 文件读取(保证恢复场景一致),此参数为备用缓存\n674\t- {competitor_analysis_summary}:P3竞品分析结果摘要(若用户跳过P3,值为"(用户跳过竞品分析)")\n675\t- {value_benefit_summary}:P3.5价值收益评估结果摘要(若用户跳过P3.5,值为"(用户跳过价值收益评估)")\n676\t- {context_md_path}:context.md文件路径\n677\t- {version_context_path}:版本级上下文文件路径\n678\t- {context_contract_path}:`.claude/config/dev-flow-context-contract.json`\n679\t- {context_revision}:context.md 当前修订号;构造 Prompt 前必须重新读取\n680\t- {prior_stage_summary}:最近一个已完成阶段的归一化摘要(<=1000字)\n681\t- {artifact_index}:当前阶段契约允许消费的产物路径子集\n682\t- {open_risks}:尚未关闭且与当前阶段相关的风险\n683\t- {decision_log}:与当前阶段相关的已确认业务/技术决策\n684\t\n685\t⚠️ 不再构造独立Prompt模板。所有阶段Prompt统一使用步骤E的"阶段Prompt构造规则"。\n686\t⚠️ BIZ API同步由主会话在逐阶段控制流程中执行(WHILE+FOR循环step 2/9),不传入subagent。\n687\t\n688\t⚠️ **function_attributes/frontendType字段填入时机**:\n689\t- Stage 0(需求澄清)完成后,主会话从澄清结果提取function_attributes和frontendType,更新context.md\n690\t- Stage 3前置步骤1执行后,将selected_agents写入context.md的selectedDevAgents字段\n691\t\n692\t⚠️ **禁止使用陈旧缓存**:除 immutable identity 外,步骤E 每进入一个 stage 都必须重新读取 versions.json、context.md、version-context.md 和产物索引。恢复流程与首次启动使用同一构造逻辑。\n693\t\n694\t**步骤E — 形态B分段交错编排**(🚨 P0级强制 — 禁止跳过或替换,⭐阶段0 spike):\n695\t\n696\t⚠️ **架构决策**:版本模式下,主会话按 SEGMENT_ORDER 段调度编排(段间屏障同步,段内按 parallel 标识并行/串行),**禁止**由单个subagent独立编排21阶段全流程(v4.0教训:subagent独立编排丢子阶段,v4.6废弃)。\n697\t\n698\t**形态B核心规则**:改源码段(S1/S2/V)串行,文档段(P1/P2/D)并行。21阶段二分与段调度函数详见 stage-hooks.md "形态B分段交错编排"章节。\n699\t\n700\t**执行流程**:\n701\t```python\n702\t# 步骤A-C 已为每个需求创建 Task/Session/Version running(603-657行保持不变)\n703\t# 步骤D 版本参数块(659-690行保持不变)\n704\t# 步骤E 改为段调度(替代原"逐需求串行A-E全流程")\n705\t\n706\t# 调用 stage-hooks.md 的段调度入口(内含 migrate_add_segment_progress 迁移)\n707\tsegments_result = execute_segments(all_requirements)\n708\t# ⭐阶段2 S11 交互强化1:execute_segments提前退出(某需求Stage9失败blocked)的用户引导\n709\tIF segments_result == "exited_with_blocked" THEN\n710\t AskUserQuestion(question="检测到需求Stage9失败已blocked,bugfix子需求已生成。如何继续?",\n711\t header="Stage9失败处理",\n712\t options=[{label:"继续开发(推荐)",description:"resume恢复,已完成需求跳过已完成段,bugfix子需求从P1开始"},\n713\t {label:"返回主菜单",description:"稍后手动选择继续开发"}])\n714\t IF "继续开发" THEN 内联执行"继续版本开发"(见 dev-flow.md "继续版本开发"章节)\n715\t ELSE 重新展示STARTED主菜单\n716\tEND IF\n717\t# execute_segments 内部:\n718\t# 1. 为每个需求迁移补 segmentProgress(向后兼容旧 versions.json)\n719\t# 2. FOR each segment IN SEGMENT_ORDER ["P1","S1","P2","S2","D","V"]:\n720\t# - pending_reqs跳过已完成段(E4 D1,支持resume:已完成段跳过,bugfix子需求从P1)\n721\t# - V段:wait_segment_barrier("D") → execute_stage_10(active_reqs) → RETURN\n722\t# - 并行段(P1/P2/D):execute_parallel_segment(N需求并发生成文档,方案C队列化commit)\n723\t# - 串行段(S1/S2):execute_serial_segment(N需求排队改源码,复用单阶段11步逻辑)\n724\t# - wait_segment_barrier(segment)(段间屏障,含completed/skipped/blocked三态)\n725\t# 3. 所有段完成 → 进入 complete-version\n726\t```\n727\t\n728\t⚠️ **阶段0 spike 边界**:限定 happy path(所有需求Stage9一次通过);Stage9失败回滚与段屏障交互待阶段2 S11实现;Stage9通过分支多需求时不直接GOTO Stage10而交外层execute_segments的V段屏障统一触发(详见stage-hooks.md WHILE+FOR Stage9通过分支)。单需求时退化为串行(向后兼容现有单需求版本流程)。\n729\t\n730\t⚠️ **禁止使用陈旧缓存**(原有约束不变):除 immutable identity 外,每进入一个 stage 都必须重新读取 versions.json、context.md、version-context.md 和产物索引。恢复流程与首次启动使用同一构造逻辑(恢复时优先读 segmentProgress 定位当前段,详见 dev-flow.md "继续版本开发")。\n731\t\n732\t---\n733\t\n734\t## ⛔ 完成验证(回复结束前必须逐项确认)\n735\t\n736\t- [ ] 幂等性检查: started = ?\n737\t- [ ] 关联需求: assigned = ?\n738\t- [ ] P0 规范化检查 = ? (通过/跳过)\n739\t- [ ] P1 步骤1 项目上下文 = ? (读取/生成/跳过)\n740\t- [ ] P1 分类结果 = ?\n741\t- [ ] P2 模板适配 = ?\n742\t- [ ] P3 竞品分析 = ? (执行/跳过)\n743\t- [ ] P3.5 价值收益评估 = ? (执行/跳过)\n744\t- [ ] P4 项目上下文确认 = ? (确认/生成/继续默认)\n745\t- [ ] P4.5 项目级交互配置 = ? (新增/调整/沿用/删除/跳过默认),loopDecisionMode = ? (auto/ask)\n746\t- [ ] P5 执行模式 = ?\n747\t- [ ] P6 工作区初始化 = ?\n748\t- [ ] P6 context contract/version-context/requirement context 三处身份一致 = ?\n749\t- [ ] P7 知识库构建 = ? (built/skipped/部分built)\n750\t- [ ] 步骤A-C: Task/Session/Version = ?\n751\t- [ ] 步骤D-E: 参数块+逐阶段启动 = ?\n752\t\n753\t⛔ 所有项确认后 → 输出需求启动状态表 → 展示主菜单\n754\t'}] + +**AI**: +已读完单需求模式和启动版本需求两个清单。信息基本齐全。最后确认 Stage 10 调用的 agent/skill,以及 plugin-dev-eval-loop 命令是否存在。... + + +## 交互记录 (2026-07-27T09:25:01.792Z) + +**用户**: +[{'tool_use_id': 'call_a645a984dfbc4ff9bdffadf6', 'type': 'tool_result', 'content': '1\t# Stage 10 版本级回归测试步骤清单\n2\t\n3\t> 来源:模块识别优化与Stage10版本级回归测试方案.md\n4\t> 用途:版本级 FOR 循环中所有需求 Stage 9 通过后,执行版本级回归测试\n5\t> v4.9 新增\n6\t\n7\t## 前置条件\n8\t\n9\t- 版本下所有需求 Stage 9 已通过(test_passed)\n10\t- versions.json 该版本 `regressionTestSetId` 非空(A5.1 已执行)\n11\t- `docs/project-knowledge/module-index.json` 存在且 config_hash 一致\n12\t- `dev/versions/{versionName}/version-context.md` 已与各需求 context.md 对账完成(contract 1.0)\n13\t\n14\t## 步骤清单(严格按顺序执行)\n15\t\n16\t### 10.1 前置检查\n17\t\n18\t```python\n19\t# 检查0:加载版本聚合上下文\n20\tRead ".claude/config/dev-flow-context-contract.json"\n21\tversion_context_path = f"dev/versions/{versionName}/version-context.md"\n22\tIF NOT 文件存在 version_context_path THEN\n23\t 从 versions.json + 各需求 context.md 重建 version-context.md(不得只靠主会话记忆)\n24\tEND IF\n25\t\n26\t# 检查1:所有需求 Stage 9 通过\n27\tFOR each req IN 版本配置.requirements:\n28\t context_path = version_context.requirementContextIndex[req.reqPrefix].contextPath\n29\t IF context_path 不存在 THEN\n30\t context_path = active/{req.task_name}/context.md 或 completed/{req.task_name}/context.md 中实际存在者\n31\t END IF\n32\t IF NOT 文件存在 THEN\n33\t OUTPUT: "❌ 需求 {req.task_name} 未完成,无法进入 Stage 10"\n34\t mcp__biz-sync__save_pending_item(\n35\t version_id="{versionName}",\n36\t task_name="Stage10-前置检查",\n37\t skip_reason="REQ_NOT_COMPLETED",\n38\t context_description=f"需求 {req.task_name} 未完成"\n39\t )\n40\t GOTO 主菜单\n41\t IF context.lastCompletedStage != 9 OR context.testResult != "test_passed" THEN\n42\t OUTPUT: "❌ 需求 {req.task_name} Stage 9 未通过"\n43\t GOTO 主菜单\n44\t\n45\t# 检查2:regressionTestSetId 非空\n46\tIF 版本配置.regressionTestSetId 为空 THEN\n47\t OUTPUT: "⚠️ regressionTestSetId 为空(A5.1 未执行或失败),Stage 10 跳过"\n48\t mcp__biz-sync__save_pending_item(\n49\t version_id="{versionName}",\n50\t task_name="Stage10-前置检查",\n51\t mcp_method="mcp__tctp-dpms-set__linkTestCaseToTestPlan",\n52\t skip_reason="REGRESSION_TEST_SET_ID_EMPTY",\n53\t context_description="A5.1未执行或失败"\n54\t )\n55\t GOTO 主菜单 # 不阻塞 complete-version\n56\t\n57\t# 检查3:module-index.json 存在\n58\tIF NOT 文件存在 "docs/project-knowledge/module-index.json" THEN\n59\t OUTPUT: "⚠️ module-index.json 不存在,建议先执行 /skill knowledge-base-builder --stages 0"\n60\t AskUserQuestion({\n61\t "questions": [{\n62\t "question": "module-index.json 不存在,是否先构建知识库?",\n63\t "header": "知识库构建",\n64\t "options": [\n65\t {"label": "构建知识库", "description": "执行 /skill knowledge-base-builder --stages 0 后继续 Stage 10"},\n66\t {"label": "跳过 Stage 10", "description": "直接进入 complete-version,回归集留空"}\n67\t ]\n68\t }]\n69\t })\n70\t IF "跳过 Stage 10" THEN GOTO 主菜单\n71\t IF "构建知识库" THEN Skill(knowledge-base-builder, "--stages 0")\n72\t```\n73\t\n74\t### 10.2 模块选择(含"全量回归"选项)\n75\t\n76\t```python\n77\t# 收集涉及模块(优先从 version-context requirementContextIndex 定位各需求 context.md)\n78\tinvolved_modules = {}\n79\tFOR each req IN 版本配置.requirements:\n80\t context_path = version_context.requirementContextIndex[req.reqPrefix].contextPath\n81\t IF context_path 不存在 THEN\n82\t context_path = active/{req.task_name}/context.md 或 completed/{req.task_name}/context.md 中实际存在者\n83\t END IF\n84\t IF 文件存在 THEN\n85\t 读取 context_path 的 YAML frontmatter\n86\t moduleId = frontmatter.get("moduleId")\n87\t moduleName = frontmatter.get("moduleName")\n88\t IF moduleId 非空 AND moduleName 非空 THEN\n89\t involved_modules[moduleId] = moduleName\n90\t\n91\t# 扫描所有有回归集的模块(兼容新旧文件名)\n92\tall_modules_with_cases = []\n93\tmodule_index = read "docs/project-knowledge/module-index.json"\n94\tFOR each module IN module_index.modules:\n95\t IF module.id == "common" THEN CONTINUE\n96\t # 文件名兼容策略(按优先级匹配)\n97\t candidates = [\n98\t f"docs/project-knowledge/testing/regression/{module.id}_回归测试集.md", # 新规约\n99\t f"docs/project-knowledge/testing/regression/{module.name}_回归.md", # 旧规约1\n100\t f"docs/project-knowledge/testing/regression/{module.name}回归.md", # 旧规约2\n101\t ]\n102\t regression_md = 第一个存在的文件\n103\t IF regression_md 为空 THEN CONTINUE\n104\t cases = parse_regression_md(regression_md)\n105\t IF len(cases) == 0 THEN CONTINUE\n106\t all_modules_with_cases.append({\n107\t "id": module.id, "name": module.name,\n108\t "caseCount": len(cases), "preview": [c["name"] for c in cases[:3]],\n109\t "isInvolved": module.id IN involved_modules,\n110\t "regressionMd": regression_md\n111\t })\n112\t\n113\tIF len(all_modules_with_cases) == 0 THEN\n114\t OUTPUT: "⚠️ 未发现任何有回归用例的模块,Stage 10 跳过"\n115\t GOTO 主菜单\n116\t\n117\t# 第1轮:策略选择\n118\tstrategy = AskUserQuestion({\n119\t "questions": [{\n120\t "question": f"发现 {len(all_modules_with_cases)} 个模块有回归用例,版本级回归测试模块选择策略:",\n121\t "header": "回归策略",\n122\t "options": [\n123\t {"label": "全量回归(推荐)", "description": f"所有 {len(all_modules_with_cases)} 个模块的回归用例都纳入"},\n124\t {"label": "手动选择模块", "description": "逐批选择需要纳入的模块"},\n125\t {"label": "跳过版本级回归测试", "description": "仅同步dpms回归用例,不执行回归测试循环"}\n126\t ]\n127\t }]\n128\t})\n129\t\n130\tIF strategy == "跳过版本级回归测试" THEN\n131\t skip_regression_execution = True\n132\t selected_modules = all_modules_with_cases # 仍需同步 dpms 用例\n133\tELIF strategy == "全量回归" THEN\n134\t selected_modules = all_modules_with_cases\n135\t skip_regression_execution = False\n136\tELSE: # 手动选择\n137\t selected_modules = []\n138\t batch = sorted(all_modules_with_cases, key=lambda x: (-x.isInvolved, -x.caseCount))\n139\t FOR i IN range(0, len(batch), 3):\n140\t chunk = batch[i:i+3]\n141\t options = [{"label": f"{\'★涉及\' if m.isInvolved else \'○可选\'} {m.name}({m.caseCount}条)",\n142\t "description": f"预览:{\', \'.join(m.preview[:2])}..."} for m in chunk]\n143\t options.append({"label": "确认完成", "description": "已选完毕,开始同步"})\n144\t ans = AskUserQuestion({\n145\t "questions": [{\n146\t "question": f"第 {i//3+1} 批模块选择(可多选):",\n147\t "header": "模块选择",\n148\t "multiSelect": True,\n149\t "options": options\n150\t }]\n151\t })\n152\t ans_list = ans["模块选择"] if isinstance(ans, dict) else ans\n153\t IF "确认完成" IN ans_list THEN BREAK\n154\t FOR name IN ans_list:\n155\t IF "确认完成" not in name:\n156\t selected = FIND chunk WHERE label == name\n157\t IF selected THEN selected_modules.append(selected)\n158\t skip_regression_execution = False\n159\t\n160\tOUTPUT: f"📦 已选 {len(selected_modules)} 个模块"\n161\t```\n162\t\n163\t### 10.3 dpms 回归用例同步(原 A5.2 迁移)\n164\t\n165\t```python\n166\t# 完全复用原 A5.2 的去重缓存 + addTestCase + linkTestCaseToTestPlan 逻辑\n167\t# 缓存路径:dev/versions/{versionId}/.regression-case-cache.json\n168\t# 用例名:【回归】{module_name}-{case.name}\n169\t# path: 功能测试,type: 功能案例,autoOrManual: 自动化\n170\t\n171\tmandatory_cases = []\n172\tFOR each module IN selected_modules:\n173\t cases = parse_regression_md(module.regressionMd)\n174\t FOR case IN cases:\n175\t mandatory_cases.append({\n176\t "moduleId": module.id, "moduleName": module.name,\n177\t "originalName": case.name,\n178\t "name": f"【回归】{module.name}-{case.name}",\n179\t "content": case.content if case.content else f"模块 {module.name} 的回归测试用例:{case.name}",\n180\t "priority": case.priority if case.priority else "P1"\n181\t })\n182\t\n183\t# 去重(基于 case name md5)\n184\tcache_path = f"dev/versions/{versionId}/.regression-case-cache.json"\n185\tcached_keys = set()\n186\tIF 文件存在 cache_path THEN\n187\t cache = read cache_path\n188\t cached_keys = {c["caseKey"] for c in cache.get("uploadedCases", [])}\n189\t\n190\tnew_cases = []\n191\tduplicate_count = 0\n192\tFOR case IN mandatory_cases:\n193\t case_key = md5(case["name"])\n194\t IF case_key NOT IN cached_keys THEN\n195\t case["key"] = case_key\n196\t new_cases.append(case)\n197\t ELSE\n198\t duplicate_count += 1\n199\t\n200\tOUTPUT: f"📊 必选用例:共{len(mandatory_cases)}条,新增{len(new_cases)}条,已存在{duplicate_count}条(跳过)"\n201\t\n202\t# 批量上传\n203\tsuccess_count = 0\n204\tfail_count = 0\n205\tuploaded_records = []\n206\tcurrent_user = 当前用户英文名\n207\t# 🆕 product_name 空值兜底(对齐 Stage6-Hook B5,stage-hooks.md:1394-1407)\n208\tproduct_name = 版本配置.productName\n209\tIF product_name 为空 THEN\n210\t # 优先从需求级 productName 取(A3后已回填,versions.json requirements[].productName)\n211\t FOR each req IN 版本配置.requirements:\n212\t IF req.productName 非空 THEN\n213\t product_name = req.productName\n214\t BREAK\n215\t IF product_name 仍为空 THEN\n216\t # 降级:用 storyId 调 get-storys 实时查询(对齐 Stage6-Hook B5)\n217\t story_id = 取首个非空 req.dpmsStoryId(或 req.storyId)\n218\t IF story_id 非空 THEN\n219\t story_result = safe_call_mcp("mcp__sdp__get-storys", {"id": story_id},\n220\t context_description="Stage10.3:productName空值兜底查询",\n221\t version_id=versionId, task_name="Stage10.3-回归用例同步")\n222\t IF story_result["success"] AND story_result["result"]["list"] 非空 THEN\n223\t product_name = story_result["result"]["list"][0]["productName"]\n224\t 更新 versions.json 当前版本 productName = product_name\n225\t ELSE\n226\t OUTPUT: "❌ 无法获取productName(get-storys失败),Stage10.3回归用例上传跳过"\n227\t mcp__biz-sync__save_pending_item(\n228\t version_id="{versionName}", task_name="Stage10.3-回归用例同步",\n229\t mcp_method="mcp__tctp-dpms-set__addTestCase",\n230\t skip_reason="PRODUCT_NAME_EMPTY",\n231\t context_description=f"productName为空且get-storys失败(story_id={story_id})")\n232\t GOTO 10.7\n233\t END IF\n234\t ELSE\n235\t OUTPUT: "❌ productName为空且无story_id可查询,Stage10.3回归用例上传跳过"\n236\t mcp__biz-sync__save_pending_item(\n237\t version_id="{versionName}", task_name="Stage10.3-回归用例同步",\n238\t mcp_method="mcp__tctp-dpms-set__addTestCase",\n239\t skip_reason="PRODUCT_NAME_EMPTY")\n240\t GOTO 10.7\n241\t END IF\n242\tEND IF\n243\tproduct_id = 版本配置.productId\n244\tregression_test_set_id = 版本配置.regressionTestSetId\n245\t\n246\tFOR case IN new_cases:\n247\t result = safe_call_mcp(\n248\t "mcp__tctp-dpms-set__addTestCase",\n249\t {\n250\t "productName": product_name,\n251\t "name": case["name"],\n252\t "content": case["content"],\n253\t "createUser": current_user,\n254\t "path": "功能测试",\n255\t "type": "功能案例",\n256\t "autoOrManual": "自动化"\n257\t },\n258\t context_description=f"Stage10.3:上传回归用例 [{case[\'name\']}]",\n259\t version_id=versionId,\n260\t task_name="Stage10.3-回归用例同步"\n261\t )\n262\t IF result["success"] THEN\n263\t test_case_id = result["result"]["testCaseId"]\n264\t link_result = safe_call_mcp(\n265\t "mcp__tctp-dpms-set__linkTestCaseToTestPlan",\n266\t {\n267\t "productId": product_id,\n268\t "testPlanId": regression_test_set_id,\n269\t "tester": current_user,\n270\t "testCaseIds": [test_case_id]\n271\t },\n272\t context_description=f"Stage10.3:关联回归用例到集 [{case[\'name\']}]",\n273\t version_id=versionId,\n274\t task_name="Stage10.3-回归用例同步"\n275\t )\n276\t IF link_result["success"] THEN\n277\t uploaded_records.append({\n278\t "caseKey": case["key"],\n279\t "testCaseId": test_case_id,\n280\t "moduleName": case["moduleName"],\n281\t "name": case["name"],\n282\t "uploadedAt": current_timestamp()\n283\t })\n284\t success_count += 1\n285\t ELSE\n286\t fail_count += 1\n287\t ELSE\n288\t fail_count += 1\n289\t\n290\t# 更新缓存\n291\tIF len(uploaded_records) > 0 THEN\n292\t IF 文件存在 cache_path THEN\n293\t cache = read cache_path\n294\t ELSE\n295\t cache = {"versionId": versionId, "regressionTestSetId": regression_test_set_id, "uploadedCases": []}\n296\t cache["uploadedCases"].extend(uploaded_records)\n297\t cache["lastSyncAt"] = current_timestamp()\n298\t write cache_path = cache\n299\t\n300\tOUTPUT: f"✅ dpms 回归用例同步完成:成功 {success_count} 条,失败 {fail_count} 条"\n301\t\n302\tIF skip_regression_execution THEN\n303\t OUTPUT: "ℹ️ 用户选择跳过回归测试执行,仅同步 dpms 用例"\n304\t # 标记 stage10Completed\n305\t 更新 versions.json 该版本 stage10Completed = True\n306\t GOTO 10.7 # 直接生成报告\n307\t```\n308\t\n309\t**parse_regression_md 函数规约**(同原 A5.2):\n310\t\n311\t输入:regression_md 文件路径\n312\t输出:[{id, name, content, priority}, ...]\n313\t\n314\t执行步骤:\n315\t1. 读取文件全文\n316\t2. 定位主章节:按优先级匹配 "## 测试用例" → 若无则匹配 "## 回归测试用例"(兼容旧格式)\n317\t - 主章节范围:从该标题行到下一个 "## " 标题行(或文件末尾)\n318\t3. 在主章节范围内,用正则 `^### (TC\\S+):\\s*(.+)$` 切分用例块\n319\t - 每个用例块 = 标题行 + 该标题到下一个 "### " 之间的正文\n320\t4. 对每个用例块提取:\n321\t - case.id = 正则第1组(如 TC001)\n322\t - case.name = 正则第2组(如 用户登录成功)\n323\t - 从正文属性表提取:\n324\t - precondition = 匹配行 "| 前置条件 | {值} |" 的 {值}\n325\t - test_steps = 匹配行 "| 测试步骤 | {值} |" 的 {值}\n326\t - expected = 匹配行 "| 预期结果 | {值} |" 的 {值}\n327\t - case.content = 拼接非空字段:\n328\t - IF precondition 非空: content += f"前置条件:{precondition}\\n"\n329\t - IF test_steps 非空: content += f"测试步骤:{test_steps}\\n"\n330\t - IF expected 非空: content += f"预期结果:{expected}"\n331\t - IF content 为空: content = f"模块回归测试用例:{case.name}"\n332\t - case.priority = "P1"(默认)\n333\t5. 忽略属性表的表头行 "| 属性 | 值 |"、分隔线 "|-----|---|"、空行\n334\t6. 返回用例列表\n335\t\n336\t### 10.4 生成版本级回归测试代码\n337\t\n338\t```python\n339\tselected_module_ids = [m["id"] for m in selected_modules]\n340\tmodules_arg = ",".join(selected_module_ids)\n341\t\n342\t# 调用 test-code-generator 回归模式,按选中模块生成测试代码\n343\t# 版本上下文通过 Skill 工作目录(dev/versions/{versionId}/)传递,无需显式 --version 参数\n344\tSkill(test-code-generator, args=f"--mode regression --modules {modules_arg}")\n345\t\n346\t# 输出路径(对齐 test-code-generator SKILL.md "输出" 章节实际声明):\n347\t# - Java项目: src/test/java/cucumber/{runner,steps,hooks}/ + src/test/resources/features/\n348\t# - TypeScript项目: test/{steps,hooks}/ + features/\n349\t# - Python项目: tests/ + features/\n350\t# - Go项目: tests/ + features/\n351\t# - test-status.json: dev/versions/{versionId}/test-status.json(version_mode 下 BASE_DIR)\n352\t# 注意:回归模式从 docs/project-knowledge/testing/features/{module}.feature 加载 Feature 文件\n353\t# 注意:test-code-generator 回归模式复用标准生成流程(第2步 生成Cucumber测试),输出路径与标准模式一致\n354\t```\n355\t\n356\t### 10.5 执行版本级回归测试\n357\t\n358\t```python\n359\t# 调用 test-executor 回归模式,按选中模块执行测试\n360\t# test-executor 输出(对齐其 SKILL.md "回归-第4步" 实际声明):\n361\t# - 结构化摘要(含 event_type)输出在 Skill 调用结果文本末尾\n362\t# - 回归报告输出到 docs/project-knowledge/testing/全量回归测试验证结果.md\n363\tskill_result = Skill(test-executor, args=f"--mode regression --modules {modules_arg}")\n364\t\n365\t# 从 Skill 调用结果文本提取 event_type(对齐 test-executor v4.7+ "结构化输出要求")\n366\t# event_type 取值:test_passed | test_failed | bug_fixed\n367\tevent_type = extract_field_from_text(skill_result, "event_type")\n368\t\n369\t# 归档到版本目录(供 Stage 10.6/10.7 使用)\n370\tversion_report_dir = f"docs/{versionName}/testing/reports/"\n371\tmkdir_p(version_report_dir)\n372\t\n373\t# 拷贝 test-executor 回归报告到版本目录\n374\tsource_report = "docs/project-knowledge/testing/全量回归测试验证结果.md"\n375\tIF 文件存在 source_report THEN\n376\t cp source_report → f"{version_report_dir}版本级回归测试执行报告.md"\n377\t\n378\t# 写入 event_type 到版本目录(供 Stage 10.6 读取,不依赖 test-status.json)\n379\twrite f"{version_report_dir}版本级回归测试-event-type.json" = {\n380\t "event_type": event_type,\n381\t "timestamp": current_timestamp(),\n382\t "modules": modules_arg\n383\t}\n384\t\n385\t# 输出:\n386\t# - docs/{versionName}/testing/reports/版本级回归测试执行报告.md(拷贝自 test-executor 输出)\n387\t# - docs/{versionName}/testing/reports/版本级回归测试-event-type.json(含 event_type)\n388\t```\n389\t\n390\t### 10.6 版本级循环决策\n391\t\n392\t```python\n393\tversion_regression_cycle_count = 0\n394\tMAX_VERSION_REGRESSION_CYCLES = 3\n395\t\n396\tWHILE True:\n397\t # 从版本目录读取 event_type(由 Stage 10.5 写入,不依赖 test-status.json)\n398\t event_type_file = f"docs/{versionName}/testing/reports/版本级回归测试-event-type.json"\n399\t IF NOT 文件存在 event_type_file THEN\n400\t OUTPUT: "❌ 未找到回归测试结果,请确认 Stage 10.5 是否执行"\n401\t GOTO 主菜单\n402\t event_data = read event_type_file\n403\t event_type = event_data["event_type"]\n404\t # ⚠️ event_type 取值对齐 test-executor v4.7+ 实际输出:test_passed / test_failed / bug_fixed\n405\t # (见 test-executor SKILL.md "结构化输出要求" 章节)\n406\t\n407\t IF event_type == "test_passed":\n408\t # 🆕 10.6.1 版本级回归用例状态流转(对齐 Stage 7 B7.5 语义,stage-hooks.md:730-749)\n409\t transition_version_regression_cases()\n410\t OUTPUT: "✅ 版本级回归测试全部通过"\n411\t BREAK\n412\t\n413\t IF event_type == "test_failed" OR event_type == "bug_fixed":\n414\t # test_failed=存在失败用例;bug_fixed=修复后重跑通过(版本级循环中视为可继续)\n415\t version_regression_cycle_count += 1\n416\t IF version_regression_cycle_count > MAX_VERSION_REGRESSION_CYCLES:\n417\t OUTPUT: f"⚠️ 版本级回归测试循环已达上限({MAX_VERSION_REGRESSION_CYCLES})"\n418\t AskUserQuestion({\n419\t "questions": [{\n420\t "question": "已达最大循环次数,如何处理?",\n421\t "header": "循环决策",\n422\t "options": [\n423\t {"label": "强制退出", "description": "保留已有产物,停止流程"},\n424\t {"label": "继续循环", "description": "再给3次机会"},\n425\t {"label": "跳过回归失败", "description": "记录到 pending,进入 complete-version"}\n426\t ]\n427\t }]\n428\t })\n429\t choice = ans["循环决策"]\n430\t IF "强制退出" THEN GOTO 主菜单\n431\t IF "跳过回归失败" THEN BREAK\n432\t IF "继续循环" THEN MAX_VERSION_REGRESSION_CYCLES += 3; CONTINUE\n433\t\n434\t AskUserQuestion({\n435\t "questions": [{\n436\t "question": f"版本级回归测试第 {version_regression_cycle_count} 次失败,如何处理?",\n437\t "header": "失败处理",\n438\t "options": [\n439\t {"label": "生成 bug fix 子需求", "description": "走 req-fix-bug-analyzer 生成版本级回归 bug fix 子需求,纳入本版本"},\n440\t {"label": "跳过回归失败", "description": "记录到 pending,进入 complete-version"},\n441\t {"label": "中止流程", "description": "停止,人工介入"}\n442\t ]\n443\t }]\n444\t })\n445\t choice = ans["失败处理"]\n446\t IF "生成 bug fix 子需求":\n447\t # 调用 req-fix-bug-analyzer 生成版本级回归 bug fix 子需求\n448\t Agent(req-fix-bug-analyzer, prompt=版本级回归bug描述)\n449\t # 子需求 currentStage=1,纳入版本 FOR 循环\n450\t # 子需求流程完成后需重新触发 Stage 10\n451\t GOTO 主菜单\n452\t IF "跳过回归失败" THEN BREAK\n453\t IF "中止流程" THEN GOTO 主菜单\n454\t```\n455\t\n456\t### 10.6.1 版本级回归用例状态流转 🆕\n457\t\n458\t> 触发条件:event_type == "test_passed"(决策点1:仅通过时流转,对齐 Stage 7 B7.5 语义 stage-hooks.md:1536-1544)\n459\t> 复用 stage-hooks.md:975-994 "HTTP POST调用容错模式"(三层错误分类)\n460\t> 数据源:`.regression-case-cache.json`(版本级用例ID缓存,stage-10:184)\n461\t\n462\t```python\n463\tFUNCTION transition_version_regression_cases():\n464\t cache_path = f"dev/versions/{versionId}/.regression-case-cache.json"\n465\t\n466\t # 1. 幂等检查(决策点2:transitionedAt 标记)\n467\t IF NOT 文件存在 cache_path THEN\n468\t OUTPUT: "⚠️ 无回归用例缓存文件,跳过状态流转"\n469\t RETURN\n470\t cache = read cache_path\n471\t IF cache.get("transitionedAt") 非空 THEN\n472\t OUTPUT: f"ℹ️ 版本级回归用例已流转过({cache[\'transitionedAt\']}),跳过重复流转"\n473\t RETURN\n474\t\n475\t # 2. 参数校验\n476\t test_case_ids = [c["testCaseId"] FOR c IN cache.get("uploadedCases", [])]\n477\t IF len(test_case_ids) == 0 THEN\n478\t OUTPUT: "⚠️ 回归用例缓存 uploadedCases 为空,跳过状态流转"\n479\t mcp__biz-sync__save_pending_item(\n480\t version_id="{versionName}", task_name="Stage10.6.1-用例流转",\n481\t mcp_method="mcp__tctp-dpms-set__updateTestCaseStatus",\n482\t skip_reason="TEST_CASE_IDS_EMPTY")\n483\t RETURN\n484\t\n485\t release_plan_id = 版本配置.releasePlanId\n486\t test_plan_id = 版本配置.regressionTestSetId\n487\t IF release_plan_id 为空 OR test_plan_id 为空 THEN\n488\t missing = []\n489\t IF NOT release_plan_id THEN missing.append("releasePlanId")\n490\t IF NOT test_plan_id THEN missing.append("regressionTestSetId")\n491\t mcp__biz-sync__save_pending_item(\n492\t version_id="{versionName}", task_name="Stage10.6.1-用例流转",\n493\t mcp_method="mcp__tctp-dpms-set__updateTestCaseStatus",\n494\t skip_reason="RELEASE_PLAN_OR_TEST_PLAN_EMPTY",\n495\t context_description=f"用例流转跳过,缺少参数:{missing}")\n496\t OUTPUT: f"⚠️ 用例流转跳过,缺少参数:{missing},已记录待补录"\n497\t RETURN\n498\t\n499\t # 3. 流转为通过(status=3)— 对齐 Stage 7 B7.5(stage-hooks.md:739-745)\n500\t operator = 当前用户英文名\n501\t 发送 HTTP POST 到 http://10.107.100.21:3000/tctptest/chatbot/updateTestCaseStatus:\n502\t {\n503\t "releasePlanId": release_plan_id,\n504\t "testPlanId": test_plan_id,\n505\t "operator": operator,\n506\t "testCaseList": [\n507\t {"testCaseId": tc_id, "status": 3, "modifier": operator, "runUser": operator}\n508\t FOR tc_id IN test_case_ids\n509\t ]\n510\t }\n511\t # 按 stage-hooks.md:975-994 "HTTP POST调用容错模式"处理(三层错误分类)\n512\t # 失败时 save_pending_item 的 mcp_method 统一用 "mcp__tctp-dpms-set__updateTestCaseStatus"\n513\t\n514\t IF HTTP成功 THEN\n515\t # 4. 回写幂等标记(决策点2)\n516\t cache["transitionedAt"] = current_timestamp()\n517\t cache["transitionStatus"] = "passed"\n518\t write cache_path = cache\n519\t OUTPUT: f"✅ 版本级回归用例已流转为通过({len(test_case_ids)}条)"\n520\t ELSE\n521\t # 容错模式已 save_pending_item;transitionedAt 不回写,允许重试\n522\t OUTPUT: "⚠️ 版本级回归用例流转失败,已记录待补录(transitionedAt未回写,可重试)"\n523\tEND FUNCTION\n524\t```\n525\t\n526\t### 10.6.2 SIT 回流:版本级回归用例状态补流转 🆕\n527\t\n528\t> **背景**:10.6.1 仅在 Stage 10.5 本地 `event_type=="test_passed"` 时触发。但版本级回归用例的业务执行方是 SIT(非本地,见 A6 测试报告 testStepList=[1,3] 含 SIT+回归)。两条路径下用例已同步入库(10.3 已 addTestCase+link,testCaseId 已生成于 `.regression-case-cache.json`)但无法流转:\n529\t> - **skip 模式**:10.5 被跳过 → 无 event_type → 10.6.1 不触发。此为**正确行为**(未执行不应标通过),不在此修复。\n530\t> - **SIT 执行后**:SIT 在版本流程外部执行,10.6.1 无感知 → 用例已通过却无流转入口 → "已同步未流转"悬挂态。**此为本函数修复对象**。\n531\t>\n532\t> **设计原则**(不臆断业务时序):\n533\t> 1. **不绑定任何"=SIT完成"的时序假设**(如"测试报告发布即SIT完成")——这类假设无法从源码确证,绑定即埋雷。\n534\t> 2. **幂等**:复用 transitionedAt 标记,10.6.1 已流转的跳过,不重复流转。\n535\t> 3. **显式触发**:由 complete-version 步骤2.5 在版本完成节点询问用户 SIT 结果后调用,不自动标通过(避免未执行标 status=3 的数据错误)。\n536\t> 4. **复用 10.6.1 流转逻辑**:HTTP POST updateTestCaseStatus status=3 + stage-hooks.md:975-994 容错,不新写流转代码。\n537\t>\n538\t> **调用方**:complete-version.md 步骤2.5(stage10Completed=True 分支内,SIT 回流兜底)。\n539\t\n540\t```python\n541\tFUNCTION transition_version_regression_cases_sit_callback():\n542\t # 与 10.6.1 transition_version_regression_cases() 共用同一缓存与幂等标记\n543\t cache_path = f"dev/versions/{versionId}/.regression-case-cache.json"\n544\t\n545\t # 1. 缓存与幂等检查(同 10.6.1 决策点2)\n546\t IF NOT 文件存在 cache_path THEN\n547\t OUTPUT: "⚠️ 无回归用例缓存文件,SIT 回流跳过"\n548\t RETURN\n549\t cache = read cache_path\n550\t IF cache.get("transitionedAt") 非空 THEN\n551\t OUTPUT: f"ℹ️ 版本级回归用例已流转过({cache[\'transitionedAt\']}),SIT 回流跳过"\n552\t RETURN\n553\t\n554\t # 2. 用例存在性校验\n555\t test_case_ids = [c["testCaseId"] FOR c IN cache.get("uploadedCases", [])]\n556\t IF len(test_case_ids) == 0 THEN\n557\t OUTPUT: "⚠️ 回归用例缓存 uploadedCases 为空,SIT 回流跳过"\n558\t mcp__biz-sync__save_pending_item(\n559\t version_id="{versionName}", task_name="Stage10.6.2-SIT回流",\n560\t mcp_method="mcp__tctp-dpms-set__updateTestCaseStatus",\n561\t skip_reason="TEST_CASE_IDS_EMPTY")\n562\t RETURN\n563\t\n564\t # 3. 参数校验(同 10.6.1)\n565\t release_plan_id = 版本配置.releasePlanId\n566\t test_plan_id = 版本配置.regressionTestSetId\n567\t IF release_plan_id 为空 OR test_plan_id 为空 THEN\n568\t missing = []\n569\t IF NOT release_plan_id THEN missing.append("releasePlanId")\n570\t IF NOT test_plan_id THEN missing.append("regressionTestSetId")\n571\t mcp__biz-sync__save_pending_item(\n572\t version_id="{versionName}", task_name="Stage10.6.2-SIT回流",\n573\t mcp_method="mcp__tctp-dpms-set__updateTestCaseStatus",\n574\t skip_reason="RELEASE_PLAN_OR_TEST_PLAN_EMPTY",\n575\t context_description=f"SIT 回流跳过,缺少参数:{missing}")\n576\t OUTPUT: f"⚠️ SIT 回流跳过,缺少参数:{missing},已记录待补录"\n577\t RETURN\n578\t\n579\t # 4. 流转为通过(status=3)— 复用 10.6.1 第3步 HTTP POST 逻辑\n580\t # (HTTP POST updateTestCaseStatus + stage-hooks.md:975-994 容错模式)\n581\t operator = 当前用户英文名\n582\t 发送 HTTP POST 到 http://10.107.100.21:3000/tctptest/chatbot/updateTestCaseStatus:\n583\t {\n584\t "releasePlanId": release_plan_id,\n585\t "testPlanId": test_plan_id,\n586\t "operator": operator,\n587\t "testCaseList": [\n588\t {"testCaseId": tc_id, "status": 3, "modifier": operator, "runUser": operator}\n589\t FOR tc_id IN test_case_ids\n590\t ]\n591\t }\n592\t # 失败时 save_pending_item 的 mcp_method 统一用 "mcp__tctp-dpms-set__updateTestCaseStatus"\n593\t\n594\t IF HTTP成功 THEN\n595\t cache["transitionedAt"] = current_timestamp()\n596\t cache["transitionStatus"] = "passed"\n597\t cache["transitionSource"] = "sit_callback" # 标记流转来源,区分 10.6.1 本地流转\n598\t write cache_path = cache\n599\t OUTPUT: f"✅ SIT 回流:版本级回归用例已流转为通过({len(test_case_ids)}条)"\n600\t ELSE\n601\t # 容错模式已 save_pending_item;transitionedAt 不回写,允许重试\n602\t OUTPUT: "⚠️ SIT 回流流转失败,已记录待补录(transitionedAt未回写,可重试)"\n603\tEND FUNCTION\n604\t```\n605\t\n606\t### 10.7 版本级回归测试报告\n607\t\n608\t```python\n609\t# 调用 test-report,使用其 SKILL.md "输入参数" 章节声明的目录路径参数\n610\t# 版本级回归测试的输入目录(对齐 test-report 实际声明的必填参数):\n611\t# - requirements_dir: 版本需求文档目录(docs/{versionName}/requirements/)\n612\t# - test_cases_dir: 回归测试用例目录(docs/project-knowledge/testing/regression/,Stage 10.2 读取的源文件位置)\n613\t# - test_execution_report_dir: 版本级回归测试执行报告目录(docs/{versionName}/testing/reports/,Stage 10.5 归档)\n614\t# - report_name: "版本级回归测试报告"\n615\tSkill(test-report, args=f"--requirements_dir docs/{versionName}/requirements/ --test_cases_dir docs/project-knowledge/testing/regression/ --test_execution_report_dir docs/{versionName}/testing/reports/ --report_name 版本级回归测试报告")\n616\t\n617\t# 输出:docs/{versionName}/testing/reports/test-report-{timestamp}/版本级回归测试报告.md\n618\t# 内容:模块列表、用例数、通过/失败数、循环次数、bug fix 子需求列表\n619\t\n620\t# 标记 stage10Completed\n621\tstage10_result = {\n622\t "stage": "10",\n623\t "status": "completed",\n624\t "summary": "版本级回归结果摘要(<=1000字)",\n625\t "artifacts": [实际存在的版本级回归报告/事件文件路径],\n626\t "decisions": [模块选择策略, 失败处理决策],\n627\t "risks": [未关闭风险],\n628\t "context_updates": {"versionRegressionResult": event_type}\n629\t}\n630\t校验 stage10_result(复用 dev-flow-context-contract.json stage_result_schema;版本级扩展字段只写 version-context)\n631\t\n632\t# 版本级两阶段checkpoint:先保存结果,再提交versions控制面,最后finalize\n633\tstage10_checkpoint_id = "{versionName}:VERSION:10:{ISO时间}"\n634\t原子写 version-context.md: checkpointId=stage10_checkpoint_id, checkpointState="pending", stage10Result=stage10_result\n635\t原子写 versions.json 该版本: stage10Completed=True, stage10CheckpointId=stage10_checkpoint_id, contextRevision+=1\n636\t原子写 version-context.md: checkpointState="clean", versionStatus="regression_completed", contextRevision=versions.contextRevision, updatedAt=now\n637\t```\n638\t\n639\t---\n640\t\n641\t## 容错规则\n642\t\n643\t- regressionTestSetId 为空 → 跳过 Stage 10,写入 pending-sync,不阻塞 complete-version\n644\t- module-index.json 不存在 → AskUserQuestion 选择构建或跳过\n645\t- 模块回归集不存在或为空 → 跳过该模块,不报错\n646\t- addTestCase 或 linkTestCaseToTestPlan 单条失败 → 记录失败计数,继续下一条\n647\t- 整个 Stage 10 失败 → 不阻塞 complete-version(但 stage10Completed=False,complete-version 步骤2.5 会提示)\n648\t\n649\t---\n650\t\n651\t## 完成验证(回复结束前必须逐项确认)\n652\t\n653\t- [ ] 10.1 前置检查 = ?(通过/跳过+pending)\n654\t- [ ] 10.2 模块选择策略 = ?(全量/手动/跳过执行)\n655\t- [ ] 10.2 selected_modules 数量 = ?\n656\t- [ ] 10.3 dpms 同步成功/失败数 = ?\n657\t- [ ] 10.4 回归测试代码生成 = ?\n658\t- [ ] 10.5 回归测试执行 event_type = ?\n659\t- [ ] 10.6 循环次数 = ?(0=一次通过)\n660\t- [ ] 10.6.1 版本级回归用例状态流转 = ?(已流转N条/跳过+pending/已流转过跳过)🆕\n661\t- [ ] 10.6.2 SIT 回流 = ?(全量回归本地通过时 10.6.1 已流转→此入口跳过 / skip或SIT场景由 complete-version 步骤2.5 触发,此处仅声明函数已就绪)🆕\n662\t- [ ] 10.7 报告生成 = ?\n663\t- [ ] versions.json stage10Completed = True\n664\t- [ ] version-context.md stage10Result/checkpointState = ?(completed/clean)\n665\t- [ ] Stage 10 输入均来自版本聚合上下文与实际产物,不依赖主会话旧缓存 = ?\n666\t\n667\t⛔ 所有项确认后 → 输出"✅ Stage 10 版本级回归测试完成" → 进入 complete-version\n668\t'}] + +**AI**: +[思考] 确认了: +- plugin-dev-eval-loop 命令存在 (.claude/commands/plugin-dev-eval-loop.md) ✅ +- Stage 10 的 agent/skill: + - 10.3: addTestCase + linkTestCaseToTestPlan (MCP, 无agent) + - 10.4: test-code-generator (Skill, --mode regression) + - 10.5: test-executor (Skill, --mode regression) + - 10.6: 循环决策 (失败时 req-fix-bug-analyzer) + - 10.6.1/10.6.2: 用例流转 (HTTP POST, 无agent) + - 10.7: test-report (Skill) + +现在我有完整信息了。让我开始写文档。 + +文档应该包含: +1. 概述:两条流程入口 +2. 流程1: /dev-flow version (版本轨) + - 入口层 stage (步骤0-2A-2B等) + - 启动版本需求 P0-P7 前置步骤 + - 21阶段 STAGE_ORDER 映射表 (每个stage的agent/skill) + - 阶段后置动作 Hook + - 完成版本 + - 变更单 +3. 流程2: /dev-flow <需求描述> (单需求轨) + - 入口语法 + - 前置步骤 P0-P7 + - 21阶段 (0-9, 不含10) 映射 + - 与版本模式差异 +4. 两条流程对比表 +5. agent/skill 完整清单(分类) + +文档输出到哪里?用户说"输出一个文档"。我应该写到一个md文件。考虑到项目有docs目录习惯,且git status显示有 docs/project-knowledge/sessions/ 目录。我写到 docs/ 下。 + +不过CLAUDE.md的文档输出规范是针对需求/设计/测试文档的。这个分析文档属于项目分析,我放在 docs/ 下即可。让我用一个清晰的文件名。 + +让我创建文档。文件名:docs/dev-flow流程Agent-Skill映射分析.md + +实际上,这是个分析文档,我应该问用户是否要写文件,还是直接输出。用户明确说"输出一个文档",所以写文件。但路径需要选择。我直接写到 docs/ 目录下。 + +让我考虑文档结构,要清晰标出: +- 具体的stage +- 具体的agent/skill名称 +- 用途 + +我会创建一个结构化的文档。 + +关于Stage 4 自动部署:dev-flow.md注意事项说"通过 project-deployer Skill 自动化管理编译与部署流程"。但映射表写"编译验证(可跳过)+git-commit+git-push"。所以Stage4实际涉及: +- project-deployer Skill (本地编译校验+git-commit+git-push) +- git-commit.md / git-push.md 命令(可能) + +我在文档中标注Stage 4: project-deployer Skill (+ git-commit/git-push命令)。 + +现在开始写文档。我要遵循verify-against-actual-agent-content,所有agent/skill名称都来自实际文件和映射表。 + +让我创建TaskCreate来跟踪?不,这是单一文档输出任务,不需要todo list。直接写。 + +文档我写到 docs/dev-flow流程Agent-Skill映射分析.md。 + +让我组织内容。我会写得详细且结构化。 + +注意:这是一个分析文档,不是实施任务,所以不需要enforce-checklist。但我需要做闭环检查。 + +让我写文档。由于内容较多,我直接Write创建文件。... + + +## 交互记录 (2026-07-27T09:25:02.772Z) + +**用户**: +[{'tool_use_id': 'call_d71ff9e94a664137a1b3be83', 'type': 'tool_result', 'content': '.claude\\commands\\git-commit.md\n.claude\\commands\\git-push.md\n.claude\\commands\\git-sync.md\n.claude\\commands\\memory-search.md\n.claude\\commands\\plugin-dev-eval-loop.md\n.claude\\commands\\plugin-execution-eval.md\n.claude\\commands\\plugin-trace-query.md\n.claude\\commands\\plugin-dependency.md\n.claude\\commands\\plugin-quality-check.md\n.claude\\commands\\merge-feature.md\n.claude\\commands\\dev-flow.md\n.claude\\commands\\dev-sync-agent-help.md'}] + +**AI**: +所有信息已齐全。确认 Stage 10 调用 `test-code-generator`/`test-executor`/`test-report` Skill,且 `plugin-dev-eval-loop` 命令存在。现在生成分析文档。 + +## 上下文回顾 + +**本次对话的核心问题**:分析 `dev-flow version` 和 `dev-flow <需求描述>` 两条流程涉及的 agent/skill,输出文档标明 stage、名称、用途。 + +**已识别的信息源**(均以实际文件内容为准): +- `dev-flow.md` — 主入口(版本轨引导菜单 + 单需求模式语法) +- `stage-hooks.md` — 阶段Agent映射表(21阶段)+ 形态B段调度 + Hook +- `standalone-mode.md` — 单需求模式 +- `start-development.md` — 启动版本需求 P0-P7 + 步骤A-E +- `stage-10-version-regression.md` — Stage 10 +- `stage-names.json` — stage 中文名映射 +- Glob 确认的 agent/skill/command 实际文件清单 + +**版本上下文**:current_version = 4.9(本次为纯分析任务,不涉及 agent 文件修改,不触发版本升级)。 + +现在写入文档:... + + +## 交互记录 (2026-07-27T09:28:07.146Z) + +**用户**: +[{'tool_use_id': 'call_fe6c2e3c549d429bb527432b', 'type': 'tool_result', 'content': 'File created successfully at: D:\\agent\\docs\\dev-flow流程Agent-Skill映射分析.md (file state is current in your context — no need to Read it back)'}] + +**AI**: +[思考] 文档已生成。让我做闭环检查。 + +## 闭环检查 + +- [x] 我的回复是否回应了用户当前问题?✅ 用户要求分析两条流程涉及的agent/skill,输出文档标出stage、名称、用途。已输出文档。 +- [x] 我的回复是否衔接了之前识别的问题?✅ 这是第一轮,无历史问题。 +- [x] 我是否引用了相关的历史分析结论?✅ 引用了memory(verify-against-actual-agent-content, analyze-project-ignore-changelog)。 +- [x] (涉及版本时)版本号合理性?本次纯分析任务,不涉及agent修改,不触发版本升级。✅ + +文档内容验证: +- 所有agent/skill名称都来自实际Glob结果 + stage-hooks.md映射表 ✅ +- 所有stage都来自stage-names.json + stage-hooks.md ✅ +- 两条流程的差异来自standalone-mode.md对比表 ✅ +- 用途描述来自各文件的实际内容 ✅ + +文档已写入 docs/dev-flow流程Agent-Skill映射分析.md。 + +现在向用户简短汇报。我应该给出文档路径和核心结论摘要,不要重复整个文档内容。 + +我应该考虑是否需要保存memory。这次分析揭示了dev-flow两条流程的完整agent/skill映射,这是一个有价值的项目知识。但是否"非显而易见"且"跨会话有用"?这是一个分析产物,已经写到docs文件了,不需要再存memory(memory规范说不要存repo已记录的内容)。文档本身就是记录。所以不存memory。 + +让我向用户汇报。简洁说明文档位置和核心发现。... + + +## 交互记录 (2026-07-28T10:31:00.876Z) + +**用户**: +test-code-generator会执行单元测试吗 + +**AI**: +## 闭环检查 + +- [x] 回应了用户问题:分析了两条流程的 agent/skill,输出文档标明 stage、名称、用途 +- [x] 衔接历史:遵循 memory `verify-against-actual-agent-content`(所有名称来自实际文件 + 映射表)、`analyze-project-ignore-changelog`(不看 changelog) +- [x] 版本:纯分析任务,不修改 agent 文件,不触发版本升级 +- [x] 多对象完整性:agent(requirement/design/development/testing/analysis/common 全目录)+ skill(全 33 个)+ command(全 11 个)均枚举 + +--- + +文档已生成:**`docs/dev-flow流程Agent-Skill映射分析.md`** + +### 核心结论 + +**两条流程共用 21 阶段引擎(STAGE_ORDER),差异在入口与后置动作**: + +1. **`/dev-flow version`(版本轨)** — 完整 21 阶段(0→10) + - 入口层:引导菜单 + 创建版本(A1/A2a/A2b/A5/A5.1 MCP)+ 需求管理 + - 前置 P0-P7:`project-context-analyzer` → `req-type-classifier` → `req-template-adapter` → `competitor-analyzer` → `knowledge-base-builder` + - 21 阶段映射:Stage 0 澄清 / 1 分析 / 2 设计 / 3 开发 / 6 测试 / 7 执行 / 9 决策 / 10 版本级回归 + - 阶段后置 Hook:B1-B7.5(DPMS 同步 + SDL + 转提测 + 用例流转)+ 注入防护 4 件套 + `api-doc-generator` + - 收尾:`complete-version` 12 步 + `version-change-order-generator` + +2. **`/dev-flow <需求描述>`(单需求轨)** — 20 阶段(0→9,无 Stage 10) + - 前置 P0-P7 与版本轨一致 + - 每个 stage 的 Agent/Skill **与版本轨完全相同** + - 差异:无 BIZ API、无 DPMS Hook、Stage 4 可跳过、Stage 9 失败回滚 Stage 1(非 blocked 模式)、保留图表同步 + 注入防护 + 接口文档生成 + +**关键分发规则**: +- Stage 1/2 按需求类型分发 6 种 `req-xxx-analyzer` / `des-xxx` +- Stage 3 按"语言 + 功能属性 + 前端检测"3D 决策分发后端/前端开发 Agent +- Stage 3.2/1.6 按技术栈分发 `java/python/go` 变体 + +文档第五节有两条流程的 Stage 全景对比表,可直接对照查阅。... + + +## 交互记录 (2026-07-28T10:31:20.594Z) + +**用户**: +[{'tool_use_id': 'call_44609880b60b4d84a7e8c23a', 'type': 'tool_result', 'content': '1\t---\n2\tname: test-code-generator\n3\ttype: testing\n4\tdescription: 基于Cucumber BDD的自动化测试代码生成专家,支持后端单元测试、接口测试、前端单元测试、Claude开发测试 and 全量回归测试代码生成\n5\tversion: 4.7\n6\tauthor: DevSyncAgent Team\n7\tlast_updated: 2026-07-16\n8\tchangelog:\n9\t v4.7 - 2026-07-16\n10\t - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则 + signals 基于职责正向设计)\n11\t v4.6 - 2026-06-01\n12\t - 🔄 概念对齐:将文档占位符 {功能名} 统一为 {需求名},与项目术语体系一致\n13\t v4.4 - 2026-05-28\n14\t - ❌ 彻底移除前端 E2E Playwright 直接生成、依赖注入及元素定位器映射等冗余逻辑,全面托管至 frontend-dynamic-tester 动态探索与录制流\n15\t - 🆕 新增测试代码与测试用例对应关系存储机制(testCodeMappings 写入 test-status.json)\n16\t - 🆕 支持在测试用例文档(_测试用例.md)中回写测试代码的路径映射(**测试代码路径**)\n17\t v4.3 - 2026-05-27\n18\t - 🆕 新增属性感知测试案例文档路径检测(优先读取{需求名}_前端测试案例.md或{需求名}_后端测试案例.md,回退到{需求名}_测试用例.md)\n19\t - 引用配置:design-doc-rules.json(splitOutputRules)\n20\t v4.2 - 2026-05-27\n21\t - 🔄 重命名 involved_terminal → function_attributes;新增 frontend_type 字段及测试路径分流\n22\t v4.1 - 2026-05-19\n23\t - 🆕 新增Claude BDD测试生成(Feature文件+评估数据集+Step Definitions)\n24\t - 🆕 解锁Claude开发模式下的Feature文件生成(SKIP_TRADITIONAL_CODE_TESTS + GENERATE_CLAUDE_BDD)\n25\t - 🆕 新增第2.6步:Claude BDD测试生成\n26\t - 🆕 新增claude-bdd模板目录\n27\t v4.0 - 2026-05-19\n28\t - 🆕 新增TypeScript后端项目Cucumber测试支持\n29\t - 🆕 新增第0.4节:TypeScript项目检测并引入@cucumber/cucumber\n30\t - 🆕 新增第2.4b节:TypeScript Cucumber Step Definitions生成\n31\t - 🐛 修复项目类型检测逻辑:TypeScript后端项目(NestJS/Express+TS)不再被误分类为web-frontend\n32\t - 🆕 支持NestJS集成测试Step示例(@nestjs/testing + supertest)\n33\t---\n34\t\n35\t# 测试代码生成器 Skill\n36\t\n37\t你是基于Cucumber BDD的自动化测试代码生成专家,专注于生成可执行的测试代码。\n38\t\n39\t## ⚠️ 路径解析优先级(version_mode兼容)\n40\t\n41\t本Skill中所有 `dev/active/{task-name}/` 路径按以下优先级解析:\n42\t\n43\t```\n44\t1. 若调用Prompt中包含【工作目录】字段 → 使用该路径作为BASE_DIR(如 dev/versions/v3.10/user-export/)\n45\t2. 否则 → 回退到默认路径 dev/active/{task-name}/\n46\t\n47\t规则:将文档中所有 dev/active/{task-name}/ 替换为 {BASE_DIR}\n48\t示例:dev/active/user-export/test-status.json → dev/versions/v3.10/user-export/test-status.json\n49\t```\n50\t\n51\t## 适用场景\n52\t\n53\t- 已有Feature文件和测试用例文档,需要生成可执行的测试代码\n54\t- 支持Java、Python、Go和TypeScript项目\n55\t- 全量回归测试代码生成\n56\t\n57\t## 核心能力\n58\t\n59\t| 能力 | 说明 |\n60\t|-----|------|\n61\t| **Cucumber场景测试** | 基于Feature文件生成BDD风格测试 |\n62\t| **TypeScript Cucumber测试** 🆕 | 基于@cucumber/cucumber生成TypeScript BDD测试 |\n63\t| **单元测试** | 为核心方法生成单元测试(含Mock) |\n64\t| **性能测试** | 生成压力测试和负载测试脚本 |\n65\t| **全量回归测试** | 基于知识库Feature文件生成全量回归测试代码 |\n66\t| **前端单元测试** 🆕 | 支持Jest/Vitest组件测试代码生成 |\n67\t| **Claude开发测试** | 检测Claude Agent/Skill/Command开发需求 |\n68\t| **源代码方法索引** | 扫描src目录构建类/方法索引 |\n69\t| **方法存在性验证** | 生成时验证调用的类/方法是否存在 |\n70\t| **代码与脚本验证** | 编译验证+脚本语法检查(block模式) |\n71\t\n72\t## 输入\n73\t\n74\t**优先级顺序**:\n75\t\n76\t1. **Feature文件**(必须):\n77\t - 主路径:`dev/active/{task-name}/features/*.feature`\n78\t - 备选路径:`dev/docs/*.feature`(主路径不存在时使用)\n79\t2. **测试用例文档**(必须):`docs/{branch}/testing/{需求名}_测试用例.md`\n80\t\n81\t > 📝 **属性感知路径检测** 🆕v4.3:当测试案例按功能属性拆分时,优先读取属性独立文档:\n82\t > - 后端测试代码生成 → 优先 `docs/{branch}/testing/{需求名}_后端测试案例.md`,回退到 `{需求名}_测试用例.md`\n83\t > - 前端 UI 测试(托管) → 优先从 `docs/{branch}/testing/{需求名}_前端测试案例.md`(或 `_测试用例.md`)读取,用于 Step 5.4 自动化路径回写\n84\t > - 数据测试代码生成 → 优先 `docs/{branch}/testing/{需求名}_数据测试案例.md`,回退到 `{需求名}_测试用例.md`\n85\t3. **项目源代码**(必须):已实现的功能代码\n86\t4. **项目上下文**:`project-context.json`\n87\t\n88\t## 输出\n89\t\n90\t**主要输出**:\n91\t- 📄 **Cucumber测试代码** - Step Definitions + Runner类\n92\t- 📄 **单元测试代码** - JUnit/pytest测试类\n93\t- 📄 **性能测试脚本** - JMeter/locust脚本\n94\t- 📄 **远程API测试脚本** - curl/requests脚本\n95\t- 📄 **test-status.json** - 测试状态文件\n96\t\n97\t**输出路径**:\n98\t```\n99\tsrc/test/java/\n100\t├── cucumber/\n101\t│ ├── runner/ # Cucumber Runner类\n102\t│ ├── steps/ # Step Definitions\n103\t│ └── hooks/ # Before/After hooks\n104\t├── unit/ # 单元测试\n105\t├── performance/ # 性能测试脚本\n106\t└── resources/\n107\t └── features/ # Feature文件副本\n108\t\n109\tdev/active/{task-name}/\n110\t└── test-status.json # 测试状态文件\n111\t```\n112\t\n113\t---\n114\t\n115\t## 子需求模式检测 🆕\n116\t\n117\t**目标**:检测当前是否为DevOps循环中子需求的测试代码生成\n118\t\n119\t### 检测逻辑\n120\t\n121\t```markdown\n122\t1. 检查 cycle-state.json 是否存在\n123\t IF 存在 THEN\n124\t 读取 parentRequirementId 和 subRequirementType\n125\t\n126\t IF subRequirementType == "bug-fix" THEN\n127\t 进入【子需求生成模式】\n128\t ELSE\n129\t 进入【标准生成模式】\n130\t END IF\n131\tELSE\n132\t 进入【标准生成模式】\n133\tEND IF\n134\t```\n135\t\n136\t### 子需求生成模式处理策略\n137\t\n138\t当检测到子需求模式时:\n139\t\n140\t**1. 读取父需求测试代码**\n141\t```markdown\n142\t路径:src/test/java/**/*.java 或 src/test/**/*.py\n143\t```\n144\t\n145\t**2. 生成策略差异**\n146\t\n147\t| 生成维度 | 标准模式 | 子需求模式 |\n148\t|---------|---------|-----------|\n149\t| 代码生成 | 生成完整测试代码 | 基于父需求代码修改/新增 |\n150\t| 测试标记 | 无标记 | 添加@Tag("sub-requirement") |\n151\t\n152\t**3. 输出调整**\n153\t- ✅ 报告中标识子需求模式\n154\t- ✅ 说明基于父需求测试的修改生成\n155\t- ✅ 提供修改后的测试代码路径\n156\t\n157\t---\n158\t\n159\t## 测试生成流程\n160\t\n161\t```mermaid\n162\tgraph TD\n163\t A[开始] --> B{回归测试模式?}\n164\t B -->|是| C[检查知识库]\n165\t C --> D{知识库为空?}\n166\t D -->|是| E[提示无法执行,退出]\n167\t D -->|否| F[扫描知识库Feature文件]\n168\t F --> G[生成全量回归测试代码]\n169\t G --> H[更新test-status.json]\n170\t H --> I[结束]\n171\t B -->|否| J[第0步: 环境检测与准备]\n172\t J --> J9[第0.9步: 源代码方法索引构建 🆕]\n173\t J9 --> K{项目语言?}\n174\t K -->|Java| L[检测Cucumber依赖]\n175\t K -->|Python| M[检测behave依赖]\n176\t K -->|Go| N[检测godog依赖]\n177\t K -->|TypeScript| NT[检测@cucumber/cucumber依赖]\n178\t L --> O[引入依赖]\n179\t M --> O\n180\t N --> O\n181\t NT --> O\n182\t O --> P[第1步: 读取输入文件]\n183\t P --> Q[第2步: 生成Cucumber测试]\n184\t Q --> QV{方法存在性验证 🆕}\n185\t QV -->|通过| R[第3步: 生成单元测试]\n186\t QV -->|失败| QW[生成TODO标记和警告]\n187\t QW --> R\n188\t R --> S[第4步: 生成性能测试]\n189\t S --> T[第4.8步: 生成远程curl测试]\n190\t T --> U[第5步: 测试代码合并]\n191\t U --> V[第5.5步: 代码与脚本合法性验证 🆕]\n192\t V --> W{验证通过?}\n193\t W -->|是| X[更新test-status.json]\n194\t W -->|否| Y[生成错误报告并阻断]\n195\t Y --> Z[结束-需修复]\n196\t X --> I\n197\t```\n198\t\n199\t### 回归测试模式参数 🆕v4.9\n200\t\n201\t```bash\n202\t# 全量回归(默认,向后兼容)\n203\t/skill test-code-generator --mode regression\n204\t\n205\t# 按模块筛选回归测试代码生成(Stage 10.4 调用)\n206\t/skill test-code-generator --mode regression --modules user,payment,mf_proxy_cors\n207\t```\n208\t\n209\t**--modules 参数说明**:\n210\t- 不传:全量回归(扫描 `docs/project-knowledge/testing/features/*.feature` 全部)—— 向后兼容\n211\t- 传入:仅生成指定模块的回归测试代码(从 `docs/project-knowledge/testing/features/{module}.feature` 加载)\n212\t\n213\t**回归模式输出路径**(复用标准生成流程,与"输出"章节一致):\n214\t- Java项目: `src/test/java/cucumber/{runner,steps,hooks}/` + `src/test/resources/features/`\n215\t- TypeScript项目: `test/{steps,hooks}/` + `features/`\n216\t- Python项目: `tests/` + `features/`\n217\t- Go项目: `tests/` + `features/`\n218\t- test-status.json: `{BASE_DIR}/test-status.json`(version_mode 下 BASE_DIR 为 `dev/versions/{versionId}/`)\n219\t\n220\t**参数解析逻辑**:\n221\t```bash\n222\tMODULES_ARG="${MODULES:-}"\n223\tREGRESSION_FEATURES_DIR="docs/project-knowledge/testing/features"\n224\tIF [ -z "$MODULES_ARG" ]; THEN\n225\t # 全量模式(向后兼容)\n226\t FEATURE_FILES=$(find "$REGRESSION_FEATURES_DIR" -name "*.feature" 2>/dev/null | sort)\n227\tELSE\n228\t # 按模块筛选\n229\t IFS=\',\' read -ra MODULE_ARRAY <<< "$MODULES_ARG"\n230\t FEATURE_FILES=""\n231\t FOR module IN "${MODULE_ARRAY[@]}"; do\n232\t FEATURE_FILE="$REGRESSION_FEATURES_DIR/${module}.feature"\n233\t IF [ -f "$FEATURE_FILE" ]; THEN\n234\t FEATURE_FILES="$FEATURE_FILES $FEATURE_FILE"\n235\t ELSE\n236\t echo "⚠️ 模块 ${module} 的 Feature 文件不存在,跳过"\n237\t fi\n238\t done\n239\tfi\n240\t```\n241\t\n242\t---\n243\t\n244\t## 第0步:环境检测与准备\n245\t\n246\t### 0.1 检测项目语言\n247\t\n248\t**检测方法**:\n249\t```bash\n250\t# 检查项目类型\n251\tif [ -f "go.mod" ]; then\n252\t PROJECT_TYPE="go"\n253\t LANGUAGE="Go"\n254\telif [ -f "pom.xml" ]; then\n255\t PROJECT_TYPE="maven"\n256\t LANGUAGE="Java"\n257\telif [ -f "build.gradle" ] || [ -f "build.gradle.kts" ]; then\n258\t PROJECT_TYPE="gradle"\n259\t LANGUAGE="Java"\n260\telif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then\n261\t PROJECT_TYPE="python"\n262\t LANGUAGE="Python"\n263\telif [ -f "setup.py" ]; then\n264\t PROJECT_TYPE="python"\n265\t LANGUAGE="Python"\n266\telif [ -f "package.json" ]; then\n267\t # 1. 优先检测TypeScript后端项目(NestJS / Express+TS / Koa+TS)\n268\t if grep -q \'"@nestjs/core"\' package.json || [ -f "nest-cli.json" ]; then\n269\t PROJECT_TYPE="typescript-backend"\n270\t LANGUAGE="TypeScript"\n271\t FRAMEWORK="nestjs"\n272\t echo "✅ 检测到TypeScript后端项目(NestJS)"\n273\t elif grep -q \'"@nestjs/common"\' package.json; then\n274\t PROJECT_TYPE="typescript-backend"\n275\t LANGUAGE="TypeScript"\n276\t FRAMEWORK="nestjs"\n277\t echo "✅ 检测到TypeScript后端项目(NestJS)"\n278\t elif [ -f "tsconfig.json" ] && (grep -q \'"express"\' package.json || grep -q \'"koa"\' package.json) && ! grep -q \'"react"\' package.json && ! grep -q \'"vue"\' package.json; then\n279\t PROJECT_TYPE="typescript-backend"\n280\t LANGUAGE="TypeScript"\n281\t FRAMEWORK="express"\n282\t echo "✅ 检测到TypeScript后端项目(Express/Koa)"\n283\t # 2. 然后检测纯前端项目\n284\t elif [ ! -f "pom.xml" ] && [ ! -f "go.mod" ] && [ ! -f "requirements.txt" ] && [ ! -f "pyproject.toml" ]; then\n285\t PROJECT_TYPE="web-frontend"\n286\t\n287\t # 检测前端框架\n288\t if grep -q \'"react"\' package.json || grep -q \'"react-dom"\' package.json; then\n289\t FRAMEWORK="react"\n290\t LANGUAGE="TypeScript"\n291\t elif grep -q \'"vue"\' package.json; then\n292\t FRAMEWORK="vue"\n293\t LANGUAGE="TypeScript"\n294\t elif grep -q \'"@angular/core"\' package.json; then\n295\t FRAMEWORK="angular"\n296\t LANGUAGE="TypeScript"\n297\t elif grep -q \'"svelte"\' package.json; then\n298\t FRAMEWORK="svelte"\n299\t LANGUAGE="TypeScript"\n300\t else\n301\t FRAMEWORK="unknown"\n302\t LANGUAGE="TypeScript"\n303\t fi\n304\t\n305\t echo "✅ 检测到纯前端项目: $FRAMEWORK"\n306\t else\n307\t echo "⚠️ 无法检测项目类型"\n308\t exit 1\n309\t fi\n310\telse\n311\t echo "⚠️ 无法检测项目类型"\n312\t exit 1\n313\tfi\n314\t```\n315\t\n316\t### 0.2 Java项目 - 检测并引入Cucumber 🔴 P0级强制执行\n317\t\n318\t**检测Cucumber依赖**:\n319\t\n320\t**Maven项目** (`pom.xml`):\n321\t```bash\n322\t# 检查是否已存在Cucumber依赖\n323\tif grep -q "io.cucumber" pom.xml; then\n324\t echo "✅ Cucumber依赖已存在"\n325\telse\n326\t echo "⚠️ Cucumber依赖不存在,准备引入..."\n327\tfi\n328\t```\n329\t\n330\t**🚨 P0级强制执行规则**:\n331\t\n332\t当检测到Cucumber依赖不存在时,**必须**执行以下操作:\n333\t\n334\t1. **立即停止生成测试代码**\n335\t2. **自动添加Cucumber依赖到pom.xml**\n336\t3. **执行 `mvn dependency:resolve` 下载依赖**\n337\t4. **验证依赖成功添加后,才能继续第1步**\n338\t\n339\t```bash\n340\t# 🔴 P0级强制执行流程\n341\tif ! grep -q "io.cucumber" pom.xml; then\n342\t echo "========================================"\n343\t echo "🔴 P0级强制步骤:添加Cucumber依赖"\n344\t echo "========================================"\n345\t\n346\t # 添加Cucumber依赖\n347\t # ...添加依赖的代码...\n348\t\n349\t echo "📌 正在下载依赖..."\n350\t mvn dependency:resolve\n351\t\n352\t echo "✅ Cucumber依赖已成功添加并下载"\n353\tfi\n354\t```\n355\t\n356\t**自动引入Cucumber依赖** (Maven) 🔴 **仅使用 JUnit 5**:\n357\t\n358\t```xml\n359\t\n360\t\n361\t \n362\t \n363\t io.cucumber\n364\t cucumber-java\n365\t 7.14.0\n366\t test\n367\t \n368\t\n369\t \n370\t \n371\t io.cucumber\n372\t cucumber-junit-platform-engine\n373\t 7.14.0\n374\t test\n375\t \n376\t\n377\t \n378\t \n379\t org.junit.platform\n380\t junit-platform-suite\n381\t 1.10.0\n382\t test\n383\t \n384\t\n385\t \n386\t \n387\t org.junit.jupiter\n388\t junit-jupiter\n389\t 5.10.0\n390\t test\n391\t \n392\t\n393\t \n394\t \n395\t io.cucumber\n396\t cucumber-picocontainer\n397\t 7.14.0\n398\t test\n399\t \n400\t\n401\t \n402\t \n403\t org.mockito\n404\t mockito-core\n405\t 5.5.0\n406\t test\n407\t \n408\t\n409\t \n410\t \n411\t org.assertj\n412\t assertj-core\n413\t 3.24.2\n414\t test\n415\t \n416\t\n417\t```\n418\t\n419\t\n420\t### 0.3 Python项目 - 检测并引入behave\n421\t\n422\t**检测behave依赖**:\n423\t\n424\t```bash\n425\t# 检查requirements.txt或已安装包\n426\tif grep -q "behave" requirements.txt 2>/dev/null || pip show behave > /dev/null 2>&1; then\n427\t echo "✅ behave依赖已存在"\n428\telse\n429\t echo "⚠️ behave依赖不存在,准备引入..."\n430\tfi\n431\t```\n432\t\n433\t**自动引入behave依赖**:\n434\t\n435\t```txt\n436\t# 添加到requirements.txt\n437\tbehave==1.2.6\n438\tpytest==7.4.3\n439\tpytest-mock==3.12.0\n440\tpytest-bdd==7.0.0\n441\tlocust==2.18.3\n442\t```\n443\t\n444\t### 0.3.1 Go项目 - 检测并引入godog 🆕\n445\t\n446\t**检测godog依赖**:\n447\t\n448\t```bash\n449\t# 检查go.mod中是否存在godog依赖\n450\tif grep -q "github.com/cucumber/godog" go.mod; then\n451\t echo "✅ godog依赖已存在"\n452\telse\n453\t echo "⚠️ godog依赖不存在,准备引入..."\n454\tfi\n455\t```\n456\t\n457\t**自动引入godog依赖**:\n458\t\n459\t```bash\n460\tgo get github.com/cucumber/godog/cmd/godog@latest\n461\tgo mod download\n462\t```\n463\t\n464\t### 0.4 TypeScript项目 - 检测并引入@cucumber/cucumber 🆕\n465\t\n466\t**检测Cucumber依赖**:\n467\t\n468\t```bash\n469\t# 检查package.json中是否存在@cucumber/cucumber依赖\n470\tif grep -q \'"@cucumber/cucumber"\' package.json; then\n471\t echo "✅ @cucumber/cucumber依赖已存在"\n472\telse\n473\t echo "⚠️ @cucumber/cucumber依赖不存在,准备引入..."\n474\tfi\n475\t```\n476\t\n477\t**自动引入@cucumber/cucumber依赖**:\n478\t\n479\t```json\n480\t// 添加到package.json的devDependencies\n481\t{\n482\t "devDependencies": {\n483\t "@cucumber/cucumber": "^10.0.0",\n484\t "ts-node": "^10.9.0",\n485\t "typescript": "^5.3.0",\n486\t "@types/node": "^20.0.0",\n487\t "chai": "^4.3.0",\n488\t "@types/chai": "^4.3.0"\n489\t },\n490\t "scripts": {\n491\t "test:cucumber": "cucumber-js test/features --require test/steps --require test/hooks --require-module ts-node/register",\n492\t "test:cucumber:report": "cucumber-js test/features --require test/steps --require test/hooks --require-module ts-node/register --format json:reports/cucumber_report.json"\n493\t }\n494\t}\n495\t```\n496\t\n497\t**Cucumber配置文件** — `cucumber.js`:\n498\t\n499\t```javascript\n500\t// cucumber.js - Cucumber配置文件(CommonJS格式)\n501\tmodule.exports = {\n502\t default: {\n503\t paths: [\'test/features/**/*.feature\'],\n504\t require: [\'test/steps/**/*.ts\', \'test/hooks/**/*.ts\'],\n505\t requireModule: [\'ts-node/register\'],\n506\t format: [\'progress\', \'json:reports/cucumber_report.json\'],\n507\t formatOptions: { snippetInterface: \'async-await\' },\n508\t parallel: 4,\n509\t },\n510\t};\n511\t```\n512\t\n513\t---\n514\t\n515\t## 第0.5步:性能测试需求检测 🆕\n516\t\n517\t**目标**:检测项目是否需要性能测试,以及性能测试的类型\n518\t\n519\t### 检测逻辑\n520\t\n521\t**Step 1:从Feature文件检测性能标签**\n522\t\n523\t```bash\n524\t# 检查Feature文件中的@performance标签\n525\tif grep -r "@performance" features/ 2>/dev/null; then\n526\t PERFORMANCE_NEEDED=true\n527\t PERFORMANCE_TYPE="feature"\n528\t echo "✅ 检测到性能测试需求(来源:Feature文件 @performance标签)"\n529\tfi\n530\t```\n531\t\n532\t**Step 2:从测试用例文档检测性能测试**\n533\t\n534\t```bash\n535\t# 检查测试用例文档中是否包含性能测试章节\n536\tif grep -r "性能测试\\|performance" docs/*/testing/*测试用例.md 2>/dev/null; then\n537\t PERFORMANCE_NEEDED=true\n538\t PERFORMANCE_TYPE="test_case"\n539\t echo "✅ 检测到性能测试需求(来源:测试用例文档)"\n540\tfi\n541\t```\n542\t\n543\t**Step 3:从需求文档检测性能要求**\n544\t\n545\t```bash\n546\t# 检查需求文档中的性能相关关键词\n547\tif grep -ri "性能\\|响应时间\\|吞吐量\\|并发\\|延迟\\|负载\\|压力" docs/*/requirements/*_需求.md 2>/dev/null; then\n548\t PERFORMANCE_NEEDED=true\n549\t PERFORMANCE_TYPE="requirement"\n550\t echo "✅ 检测到性能测试需求(来源:需求文档)"\n551\tfi\n552\t```\n553\t\n554\t---\n555\t\n556\t## 第0.5b步:性能基线确认与读取 🆕\n557\t\n558\t**目标**:根据需求类型读取或确认性能基线,为性能测试提供阈值对比标准\n559\t\n560\t### 基线来源策略\n561\t\n562\t| 需求类型 | 基线来源 | 读取逻辑 |\n563\t|---------|---------|---------|\n564\t| **OPTIMIZE** | 性能设计文档 | 读取`docs/{branch}/design/{需求名}_设计.md`中的"当前值"和"目标值" |\n565\t| **FIX BUG** | 基线测试或监控数据 | 提示用户执行基线测试或从监控系统提取 |\n566\t| **NEW/ENHANCE** | 需求文档非功能需求 | 读取需求文档中的性能要求,无则询问用户 |\n567\t| **默认** | 行业标准参考 | 使用默认性能阈值 |\n568\t\n569\t### 检测与读取逻辑\n570\t\n571\t**Step 1:检测需求类型**\n572\t\n573\t```bash\n574\t# 识别需求类型\n575\tif grep -r "优化需求\\|OPTIMIZE\\|性能优化" docs/*/requirements/*.md 2>/dev/null; then\n576\t REQUIREMENT_TYPE="OPTIMIZE"\n577\telif grep -r "修复需求\\|FIX BUG\\|问题修复" docs/*/requirements/*.md 2>/dev/null; then\n578\t REQUIREMENT_TYPE="FIX_BUG"\n579\telif grep -r "新增需求\\|NEW\\|新功能" docs/*/requirements/*.md 2>/dev/null; then\n580\t REQUIREMENT_TYPE="NEW"\n581\telif grep -r "增强需求\\|ENHANCE\\|功能增强" docs/*/requirements/*.md 2>/dev/null; then\n582\t REQUIREMENT_TYPE="ENHANCE"\n583\tfi\n584\t```\n585\t\n586\t**Step 2:生成/更新performance-baseline.json**\n587\t\n588\t```bash\n589\tBASELINE_FILE=".claude/data/testing/baseline/performance-baseline.json"\n590\t\n591\t# 如果基线文件不存在,创建默认模板\n592\tif [ ! -f "$BASELINE_FILE" ]; then\n593\t cat > "$BASELINE_FILE" </dev/null; then\n682\t FRONTEND_NEEDED=true\n683\t echo "✅ 检测到前端测试需求(@frontend标签)"\n684\tfi\n685\t```\n686\t\n687\t**Step 4:前端子目录扫描(所有项目类型)🔧 v3.9修复**\n688\t\n689\t```bash\n690\t# 扫描常见的前端子目录(适用于所有后端项目类型)\n691\t# 包括:Java/Spring Boot、Python/Django/Flask、Go等\n692\t\n693\t# 通用前端目录\n694\tFRONTEND_DIRS=("frontend" "web" "static" "client" "ui" "app/frontend")\n695\t\n696\t# Java/Spring Boot 特有目录\n697\tif [ "$PROJECT_TYPE" = "java" ]; then\n698\t SPRING_FRONTEND_DIRS=("src/main/resources/static" "src/main/resources/templates" "src/main/resources/public")\n699\t FRONTEND_DIRS=("${FRONTEND_DIRS[@]}" "${SPRING_FRONTEND_DIRS[@]}")\n700\tfi\n701\t\n702\t# Python/Django/Flask 特有目录\n703\tif [ "$PROJECT_TYPE" = "python" ]; then\n704\t PYTHON_FRONTEND_DIRS=("templates" "static" "frontend" "webapp")\n705\t FRONTEND_DIRS=("${FRONTEND_DIRS[@]}" "${PYTHON_FRONTEND_DIRS[@]}")\n706\tfi\n707\t\n708\tfor dir in "${FRONTEND_DIRS[@]}"; do\n709\t if [ -d "$dir" ]; then\n710\t # 检查是否为前端目录(有package.json或包含HTML/JS文件)\n711\t if [ -f "$dir/package.json" ] || ls "$dir"/*.html 1>/dev/null 2>&1; then\n712\t FRONTEND_FOUND="$dir"\n713\t FRONTEND_DIR_PATH="$dir"\n714\t break\n715\t fi\n716\t fi\n717\tdone\n718\t\n719\tif [ -n "$FRONTEND_FOUND" ]; then\n720\t echo "✅ 检测到$PROJECT_TYPE项目前端子目录:$FRONTEND_FOUND"\n721\t FRONTEND_NEEDED=true\n722\tfi\n723\t```\n724\t\n725\t---\n726\t\n727\t## 第0.6a步:前端测试模式选择 🆕\n728\t\n729\t**目标**:当检测到前端功能时,询问用户选择测试执行模式\n730\t\n731\t**触发条件**:`FRONTEND_NEEDED = true`\n732\t\n733\t### 模式选择与前端 E2E 托管策略\n734\t\n735\t**原则**:为了彻底避免 AI 静态推导对复杂前端页面交互(如动态 DOM、SSO 登录、Canvas 渲染)时发生“定位器不准(Flaky Selector)”和“异步时序错位”的问题,本 Skill **移除了直接静态生成前端 Playwright spec.ts 代码的逻辑**。\n736\t\n737\t* **后端功能/接口测试**:继续使用当前 Skill 执行静态代码模式,生成单元测试、Mock 配置或 Cucumber 步骤绑定代码。\n738\t* **前端 UI/E2E 交互测试**:**完全托管给 `frontend-dynamic-tester`**。通过“动态跑一次 $\\to$ 录制沉淀 Playwright 代码 $\\to$ 提交 Git”的方式生成,本 Skill 仅在 Step 5.4 负责读取这些高可用录制脚本并回写对照映射。\n739\t\n740\t```mermaid\n741\tgraph TD\n742\t A[检测到功能需求] --> B{需求属性?}\n743\t B -->|后端/接口测试| C[静态代码模式 test-code-generator]\n744\t B -->|前端 UI/E2E 测试| D[动态录制沉淀模式 frontend-dynamic-tester]\n745\t C --> E[生成 JUnit/pytest/Mock 代码]\n746\t D --> F[真机浏览器交互录制 & 沉淀 Playwright 代码]\n747\t F --> G[在用例文档中回写对照映射]\n748\t```\n749\t\n750\t### 询问用户选择\n751\t\n752\t**执行方式**:使用 AskUserQuestion 工具\n753\t\n754\t```javascript\n755\tAskUserQuestion({\n756\t questions: [{\n757\t question: "检测到测试用例包含前端 UI / E2E 交互。请选择测试生成模式:",\n758\t header: "测试模式分流",\n759\t multiSelect: false,\n760\t options: [\n761\t {\n762\t label: "后端逻辑与集成测试生成",\n763\t description: "由 test-code-generator 生成后端单元测试、接口 curl 脚本及 BDD Steps 胶水代码。"\n764\t },\n765\t {\n766\t label: "动态 UI 录制与沉淀(推荐)",\n767\t description: "调用 frontend-dynamic-tester 打开真机浏览器,录制精准的 Playwright 用例资产并自动沉淀。"\n768\t }\n769\t ]\n770\t }]\n771\t})\n772\t```\n773\t\n774\t### 用户选择后的处理\n775\t\n776\t**选择“后端逻辑与集成测试生成”**:\n777\t- 继续执行当前 SKILL 的后续流程,生成后端测试文件。\n778\t\n779\t**选择“动态 UI 录制与沉淀”**:\n780\t- 引导用户运行 `frontend-dynamic-tester`,并终止当前 Skill 的前端 UI/E2E 流程:\n781\t\n782\t```markdown\n783\t## 🔄 转交至动态 UI 录制与沉淀流程\n784\t\n785\t您选择了动态 UI 录制模式,为了确保元素定位的 100% 准确性,请调用 `frontend-dynamic-tester` 进行页面探索与录制:\n786\t\n787\t```\n788\t/skill frontend-dynamic-tester\n789\t```\n790\t\n791\t### 录制完成后\n792\t录制沉淀出的 `*.spec.ts` 脚本将自动保存至 `src/test/playwright/`。再次运行 `test-code-generator` 时,它将自动在 `_测试用例.md` 中回写该自动化测试代码的物理路径映射。\n793\t```\n794\t\n795\t---\n796\t\n797\t## 第0.6b步:自动页面分析与澄清 🚀v3.10\n798\t\n799\t**目标**:使用 Playwright 自动抓取页面元素,最小化用户交互成本,确保定位器基于真实页面。\n800\t\n801\t### 🚨 核心改进\n802\t\n803\t| 问题 | 原方案 | 新方案 |\n804\t|-----|-------|-------|\n805\t| **澄清未触发** | SKILL.md 只有伪代码注释 | ✅ 明确的 AskUserQuestion 调用流程 |\n806\t| **元素定位不准** | 用户凭记忆回答 | ✅ Playwright 自动抓取页面元素 |\n807\t| **交互成本高** | 回答10+问题 | ✅ 1-2次交互即可完成 |\n808\t| **认证方式单一** | 仅支持用户名密码 | ✅ 支持 Cookie/Token/用户名密码 |\n809\t\n810\t### 触发条件\n811\t\n812\t当满足以下任一条件时触发澄清流程:\n813\t\n814\t| 条件 | 说明 |\n815\t|-----|------|\n816\t| `FRONTEND_NEEDED = true` | 第0.6步检测到前端测试需求 |\n817\t| `requirementAttribute = "前端开发"` | 需求属性识别为前端开发 |\n818\t| Feature文件含 `@frontend` 标签 | 明确的前端测试标记 |\n819\t\n820\t### 澄清执行流程\n821\t\n822\t```mermaid\n823\tgraph TD\n824\t A[检测前端测试需求] --> B{FRONTEND_NEEDED?}\n825\t B -->|否| C[跳过澄清]\n826\t B -->|是| D[检查澄清配置文件]\n827\t D --> E{配置文件存在?}\n828\t E -->|是| F[加载已有配置]\n829\t E -->|否| G[询问页面URL]\n830\t G --> H[询问认证方式]\n831\t H --> I{认证类型?}\n832\t I -->|Cookie| J[收集Cookie]\n833\t I -->|用户名密码| K[收集登录信息]\n834\t I -->|Token| L[收集Token]\n835\t I -->|无需认证| M[跳过认证]\n836\t J --> N[执行Playwright自动分析]\n837\t K --> N\n838\t L --> N\n839\t M --> N\n840\t N --> O[展示AI分析结果]\n841\t O --> P{用户确认?}\n842\t P -->|全部正确| Q[生成配置文件]\n843\t P -->|部分修改| R[详细澄清]\n844\t P -->|重新分析| N\n845\t R --> Q\n846\t F --> S[继续测试代码生成]\n847\t Q --> S\n848\t C --> S\n849\t```\n850\t\n851\t---\n852\t\n853\t## 第0.6b.1步:询问页面URL 🚀\n854\t\n855\t**执行方式**:使用 AskUserQuestion 工具\n856\t\n857\t```javascript\n858\tAskUserQuestion({\n859\t questions: [{\n860\t question: "请提供目标页面的URL:",\n861\t header: "页面URL",\n862\t multiSelect: false,\n863\t options: [\n864\t {\n865\t label: "手动输入URL",\n866\t description: "输入完整URL,如 https://data-platform.example.com"\n867\t }\n868\t ]\n869\t }]\n870\t})\n871\t```\n872\t\n873\t**用户回答示例**:\n874\t- `https://data-platform.weoa.com/task-manage`\n875\t\n876\t---\n877\t\n878\t## 第0.6b.2步:询问认证方式 🚀\n879\t\n880\t**执行方式**:使用 AskUserQuestion 工具\n881\t\n882\t```javascript\n883\tAskUserQuestion({\n884\t questions: [{\n885\t question: "目标页面是否需要认证?",\n886\t header: "认证方式",\n887\t multiSelect: false,\n888\t options: [\n889\t {\n890\t label: "无需认证",\n891\t description: "公开页面,无需登录"\n892\t },\n893\t {\n894\t label: "Cookie 认证(推荐)",\n895\t description: "从浏览器复制 Cookie,支持 SSO/已登录会话"\n896\t },\n897\t {\n898\t label: "用户名/密码登录",\n899\t description: "提供账号密码,自动执行登录"\n900\t },\n901\t {\n902\t label: "Token 认证",\n903\t description: "提供 Authorization Token"\n904\t }\n905\t ]\n906\t }]\n907\t})\n908\t```\n909\t\n910\t**用户回答示例**:\n911\t- 选择 `Cookie 认证(推荐)`\n912\t\n913\t---\n914\t\n915\t## 第0.6b.3步:收集认证信息 🚀\n916\t\n917\t### 场景A:Cookie 认证\n918\t\n919\t**执行方式**:使用 AskUserQuestion 工具\n920\t\n921\t```javascript\n922\tAskUserQuestion({\n923\t questions: [{\n924\t question: "请提供 Cookie(从浏览器 DevTools 复制):",\n925\t header: "Cookie",\n926\t multiSelect: false,\n927\t options: [\n928\t {\n929\t label: "粘贴 Cookie 字符串",\n930\t description: "格式:session=xxx; token=yyy"\n931\t },\n932\t {\n933\t label: "上传 Cookie 文件",\n934\t description: "JSON 格式的 Cookie 文件"\n935\t },\n936\t {\n937\t label: "查看获取方法",\n938\t description: "显示如何从浏览器获取 Cookie 的说明"\n939\t }\n940\t ]\n941\t }]\n942\t})\n943\t```\n944\t\n945\t**用户回答示例**:\n946\t```\n947\tsession=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...; token=abc123def456\n948\t```\n949\t\n950\t**Cookie 获取说明**(当用户选择"查看获取方法"时显示):\n951\t\n952\t```markdown\n953\t## 🍪 如何从浏览器获取 Cookie\n954\t\n955\t### 方法1:Chrome DevTools(推荐)\n956\t\n957\t1. 打开目标页面(确保已登录)\n958\t2. 按 F12 打开 DevTools\n959\t3. 切换到 **Application** 标签\n960\t4. 左侧找到 **Cookies** → 点击目标域名\n961\t5. 复制所需 Cookie\n962\t\n963\t### 方法2:Console 一键导出\n964\t\n965\t在浏览器 Console 中执行:\n966\t\n967\t```javascript\n968\tcopy(document.cookie)\n969\t```\n970\t\n971\t### Cookie 格式示例\n972\t\n973\t**字符串格式(推荐):**\n974\tsession=xxx; token=yyy; userId=user001\n975\t\n976\t**JSON 格式:**\n977\t[\n978\t {"name": "session", "value": "xxx", "domain": ".example.com"}\n979\t]\n980\t```\n981\t\n982\t---\n983\t\n984\t### 场景B:用户名/密码登录\n985\t\n986\t**执行方式**:使用 AskUserQuestion 工具\n987\t\n988\t```javascript\n989\t// 第1问:登录页面URL\n990\tAskUserQuestion({\n991\t questions: [{\n992\t question: "请提供登录页面URL(可选,默认为目标URL的/login路径):",\n993\t header: "登录URL",\n994\t multiSelect: false,\n995\t options: [\n996\t {label: "使用默认路径", description: "/login"},\n997\t {label: "手动输入", description: "输入完整登录URL"}\n998\t ]\n999\t }]\n1000\t})\n1001\t\n1002\t// 第2问:用户名\n1003\tAskUserQuestion({\n1004\t questions: [{\n1005\t question: "请输入用户名:",\n1006\t header: "用户名",\n1007\t multiSelect: false,\n1008\t options: [{label: "手动输入", description: "输入用户名"}]\n1009\t }]\n1010\t})\n1011\t\n1012\t// 第3问:密码\n1013\tAskUserQuestion({\n1014\t questions: [{\n1015\t question: "请输入密码:",\n1016\t header: "密码",\n1017\t multiSelect: false,\n1018\t options: [{label: "手动输入", description: "输入密码"}]\n1019\t }]\n1020\t})\n1021\t```\n1022\t\n1023\t---\n1024\t\n1025\t### 场景C:Token 认证\n1026\t\n1027\t**执行方式**:使用 AskUserQuestion 工具\n1028\t\n1029\t```javascript\n1030\tAskUserQuestion({\n1031\t questions: [{\n1032\t question: "请提供认证 Token:",\n1033\t header: "Token",\n1034\t multiSelect: false,\n1035\t options: [\n1036\t {label: "粘贴 Token", description: "Bearer Token 或自定义格式"}\n1037\t ]\n1038\t }]\n1039\t})\n1040\t```\n1041\t\n1042\t---\n1043\t\n1044\t## 第0.6b.4步:执行 Playwright 自动页面分析 🚀\n1045\t\n1046\t**执行命令**:\n1047\t\n1048\t### Cookie 认证模式\n1049\t\n1050\t```bash\n1051\tnode .claude/dev-tools/playwright-page-analyzer.js \\\n1052\t --url="{用户提供的URL}" \\\n1053\t --cookies="{用户提供的Cookie}" \\\n1054\t --output="dev/active/${TASK_NAME}/page-snapshot.json" \\\n1055\t --headless=true\n1056\t```\n1057\t\n1058\t### 用户名/密码登录模式\n1059\t\n1060\t```bash\n1061\tnode .claude/dev-tools/playwright-page-analyzer.js \\\n1062\t --url="{用户提供的URL}" \\\n1063\t --loginUrl="{登录页面URL}" \\\n1064\t --username="{用户名}" \\\n1065\t --password="{密码}" \\\n1066\t --output="dev/active/${TASK_NAME}/page-snapshot.json" \\\n1067\t --headless=true\n1068\t```\n1069\t\n1070\t### Token 认证模式\n1071\t\n1072\t```bash\n1073\tnode .claude/dev-tools/playwright-page-analyzer.js \\\n1074\t --url="{用户提供的URL}" \\\n1075\t --authToken="{Token}" \\\n1076\t --authHeader="Authorization" \\\n1077\t --output="dev/active/${TASK_NAME}/page-snapshot.json" \\\n1078\t --headless=true\n1079\t```\n1080\t\n1081\t### 无需认证模式\n1082\t\n1083\t```bash\n1084\tnode .claude/dev-tools/playwright-page-analyzer.js \\\n1085\t --url="{用户提供的URL}" \\\n1086\t --output="dev/active/${TASK_NAME}/page-snapshot.json" \\\n1087\t --headless=true\n1088\t```\n1089\t\n1090\t---\n1091\t\n1092\t## 第0.6b.5步:展示分析结果,用户确认 🚀\n1093\t\n1094\t**AI 输出示例**:\n1095\t\n1096\t```markdown\n1097\t🔍 正在自动分析页面...\n1098\t\n1099\t🍪 已注入 2 个 Cookie\n1100\t⏳ 访问页面...\n1101\t⏳ 抓取元素...\n1102\t⏳ 识别登录表单...\n1103\t⏳ 生成定位器...\n1104\t\n1105\t✅ 分析完成!\n1106\t\n1107\t┌─────────────────────────────────────────────────────────────────┐\n1108\t│ 🔍 AI 已自动分析页面,发现以下元素定位信息: │\n1109\t├─────────────────────────────────────────────────────────────────┤\n1110\t│ │\n1111\t│ 📌 登录表单元素 │\n1112\t│ ✅ 用户名输入框: getByTestId(\'username-input\') │\n1113\t│ ✅ 密码输入框: locator(\'input[type="password"]\') │\n1114\t│ ✅ 登录按钮: getByText(\'登 录\') │\n1115\t│ │\n1116\t│ 📌 核心操作按钮 │\n1117\t│ ✅ 变更任务菜单: getByText(\'变更任务\') │\n1118\t│ ✅ 批量审批按钮: getByTestId(\'batch-approve-btn\') │\n1119\t│ ✅ 通过按钮: getByText(\'通过\') │\n1120\t│ ✅ 确认按钮: getByText(\'确定\') │\n1121\t│ │\n1122\t│ 📌 特殊处理 │\n1123\t│ ✅ 动态加载: 等待 .ant-spin 消失 │\n1124\t│ │\n1125\t└─────────────────────────────────────────────────────────────────┘\n1126\t```\n1127\t\n1128\t**用户确认**:\n1129\t\n1130\t```javascript\n1131\tAskUserQuestion({\n1132\t questions: [{\n1133\t question: "以上定位器是否正确?",\n1134\t header: "确认定位器",\n1135\t multiSelect: false,\n1136\t options: [\n1137\t {\n1138\t label: "✅ 全部正确",\n1139\t description: "一键确认,生成配置文件"\n1140\t },\n1141\t {\n1142\t label: "⚠️ 部分需要修改",\n1143\t description: "手动调整部分定位器"\n1144\t },\n1145\t {\n1146\t label: "❌ 重新分析",\n1147\t description: "重新执行页面分析"\n1148\t }\n1149\t ]\n1150\t }]\n1151\t})\n1152\t```\n1153\t\n1154\t**处理逻辑**:\n1155\t\n1156\t- **选择"✅ 全部正确"** → 直接生成 `test-clarification-config.json`,跳过详细澄清\n1157\t- **选择"⚠️ 部分需要修改"** → 进入详细澄清流程(逐个元素确认)\n1158\t- **选择"❌ 重新分析"** → 重新执行 Playwright 分析\n1159\t\n1160\t---\n1161\t\n1162\t## 第0.6b.6步:生成配置文件 🚀\n1163\t\n1164\t**路径**:`dev/active/${TASK_NAME}/test-clarification-config.json`\n1165\t\n1166\t### 澄清输出文件\n1167\t\n1168\t**路径**:`dev/active/${TASK_NAME}/test-clarification-config.json`\n1169\t\n1170\t**结构示例**:\n1171\t```json\n1172\t{\n1173\t "version": "1.0",\n1174\t "clarificationType": "frontend",\n1175\t "generatedAt": "2026-03-23T10:00:00Z",\n1176\t "environment": {\n1177\t "baseUrl": "https://data-platform.example.com",\n1178\t "loginPath": "/login",\n1179\t "authType": "username_password"\n1180\t },\n1181\t "elementLocator": {\n1182\t "usernameInput": {\n1183\t "primary": {"type": "placeholder", "value": "用户名"},\n1184\t "fallback": [{"type": "name", "value": "username"}]\n1185\t },\n1186\t "passwordInput": {\n1187\t "primary": {"type": "auto", "value": "type=\'password\'"}\n1188\t },\n1189\t "loginButton": {\n1190\t "primary": {"type": "text", "value": "登录"}\n1191\t },\n1192\t "successIndicators": ["urlChange", "elementAppear"]\n1193\t },\n1194\t "operationFlow": {\n1195\t "coreOperations": ["query", "export"],\n1196\t "operationSteps": {\n1197\t "query": [\n1198\t {"step": 1, "action": "点击左侧菜单「用户管理」"},\n1199\t {"step": 2, "action": "在搜索框输入「张三」"},\n1200\t {"step": 3, "action": "点击「查询」按钮"}\n1201\t ]\n1202\t }\n1203\t },\n1204\t "specialHandling": {\n1205\t "captcha": {"type": "none"},\n1206\t "dynamicLoading": {\n1207\t "enabled": true,\n1208\t "strategy": "waitForLoadingHide"\n1209\t }\n1210\t }\n1211\t}\n1212\t```\n1213\t\n1214\t\n1215\t---\n1216\t\n1217\t## 第0.7步:Claude开发需求检测 🆕v3.7\n1218\t\n1219\t**目标**:识别当前需求是否为Claude开发类型(Agent/Skill/Command),决定是否执行Claude测试\n1220\t\n1221\t### 检测逻辑\n1222\t\n1223\t**Step 1:从需求文档提取dev_target字段**\n1224\t\n1225\t```bash\n1226\t# 检查需求文档中的dev_target字段\n1227\tREQUIREMENT_DOC="docs/{branch}/requirements/{需求名}_需求.md"\n1228\t\n1229\tif [ -f "$REQUIREMENT_DOC" ]; then\n1230\t # 提取dev_target字段\n1231\t DEV_TARGET=$(grep -A5 "开发目标类型" "$REQUIREMENT_DOC" | grep -E "Agent|Skill|Command" | head -1)\n1232\t\n1233\t if [ -n "$DEV_TARGET" ]; then\n1234\t echo "✅ 检测到Claude开发需求:$DEV_TARGET"\n1235\t CLAUDE_DEV_NEEDED=true\n1236\t CLAUDE_DEV_TYPE="$DEV_TARGET"\n1237\t fi\n1238\tfi\n1239\t```\n1240\t\n1241\t**Step 2:从stage-flow-rules.json读取触发条件**\n1242\t\n1243\t```bash\n1244\t# 检查是否通过claude-code-developer agent触发\n1245\tSTAGE_CONFIG="dev/active/${TASK_NAME}/stage-config.json"\n1246\t\n1247\tif [ -f "$STAGE_CONFIG" ]; then\n1248\t TRIGGERED_AGENT=$(jq -r \'.triggeredAgent // empty\' "$STAGE_CONFIG")\n1249\t\n1250\t if [ "$TRIGGERED_AGENT" = "claude-code-developer" ]; then\n1251\t echo "✅ 检测到Claude开发Agent触发"\n1252\t CLAUDE_DEV_NEEDED=true\n1253\t fi\n1254\tfi\n1255\t```\n1256\t\n1257\t**Step 3:从设计文档检测Claude产物类型**\n1258\t\n1259\t```bash\n1260\t# 检查设计文档中的产物类型\n1261\tDESIGN_DOC="docs/{branch}/design/{需求名}_设计.md"\n1262\t\n1263\tif [ -f "$DESIGN_DOC" ]; then\n1264\t if grep -qE "Agent文件|Skill文件|Command文件|\\.claude/agents/|\\.claude/skills/|\\.claude/commands/" "$DESIGN_DOC"; then\n1265\t echo "✅ 检测到Claude产物设计"\n1266\t CLAUDE_DEV_NEEDED=true\n1267\t\n1268\t # 识别具体类型\n1269\t if grep -q "\\.claude/agents/" "$DESIGN_DOC"; then\n1270\t CLAUDE_DEV_TYPE="Agent"\n1271\t elif grep -q "\\.claude/skills/" "$DESIGN_DOC"; then\n1272\t CLAUDE_DEV_TYPE="Skill"\n1273\t elif grep -q "\\.claude/commands/" "$DESIGN_DOC"; then\n1274\t CLAUDE_DEV_TYPE="Command"\n1275\t fi\n1276\t fi\n1277\tfi\n1278\t```\n1279\t\n1280\t### Claude开发类型映射\n1281\t\n1282\t| dev_target值 | 产物路径 | 测试工具 |\n1283\t|-------------|---------|---------|\n1284\t| Agent | `.claude/agents/{category}/{name}.md` | prompt-validator.py, agent-tester.py |\n1285\t| Skill | `.claude/skills/{name}/SKILL.md` | prompt-validator.py |\n1286\t| Command | `.claude/commands/{name}.md` | prompt-validator.py |\n1287\t\n1288\t### 检测结果输出\n1289\t\n1290\t```markdown\n1291\t## Claude开发需求检测结果 🆕v3.7\n1292\t\n1293\t| 检测项 | 结果 |\n1294\t|-------|-----|\n1295\t| Claude开发需求 | ✅ 是 / ❌ 否 |\n1296\t| 开发类型 | {Agent/Skill/Command/无} |\n1297\t| 产物路径 | {.claude/agents/xxx/SKILL.md等} |\n1298\t| 测试工具 | {prompt-validator.py等} |\n1299\t```\n1300\t\n1301\t### 与传统代码测试的互斥关系\n1302\t\n1303\t**重要**:Claude开发测试与传统代码测试**互斥**,不会同时执行:\n1304\t\n1305\t| 模式 | 测试代码生成 | Feature文件 | 执行方式 |\n1306\t|-----|:----------:|:----------:|---------|\n1307\t| **传统代码开发** | ✅ 生成Cucumber/JUnit代码 | ✅ 需要Feature文件 | mvn test / pytest |\n1308\t| **Claude开发** | ❌ 不生成传统测试代码项目 | ✅ 生成Claude BDD Feature + 评估数据集 | agent-behavior-tester.py |\n1309\t\n1310\t### Claude开发测试的正确流程 🆕v3.7\n1311\t\n1312\t```\n1313\t┌─────────────────────────────────────────────────────────────────┐\n1314\t│ Claude开发测试流程(与传统代码测试完全不同) │\n1315\t├─────────────────────────────────────────────────────────────────┤\n1316\t│ │\n1317\t│ 输入:Claude产物 (Agent/Skill/Command MD文件) │\n1318\t│ │\n1319\t│ ❌ 不生成的内容: │\n1320\t│ • 不生成Cucumber Step Definitions │\n1321\t│ • 不生成JUnit/pytest测试类 │\n1322\t│ • 不创建测试项目(避免触发错误的开发Agent) │\n1323\t│ │\n1324\t│ ✅ 生成的内容: │\n1325\t│ • Claude BDD Feature文件(行为场景定义) │\n1326\t│ • 评估数据集(evaluation-dataset.json) │\n1327\t│ • Claude BDD Step Definitions(规则匹配引擎) │\n1328\t│ │\n1329\t│ ✅ 直接执行的内容(由test-executor完成): │\n1330\t│ 1. python3 .claude/dev-tools/claude-dev/prompt-validator.py │\n1331\t│ 2. python3 .claude/dev-tools/claude-dev/agent-tester.py │\n1332\t│ 3. python3 .claude/dev-tools/claude-dev/agent-behavior-tester.py │\n1333\t│ │\n1334\t│ ✅ 生成的报告: │\n1335\t│ • docs/{branch}/testing/{需求名}_Claude验证报告.md │\n1336\t│ │\n1337\t└─────────────────────────────────────────────────────────────────┘\n1338\t```\n1339\t\n1340\t```bash\n1341\tif [ "$CLAUDE_DEV_NEEDED" = true ]; then\n1342\t echo "📌 Claude开发模式:跳过传统代码测试生成,启用Claude BDD测试"\n1343\t echo "📌 不生成:Cucumber代码、JUnit测试类、测试项目"\n1344\t echo "📌 生成:Claude BDD Feature文件 + 评估数据集 + Step Definitions"\n1345\t echo "📌 将由test-executor执行:prompt-validator.py + agent-tester.py + agent-behavior-tester.py"\n1346\t SKIP_TRADITIONAL_CODE_TESTS=true\n1347\t GENERATE_CLAUDE_BDD=true\n1348\telse\n1349\t echo "📌 传统开发模式:执行常规测试流程(生成测试代码+执行)"\n1350\tfi\n1351\t```\n1352\t\n1353\t---\n1354\t\n1355\t## 第0.8步:跨组件需求检测 🆕v3.8\n1356\t\n1357\t**目标**:识别当前需求是否涉及跨组件/跨系统调用,决定是否启用跨系统测试模式\n1358\t\n1359\t### 检测逻辑\n1360\t\n1361\t**Step 1:检测需求类型**\n1362\t\n1363\t```bash\n1364\t# 检查需求类型是否为INTEGRATE\n1365\tREQUIREMENT_DOC="docs/{branch}/requirements/{需求名}_需求.md"\n1366\t\n1367\tif [ -f "$REQUIREMENT_DOC" ]; then\n1368\t REQUIREMENT_TYPE=$(grep -E "需求类型|requirementType" "$REQUIREMENT_DOC" | grep -i "INTEGRATE" | head -1)\n1369\t\n1370\t if [ -n "$REQUIREMENT_TYPE" ]; then\n1371\t echo "✅ 检测到INTEGRATE类型需求"\n1372\t CROSS_SYSTEM_NEEDED=true\n1373\t fi\n1374\tfi\n1375\t```\n1376\t\n1377\t**Step 2:从设计文档提取外部依赖信息**\n1378\t\n1379\t```bash\n1380\t# 检查设计文档中的外部依赖章节\n1381\tDESIGN_DOC="docs/{branch}/design/{需求名}_设计.md"\n1382\t\n1383\tif [ -f "$DESIGN_DOC" ]; then\n1384\t # 检查是否存在"外部依赖接口设计"章节\n1385\t if grep -q "外部依赖接口设计\\|外部服务契约状态总览" "$DESIGN_DOC"; then\n1386\t echo "✅ 检测到外部依赖章节"\n1387\t\n1388\t # 提取外部服务列表\n1389\t EXTERNAL_SERVICES=$(grep -A 20 "外部服务契约状态总览" "$DESIGN_DOC" | grep -E "^\\|" | tail -n +2 | grep -v "^--")\n1390\t\n1391\t # 统计外部系统数量\n1392\t SERVICE_COUNT=$(echo "$EXTERNAL_SERVICES" | grep -v "^$" | wc -l)\n1393\t\n1394\t if [ "$SERVICE_COUNT" -gt 1 ]; then\n1395\t echo "✅ 检测到 $SERVICE_COUNT 个外部系统,启用跨系统测试模式"\n1396\t CROSS_SYSTEM_NEEDED=true\n1397\t fi\n1398\t fi\n1399\tfi\n1400\t```\n1401\t\n1402\t### 询问用户调用方式\n1403\t\n1404\t当 `CROSS_SYSTEM_NEEDED=true` 时,使用 `AskUserQuestion` 工具询问以下信息:\n1405\t\n1406\t**问题1:调用模式**\n1407\t```json\n1408\t{\n1409\t "question": "外部系统间的调用模式是什么?",\n1410\t "header": "调用模式",\n1411\t "multiSelect": false,\n1412\t "options": [\n1413\t {\n1414\t "label": "串行调用",\n1415\t "description": "本系统 → 系统A → 系统B(如下单→支付→短信通知)"\n1416\t },\n1417\t {\n1418\t "label": "并行调用",\n1419\t "description": "本系统同时调用多个系统(如聚合多个数据源)"\n1420\t },\n1421\t {\n1422\t "label": "混合调用",\n1423\t "description": "含串行、并行、回调、轮询等复杂场景"\n1424\t }\n1425\t ]\n1426\t}\n1427\t```\n1428\t\n1429\t**问题2:测试范围**\n1430\t```json\n1431\t{\n1432\t "question": "需要测试哪些系统的集成?",\n1433\t "header": "测试范围",\n1434\t "multiSelect": false,\n1435\t "options": [\n1436\t {\n1437\t "label": "接口测试",\n1438\t "description": "仅测试本系统与各外部系统的接口对接"\n1439\t },\n1440\t {\n1441\t "label": "调用链测试",\n1442\t "description": "测试完整的跨系统调用链(端到端)"\n1443\t },\n1444\t {\n1445\t "label": "分别测试",\n1446\t "description": "分别测试各外部系统的独立功能"\n1447\t }\n1448\t ]\n1449\t}\n1450\t```\n1451\t\n1452\t**问题3:外部服务配置**(根据设计文档中的外部系统列表,逐个询问地址)\n1453\t\n1454\t```json\n1455\t{\n1456\t "question": "外部系统「{系统名}」的测试地址是什么?",\n1457\t "header": "服务地址",\n1458\t "multiSelect": false,\n1459\t "options": [\n1460\t {\n1461\t "label": "使用设计文档地址",\n1462\t "description": "从设计文档读取的默认地址:{baseUrl}"\n1463\t },\n1464\t {\n1465\t "label": "手动输入地址",\n1466\t "description": "输入实际的测试环境地址"\n1467\t }\n1468\t ]\n1469\t}\n1470\t```\n1471\t\n1472\t### 生成跨系统配置文件\n1473\t\n1474\t根据用户回答,生成 `dev/active/${TASK_NAME}/cross-system-config.json`:\n1475\t\n1476\t```json\n1477\t{\n1478\t "crossSystemMode": true,\n1479\t "callPattern": "serial|parallel|mixed",\n1480\t "testScope": "interface|chain|individual",\n1481\t "externalSystems": [\n1482\t {\n1483\t "name": "支付网关",\n1484\t "baseUrl": "https://api.payment.test.com",\n1485\t "enabled": true,\n1486\t "timeout": 5000\n1487\t },\n1488\t {\n1489\t "name": "短信服务",\n1490\t "baseUrl": "https://api.sms.test.com",\n1491\t "enabled": true,\n1492\t "timeout": 3000\n1493\t }\n1494\t ]\n1495\t}\n1496\t```\n1497\t\n1498\t### 检测结果输出\n1499\t\n1500\t```markdown\n1501\t## 跨组件需求检测结果 🆕v3.8\n1502\t\n1503\t| 检测项 | 结果 |\n1504\t|-------|-----|\n1505\t| 跨系统需求 | ✅ 是 / ❌ 否 |\n1506\t| 调用模式 | {串行/并行/混合} |\n1507\t| 测试范围 | {接口/调用链/分别测试} |\n1508\t| 外部系统数量 | {N}个 |\n1509\t| 配置文件路径 | {cross-system-config.json路径} |\n1510\t```\n1511\t\n1512\t### 与传统测试的兼容性\n1513\t\n1514\t**重要**:跨系统测试是传统测试的**增强模式**,不影响原有测试流程:\n1515\t\n1516\t| 模式 | 测试代码生成 | 执行方式 |\n1517\t|-----|:----------:|---------|\n1518\t| **单系统模式** | 生成原有测试代码 | 原有测试流程 |\n1519\t| **跨系统模式** | 增强生成跨系统测试代码 | 执行跨系统测试脚本 |\n1520\t\n1521\t---\n1522\t\n1523\t## 第0.9步:源代码方法索引构建 🆕v3.9\n1524\t\n1525\t**目标**:扫描src目录,构建类/方法索引,为后续生成测试代码提供合法性验证依据\n1526\t\n1527\t### 索引文件路径\n1528\t\n1529\t```bash\n1530\tINDEX_FILE=".claude/data/testing/src-method-index.json"\n1531\t```\n1532\t\n1533\t### 扫描策略\n1534\t\n1535\t#### Java项目扫描\n1536\t\n1537\t```bash\n1538\tscan_java_sources() {\n1539\t echo "📋 正在扫描Java源代码..."\n1540\t INDEX_FILE=".claude/data/testing/src-method-index.json"\n1541\t\n1542\t # 确保目录存在\n1543\t mkdir -p "$(dirname "$INDEX_FILE")"\n1544\t\n1545\t # 初始化索引\n1546\t echo \'{"version":"1.0","lastUpdated":"","projectType":"java","classes":{},"functions":{}}\' > "$INDEX_FILE"\n1547\t\n1548\t # 扫描所有Java类\n1549\t find src/main/java -name "*.java" 2>/dev/null | while read file; do\n1550\t # 提取包名\n1551\t PACKAGE=$(grep -oP "package\\s+\\K[^;]+" "$file" 2>/dev/null)\n1552\t # 提取类名\n1553\t CLASS_NAME=$(grep -oP "public\\s+(?:class|interface|enum)\\s+\\K\\w+" "$file" 2>/dev/null | head -1)\n1554\t\n1555\t if [ -n "$CLASS_NAME" ] && [ -n "$PACKAGE" ]; then\n1556\t FULL_CLASS_NAME="${PACKAGE}.${CLASS_NAME}"\n1557\t # 提取公共方法\n1558\t METHODS=$(grep -oP "public\\s+(?!class|interface|enum)[\\w<>[\\],\\s]+\\s+\\K\\w+(?=\\s*\\([^)]*\\))" "$file" 2>/dev/null)\n1559\t echo " 扫描类: $FULL_CLASS_NAME"\n1560\t fi\n1561\t done\n1562\t\n1563\t echo "✅ Java源代码索引构建完成: $INDEX_FILE"\n1564\t}\n1565\t```\n1566\t\n1567\t#### Python项目扫描\n1568\t\n1569\t```bash\n1570\tscan_python_sources() {\n1571\t echo "📋 正在扫描Python源代码..."\n1572\t INDEX_FILE=".claude/data/testing/src-method-index.json"\n1573\t\n1574\t mkdir -p "$(dirname "$INDEX_FILE")"\n1575\t\n1576\t # 扫描Python模块\n1577\t find src -name "*.py" 2>/dev/null | while read file; do\n1578\t # 提取模块名\n1579\t MODULE=$(echo "$file" | sed \'s|src/||;s|/|.|g;s|\\.py$||\')\n1580\t # 提取类\n1581\t CLASSES=$(grep -oP "^class\\s+\\K\\w+" "$file" 2>/dev/null)\n1582\t # 提取函数\n1583\t FUNCTIONS=$(grep -oP "^def\\s+\\K\\w+" "$file" 2>/dev/null)\n1584\t echo " 扫描模块: $MODULE"\n1585\t done\n1586\t\n1587\t echo "✅ Python源代码索引构建完成: $INDEX_FILE"\n1588\t}\n1589\t```\n1590\t\n1591\t#### Go项目扫描\n1592\t\n1593\t```bash\n1594\tscan_go_sources() {\n1595\t echo "📋 正在扫描Go源代码..."\n1596\t INDEX_FILE=".claude/data/testing/src-method-index.json"\n1597\t\n1598\t mkdir -p "$(dirname "$INDEX_FILE")"\n1599\t\n1600\t # 扫描Go结构体和方法\n1601\t find . -name "*.go" -not -path "./vendor/*" -not -path "./.git/*" 2>/dev/null | while read file; do\n1602\t # 提取结构体\n1603\t STRUCTS=$(grep -oP "type\\s+\\K\\w+(?=\\s+struct)" "$file" 2>/dev/null)\n1604\t # 提取方法(带接收器)\n1605\t METHODS=$(grep -oP "func\\s+\\(\\w+\\s+\\*?\\K\\w+(?=\\))" "$file" 2>/dev/null)\n1606\t echo " 扫描文件: $file"\n1607\t done\n1608\t\n1609\t echo "✅ Go源代码索引构建完成: $INDEX_FILE"\n1610\t}\n1611\t```\n1612\t\n1613\t### 索引文件格式\n1614\t\n1615\t```json\n1616\t{\n1617\t "version": "1.0",\n1618\t "lastUpdated": "2026-03-18T10:00:00Z",\n1619\t "projectType": "java",\n1620\t "classes": {\n1621\t "com.example.service.BubbleSortService": {\n1622\t "file": "src/main/java/com/example/service/BubbleSortService.java",\n1623\t "type": "class",\n1624\t "methods": {\n1625\t "sort": {\n1626\t "returnType": "int[]",\n1627\t "parameters": ["int[]"],\n1628\t "modifiers": ["public"],\n1629\t "lineNumber": 15\n1630\t },\n1631\t "validate": {\n1632\t "returnType": "boolean",\n1633\t "parameters": ["int[]"],\n1634\t "modifiers": ["public", "static"],\n1635\t "lineNumber": 25\n1636\t }\n1637\t }\n1638\t }\n1639\t },\n1640\t "functions": {\n1641\t "com.example.util.ArrayUtils.parseArray": {\n1642\t "file": "src/main/java/com/example/util/ArrayUtils.java",\n1643\t "returnType": "int[]",\n1644\t "parameters": ["String"],\n1645\t "modifiers": ["public", "static"]\n1646\t }\n1647\t }\n1648\t}\n1649\t```\n1650\t\n1651\t### 索引更新策略\n1652\t\n1653\t| 场景 | 策略 |\n1654\t|-----|------|\n1655\t| 索引文件不存在 | 全量扫描并创建 |\n1656\t| 索引文件存在且时间 < 1小时 | 直接使用缓存 |\n1657\t| 索引文件存在且时间 ≥ 1小时 | 增量更新(检测文件变更) |\n1658\t| 强制更新参数 `--rebuild-index` | 全量重建 |\n1659\t\n1660\t### 索引使用示例\n1661\t\n1662\t```bash\n1663\t# 检查类是否存在\n1664\tcheck_class_exists() {\n1665\t local class_name="$1"\n1666\t local index_file=".claude/data/testing/src-method-index.json"\n1667\t\n1668\t if [ -f "$index_file" ]; then\n1669\t if jq -e ".classes[\\"$class_name\\"]" "$index_file" > /dev/null 2>&1; then\n1670\t return 0 # 存在\n1671\t fi\n1672\t fi\n1673\t return 1 # 不存在\n1674\t}\n1675\t\n1676\t# 检查方法是否存在\n1677\tcheck_method_exists() {\n1678\t local class_name="$1"\n1679\t local method_name="$2"\n1680\t local index_file=".claude/data/testing/src-method-index.json"\n1681\t\n1682\t if [ -f "$index_file" ]; then\n1683\t if jq -e ".classes[\\"$class_name\\"].methods[\\"$method_name\\"]" "$index_file" > /dev/null 2>&1; then\n1684\t return 0 # 存在\n1685\t fi\n1686\t fi\n1687\t return 1 # 不存在\n1688\t}\n1689\t```\n1690\t\n1691\t---\n1692\t\n1693\t## 第1步:读取输入文件\n1694\t\n1695\t### 1.1 读取Feature文件\n1696\t\n1697\t**扫描路径**(支持多路径fallback):\n1698\t```bash\n1699\tPRIMARY_FEATURE_DIR="dev/active/${TASK_NAME}/features"\n1700\tFALLBACK_FEATURE_DIR="dev/docs"\n1701\t\n1702\tFEATURE_FILES=""\n1703\t\n1704\t# 优先从主路径查找\n1705\tif [ -d "$PRIMARY_FEATURE_DIR" ]; then\n1706\t FOUND_FILES=$(find "$PRIMARY_FEATURE_DIR" -name "*.feature" 2>/dev/null)\n1707\t if [ -n "$FOUND_FILES" ]; then\n1708\t FEATURE_FILES="$FOUND_FILES"\n1709\t echo "✅ 从主路径找到 Feature 文件: $PRIMARY_FEATURE_DIR"\n1710\t fi\n1711\tfi\n1712\t\n1713\t# 如果主路径未找到,从备选路径查找\n1714\tif [ -z "$FEATURE_FILES" ] && [ -d "$FALLBACK_FEATURE_DIR" ]; then\n1715\t FOUND_FILES=$(find "$FALLBACK_FEATURE_DIR" -name "*.feature" 2>/dev/null)\n1716\t if [ -n "$FOUND_FILES" ]; then\n1717\t FEATURE_FILES="$FOUND_FILES"\n1718\t echo "⚠️ 主路径未找到,从备选路径找到 Feature 文件: $FALLBACK_FEATURE_DIR"\n1719\t fi\n1720\tfi\n1721\t```\n1722\t\n1723\t### 1.2 读取测试用例文档\n1724\t\n1725\t**解析测试用例**:\n1726\t- 单元测试用例(测试类型="单元测试")\n1727\t- 接口测试用例(测试类型="接口测试")\n1728\t- 性能测试用例(优先级=P1,包含性能要求)\n1729\t\n1730\t### 1.3 读取项目源代码\n1731\t\n1732\t**扫描策略**:\n1733\t```bash\n1734\t# 根据Feature文件推断源代码位置\n1735\t# 例如: bubble-sort.feature -> src/main/java/**/BubbleSort*.java\n1736\t\n1737\t# 查找相关的Java类\n1738\tfind src/main/java -name "*[Bb]ubble[Ss]ort*.java"\n1739\t\n1740\t# 查找相关的Python模块\n1741\tfind src -name "*bubble*sort*.py"\n1742\t```\n1743\t\n1744\t---\n1745\t\n1746\t## 第2步:生成Cucumber测试\n1747\t\n1748\t### 2.1 生成Step Definitions\n1749\t\n1750\t**方法命名规范(强制要求)**:\n1751\t\n1752\t| 规则 | 说明 | 示例 |\n1753\t|-----|------|------|\n1754\t| 禁止中文 | 方法名必须使用英文 | ❌ `void 输入参数为_null()` |\n1755\t| 驼峰命名 | 使用camelCase命名方式 | ✅ `void givenInputParameterIsNull()` |\n1756\t| 动词开头 | Given用`given`/`when`/`then`开头 | ✅ `void whenSortIsExecuted()` |\n1757\t| 语义清晰 | 方法名应清晰描述步骤意图 | ✅ `void thenResultShouldBeSorted()` |\n1758\t\n1759\t### 2.1.5 方法存在性验证 🆕v3.9\n1760\t\n1761\t**触发时机**:生成Step Definition中调用业务代码时\n1762\t\n1763\t#### 验证流程\n1764\t\n1765\t```\n1766\t┌─────────────────────────────────────────────────────────────────┐\n1767\t│ 方法存在性验证流程 │\n1768\t├─────────────────────────────────────────────────────────────────┤\n1769\t│ │\n1770\t│ 1. 从Feature步骤解析预期的类名和方法名 │\n1771\t│ ↓ │\n1772\t│ 2. 加载src-method-index.json │\n1773\t│ ↓ │\n1774\t│ 3. 执行三重验证: │\n1775\t│ - 类存在性验证 │\n1776\t│ - 方法存在性验证 │\n1777\t│ - 方法签名匹配验证 │\n1778\t│ ↓ │\n1779\t│ 4. 根据验证结果决定生成策略 │\n1780\t│ │\n1781\t└─────────────────────────────────────────────────────────────────┘\n1782\t```\n1783\t\n1784\t#### 验证逻辑\n1785\t\n1786\t```python\n1787\tdef validate_method_reference(class_name, method_name, params=None):\n1788\t """\n1789\t 验证方法引用是否合法\n1790\t\n1791\t Args:\n1792\t class_name: 类全限定名(如 com.example.service.BubbleSortService)\n1793\t method_name: 方法名(如 sort)\n1794\t params: 参数类型列表(如 ["int[]"])\n1795\t\n1796\t Returns:\n1797\t {\n1798\t \'valid\': True/False,\n1799\t \'error\': None 或错误信息,\n1800\t \'suggestion\': None 或建议信息,\n1801\t \'matched_method\': None 或匹配到的方法信息\n1802\t }\n1803\t """\n1804\t index = load_src_method_index()\n1805\t\n1806\t # 1. 类存在性验证\n1807\t if class_name not in index[\'classes\']:\n1808\t similar_classes = find_similar_classes(class_name, index)\n1809\t return {\n1810\t \'valid\': False,\n1811\t \'error\': f\'类不存在: {class_name}\',\n1812\t \'suggestion\': f\'可用的相似类: {similar_classes}\' if similar_classes else \'请检查类名是否正确\'\n1813\t }\n1814\t\n1815\t # 2. 方法存在性验证\n1816\t class_info = index[\'classes\'][class_name]\n1817\t if method_name not in class_info[\'methods\']:\n1818\t available_methods = list(class_info[\'methods\'].keys())\n1819\t similar_methods = find_similar_methods(method_name, available_methods)\n1820\t return {\n1821\t \'valid\': False,\n1822\t \'error\': f\'方法不存在: {class_name}.{method_name}()\',\n1823\t \'suggestion\': f\'可用的方法: {available_methods}\' if len(available_methods) <= 5 else f\'相似方法: {similar_methods}\'\n1824\t }\n1825\t\n1826\t # 3. 方法签名匹配(如果提供了参数)\n1827\t if params:\n1828\t method_info = class_info[\'methods\'][method_name]\n1829\t expected_count = len(method_info[\'parameters\'])\n1830\t actual_count = len(params)\n1831\t\n1832\t if expected_count != actual_count:\n1833\t return {\n1834\t \'valid\': False,\n1835\t \'error\': f\'参数数量不匹配: 期望{expected_count}个, 实际{actual_count}个\',\n1836\t \'suggestion\': f\'方法签名: {method_name}({", ".join(method_info["parameters"])})\'\n1837\t }\n1838\t\n1839\t return {\n1840\t \'valid\': True,\n1841\t \'matched_method\': class_info[\'methods\'][method_name]\n1842\t }\n1843\t```\n1844\t\n1845\t#### 验证失败处理策略\n1846\t\n1847\t| 验证结果 | 处理策略 |\n1848\t|---------|---------|\n1849\t| 类不存在 | 1. 生成TODO注释 2. 输出警告 3. 提供相似类建议 |\n1850\t| 方法不存在 | 1. 生成TODO注释 2. 输出警告 3. 提供可用方法列表 |\n1851\t| 参数不匹配 | 1. 自动修正参数 2. 输出提示信息 |\n1852\t\n1853\t#### 生成代码示例(验证失败时)\n1854\t\n1855\t```java\n1856\t// ⚠️ 方法存在性验证警告\n1857\t// 类 com.example.service.PaymentService 不存在于src目录\n1858\t// 建议检查:\n1859\t// 1. 类名是否正确\n1860\t// 2. 类是否已实现\n1861\t// TODO: 请确认 PaymentService 类已正确实现\n1862\t@When("用户支付订单")\n1863\tpublic void whenUserPayOrder() {\n1864\t // PaymentService paymentService = new PaymentService();\n1865\t // paymentService.pay(orderId);\n1866\t throw new PendingException("请先实现 PaymentService 类");\n1867\t}\n1868\t```\n1869\t\n1870\t#### 验证报告输出\n1871\t\n1872\t```markdown\n1873\t## 方法存在性验证报告\n1874\t\n1875\t| 步骤 | 引用的类 | 引用的方法 | 验证结果 | 建议 |\n1876\t|-----|---------|-----------|:-------:|------|\n1877\t| Given 用户创建订单 | OrderService | createOrder | ✅ 通过 | - |\n1878\t| When 用户支付订单 | PaymentService | pay | ❌ 失败 | 类不存在,请先实现 |\n1879\t| Then 订单状态变更 | OrderService | updateStatus | ✅ 通过 | - |\n1880\t\n1881\t**统计**:\n1882\t- 总步骤: 3\n1883\t- 验证通过: 2 (66.7%)\n1884\t- 验证失败: 1 (33.3%)\n1885\t\n1886\t⚠️ 存在验证失败的步骤,生成的测试代码包含TODO标记\n1887\t```\n1888\t\n1889\t**Step Definition模板**(Java示例):\n1890\t\n1891\t```java\n1892\tpackage com.example.cucumber.steps;\n1893\t\n1894\timport io.cucumber.java.Before;\n1895\timport io.cucumber.java.en.Given;\n1896\timport io.cucumber.java.en.When;\n1897\timport io.cucumber.java.en.Then;\n1898\timport static org.assertj.core.api.Assertions.*;\n1899\t\n1900\tpublic class BubbleSortSteps {\n1901\t\n1902\t private BubbleSortService bubbleSortService;\n1903\t private int[] inputArray;\n1904\t private int[] resultArray;\n1905\t\n1906\t @Before\n1907\t public void setup() {\n1908\t bubbleSortService = new BubbleSortService();\n1909\t }\n1910\t\n1911\t @Given("有一个整数数组 {string}")\n1912\t public void givenAnIntegerArray(String arrayStr) {\n1913\t inputArray = parseArrayString(arrayStr);\n1914\t }\n1915\t\n1916\t @When("执行冒泡排序算法")\n1917\t public void whenExecuteBubbleSort() {\n1918\t resultArray = bubbleSortService.sort(inputArray.clone());\n1919\t }\n1920\t\n1921\t @Then("结果应该是升序排列的")\n1922\t public void thenResultShouldBeSorted() {\n1923\t assertThat(resultArray).isSorted();\n1924\t }\n1925\t}\n1926\t```\n1927\t\n1928\t### 2.2 生成Cucumber Runner类\n1929\t\n1930\t**Java Runner示例(JUnit 5)**:\n1931\t```java\n1932\tpackage com.example.cucumber.runner;\n1933\t\n1934\timport io.cucumber.junit.platform.engine.Cucumber;\n1935\timport org.junit.platform.suite.api.IncludeClassNamePatterns;\n1936\timport org.junit.platform.suite.api.SelectClasspathResource;\n1937\timport org.junit.platform.suite.api.Suite;\n1938\t\n1939\t@Suite\n1940\t@IncludeClassNamePatterns(".*Test")\n1941\t@SelectClasspathResource("features")\n1942\t@Cucumber(\n1943\t plugin = {\n1944\t "pretty",\n1945\t "html:target/cucumber-reports.html",\n1946\t "json:target/cucumber-reports.json"\n1947\t },\n1948\t tags = "not @Ignore"\n1949\t)\n1950\tpublic class CucumberRunnerTest {\n1951\t}\n1952\t```\n1953\t\n1954\t\n1955\t\n1956\t### 2.4 生成godog Step Definitions(Go项目)🆕\n1957\t\n1958\t**godog是Go语言的Cucumber官方实现**,完全兼容Gherkin语法。\n1959\t\n1960\t```go\n1961\tpackage steps\n1962\t\n1963\timport (\n1964\t "context"\n1965\t "github.com/cucumber/godog"\n1966\t)\n1967\t\n1968\tfunc InitializeScenario(ctx *godog.ScenarioContext) {\n1969\t ctx.Step(`^有一个整数数组 (.+)$`, aIntegerArray)\n1970\t ctx.Step(`^执行冒泡排序算法$`, executeBubbleSort)\n1971\t ctx.Step(`^结果应该是升序排列的$`, resultShouldBeSorted)\n1972\t}\n1973\t```\n1974\t\n1975\t### 2.4b 生成Cucumber TypeScript Step Definitions(TypeScript项目)🆕\n1976\t\n1977\t**@cucumber/cucumber是TypeScript/JavaScript的Cucumber官方实现**,完全兼容Gherkin语法,通过ts-node支持TypeScript。\n1978\t\n1979\t**生成路径**:\n1980\t```\n1981\ttest/\n1982\t├── steps/ # Step Definitions\n1983\t│ └── {feature-name}.steps.ts\n1984\t├── hooks/ # Before/After hooks\n1985\t│ └── hooks.ts\n1986\tfeatures/ # Feature文件(从docs/{branch}/features/复制)\n1987\treports/ # 测试报告输出\n1988\t```\n1989\t\n1990\t**Step Definition模板**(TypeScript):\n1991\t\n1992\t```typescript\n1993\timport { Given, When, Then, setWorldConstructor, Before, After } from \'@cucumber/cucumber\';\n1994\timport { expect } from \'chai\';\n1995\t\n1996\t// ===== 测试上下文 =====\n1997\tclass CustomWorld {\n1998\t testData: Map;\n1999\t lastResponse: any;\n2000\t lastError: Error | null;\n2001\t\n2002\t constructor() {\n2003\t this.testData = new Map();\n2004\t this.lastResponse = null;\n2005\t this.lastError = null;\n2006\t }\n2007\t}\n2008\t\n2009\tsetWorldConstructor(CustomWorld);\n2010\t\n2011\t// ===== Before钩子 =====\n2012\tBefore(function () {\n2013\t this.testData = new Map();\n2014\t this.lastResponse = null;\n2015\t this.lastError = null;\n2016\t});\n2017\t\n2018\t// ===== After钩子 =====\n2019\tAfter(function () {\n2020\t this.testData.clear();\n2021\t this.lastResponse = null;\n2022\t this.lastError = null;\n2023\t});\n2024\t\n2025\t// ===== Given步骤 =====\n2026\t// 根据Feature文件中的Scenario步骤,实现对应的Step函数\n2027\t\n2028\t// ===== When步骤 =====\n2029\t\n2030\t// ===== Then步骤 =====\n2031\t```\n2032\t\n2033\t**NestJS集成测试Step示例**:\n2034\t\n2035\t```typescript\n2036\timport { Test, TestingModule } from \'@nestjs/testing\';\n2037\timport request from \'supertest\';\n2038\timport { AppModule } from \'../../src/app.module\';\n2039\t\n2040\tlet app: INestApplication;\n2041\t\n2042\tBefore(async function () {\n2043\t const moduleFixture: TestingModule = await Test.createTestingModule({\n2044\t imports: [AppModule],\n2045\t }).compile();\n2046\t app = moduleFixture.createNestApplication();\n2047\t await app.init();\n2048\t});\n2049\t\n2050\tAfter(async function () {\n2051\t await app.close();\n2052\t});\n2053\t\n2054\tWhen(\'调用创建用户接口\', async function () {\n2055\t this.lastResponse = await request(app.getHttpServer())\n2056\t .post(\'/api/v1/users\')\n2057\t .send(this.testData.get(\'createUserPayload\'));\n2058\t});\n2059\t\n2060\tThen(\'返回状态码应为{int}\', async function (expectedCode: number) {\n2061\t expect(this.lastResponse.status).to.equal(expectedCode);\n2062\t});\n2063\t```\n2064\t\n2065\t**执行命令**:\n2066\t\n2067\t```bash\n2068\tnpm run test:cucumber\n2069\t# 或指定Feature文件\n2070\tnpx cucumber-js test/features/{feature-name}.feature --require test/steps --require-module ts-node/register\n2071\t```\n2072\t\n2073\t### 2.5 生成Mock单元测试模板 🆕\n2074\t\n2075\t**生成Mock测试**(Java示例):\n2076\t\n2077\t```java\n2078\tpackage com.example.service;\n2079\t\n2080\timport org.junit.jupiter.api.Test;\n2081\timport org.mockito.InjectMocks;\n2082\timport org.mockito.Mock;\n2083\timport static org.mockito.Mockito.*;\n2084\timport static org.assertj.core.api.Assertions.*;\n2085\t\n2086\tclass BubbleSortServiceTest {\n2087\t\n2088\t @Mock\n2089\t private ArrayValidator validator;\n2090\t\n2091\t @InjectMocks\n2092\t private BubbleSortService bubbleSortService;\n2093\t\n2094\t @Test\n2095\t void testSort_withValidArray() {\n2096\t // Given\n2097\t int[] input = {3, 1, 4, 1, 5};\n2098\t when(validator.validate(input)).thenReturn(true);\n2099\t\n2100\t // When\n2101\t int[] result = bubbleSortService.sort(input);\n2102\t\n2103\t // Then\n2104\t assertThat(result).containsExactly(1, 1, 3, 4, 5);\n2105\t verify(validator).validate(input);\n2106\t }\n2107\t}\n2108\t```\n2109\t\n2110\t---\n2111\t\n2112\t## 第2.5步:前端单元测试生成 🆕\n2113\t\n2114\t**触发条件**:`PROJECT_TYPE == "web-frontend"`\n2115\t\n2116\t### 2.5.1 检测测试框架\n2117\t\n2118\t```bash\n2119\t# 检测已配置的测试框架\n2120\tif grep -q \'"vitest"\' package.json; then\n2121\t TEST_FRAMEWORK="vitest"\n2122\t echo "✅ 检测到Vitest测试框架"\n2123\telif grep -q \'"jest"\' package.json; then\n2124\t TEST_FRAMEWORK="jest"\n2125\t echo "✅ 检测到Jest测试框架"\n2126\telse\n2127\t # 默认推荐vitest(Vite项目优先)\n2128\t if grep -q \'"vite"\' package.json; then\n2129\t TEST_FRAMEWORK="vitest"\n2130\t echo "📌 未检测到测试框架,推荐使用Vitest(Vite项目)"\n2131\t else\n2132\t TEST_FRAMEWORK="jest"\n2133\t echo "📌 未检测到测试框架,推荐使用Jest"\n2134\t fi\n2135\tfi\n2136\t```\n2137\t\n2138\t### 2.5.2 生成测试配置文件\n2139\t\n2140\t**Vitest配置生成**:\n2141\t```bash\n2142\t# 生成 vitest.config.ts\n2143\tapply_template "vitest/vitest.config.ts.template" "vitest.config.ts"\n2144\t\n2145\t# 生成 setupTests.ts(如果不存在)\n2146\tif [ ! -f "src/setupTests.ts" ]; then\n2147\t cat > src/setupTests.ts << \'EOF\'\n2148\timport \'@testing-library/jest-dom\';\n2149\tEOF\n2150\t echo "✅ 已生成 src/setupTests.ts"\n2151\tfi\n2152\t```\n2153\t\n2154\t**Jest配置生成**:\n2155\t```bash\n2156\t# 生成 jest.config.js\n2157\tapply_template "jest/jest.config.js.template" "jest.config.js"\n2158\t\n2159\t# 生成 setupTests.ts(如果不存在)\n2160\tif [ ! -f "src/setupTests.ts" ]; then\n2161\t cat > src/setupTests.ts << \'EOF\'\n2162\timport \'@testing-library/jest-dom\';\n2163\tEOF\n2164\t echo "✅ 已生成 src/setupTests.ts"\n2165\tfi\n2166\t```\n2167\t\n2168\t### 2.5.3 生成组件测试文件\n2169\t\n2170\t**扫描组件目录**:\n2171\t```bash\n2172\t# 扫描src/components下的组件\n2173\tfor component_dir in src/components/*/; do\n2174\t COMPONENT_NAME=$(basename "$component_dir")\n2175\t\n2176\t # 跳过非组件目录\n2177\t if [ -f "$component_dir/__tests__/${COMPONENT_NAME}.test.tsx" ] || \\\n2178\t [ -f "$component_dir/__tests__/${COMPONENT_NAME}.test.ts" ]; then\n2179\t echo "⏭️ 跳过 $COMPONENT_NAME,测试文件已存在"\n2180\t continue\n2181\t fi\n2182\t\n2183\t # 创建测试目录\n2184\t mkdir -p "$component_dir/__tests__"\n2185\t\n2186\t # 根据框架选择模板\n2187\t if [ "$FRAMEWORK" = "react" ]; then\n2188\t if [ "$TEST_FRAMEWORK" = "vitest" ]; then\n2189\t apply_template "vitest/component.test.ts.template" \\\n2190\t "$component_dir/__tests__/${COMPONENT_NAME}.test.tsx" \\\n2191\t COMPONENT_NAME="$COMPONENT_NAME"\n2192\t else\n2193\t apply_template "jest/component.test.tsx.template" \\\n2194\t "$component_dir/__tests__/${COMPONENT_NAME}.test.tsx" \\\n2195\t COMPONENT_NAME="$COMPONENT_NAME"\n2196\t fi\n2197\t elif [ "$FRAMEWORK" = "vue" ]; then\n2198\t apply_template "vitest/component.test.ts.template" \\\n2199\t "$component_dir/__tests__/${COMPONENT_NAME}.test.ts" \\\n2200\t COMPONENT_NAME="$COMPONENT_NAME"\n2201\t fi\n2202\t\n2203\t echo "✅ 生成测试文件: $component_dir/__tests__/${COMPONENT_NAME}.test.tsx"\n2204\tdone\n2205\t```\n2206\t\n2207\t### 2.5.4 更新package.json依赖\n2208\t\n2209\t**合并测试依赖**:\n2210\t```bash\n2211\t# 检测包管理器\n2212\tif [ -f "pnpm-lock.yaml" ]; then\n2213\t PKG_MANAGER="pnpm"\n2214\telif [ -f "yarn.lock" ]; then\n2215\t PKG_MANAGER="yarn"\n2216\telse\n2217\t PKG_MANAGER="npm"\n2218\tfi\n2219\t\n2220\t# 合并依赖\n2221\tif [ "$TEST_FRAMEWORK" = "vitest" ]; then\n2222\t echo "📌 合并Vitest测试依赖..."\n2223\t merge_json_fragment "vitest/package-fragment.json.template" "package.json"\n2224\telse\n2225\t echo "📌 合并Jest测试依赖..."\n2226\t merge_json_fragment "jest/package-fragment.json.template" "package.json"\n2227\tfi\n2228\t\n2229\techo "✅ 已更新package.json测试依赖"\n2230\techo "💡 请运行 $PKG_MANAGER install 安装依赖"\n2231\t```\n2232\t\n2233\t### 2.5.5 生成覆盖率配置\n2234\t\n2235\t```bash\n2236\t# 生成Istanbul/nyc覆盖率配置\n2237\tapply_template "istanbul/nyc.config.json.template" ".nycrc"\n2238\techo "✅ 已生成覆盖率配置文件 .nycrc"\n2239\t```\n2240\t\n2241\t### 2.5.6 前端测试输出格式\n2242\t\n2243\t```markdown\n2244\t## ✅ 前端单元测试生成完成\n2245\t\n2246\t### 测试框架\n2247\t- **框架**: {TEST_FRAMEWORK}\n2248\t- **前端框架**: {FRAMEWORK}\n2249\t\n2250\t### 生成文件\n2251\t| 类型 | 文件路径 |\n2252\t|-----|---------|\n2253\t| 配置文件 | vitest.config.ts / jest.config.js |\n2254\t| 测试设置 | src/setupTests.ts |\n2255\t| 覆盖率配置 | .nycrc |\n2256\t\n2257\t### 组件测试文件\n2258\t| 组件 | 测试文件 |\n2259\t|-----|---------|\n2260\t| Xxx | src/components/Xxx/__tests__/Xxx.test.tsx |\n2261\t| Yyy | src/components/Yyy/__tests__/Yyy.test.tsx |\n2262\t\n2263\t### 下一步\n2264\t1. 运行 `{PKG_MANAGER} install` 安装测试依赖\n2265\t2. 运行 `{PKG_MANAGER} test` 执行测试\n2266\t3. 运行 `{PKG_MANAGER} test:coverage` 生成覆盖率报告\n2267\t```\n2268\t\n2269\t---\n2270\t\n2271\t## 第2.6步:Claude BDD测试生成 🆕v4.1\n2272\t\n2273\t**触发条件**:`GENERATE_CLAUDE_BDD == true`(Claude开发模式时自动启用)\n2274\t\n2275\t**目标**:为Claude插件(Agent/Skill/Command)生成BDD行为测试文件,包括Feature文件、评估数据集和规则匹配Step Definitions。\n2276\t\n2277\t### 2.6.1 生成Claude BDD Feature文件\n2278\t\n2279\t基于目标Prompt文件的内容,生成Gherkin格式的Feature文件:\n2280\t\n2281\t```bash\n2282\t# 输出路径\n2283\tFEATURE_DIR="docs/{branch}/features"\n2284\tmkdir -p "$FEATURE_DIR"\n2285\t\n2286\t# 基于模板生成Feature文件\n2287\tapply_template "claude-bdd/feature.template" "$FEATURE_DIR/{agent_name}.feature"\n2288\t\n2289\t# 替换模板变量\n2290\tsed -i "s/{agent_name}/$TARGET_NAME/g" "$FEATURE_DIR/$TARGET_NAME.feature"\n2291\t\n2292\t# 根据Prompt内容生成工具期望\n2293\t# 扫描Prompt文件中的工具调用模式\n2294\tTOOL_EXPECTATIONS=""\n2295\tif grep -q "AskUserQuestion" "$PROMPT_FILE"; then\n2296\t TOOL_EXPECTATIONS="$TOOL_EXPECTATIONS\\n 那么 它应该使用 \\"AskUserQuestion\\" 工具"\n2297\tfi\n2298\tif grep -q "subagent_type" "$PROMPT_FILE"; then\n2299\t TOOL_EXPECTATIONS="$TOOL_EXPECTATIONS\\n 那么 它应该使用 \\"Agent\\" 工具"\n2300\tfi\n2301\tif grep -q "mcp__" "$PROMPT_FILE"; then\n2302\t TOOL_EXPECTATIONS="$TOOL_EXPECTATIONS\\n 那么 它应该使用 \\"MCP\\" 工具"\n2303\tfi\n2304\t\n2305\tsed -i "s/{tool_expectations}/$TOOL_EXPECTATIONS/g" "$FEATURE_DIR/$TARGET_NAME.feature"\n2306\techo "✅ 已生成Claude BDD Feature文件: $FEATURE_DIR/$TARGET_NAME.feature"\n2307\t```\n2308\t\n2309\t### 2.6.2 生成评估数据集\n2310\t\n2311\t基于目标Prompt文件的章节结构和行为特征,生成评估数据集:\n2312\t\n2313\t```bash\n2314\t# 输出路径\n2315\tDATASET_DIR="docs/{branch}/testing"\n2316\tmkdir -p "$DATASET_DIR"\n2317\t\n2318\t# 基于模板生成评估数据集\n2319\tapply_template "claude-bdd/evaluation-dataset.template.json" "$DATASET_DIR/{agent_name}-evaluation.json"\n2320\t\n2321\t# 替换模板变量\n2322\tsed -i "s/{agent_name}/$TARGET_NAME/g" "$DATASET_DIR/$TARGET_NAME-evaluation.json"\n2323\t\n2324\t# 从Prompt文件提取章节信息,填充expected_sections\n2325\techo "✅ 已生成评估数据集: $DATASET_DIR/$TARGET_NAME-evaluation.json"\n2326\t```\n2327\t\n2328\t### 2.6.3 生成Claude BDD Step Definitions\n2329\t\n2330\t基于规则匹配引擎的Step Definitions,不依赖LLM执行:\n2331\t\n2332\t```bash\n2333\t# 输出路径\n2334\tSTEPS_DIR="docs/{branch}/testing/claude-bdd-steps"\n2335\tmkdir -p "$STEPS_DIR"\n2336\t\n2337\t# 基于模板生成Step Definitions\n2338\tapply_template "claude-bdd/steps.py.template" "$STEPS_DIR/{agent_name}_steps.py"\n2339\t\n2340\t# 替换模板变量\n2341\tsed -i "s/{agent_name}/$TARGET_NAME/g" "$STEPS_DIR/$TARGET_NAME_steps.py"\n2342\t\n2343\techo "✅ 已生成Claude BDD Step Definitions: $STEPS_DIR/$TARGET_NAME_steps.py"\n2344\t```\n2345\t\n2346\t### 2.6.4 输出汇总\n2347\t\n2348\t```\n2349\t┌─────────────────────────────────────────────────────────────────┐\n2350\t│ Claude BDD测试生成完成 │\n2351\t├─────────────────────────────────────────────────────────────────┤\n2352\t│ │\n2353\t│ 生成的文件: │\n2354\t│ • docs/{branch}/features/{agent_name}.feature │\n2355\t│ • docs/{branch}/testing/{agent_name}-evaluation.json │\n2356\t│ • docs/{branch}/testing/claude-bdd-steps/{agent_name}_steps.py │\n2357\t│ │\n2358\t│ 后续由test-executor执行: │\n2359\t│ 1. python3 .claude/dev-tools/claude-dev/prompt-validator.py --agent │\n2360\t│ 2. python3 .claude/dev-tools/claude-dev/agent-tester.py --agent │\n2361\t│ 3. python3 .claude/dev-tools/claude-dev/agent-behavior-tester.py --dataset │\n2362\t│ │\n2363\t└─────────────────────────────────────────────────────────────────┘\n2364\t```\n2365\t\n2366\t---\n2367\t\n2368\t## 第3步:生成单元测试\n2369\t\n2370\t### 3.1 单元测试模板\n2371\t\n2372\t**Java JUnit 5示例**:\n2373\t\n2374\t```java\n2375\tpackage com.example.service;\n2376\t\n2377\timport org.junit.jupiter.api.Test;\n2378\timport org.junit.jupiter.api.DisplayName;\n2379\timport static org.assertj.core.api.Assertions.*;\n2380\t\n2381\t@DisplayName("冒泡排序服务单元测试")\n2382\tclass BubbleSortServiceTest {\n2383\t\n2384\t @Test\n2385\t @DisplayName("应该正确排序普通数组")\n2386\t void shouldSortNormalArray() {\n2387\t // Given\n2388\t BubbleSortService service = new BubbleSortService();\n2389\t int[] input = {5, 2, 8, 1, 9};\n2390\t\n2391\t // When\n2392\t int[] result = service.sort(input);\n2393\t\n2394\t // Then\n2395\t assertThat(result).containsExactly(1, 2, 5, 8, 9);\n2396\t }\n2397\t\n2398\t @Test\n2399\t @DisplayName("应该处理空数组")\n2400\t void shouldHandleEmptyArray() {\n2401\t // Given\n2402\t BubbleSortService service = new BubbleSortService();\n2403\t int[] input = {};\n2404\t\n2405\t // When\n2406\t int[] result = service.sort(input);\n2407\t\n2408\t // Then\n2409\t assertThat(result).isEmpty();\n2410\t }\n2411\t}\n2412\t```\n2413\t\n2414\t---\n2415\t\n2416\t## 第4步:生成性能测试\n2417\t\n2418\t### 4.1 性能测试类型\n2419\t\n2420\t| 项目类型 | 测试方案 | 说明 |\n2421\t|---------|---------|------|\n2422\t| **HTTP接口** | JMeter / Locust | HTTP接口压力测试 |\n2423\t| **算法/方法** | JUnit性能测试 | 方法执行时间测量 |\n2424\t| **数据库操作** | JDBC性能测试 | 数据库查询性能 |\n2425\t| **默认轻量级** | 简单时间测量 | 基础性能验证 |\n2426\t\n2427\t### 4.2 JUnit性能测试示例\n2428\t\n2429\t```java\n2430\tpackage com.example.performance;\n2431\t\n2432\timport org.junit.jupiter.api.Test;\n2433\timport org.junit.jupiter.api.Tag;\n2434\timport org.junit.jupiter.api.Timeout;\n2435\timport java.util.concurrent.TimeUnit;\n2436\t\n2437\t@Tag("performance")\n2438\tclass BubbleSortPerformanceTest {\n2439\t\n2440\t @Test\n2441\t @Tag("performance")\n2442\t @Timeout(value = 5, unit = TimeUnit.SECONDS)\n2443\t @DisplayName("大规模数组排序性能测试")\n2444\t void shouldSortLargeArrayWithinTimeLimit() {\n2445\t // Given\n2446\t BubbleSortService service = new BubbleSortService();\n2447\t int[] largeArray = generateRandomArray(10000);\n2448\t\n2449\t // When\n2450\t long startTime = System.nanoTime();\n2451\t int[] result = service.sort(largeArray);\n2452\t long endTime = System.nanoTime();\n2453\t\n2454\t // Then\n2455\t long durationMs = (endTime - startTime) / 1_000_000;\n2456\t System.out.println("排序耗时: " + durationMs + "ms");\n2457\t assertThat(durationMs).isLessThan(5000); // 5秒内完成\n2458\t }\n2459\t}\n2460\t```\n2461\t\n2462\t### 4.3 JMeter测试计划\n2463\t\n2464\t**生成路径**:`performance/test-plan.jmx`\n2465\t\n2466\t**模板路径**:`.claude/skills/test-code-generator/templates/jmeter/`\n2467\t\n2468\t---\n2469\t\n2470\t## 第4.8步:生成远程curl测试用例 🆕\n2471\t\n2472\t**目标**:生成可直接调用的远程API测试脚本\n2473\t\n2474\t### 4.8.1 生成remote-api-test.sh\n2475\t\n2476\t**读取部署配置**:\n2477\t```bash\n2478\t# 读取deployment-config.json获取远端服务配置\n2479\tif [ -f ".claude/config/deployment-config.json" ]; then\n2480\t BASE_URL=$(jq -r \'.remoteServer.baseUrl\' .claude/config/deployment-config.json)\n2481\t API_BASE_PATH=$(jq -r \'.remoteServer.apiBasePath // ""\' .claude/config/deployment-config.json)\n2482\tfi\n2483\t```\n2484\t\n2485\t**生成脚本**(Shell示例):\n2486\t```bash\n2487\t#!/bin/bash\n2488\t# remote-api-test.sh - 远程API测试脚本\n2489\t\n2490\tset -eo pipefail\n2491\t\n2492\t# 配置(从deployment-config.json读取的实际值)\n2493\tBASE_URL="${BASE_URL:-http://localhost:8080}"\n2494\tAPI_BASE_PATH="${API_BASE_PATH:-/api}"\n2495\t\n2496\techo "========================================"\n2497\techo "远程API测试"\n2498\techo "========================================"\n2499\techo "BASE_URL: $BASE_URL"\n2500\techo "API_BASE_PATH: $API_BASE_PATH"\n2501\techo ""\n2502\t\n2503\t# 测试用例1:用户登录\n2504\techo "[测试1] 用户登录"\n2505\tRESPONSE=$(curl -s -X POST \\\n2506\t "$BASE_URL$API_BASE_PATH/auth/login" \\\n2507\t -H "Content-Type: application/json" \\\n2508\t -d \'{"username":"test","password":"test123"}\')\n2509\t\n2510\techo "响应: $RESPONSE"\n2511\t\n2512\t# 验证响应\n2513\tif echo "$RESPONSE" | jq -e \'.success == true\' > /dev/null; then\n2514\t echo "✅ 测试通过"\n2515\telse\n2516\t echo "❌ 测试失败"\n2517\tfi\n2518\t```\n2519\t\n2520\t---\n2521\t\n2522\t## 第5步:测试代码合并\n2523\t\n2524\t### 5.1 检测现有测试代码\n2525\t\n2526\t**扫描现有测试文件**:\n2527\t```bash\n2528\t# 查找已存在的测试文件\n2529\tfind src/test -name "*Test.java" -o -name "*Steps.java"\n2530\tfind tests -name "test_*.py" -o -name "*_steps.py"\n2531\t```\n2532\t\n2533\t### 5.2 合并策略\n2534\t\n2535\t| 场景 | 策略 |\n2536\t|-----|------|\n2537\t| 测试文件不存在 | 直接创建新文件 |\n2538\t| 测试文件已存在 | 追加新测试方法到文件末尾 |\n2539\t| 测试方法已存在 | 跳过(不重复生成) |\n2540\t| Step Definition已存在 | 合并到现有类 |\n2541\t\n2542\t### 5.3 合并执行\n2543\t\n2544\t```bash\n2545\t# 合并Step Definitions\n2546\tif [ -f "src/test/java/cucumber/steps/BubbleSortSteps.java" ]; then\n2547\t echo "检测到现有Step Definitions,执行合并..."\n2548\t # 备份原文件\n2549\t cp src/test/java/cucumber/steps/BubbleSortSteps.java \\\n2550\t src/test/java/cucumber/steps/BubbleSortSteps.java.backup\n2551\t # 追加新的Step Definitions\n2552\tfi\n2553\t```\n2554\t\n2555\t---\n2556\t\n2557\t### 5.4 回写测试代码路径映射到测试用例文档 🆕v4.2\n2558\t\n2559\t**目标**:将生成的自动化测试代码路径回写到用例文档 `docs/{branch}/testing/{需求名}_测试用例.md` 中,使得测试用例与测试代码路径形成显式映射。\n2560\t\n2561\t**执行策略**:\n2562\t1. **解析用例文档**:扫描 `docs/{branch}/testing/{需求名}_测试用例.md`,使用正则或词法匹配定位所有的测试用例标识(如 `### TC001:`、`### TC010:`)。\n2563\t2. **构建映射字典**:根据本次生成测试代码时的输出路径,自动构建用例 ID 到文件相对路径的映射:\n2564\t - 单元测试/Mock测试方法 -> 映射到对应的单元测试文件路径,如 `src/test/java/unit/com/example/controller/UserControllerTest.java`\n2565\t - BDD 步骤场景 -> 映射到对应的 Step Definitions 和 Runner 文件路径,如 `src/test/java/cucumber/steps/UserLoginSteps.java`\n2566\t - 接口集成测试场景 -> 映射到对应的 `remote-api-test.sh` 脚本路径\n2567\t - 性能测试场景 -> 映射到对应的压测脚本路径\n2568\t3. **回写文档内容**:\n2569\t - 对每一个匹配到的用例小节,在小节末尾(如在“覆盖场景”或“优先级”字段之后)检测是否已存在 `**测试代码路径**` 字段。\n2570\t - 若不存在,自动追加 `**测试代码路径**:[文件名](file:///{项目绝对路径}/{相对文件路径})`。\n2571\t - 若已存在且路径不一致,进行增量更新或追加,避免覆盖已手动建立的映射。\n2572\t4. **输出总结对照表**:\n2573\t - 在用例文档的末尾,自动追加或更新“## 自动化测试代码对照表”章节,以 Markdown 表格形式汇总展示所有映射关系,便于人工审计与自动化流程读取。\n2574\t\n2575\t**回写格式示例**:\n2576\t```markdown\n2577\t### TC001:UserController.create() - 正常创建用户\n2578\t...\n2579\t**优先级**:P0\n2580\t**测试类型**:单元测试\n2581\t**覆盖场景**:关键路径 - 正常流程\n2582\t**测试代码路径**:[UserControllerTest.java](file:///C:/Users/stephenzhou/IdeaProjects/dev-sync-agent/src/test/java/unit/com/example/controller/UserControllerTest.java)\n2583\t```\n2584\t\n2585\t---\n2586\t\n2587\t## 第5.5步:代码与脚本合法性验证 🆕v3.9\n2588\t\n2589\t**目标**:验证生成的测试代码和脚本能够成功编译/执行,确保代码和脚本合法性\n2590\t\n2591\t**验证行为**: `block`(阻断模式) - 验证失败时停止流程,要求先修复问题\n2592\t\n2593\t### 5.5.1 验证范围'}] + +**AI**: +[思考] 用户问 test-code-generator 会执行单元测试吗。这是一个具体的事实查询问题,需要我查看 test-code-generator skill 的实际内容来回答。遵循 memory `verify-against-actual-agent-content`,我必须读实际文件,不能凭假设。 + +从之前的分析中,我知道: +- test-code-generator 是 Skill(.claude/skills/test-code-generator/SKILL.md) +- 在 Stage 7 被调用,与 test-executor 串行:`test-code-generator(Skill) -> test-executor(Skill)` +- 在 Stage 10.4 也被调用(--mode regression) + +从映射表看,Stage 7 是"测试执行",包含 test-code-generator 和 test-executor 两个 Skill。test-code-generator 看名字是"生成测试代码",test-executor 是"执行测试"。所以初步判断 test-code-generator 只生成不执行。 + +但用户具体问"会执行单元测试吗",我需要读实际文件确认。不能凭名字假设。 + +让我读 .claude/skills/test-code-generator/SKILL.md。 + +我应该直接读这个文件。如果它还有引用其他文件,再跟进。... + + +## 交互记录 (2026-07-28T10:31:44.202Z) + +**用户**: +[{'tool_use_id': 'call_2ce3dd7ff7764296a7b862f7', 'type': 'tool_result', 'content': '2587\t## 第5.5步:代码与脚本合法性验证 🆕v3.9\n2588\t\n2589\t**目标**:验证生成的测试代码和脚本能够成功编译/执行,确保代码和脚本合法性\n2590\t\n2591\t**验证行为**: `block`(阻断模式) - 验证失败时停止流程,要求先修复问题\n2592\t\n2593\t### 5.5.1 验证范围\n2594\t\n2595\t| 类别 | 文件类型 | 验证方式 | 超时时间 |\n2596\t|-----|---------|---------|:-------:|\n2597\t| **测试代码** | Java | `mvn test-compile -q` | 120s |\n2598\t| | Python | `python -m py_compile ` | 30s |\n2599\t| | Go | `go build ./...` | 60s |\n2600\t| **集成测试脚本** | Shell (.sh) | `bash -n ` (语法检查) | 10s |\n2601\t| | HTTP (.http) | 解析验证HTTP格式 | 5s |\n2602\t| **性能测试脚本** | JMeter (.jmx) | XML格式验证 + JMeter验证 | 30s |\n2603\t| | Locust (.py) | `python -m py_compile ` | 15s |\n2604\t| **跨系统配置** | JSON | 验证外部系统配置有效性 | 5s |\n2605\t\n2606\t### 5.5.2 测试代码编译验证\n2607\t\n2608\t#### Java项目编译验证\n2609\t\n2610\t```bash\n2611\tverify_java_compilation() {\n2612\t echo "📋 [1/4] 正在验证Java测试代码编译..."\n2613\t\n2614\t # 执行编译\n2615\t COMPILE_OUTPUT=$(mvn test-compile -q 2>&1)\n2616\t\n2617\t if [ $? -eq 0 ]; then\n2618\t echo "✅ Java测试代码编译通过"\n2619\t return 0\n2620\t else\n2621\t echo "❌ Java测试代码编译失败"\n2622\t echo "📋 正在解析编译错误..."\n2623\t parse_java_compile_errors "$COMPILE_OUTPUT"\n2624\t return 1\n2625\t fi\n2626\t}\n2627\t parse_java_compile_errors() {\n2628\t local output="$1"\n2629\t local error_file=".claude/data/testing/compilation-errors.json"\n2630\t\n2631\t # 解析编译错误\n2632\t ERRORS=$(echo "$output" | grep -E "^\\[ERROR\\]" | head -20)\n2633\t\n2634\t # 生成错误报告\n2635\t cat > "$error_file" </dev/null); do\n2664\t if ! python -m py_compile "$file" 2>&1; then\n2665\t echo "❌ 语法错误: $file"\n2666\t ERROR_COUNT=$((ERROR_COUNT + 1))\n2667\t # 记录错误\n2668\t ERROR_MSG=$(python -m py_compile "$file" 2>&1)\n2669\t ERROR_LIST=$(echo "$ERROR_LIST" | jq ". += [{\\"file\\": \\"$file\\", \\"error\\": \\"$ERROR_MSG\\"}]")\n2670\t fi\n2671\t done\n2672\t\n2673\t if [ $ERROR_COUNT -eq 0 ]; then\n2674\t echo "✅ Python测试代码语法检查通过"\n2675\t return 0\n2676\t else\n2677\t echo "❌ 发现 $ERROR_COUNT 个语法错误"\n2678\t echo "$ERROR_LIST" | jq \'.\' > "$ERROR_FILE"\n2679\t return 1\n2680\t fi\n2681\t}\n2682\t```\n2683\t\n2684\t**Go项目验证**:\n2685\t\n2686\t```bash\n2687\tverify_go_compilation() {\n2688\t echo "📋 [1/4] 正在验证Go测试代码编译..."\n2689\t\n2690\t if go build ./... 2>&1; then\n2691\t echo "✅ Go测试代码编译通过"\n2692\t return 0\n2693\t else\n2694\t echo "❌ Go测试代码编译失败"\n2695\t return 1\n2696\t fi\n2697\t}\n2698\t```\n2699\t\n2700\t### 5.5.3 集成测试脚本验证 🆕\n2701\t\n2702\t**Shell脚本语法检查**:\n2703\t\n2704\t```bash\n2705\tverify_shell_scripts() {\n2706\t echo "📋 [2/4] 正在验证Shell脚本语法..."\n2707\t\n2708\t SCRIPT_DIR="tests/scripts"\n2709\t ERROR_COUNT=0\n2710\t SYNTAX_ERRORS="[]"\n2711\t\n2712\t if [ -d "$SCRIPT_DIR" ]; then\n2713\t for script in $(find "$SCRIPT_DIR" -name "*.sh"); do\n2714\t # 使用 bash -n 进行语法检查(不执行)\n2715\t if ! bash -n "$script" 2>&1; then\n2716\t echo "❌ Shell语法错误: $script"\n2717\t ERROR_COUNT=$((ERROR_COUNT + 1))\n2718\t ERROR_MSG=$(bash -n "$script" 2>&1)\n2719\t SYNTAX_ERRORS=$(echo "$SYNTAX_ERRORS" | jq ". += [{\\"file\\": \\"$script\\", \\"error\\": \\"$ERROR_MSG\\"}]")\n2720\t else\n2721\t echo " ✅ $script 语法正确"\n2722\t fi\n2723\t done\n2724\t fi\n2725\t\n2726\t if [ $ERROR_COUNT -eq 0 ]; then\n2727\t echo "✅ Shell脚本语法检查通过"\n2728\t return 0\n2729\t else\n2730\t echo "❌ 发现 $ERROR_COUNT 个Shell语法错误"\n2731\t echo "$SYNTAX_ERRORS" | jq \'.\' > ".claude/data/testing/shell-syntax-errors.json"\n2732\t return 1\n2733\t fi\n2734\t}\n2735\t```\n2736\t\n2737\t**检查脚本中调用的API端点**:\n2738\t\n2739\t```bash\n2740\tverify_script_api_endpoints() {\n2741\t echo "📋 正在检查脚本中的API端点..."\n2742\t\n2743\t SCRIPT_DIR="tests/scripts"\n2744\t INDEX_FILE=".claude/data/testing/src-method-index.json"\n2745\t API_ERRORS="[]"\n2746\t\n2747\t if [ -d "$SCRIPT_DIR" ]; then\n2748\t for script in $(find "$SCRIPT_DIR" -name "*.sh"); do\n2749\t # 提取curl命令中的URL\n2750\t API_CALLS=$(grep -oP \'curl\\s+[^"]*\\K[^"]+\' "$script" | grep -v "sed \'s/curl//g\'")\n2751\t\n2752\t for api_call in $API_CALLS; do\n2753\t # 提取API路径(如 /api/payment/process)\n2754\t API_PATH=$(echo "$api_call" | grep -oP \'/api/[^"\'\\s]+\' | head -1)\n2755\t\n2756\t if [ -n "$API_PATH" ]; then\n2757\t # 验证API路径是否在索引中\n2758\t validate_api_endpoint "$API_PATH" "$INDEX_FILE"\n2759\t fi\n2760\t done\n2761\t done\n2762\t fi\n2763\t\n2764\t if [ ${#API_ERRORS[@]} -eq 0 ]; then\n2765\t echo "✅ API端点检查通过"\n2766\t return 0\n2767\t else\n2768\t echo "❌ 发现未实现的API端点"\n2769\t return 1\n2770\t fi\n2771\t}\n2772\t\n2773\tvalidate_api_endpoint() {\n2774\t local api_path="$1"\n2775\t local index_file="$2"\n2776\t\n2777\t # 从API路径推断Controller和方法(如 /api/payment/process -> PaymentController.process)\n2778\t CONTROLLER=$(echo "$api_path" | awk -F\'/\' \'{print toupper toupper substr(0,1)}\'Controller\')\n2779\t METHOD=$(echo "$api_path" | awk -F\'/\' \'{print tolower}\')\n2780\t\n2781\t # 在索引中查找\n2782\t if [ -f "$index_file" ]; then\n2783\t CONTROLLER_CLASS="${CONTROLLER}Controller"\n2784\t if ! jq -e ".classes[\\"$CONTROLLER_CLASS\\"].methods[\\"$METHOD\\"]" "$index_file" > /dev/null 2>&1; then\n2785\t API_ERRORS+=("{\\"file\\": \\"$script\\", \\"api\\": \\"$api_path\\", \\"error\\": \\"方法不存在: ${CONTROLLER_CLASS}.${METHOD}()\\"}")\n2786\t fi\n2787\t fi\n2788\t}\n2789\t```\n2790\t\n2791\t### 5.5.4 性能测试脚本验证 🆕\n2792\t\n2793\t **JMeter脚本验证**:\n2794\t\n2795\t```bash\n2796\tverify_jmeter_scripts() {\n2797\t echo "📋 [3/4] 正在验证JMeter脚本..."\n2798\t\n2799\t JMETER_DIR="performance"\n2800\t ERROR_COUNT=0\n2801\t\n2802\t if [ -d "$JMETER_DIR" ]; then\n2803\t for jmx in $(find "$JMETER_DIR" -name "*.jmx"); do\n2804\t # XML格式验证\n2805\t if ! xmllint --noout "$jmx" 2>&1; then\n2806\t echo "❌ JMX格式错误: $jmx"\n2807\t ERROR_COUNT=$((ERROR_COUNT + 1))\n2808\t else\n2809\t echo " ✅ $jmx 格式正确"\n2810\t fi\n2811\t done\n2812\t fi\n2813\t\n2814\t if [ $ERROR_COUNT -eq 0 ]; then\n2815\t echo "✅ JMeter脚本验证通过"\n2816\t return 0\n2817\t else\n2818\t echo "❌ 发现 $ERROR_COUNT 个JMeter脚本错误"\n2819\t return 1\n2820\t fi\n2821\t}\n2822\t```\n2823\t\n2824\t**Locust脚本验证**:\n2825\t\n2826\t```bash\n2827\tverify_locust_scripts() {\n2828\t echo "📋 [3/4] 正在验证Locust脚本..."\n2829\t\n2830\t LOCUST_DIR="performance"\n2831\t ERROR_COUNT=0\n2832\t\n2833\t if [ -d "$LOCUST_DIR" ]; then\n2834\t for py in $(find "$LOCUST_DIR" -name "locust*.py"); do\n2835\t if ! python -m py_compile "$py" 2>&1; then\n2836\t echo "❌ Locust脚本语法错误: $py"\n2837\t ERROR_COUNT=$((ERROR_COUNT + 1))\n2838\t else\n2839\t echo " ✅ $py 语法正确"\n2840\t fi\n2841\t done\n2842\t fi\n2843\t\n2844\t if [ $ERROR_COUNT -eq 0 ]; then\n2845\t echo "✅ Locust脚本验证通过"\n2846\t return 0\n2847\t else\n2848\t echo "❌ 发现 $ERROR_COUNT 个Locust脚本错误"\n2849\t return 1\n2850\t fi\n2851\t}\n2852\t```\n2853\t\n2854\t### 5.5.5 跨系统配置验证 🆕\n2855\t\n2856\t```bash\n2857\tverify_cross_system_config() {\n2858\t echo "📋 [4/4] 正在验证跨系统配置..."\n2859\t\n2860\t CONFIG_FILE="dev/active/${TASK_NAME}/cross-system-config.json"\n2861\t\n2862\t if [ ! -f "$CONFIG_FILE" ]; then\n2863\t echo "⏭ 未检测到跨系统配置,跳过验证"\n2864\t return 0\n2865\t fi\n2866\t\n2867\t # 验证外部系统地址格式\n2868\t EXTERNAL_SYSTEMS=$(jq -r \'.externalSystems[]\' "$CONFIG_FILE" 2>/dev/null)\n2869\t\n2870\t for system in $EXTERNAL_SYSTEMS; do\n2871\t BASE_URL=$(echo "$system" | jq -r \'.baseUrl\')\n2872\t\n2873\t # 验证URL格式\n2874\t if ! [[ "$BASE_URL" =~ ^https?:// ]]; then\n2875\t echo "⚠️ 无效的URL格式: $BASE_URL"\n2876\t fi\n2877\t\n2878\t # 可选:检查服务可达性(如果配置了checkReachability)\n2879\t CHECK_REACHABILITY=$(echo "$system" | jq -r \'.checkReachability // false\')\n2880\t if [ "$CHECK_REACHABILITY" = "true" ]; then\n2881\t if ! curl -s --connect-timeout 5 "$BASE_URL/health" > /dev/null 2>&1; then\n2882\t echo "⚠️ 服务不可达: $BASE_URL"\n2883\t fi\n2884\t fi\n2885\t done\n2886\t\n2887\t echo "✅ 跨系统配置验证通过"\n2888\t return 0\n2889\t}\n2890\t```\n2891\t\n2892\t### 5.5.6 完整验证流程\n2893\t\n2894\t ```bash\n2895\trun_all_verifications() {\n2896\t echo "========================================"\n2897\t echo "📋 代码与脚本合法性验证"\n2898\t echo "========================================"\n2899\t\n2900\t ALL_PASSED=true\n2901\t ERRORS="[]"\n2902\t\n2903\t # 1. 测试代码编译验证\n2904\t if ! verify_test_code_compilation; then\n2905\t ALL_PASSED=false\n2906\t ERRORS+=("{\\"type\\": \\"compilation\\", \\"details\\": \\"测试代码编译失败\\"}")\n2907\t fi\n2908\t\n2909\t # 2. 集成测试脚本验证\n2910\t if ! verify_shell_scripts; then\n2911\t ALL_PASSED=false\n2912\t ERRORS+=("{\\"type\\": \\"shell_script\\", \\"details\\": \\"Shell脚本语法错误\\"}")\n2913\t fi\n2914\t\n2915\t if ! verify_script_api_endpoints; then\n2916\t ALL_PASSED=false\n2917\t ERRORS+=("{\\"type\\": \\"api_endpoint\\", \\"details\\": \\"脚本调用未实现的API\\"}")\n2918\t fi\n2919\t\n2920\t # 3. 性能测试脚本验证\n2921\t if ! verify_performance_scripts; then\n2922\t ALL_PASSED=false\n2923\t ERRORS+=("{\\"type\\": \\"performance_script\\", \\"details\\": \\"性能测试脚本错误\\"}")\n2924\t fi\n2925\t\n2926\t # 4. 跨系统配置验证\n2927\t if ! verify_cross_system_config; then\n2928\t ALL_PASSED=false\n2929\t ERRORS+=("{\\"type\\": \\"cross_system_config\\", \\"details\\": \\"跨系统配置验证失败\\"}")\n2930\t fi\n2931\t\n2932\t echo "========================================"\n2933\t\n2934\t if [ "$ALL_PASSED" = true ]; then\n2935\t echo "✅ 所有验证通过"\n2936\t return 0\n2937\t else\n2938\t echo "❌ 验证失败,流程阻断"\n2939\t generate_verification_error_report "$ERRORS"\n2940\t return 1\n2941\t fi\n2942\t}\n2943\t```\n2944\t\n2945\t### 5.5.7 验证失败处理(Block模式)\n2946\t\n2947\t 当验证失败时:\n2948\t\n2949\t```bash\n2950\tgenerate_verification_error_report() {\n2951\t local errors="$1"\n2952\t local report_file="docs/${BRANCH}/testing/${TASK_NAME}_验证失败报告.md"\n2953\t\n2954\t cat > "$report_file" <> "$report_file" < W{验证通过?} -> X[更新test-status.json],验证失败->Y[生成错误报告并阻断] +5. 流程中没有"执行单元测试"的步骤,最后是更新test-status.json然后结束 + +但是,我需要确认5.5步的验证到底是什么。如果只是编译验证(mvn compile/语法检查),那不是执行单元测试。让我读5.5步的详细内容确认。 + +另外,从stage-hooks.md的映射表明确写的是:`7 | 测试执行 | test-code-generator(Skill)->test-executor(Skill)`。也就是说test-code-generator生成代码,test-executor执行测试。这进一步印证test-code-generator不执行单元测试,而是由test-executor执行。 + +但用户问的是test-code-generator本身会不会执行单元测试。我需要看5.5步的完整内容来确认。让我读2587行之后的内容。... + + +## 交互记录 (2026-07-28T10:34:58.209Z) + +**用户**: +[{'tool_use_id': 'call_fd274ff53b3d4429804e628f', 'type': 'tool_result', 'content': '1\t---\n2\tname: test-executor\n3\ttype: testing\n4\tdescription: 自动化测试执行专家,执行测试并生成验证结果报告,支持前端E2E测试、前端单元测试、Claude开发测试和全量回归测试\n5\tversion: 4.9\n6\tauthor: DevSyncAgent Team\n7\tlast_updated: 2026-07-16\n8\tchangelog:\n9\t v4.9 - 2026-07-16\n10\t - 🆕 接入 GEP 自进化:追加 Gene 召回机制段落(gep_recall/gep_record_outcome + GEP-INJECT 注入 + project_name 三级取值规则 + signals 基于职责正向设计)\n11\t v4.8 - 2026-07-10\n12\t - 🆕 新增失败用例失败原因提取(7.1.2小节):从JUnit XML /、Cucumber error_message、远程API测试执行时捕获的HTTP状态码/响应体/连接错误、E2E日志提取每条失败用例failure_reason(关键摘要,截断200字符)\n13\t - 🆕 结构化输出新增failure_reasons字段(仅failed_cases>0时输出),双通道(报告表格+结构化字段)传递供test-report未通过清单填充\n14\t - 🆕 详细测试结果表5个子表(单元/Cucumber/性能/远程API/E2E)新增「失败原因」列\n15\t - 🛡️ 远程API失败原因执行时直接捕获,不依赖remote-api-test.log事后解析(日志可能因脚本不存在/未按tee落盘而缺失)\n16\t v4.7 - 2026-06-11\n17\t - 🆕 新增结构化输出要求:测试完成后必须输出event_type字段(test_passed/test_failed/bug_fixed),供主会话Stage7-Hook自动判断执行分支\n18\t v4.6 - 2026-06-01\n19\t - 🔄 概念对齐:将文档占位符 {功能名} 统一为 {需求名},与项目术语体系一致\n20\t v3.9 - 2026-05-27\n21\t - 🆕 新增属性感知测试案例文档路径适配(匹配{需求名}_前端测试案例.md、{需求名}_后端测试案例.md等拆分文件名)\n22\t - 引用配置:design-doc-rules.json(splitOutputRules)\n23\t v3.8 - 2026-03-19\n24\t - 🆕 新增前端单元测试执行支持(Jest/Vitest)\n25\t - 🆕 新增第6.5步:前端单元测试执行流程\n26\t - 🆕 支持纯前端项目(React/Vue)的测试执行\n27\t - 🔧 新增前端项目检测和包管理器识别\n28\t - 🔧 新增前端覆盖率报告解析(Istanbul/c8)\n29\t - 🆕 新增第-0.5步:跨组件配置加载\n30\t - 🆕 支持读取cross-system-config.json配置文件\n31\t - 🆕 将跨系统配置传递给测试脚本\n32\t v3.7 - 2026-03-10\n33\t - 🆕 新增第-0.5步:跨组件配置加载\n34\t - 🆕 支持读取cross-system-config.json配置文件\n35\t - 🆕 将跨系统配置传递给测试脚本\n36\t - 🆕 新增Claude开发测试支持(Agent/Skill/Command)\n37\t - 🆕 新增Claude Prompt测试执行(prompt-validator.py)\n38\t - 🆕 新增Claude Agent调用测试执行(agent-tester.py)\n39\t - 🆕 新增Claude测试结果解析和报告生成\n40\t - ✅ 与claude-code-developer联动,支持Claude产物验证\n41\t v3.6 - 2026-03-10\n42\t - 从 automated-test-executor 拆分,专注于测试执行\n43\t - 移除测试代码生成相关功能,移至 test-code-generator skill\n44\t v3.5 - 2026-02-27\n45\t - 继承自 automated-test-executor v3.5\n46\t - 支持代码覆盖率报告\n47\t - 支持全量回归测试执行\n48\t---\n49\t\n50\t# 测试执行器 Skill\n51\t\n52\t你是自动化测试执行专家,负责执行测试并生成验证结果报告。\n53\t\n54\t## ⚠️ 路径解析优先级(version_mode兼容)\n55\t\n56\t本Skill中所有 `dev/active/{task-name}/` 路径按以下优先级解析:\n57\t\n58\t```\n59\t1. 若调用Prompt中包含【工作目录】字段 → 使用该路径作为BASE_DIR(如 dev/versions/v3.10/user-export/)\n60\t2. 否则 → 回退到默认路径 dev/active/{task-name}/\n61\t\n62\t规则:将文档中所有 dev/active/{task-name}/ 替换为 {BASE_DIR}\n63\t```\n64\t\n65\t## 适用场景\n66\t\n67\t- 已有测试代码,需要执行测试\n68\t- 需要获取测试执行结果\n69\t- 支持Java、Python、Go和纯前端项目\n70\t- 全量回归测试执行\n71\t\n72\t## 核心能力\n73\t\n74\t| 能力 | 说明 |\n75\t|-----|------|\n76\t| **单元测试执行** | 执行JUnit/pytest/go test/Jest/Vitest单元测试 |\n77\t| **Cucumber测试执行** | 执行BDD场景测试 |\n78\t| **性能测试执行** | 执行JMeter/locust/JUnit性能测试 |\n79\t| **前端E2E测试执行** | 执行Playwright前端测试 |\n80\t| **前端单元测试执行** 🆕 | 执行Jest/Vitest组件测试 |\n81\t| **远程API测试执行** | 执行curl/requests API测试 |\n82\t| **Claude开发测试** | 执行Claude Agent/Skill/Command验证测试 |\n83\t| **覆盖率报告生成** | 生成JaCoCo/pytest-cov/go test/Istanbul覆盖率报告 |\n84\t| **全量回归测试** | 执行知识库中的全量回归测试 |\n85\t| **验证结果生成** | 生成测试验证结果报告 |\n86\t\n87\t## 📎 版本模式文档命名规则(P0级)\n88\t\n89\t**触发条件**:当prompt中包含【需求编号】(如 `REQ-01`)时启用版本模式前缀。\n90\t\n91\t**规则**:\n92\t- 所有生成/引用的文档**文件名**在`{需求名}`前加 `REQ-NN_` 前缀\n93\t- 文档**内部标题和内容**始终使用纯需求名,不加编号\n94\t- 设计文档拆分场景(前端/后端/数据):每个属性测试案例文档均加前缀\n95\t\n96\t**命名对照**:\n97\t\n98\t| 文档类型 | 标准命名(单需求模式) | 版本模式命名 |\n99\t|---------|-------------------|------------|\n100\t| 需求文档(输入) | `{需求名}_需求.md` | `REQ-01_{需求名}_需求.md` |\n101\t| 设计文档(输入) | `{需求名}_设计.md` | `REQ-01_{需求名}_设计.md` |\n102\t| 测试案例 | `{需求名}_测试案例.md` | `REQ-01_{需求名}_测试案例.md` |\n103\t| 前端测试案例 | `{需求名}_前端测试案例.md` | `REQ-01_{需求名}_前端测试案例.md` |\n104\t| 后端测试案例 | `{需求名}_后端测试案例.md` | `REQ-01_{需求名}_后端测试案例.md` |\n105\t| 数据测试案例 | `{需求名}_数据测试案例.md` | `REQ-01_{需求名}_数据测试案例.md` |\n106\t| 测试执行报告 | `{需求名}_测试执行报告.md` | `REQ-01_{需求名}_测试执行报告.md` |\n107\t| 最终测试报告 | `{需求名}_最终测试报告.md` | `REQ-01_{需求名}_最终测试报告.md` |\n108\t\n109\t**示例**:需求名="用户注册",编号="REQ-01"\n110\t- 测试案例文件名:`docs/{branch}/testing/REQ-01_用户注册_测试案例.md` ✅\n111\t- 内部标题:`用户注册 测试案例` ✅(不加编号)\n112\t\n113\t## 输入\n114\t\n115\t**优先级顺序**:\n116\t\n117\t1. **测试代码**(必须):\n118\t - 单元测试:`src/test/java/**/*Test.java` 或 `tests/**/test_*.py`\n119\t - Cucumber测试:`src/test/java/cucumber/` 或 `tests/`\n120\t - Feature文件:`dev/active/{task-name}/features/*.feature`\n121\t2. **项目配置**(必须):`project-context.json`\n122\t3. **test-status.json**:测试状态文件\n123\t\n124\t > 📝 **属性感知路径适配** 🆕v3.9:当测试案例按功能属性拆分时,测试代码路径不变(仍为src/test/...),但参考文档可能已拆分:\n125\t > - 后端测试 → 参考 `docs/{branch}/testing/{需求名}_后端测试案例.md`(如存在)\n126\t > - 前端E2E测试 → 参考 `docs/{branch}/testing/{需求名}_前端测试案例.md`(如存在)\n127\t > - 若拆分文件不存在,回退到 `{需求名}_测试用例.md`\n128\t\n129\t## 输出\n130\t\n131\t**主要输出**:\n132\t- 📊 **测试验证结果报告** - `docs/{branch}/testing/reports/{需求名}_测试执行报告.md`\n133\t- 📄 **代码覆盖率报告** - JaCoCo/pytest-cov/go test报告\n134\t- 📄 **测试日志** - 执行日志文件\n135\t\n136\t**🚨 结构化输出要求(v4.7+,供主会话Stage7-Hook消费)**:\n137\t\n138\t测试执行完成后,**必须**在最终输出的末尾包含以下结构化字段:\n139\t\n140\t```\n141\t【测试结果摘要】\n142\tevent_type: test_passed | test_failed | bug_fixed\n143\ttotal_cases: {总数}\n144\tpassed_cases: {通过数}\n145\tfailed_cases: {失败数}\n146\tfailure_reasons: [{case_id: "用例标识", reason: "失败原因摘要"}, ...] # 🆕v4.8 仅failed_cases>0时输出,供test-report未通过清单填充失败原因列\n147\t```\n148\t\n149\t**event_type判定规则**:\n150\t- `test_passed`:所有测试用例通过(failed_cases == 0),且无已知Bug\n151\t- `test_failed`:存在失败用例(failed_cases > 0)\n152\t- `bug_fixed`:之前失败的用例修复后重新执行通过\n153\t\n154\t⚠️ 此字段供主会话Stage7-Hook(B6/B7/B7.5)自动判断执行分支。缺少此字段将导致主会话无法自动执行用例流转,必须通过AskUserQuestion人工确认。\n155\t\n156\t---\n157\t\n158\t## 测试执行流程\n159\t\n160\t```mermaid\n161\tgraph TD\n162\t A[开始] --> B{回归测试模式?}\n163\t B -->|是| C[检查知识库]\n164\t C --> D{知识库为空?}\n165\t D -->|是| E[提示无法执行,退出]\n166\t D -->|否| F[扫描知识库Feature文件]\n167\t F --> G[执行全量回归测试]\n168\t G --> H[生成回归测试验证结果]\n169\t H --> I[结束]\n170\t B -->|否| J[第-1步: 检查测试状态]\n171\t J --> K{测试已生成?}\n172\t K -->|是| L[跳到第6步: 执行测试]\n173\t K -->|否| M[提示先生成测试代码]\n174\t M --> I\n175\t L --> N[执行单元测试]\n176\t N --> O[执行Cucumber测试]\n177\t O --> P[执行性能测试]\n178\t P --> Q[执行远程API测试]\n179\t Q --> R[生成代码覆盖率报告]\n180\t R --> S[生成验证结果]\n181\t S --> I\n182\t```\n183\t\n184\t---\n185\t\n186\t## 第-1步:检查测试状态 🆕\n187\t\n188\t**目标**:检查测试是否已生成,避免执行不存在的测试\n189\t\n190\t### 状态文件位置\n191\t\n192\t```bash\n193\tSTATUS_FILE="dev/active/{task-name}/test-status.json"\n194\t```\n195\t\n196\t### 检查逻辑\n197\t\n198\t```bash\n199\t# 检查测试状态文件是否存在\n200\tif [ -f "$STATUS_FILE" ]; then\n201\t # 读取状态\n202\t TEST_CODE_GENERATED=$(jq -r \'.testCodeGenerated // false\' $STATUS_FILE)\n203\t\n204\t if [ "$TEST_CODE_GENERATED" = "true" ]; then\n205\t echo "✅ 测试代码已生成,继续执行测试"\n206\t goto_step_6\n207\t fi\n208\tfi\n209\t\n210\techo "❌ 测试代码未生成"\n211\techo "💡 请先使用 test-code-generator skill 生成测试代码"\n212\texit 1\n213\t```\n214\t\n215\t---\n216\t\n217\t## 第-0.5步:跨组件配置加载 🆕v3.8\n218\t\n219\t**目标**:检查是否存在跨系统测试配置,加载并传递给测试脚本\n220\t\n221\t### 配置文件位置\n222\t\n223\t```bash\n224\tCROSS_SYSTEM_CONFIG="dev/active/${TASK_NAME}/cross-system-config.json"\n225\t```\n226\t\n227\t### 加载逻辑\n228\t\n229\t```bash\n230\t# 初始化跨系统模式标志\n231\tCROSS_SYSTEM_MODE=false\n232\tCALL_PATTERN=""\n233\tTEST_SCOPE=""\n234\t\n235\t# 检查是否存在跨系统配置文件\n236\tif [ -f "$CROSS_SYSTEM_CONFIG" ]; then\n237\t echo "========================================"\n238\t echo "检测到跨系统测试配置"\n239\t echo "========================================"\n240\t\n241\t # 读取跨系统配置\n242\t CROSS_SYSTEM_MODE=$(jq -r \'.crossSystemMode // false\' "$CROSS_SYSTEM_CONFIG")\n243\t CALL_PATTERN=$(jq -r \'.callPattern // ""\' "$CROSS_SYSTEM_CONFIG")\n244\t TEST_SCOPE=$(jq -r \'.testScope // ""\' "$CROSS_SYSTEM_CONFIG")\n245\t\n246\t # 统计外部系统数量\n247\t SYSTEM_COUNT=$(jq \'.externalSystems | length\' "$CROSS_SYSTEM_CONFIG")\n248\t\n249\t # 显示配置信息\n250\t echo "📋 跨系统模式: $CROSS_SYSTEM_MODE"\n251\t echo "📋 调用模式: $CALL_PATTERN"\n252\t echo "📋 测试范围: $TEST_SCOPE"\n253\t echo "📋 外部系统数量: $SYSTEM_COUNT"\n254\t\n255\t # 列出外部系统\n256\t echo ""\n257\t echo "📋 配置的外部系统:"\n258\t for ((i=0; i/dev/null | wc -l)\n323\tif [ "$FEATURE_COUNT" -eq 0 ]; then\n324\t echo "❌ 知识库为空"\n325\t exit 1\n326\tfi\n327\t\n328\techo "✅ 知识库检测通过"\n329\techo "Feature文件数量: $FEATURE_COUNT"\n330\t```\n331\t\n332\t### 回归-第2步:扫描知识库Feature文件(支持 --modules 筛选)🆕v4.9\n333\t\n334\t```bash\n335\techo "📋 扫描知识库Feature文件"\n336\t\n337\t# 🆕v4.9 支持 --modules 参数筛选(向后兼容:不传时全量)\n338\tMODULES_ARG="${MODULES:-}"\n339\tIF [ -z "$MODULES_ARG" ]; THEN\n340\t # 全量模式(向后兼容)\n341\t FEATURE_FILES=$(find "$REGRESSION_FEATURES_DIR" -name "*.feature" 2>/dev/null | sort)\n342\tELSE\n343\t # 按模块筛选(Stage 10.5 调用)\n344\t IFS=\',\' read -ra MODULE_ARRAY <<< "$MODULES_ARG"\n345\t FEATURE_FILES=""\n346\t FOR module IN "${MODULE_ARRAY[@]}"; do\n347\t FEATURE_FILE="$REGRESSION_FEATURES_DIR/${module}.feature"\n348\t IF [ -f "$FEATURE_FILE" ]; THEN\n349\t FEATURE_FILES="$FEATURE_FILES $FEATURE_FILE"\n350\t ELSE\n351\t echo "⚠️ 模块 ${module} 的 Feature 文件不存在,跳过"\n352\t fi\n353\t done\n354\tfi\n355\t\n356\t# 显示Feature文件列表\n357\techo "📄 发现的Feature文件:"\n358\techo "$FEATURE_FILES" | while read -r feature_file; do\n359\t feature_name=$(basename "$feature_file")\n360\t scenario_count=$(grep -c "^ Scenario" "$feature_file" 2>/dev/null || echo 0)\n361\t echo " - $feature_name ($scenario_count scenarios)"\n362\tdone\n363\t```\n364\t\n365\t### 回归-第3步:执行全量回归测试\n366\t\n367\t```bash\n368\techo "▶️ 执行全量回归测试"\n369\t\n370\t# 根据项目语言执行测试\n371\tif [ "$PROJECT_TYPE" = "maven" ] || [ "$PROJECT_TYPE" = "gradle" ]; then\n372\t mvn test -Dcucumber.filter.tags="@regression"\n373\telif [ "$PROJECT_TYPE" = "python" ]; then\n374\t behave "$REGRESSION_TEST_RESOURCES" --tags=@regression\n375\telif [ "$PROJECT_TYPE" = "go" ]; then\n376\t godog build --tags=@regression\n377\tfi\n378\t```\n379\t\n380\t### 回归-第4步:生成回归测试验证结果\n381\t\n382\t**报告输出路径**:\n383\t```bash\n384\tREGRESSION_REPORT="docs/project-knowledge/testing/全量回归测试验证结果.md"\n385\t```\n386\t\n387\t---\n388\t\n389\t## 第6步:执行测试\n390\t\n391\t### 6.1 测试执行顺序\n392\t\n393\t**传统代码开发模式**:\n394\t```\n395\t1. 单元测试 (快速反馈)\n396\t └─> JUnit / pytest / go test\n397\t └─> 执行时间: < 1分钟\n398\t\n399\t2. Cucumber场景测试 (集成测试)\n400\t └─> Cucumber / behave / godog\n401\t └─> 执行时间: 1-5分钟\n402\t\n403\t3. 性能测试 (压力测试)\n404\t └─> JMeter / locust / JUnit @Tag("performance")\n405\t └─> 执行时间: 5-10分钟\n406\t\n407\t4. 远程API测试 (接口测试)\n408\t └─> curl / requests\n409\t └─> 执行时间: 1-3分钟\n410\t\n411\t5. 前端E2E测试 (前端测试)\n412\t └─> Playwright / npx playwright\n413\t └─> 执行时间: 2-5分钟\n414\t\n415\t6. 代码覆盖率测试\n416\t └─> JaCoCo / pytest-cov / go test -cover\n417\t └─> 执行时间: 1-2分钟\n418\t```\n419\t\n420\t**Claude开发模式** 🆕v3.7:\n421\t```\n422\t1. Prompt语法验证 (静态检查)\n423\t └─> prompt-validator.py\n424\t └─> 执行时间: < 10秒\n425\t\n426\t2. Agent调用测试 (动态测试)\n427\t └─> agent-tester.py(仅Agent类型)\n428\t └─> 执行时间: 30秒-1分钟\n429\t```\n430\t\n431\t### 6.2 Java项目测试执行\n432\t\n433\t**执行脚本**:\n434\t```bash\n435\t#!/bin/bash\n436\t# test-runner.sh - Java测试执行脚本\n437\t\n438\tset -eo pipefail\n439\t\n440\tREPORT_DIR="test-results"\n441\tmkdir -p "$REPORT_DIR"\n442\t\n443\techo "========================================"\n444\techo "开始执行测试套件"\n445\techo "========================================"\n446\t\n447\t# 前置检查: 项目编译验证\n448\techo "[前置检查] 验证项目编译状态..."\n449\tif ! mvn clean compile -q; then\n450\t echo "❌ 项目编译失败!"\n451\t exit 1\n452\tfi\n453\techo "✅ 项目编译成功"\n454\t\n455\t# 前置检查: 验证测试类存在\n456\techo "[前置检查] 验证测试类存在..."\n457\tTEST_COUNT=$(find src/test/java -name "*Test.java" 2>/dev/null | wc -l)\n458\tif [ "$TEST_COUNT" -eq 0 ]; then\n459\t echo "❌ 未找到任何测试类!"\n460\t exit 1\n461\tfi\n462\techo "✅ 找到 $TEST_COUNT 个测试类"\n463\t\n464\t# 步骤1: 单元测试\n465\techo "[1/6] 执行单元测试..."\n466\tmvn test -Dtest="*Test" 2>&1 | tee "$REPORT_DIR/unit-test.log"\n467\tUNIT_TEST_STATUS=${PIPESTATUS[0]}\n468\t\n469\t# 步骤2: Cucumber测试\n470\techo "[2/6] 执行Cucumber场景测试..."\n471\tmvn verify -DskipUnitTests 2>&1 | tee "$REPORT_DIR/cucumber-test.log"\n472\tCUCUMBER_STATUS=${PIPESTATUS[0]}\n473\t\n474\t# 步骤3: 性能测试\n475\techo "[3/6] 执行性能测试..."\n476\tmvn test -Dtest="*Performance*" -DfailIfNoTests=false 2>&1 | tee "$REPORT_DIR/performance-test.log"\n477\t\n478\t# 步骤4: 远程API测试\n479\techo "[4/6] 执行远程API测试..."\n480\tif [ -f "tests/scripts/remote-api-test.sh" ]; then\n481\t bash tests/scripts/remote-api-test.sh 2>&1 | tee "$REPORT_DIR/remote-api-test.log"\n482\t # 🆕v4.8 对每个失败请求捕获失败原因(执行时直接捕获,不依赖日志事后解析)\n483\t # 捕获:HTTP状态码 + 响应体片段 / 连接错误(Connection refused/timeout/UnknownHost)\n484\t # 格式:HTTP {status}: {响应体片段} 或 {ErrorType}: {host:port},截断到200字符\n485\t # 写入「远程API测试结果」表「失败原因」列 + failure_reasons\n486\tfi\n487\t\n488\t# 步骤5: 前端E2E测试 🆕\n489\techo "[5/6] 执行前端E2E测试..."\n490\tif [ -f "frontend/e2e/package.json" ]; then\n491\t cd frontend/e2e\n492\t npx playwright test 2>&1 | tee "../$REPORT_DIR/e2e-test.log"\n493\t cd ../..\n494\tfi\n495\t\n496\t# 步骤6: 代码覆盖率 🆕\n497\techo "[6/6] 生成代码覆盖率报告..."\n498\tmvn jacoco:report 2>&1 | tee "$REPORT_DIR/coverage.log"\n499\t\n500\techo "========================================"\n501\techo "测试执行完成"\n502\techo "========================================"\n503\t```\n504\t\n505\t### 6.3 Python项目测试执行\n506\t\n507\t**执行脚本**:\n508\t```bash\n509\t#!/bin/bash\n510\t# test-runner.sh - Python测试执行脚本\n511\t\n512\tREPORT_DIR="test-results"\n513\tmkdir -p "$REPORT_DIR"\n514\t\n515\techo "========================================"\n516\techo "开始执行测试套件"\n517\techo "========================================"\n518\t\n519\t# 步骤1: 单元测试\n520\techo "[1/6] 执行单元测试..."\n521\tpytest tests/ -v --tb=short 2>&1 | tee "$REPORT_DIR/unit-test.log"\n522\t\n523\t# 步骤2: Cucumber测试\n524\techo "[2/6] 执行behave场景测试..."\n525\tbehave features/ -f pretty 2>&1 | tee "$REPORT_DIR/cucumber-test.log"\n526\t\n527\t# 步骤3: 性能测试\n528\techo "[3/6] 执行性能测试..."\n529\tif [ -f "performance/locustfile.py" ]; then\n530\t locust -f performance/locustfile.py --headless --users 10 --spawn-rate 1 \\\n531\t -t 10s 2>&1 | tee "$REPORT_DIR/performance-test.log"\n532\tfi\n533\t\n534\t# 步骤4: 远程API测试\n535\techo "[4/6] 执行远程API测试..."\n536\tif [ -f "tests/scripts/remote_api_test.py" ]; then\n537\t python tests/scripts/remote_api_test.py 2>&1 | tee "$REPORT_DIR/remote-api-test.log"\n538\t # 🆕v4.8 对每个失败请求捕获失败原因(执行时直接捕获,不依赖日志事后解析)\n539\t # 捕获:HTTP状态码 + 响应体片段 / 连接错误(Connection refused/timeout/UnknownHost)\n540\t # 格式:HTTP {status}: {响应体片段} 或 {ErrorType}: {host:port},截断到200字符\n541\t # 写入「远程API测试结果」表「失败原因」列 + failure_reasons\n542\tfi\n543\t\n544\t# 步骤5: 前端E2E测试 🆕\n545\techo "[5/6] 执行前端E2E测试..."\n546\tif [ -f "frontend/e2e/package.json" ]; then\n547\t cd frontend/e2e\n548\t npx playwright test 2>&1 | tee "../$REPORT_DIR/e2e-test.log"\n549\t cd ../..\n550\tfi\n551\t\n552\t# 步骤6: 代码覆盖率 🆕\n553\techo "[6/6] 生成代码覆盖率报告..."\n554\tpytest --cov=src --cov-report=html --cov-report=xml 2>&1 | tee "$REPORT_DIR/coverage.log"\n555\t\n556\techo "========================================"\n557\techo "测试执行完成"\n558\techo "========================================"\n559\t```\n560\t\n561\t### 6.4 Go项目测试执行 🆕\n562\t\n563\t**执行脚本**:\n564\t```bash\n565\t#!/bin/bash\n566\t# test-runner.sh - Go测试执行脚本\n567\t\n568\tREPORT_DIR="test-results"\n569\tmkdir -p "$REPORT_DIR"\n570\t\n571\techo "========================================"\n572\techo "开始执行测试套件"\n573\techo "========================================"\n574\t\n575\t# 步骤1: 单元测试\n576\techo "[1/6] 执行单元测试..."\n577\tgo test -v ./... 2>&1 | tee "$REPORT_DIR/unit-test.log"\n578\t\n579\t# 步骤2: godog测试\n580\techo "[2/6] 执行godog场景测试..."\n581\tgodog run --format=pretty 2>&1 | tee "$REPORT_DIR/cucumber-test.log"\n582\t\n583\t# 步骤3: 性能测试\n584\techo "[3/6] 执行性能测试..."\n585\tgo test -bench=. -benchmem ./... 2>&1 | tee "$REPORT_DIR/performance-test.log"\n586\t\n587\t# 步骤4: 远程API测试\n588\techo "[4/6] 执行远程API测试..."\n589\tif [ -f "tests/scripts/remote_api_test.go" ]; then\n590\t go run tests/scripts/remote_api_test.go 2>&1 | tee "$REPORT_DIR/remote-api-test.log"\n591\t # 🆕v4.8 对每个失败请求捕获失败原因(执行时直接捕获,不依赖日志事后解析)\n592\t # 捕获:HTTP状态码 + 响应体片段 / 连接错误(Connection refused/timeout/UnknownHost)\n593\t # 格式:HTTP {status}: {响应体片段} 或 {ErrorType}: {host:port},截断到200字符\n594\t # 写入「远程API测试结果」表「失败原因」列 + failure_reasons\n595\tfi\n596\t\n597\t# 步骤5: 前端E2E测试 🆕\n598\techo "[5/6] 执行前端E2E测试..."\n599\tif [ -f "frontend/e2e/package.json" ]; then\n600\t cd frontend/e2e\n601\t npx playwright test 2>&1 | tee "../$REPORT_DIR/e2e-test.log"\n602\t cd ../..\n603\tfi\n604\t\n605\t# 步骤6: 代码覆盖率 🆕\n606\techo "[6/6] 生成代码覆盖率报告..."\n607\tgo test -coverprofile=coverage.out ./...\n608\tgo tool cover -html=coverage.out -o coverage.html 2>&1 | tee "$REPORT_DIR/coverage.log"\n609\t\n610\techo "========================================"\n611\techo "测试执行完成"\n612\techo "========================================"\n613\t```\n614\t\n615\t---\n616\t\n617\t## 第6.5步:生成代码覆盖率报告 🆕\n618\t\n619\t### 6.5.1 Java项目 - JaCoCo\n620\t\n621\t**配置文件**:`.claude/skills/test-executor/templates/jacoco/jacoco.xml`\n622\t\n623\t**执行命令**:\n624\t```bash\n625\tmvn jacoco:report\n626\t```\n627\t\n628\t**报告路径**:\n629\t- HTML报告:`target/site/jacoco/index.html`\n630\t- XML报告:`target/site/jacoco/jacoco.xml`\n631\t\n632\t### 6.5.2 Python项目 - pytest-cov\n633\t\n634\t**执行命令**:\n635\t```bash\n636\tpytest --cov=src --cov-report=html --cov-report=xml\n637\t```\n638\t\n639\t**报告路径**:\n640\t- HTML报告:`htmlcov/index.html`\n641\t- XML报告:`coverage.xml`\n642\t\n643\t### 6.5.3 Go项目 - go test\n644\t\n645\t**执行命令**:\n646\t```bash\n647\tgo test -coverprofile=coverage.out ./...\n648\tgo tool cover -html=coverage.out -o coverage.html\n649\t```\n650\t\n651\t**报告路径**:\n652\t- HTML报告:`coverage.html`\n653\t\n654\t---\n655\t\n656\t### 6.5 Claude开发测试执行 🆕v3.7\n657\t\n658\t**触发条件**:`CLAUDE_DEV_NEEDED=true`(由test-code-generator第0.7步检测)\n659\t\n660\t**执行脚本**:\n661\t```bash\n662\t#!/bin/bash\n663\t# claude-test-runner.sh - Claude开发测试执行脚本\n664\t\n665\tset -eo pipefail\n666\t\n667\tREPORT_DIR="test-results/claude"\n668\tmkdir -p "$REPORT_DIR"\n669\t\n670\techo "========================================"\n671\techo "Claude开发测试执行"\n672\techo "========================================"\n673\t\n674\tCLAUDE_PRODUCT_PATH="$1" # 产物路径,如.claude/agents/xxx/xxx.md\n675\tCLAUDE_PRODUCT_TYPE="$2" # 产物类型:agent/skill/command\n676\t\n677\t# 步骤1: Prompt语法验证\n678\techo ""\n679\techo "[1/2] 执行Prompt语法验证..."\n680\t\n681\tPROMPT_VALIDATOR=".claude/dev-tools/claude-dev/prompt-validator.py"\n682\t\n683\tif [ ! -f "$PROMPT_VALIDATOR" ]; then\n684\t echo "❌ Prompt验证工具不存在: $PROMPT_VALIDATOR"\n685\t exit 1\n686\tfi\n687\t\n688\tpython3 "$PROMPT_VALIDATOR" --"$CLAUDE_PRODUCT_TYPE" "$CLAUDE_PRODUCT_PATH" 2>&1 | tee "$REPORT_DIR/prompt-validation.log"\n689\tPROMPT_STATUS=$?\n690\t\n691\tif [ $PROMPT_STATUS -eq 0 ]; then\n692\t echo "✅ Prompt语法验证通过"\n693\telse\n694\t echo "❌ Prompt语法验证失败"\n695\t echo "📄 请查看日志: $REPORT_DIR/prompt-validation.log"\n696\tfi\n697\t\n698\t# 步骤2: Agent调用测试(仅Agent类型)\n699\techo ""\n700\techo "[2/2] 执行Agent调用测试..."\n701\t\n702\tif [ "$CLAUDE_PRODUCT_TYPE" = "agent" ]; then\n703\t AGENT_TESTER=".claude/dev-tools/claude-dev/agent-tester.py"\n704\t\n705\t if [ ! -f "$AGENT_TESTER" ]; then\n706\t echo "⚠️ Agent测试工具不存在: $AGENT_TESTER"\n707\t echo "⚠️ 跳过Agent调用测试"\n708\t AGENT_STATUS=0\n709\t else\n710\t # 提取Agent名称\n711\t AGENT_NAME=$(basename "$CLAUDE_PRODUCT_PATH" .md)\n712\t\n713\t python3 "$AGENT_TESTER" --agent "$AGENT_NAME" 2>&1 | tee "$REPORT_DIR/agent-test.log"\n714\t AGENT_STATUS=$?\n715\t\n716\t if [ $AGENT_STATUS -eq 0 ]; then\n717\t echo "✅ Agent调用测试通过"\n718\t else\n719\t echo "❌ Agent调用测试失败"\n720\t echo "📄 请查看日志: $REPORT_DIR/agent-test.log"\n721\t fi\n722\t fi\n723\telse\n724\t echo "ℹ️ 非Agent类型,跳过调用测试"\n725\t AGENT_STATUS=0\n726\tfi\n727\t\n728\t# 汇总结果\n729\techo ""\n730\techo "========================================"\n731\techo "Claude开发测试结果"\n732\techo "========================================"\n733\t\n734\tif [ $PROMPT_STATUS -eq 0 ] && [ $AGENT_STATUS -eq 0 ]; then\n735\t echo "✅ 所有Claude测试通过"\n736\t CLAUDE_TEST_PASSED=true\n737\telse\n738\t echo "❌ 部分Claude测试失败"\n739\t CLAUDE_TEST_PASSED=false\n740\tfi\n741\t```\n742\t\n743\t### 6.6 Claude测试结果示例 🆕v3.7\n744\t\n745\t**Prompt验证成功示例**:\n746\t```\n747\t---\n748\t# Prompt语法验证报告\n749\t\n750\t**文件**: .claude/agents/development/claude-code-developer.md\n751\t**产物类型**: agent\n752\t**验证时间**: 2026-03-10 15:30:00\n753\t\n754\t## 验证结果\n755\t\n756\t| 检查项 | 状态 | 说明 |\n757\t|:------:|:----:|------|\n758\t| YAML头部格式 | [OK] | 解析成功 |\n759\t| 产物类型识别 | [OK] | agent |\n760\t| 必填字段 | [OK] | 完整 |\n761\t| 版本号格式 | [OK] | 正确 |\n762\t| Markdown语法 | [OK] | 正确 |\n763\t\n764\t**总体结果**: [PASS]\n765\t---\n766\t```\n767\t\n768\t**Agent测试成功示例**:\n769\t```\n770\t============================================================\n771\tClaude Agent 测试报告\n772\t============================================================\n773\t\n774\t总计: 1 | 通过: 1 | 失败: 0\n775\t\n776\t--- claude-code-developer [PASS] ---\n777\t File: .claude/agents/development/claude-code-developer.md\n778\t\n779\t============================================================\n780\t```\n781\t\n782\t---\n783\t\n784\t## 第6.5步:前端单元测试执行 🆕\n785\t\n786\t**触发条件**:`PROJECT_TYPE == "web-frontend"`\n787\t\n788\t### 6.5.1 检测项目环境\n789\t\n790\t```bash\n791\techo "========================================"\n792\techo "前端单元测试执行"\n793\techo "========================================"\n794\t\n795\t# 检测包管理器\n796\tif [ -f "pnpm-lock.yaml" ]; then\n797\t PKG_MANAGER="pnpm"\n798\t INSTALL_CMD="pnpm install"\n799\telif [ -f "yarn.lock" ]; then\n800\t PKG_MANAGER="yarn"\n801\t INSTALL_CMD="yarn install"\n802\telif [ -f "package-lock.json" ]; then\n803\t PKG_MANAGER="npm"\n804\t INSTALL_CMD="npm install"\n805\telse\n806\t PKG_MANAGER="npm"\n807\t INSTALL_CMD="npm install"\n808\tfi\n809\t\n810\techo "📌 包管理器: $PKG_MANAGER"\n811\t\n812\t# 检测测试框架\n813\tif grep -q \'"vitest"\' package.json; then\n814\t TEST_FRAMEWORK="vitest"\n815\t TEST_CMD="${PKG_MANAGER} run test:coverage"\n816\t echo "✅ 检测到Vitest测试框架"\n817\telif grep -q \'"jest"\' package.json; then\n818\t TEST_FRAMEWORK="jest"\n819\t TEST_CMD="${PKG_MANAGER} run test:coverage"\n820\t echo "✅ 检测到Jest测试框架"\n821\telse\n822\t echo "⚠️ 未检测到测试框架,跳过前端单元测试"\n823\t TEST_FRAMEWORK="none"\n824\tfi\n825\t```\n826\t\n827\t### 6.5.2 安装测试依赖\n828\t\n829\t```bash\n830\tif [ "$TEST_FRAMEWORK" != "none" ]; then\n831\t echo "========================================"\n832\t echo "📦 检查并安装测试依赖"\n833\t echo "========================================"\n834\t\n835\t # 检查node_modules是否存在\n836\t if [ ! -d "node_modules" ]; then\n837\t echo "📌 node_modules不存在,执行安装..."\n838\t $INSTALL_CMD\n839\t else\n840\t echo "✅ node_modules已存在,跳过安装"\n841\t fi\n842\tfi\n843\t```\n844\t\n845\t### 6.5.3 执行前端测试\n846\t\n847\t```bash\n848\tif [ "$TEST_FRAMEWORK" != "none" ]; then\n849\t echo "========================================"\n850\t echo "🚀 执行前端单元测试"\n851\t echo "========================================"\n852\t\n853\t # 创建测试结果目录\n854\t REPORT_DIR="test-results"\n855\t mkdir -p "$REPORT_DIR"\n856\t\n857\t # 执行测试\n858\t echo "📌 执行命令: $TEST_CMD"\n859\t $TEST_CMD 2>&1 | tee "$REPORT_DIR/frontend-unit-test.log"\n860\t TEST_EXIT_CODE=$?\n861\t\n862\t if [ $TEST_EXIT_CODE -eq 0 ]; then\n863\t echo "✅ 前端单元测试执行成功"\n864\t TEST_RESULT="passed"\n865\t else\n866\t echo "❌ 前端单元测试执行失败"\n867\t TEST_RESULT="failed"\n868\t fi\n869\tfi\n870\t```\n871\t\n872\t### 6.5.4 解析覆盖率报告\n873\t\n874\t```bash\n875\tif [ "$TEST_FRAMEWORK" != "none" ] && [ -f "coverage/coverage-summary.json" ]; then\n876\t echo "========================================"\n877\t echo "📊 解析覆盖率报告"\n878\t echo "========================================"\n879\t\n880\t # 读取覆盖率数据\n881\t COVERAGE_LINES=$(jq \'.total.lines.pct\' coverage/coverage-summary.json)\n882\t COVERAGE_BRANCHES=$(jq \'.total.branches.pct\' coverage/coverage-summary.json)\n883\t COVERAGE_FUNCTIONS=$(jq \'.total.functions.pct\' coverage/coverage-summary.json)\n884\t COVERAGE_STATEMENTS=$(jq \'.total.statements.pct\' coverage/coverage-summary.json)\n885\t\n886\t echo "📊 覆盖率报告:"\n887\t echo " - 行覆盖率: ${COVERAGE_LINES}%"\n888\t echo " - 分支覆盖率: ${COVERAGE_BRANCHES}%"\n889\t echo " - 函数覆盖率: ${COVERAGE_FUNCTIONS}%"\n890\t echo " - 语句覆盖率: ${COVERAGE_STATEMENTS}%"\n891\t\n892\t # 检查覆盖率阈值\n893\t THRESHOLD=70\n894\t if (( $(echo "$COVERAGE_LINES < $THRESHOLD" | bc -l) )); then\n895\t echo "⚠️ 行覆盖率低于阈值 ${THRESHOLD}%"\n896\t fi\n897\tfi\n898\t```\n899\t\n900\t### 6.5.5 统计测试用例\n901\t\n902\t```bash\n903\tif [ "$TEST_FRAMEWORK" != "none" ]; then\n904\t # 解析测试日志统计用例\n905\t if [ -f "$REPORT_DIR/frontend-unit-test.log" ]; then\n906\t # Vitest格式\n907\t PASSED_TESTS=$(grep -c "✓" "$REPORT_DIR/frontend-unit-test.log" 2>/dev/null || echo "0")\n908\t FAILED_TESTS=$(grep -c "✗\\|FAIL\\|Error:" "$REPORT_DIR/frontend-unit-test.log" 2>/dev/null || echo "0")\n909\t\n910\t echo ""\n911\t echo "📋 测试统计:"\n912\t echo " - 通过: $PASSED_TESTS"\n913\t echo " - 失败: $FAILED_TESTS"\n914\t echo " - 总计: $((PASSED_TESTS + FAILED_TESTS))"\n915\t fi\n916\tfi\n917\t```\n918\t\n919\t### 6.5.6 更新test-status.json\n920\t\n921\t```bash\n922\tif [ "$TEST_FRAMEWORK" != "none" ]; then\n923\t # 更新测试状态文件\n924\t STATUS_FILE="dev/active/${TASK_NAME}/test-status.json"\n925\t\n926\t if [ -f "$STATUS_FILE" ]; then\n927\t jq --arg result "$TEST_RESULT" \\\n928\t --arg lines "$COVERAGE_LINES" \\\n929\t --arg branches "$COVERAGE_BRANCHES" \\\n930\t --arg functions "$COVERAGE_FUNCTIONS" \\\n931\t --arg statements "$COVERAGE_STATEMENTS" \\\n932\t --arg passed "$PASSED_TESTS" \\\n933\t --arg failed "$FAILED_TESTS" \\\n934\t \'.frontendUnitTest = {\n935\t "status": $result,\n936\t "framework": "\'"$TEST_FRAMEWORK"\'",\n937\t "coverage": {\n938\t "lines": ($lines | tonumber),\n939\t "branches": ($branches | tonumber),\n940\t "functions": ($functions | tonumber),\n941\t "statements": ($statements | tonumber)\n942\t },\n943\t "passedCases": ($passed | tonumber),\n944\t "failedCases": ($failed | tonumber),\n945\t "executedAt": (now | todate)\n946\t }\' "$STATUS_FILE" > "${STATUS_FILE}.tmp" && mv "${STATUS_FILE}.tmp" "$STATUS_FILE"\n947\t\n948\t echo "✅ 已更新测试状态文件"\n949\t fi\n950\tfi\n951\t```\n952\t\n953\t### 6.5.7 输出格式\n954\t\n955\t```markdown\n956\t## ✅ 前端单元测试执行完成\n957\t\n958\t### 测试框架\n959\t- **框架**: {TEST_FRAMEWORK}\n960\t- **包管理器**: {PKG_MANAGER}\n961\t\n962\t### 执行结果\n963\t| 指标 | 值 |\n964\t|-----|---|\n965\t| **状态** | {TEST_RESULT} |\n966\t| **通过用例** | {PASSED_TESTS} |\n967\t| **失败用例** | {FAILED_TESTS} |\n968\t\n969\t### 覆盖率报告\n970\t| 类型 | 覆盖率 |\n971\t|-----|-------|\n972\t| 行覆盖率 | {COVERAGE_LINES}% |\n973\t| 分支覆盖率 | {COVERAGE_BRANCHES}% |\n974\t| 函数覆盖率 | {COVERAGE_FUNCTIONS}% |\n975\t| 语句覆盖率 | {COVERAGE_STATEMENTS}% |\n976\t\n977\t### 输出文件\n978\t- 📄 测试日志: test-results/frontend-unit-test.log\n979\t- 📊 覆盖率报告: coverage/\n980\t```\n981\t\n982\t---\n983\t\n984\t## 第7步:生成验证结果\n985\t\n986\t### 7.1 解析测试结果\n987\t\n988\t**解析JUnit测试报告**:\n989\t```bash\n990\t# 解析JUnit XML报告\n991\tUNIT_TEST_RESULTS=$(find target/surefire-reports -name "TEST-*.xml" 2>/dev/null)\n992\tUNIT_TEST_PASSED=0\n993\tUNIT_TEST_FAILED=0\n994\tUNIT_TEST_TOTAL=0\n995\t\n996\tfor xml_file in $UNIT_TEST_RESULTS; do\n997\t TESTS=$(xmllint --xpath "string(//testsuite/@tests)" "$xml_file" 2>/dev/null)\n998\t FAILURES=$(xmllint --xpath "string(//testsuite/@failures)" "$xml_file" 2>/dev/null)\n999\t ERRORS=$(xmllint --xpath "string(//testsuite/@errors)" "$xml_file" 2>/dev/null)\n1000\t\n1001\t UNIT_TEST_TOTAL=$((UNIT_TEST_TOTAL + TESTS))\n1002\t UNIT_TEST_FAILED=$((UNIT_TEST_FAILED + FAILURES + ERRORS))\n1003\tdone\n1004\t\n1005\tUNIT_TEST_PASSED=$((UNIT_TEST_TOTAL - UNIT_TEST_FAILED))\n1006\t```\n1007\t\n1008\t**解析Cucumber JSON报告**:\n1009\t```bash\n1010\t# 解析Cucumber JSON报告\n1011\tCUCUMBER_REPORT="target/cucumber-reports.json"\n1012\tCUCUMBER_SCENARIOS=$(jq \'.[].elements | length\' "$CUCUMBER_REPORT" 2>/dev/null | awk \'{sum+=$1} END {print sum}\')\n1013\tCUCUMBER_PASSED=$(jq \'[.[].elements[] | select(.status=="passed")] | length\' "$CUCUMBER_REPORT" 2>/dev/null)\n1014\tCUCUMBER_FAILED=$(jq \'[.[].elements[] | select(.status=="failed")] | length\' "$CUCUMBER_REPORT" 2>/dev/null)\n1015\t```\n1016\t\n1017\t### 7.1.2 提取失败用例的失败原因 🆕v4.8\n1018\t\n1019\t**目标**:为每条失败用例提取关键摘要形式的 failure_reason,供 test-report「未通过测试用例清单」的「失败原因」列填充。现状(v4.7)只提取通过/失败计数,不提取失败原因,导致下游报告失败原因列恒为空。\n1020\t\n1021\t**提取规则**(按测试类型):\n1022\t\n1023\t| 测试类型 | 数据来源 | 提取内容 | failure_reason 格式 |\n1024\t|---------|---------|---------|---------------------|\n1025\t| 单元测试 | JUnit XML `` / `` | 异常类型 + message 首行 | `{ExceptionType}: {首行消息}` |\n1026\t| Cucumber | JSON `error_message` 字段 | 首行 | `{ErrorType}: {首行消息}` |\n1027\t| 远程API测试 | 执行时捕获(见6.2步骤4,不依赖日志文件事后解析) | HTTP状态码+响应体片段 / 连接错误 | `HTTP {status}: {响应体片段}` 或 `{ErrorType}: {host:port}` |\n1028\t| 前端E2E | e2e-test.log 失败行 | 错误首行 | `{ErrorType}: {首行消息}` |\n1029\t\n1030\t**格式化要求**:\n1031\t- 截断到 ~200 字符,保留异常类型 + 首行消息\n1032\t- 通过的用例不提取(failure_reason 留空或填 `-`)\n1033\t- 示例:\n1034\t - `AssertionError: expected [200] but found [500]`\n1035\t - `HTTP 500: {"error":"disk full"}`\n1036\t - `Connection refused: 10.0.0.1:8080`\n1037\t - `NullPointerException: Cannot invoke method on null object`\n1038\t\n1039\t**输出**:每条失败用例生成 `{case_id, reason}`,汇总为 failure_reasons 列表,同时写入「详细测试结果」表「失败原因」列(见7.2报告模板)和结构化输出 failure_reasons 字段(见上方结构化输出要求)。\n1040\t\n1041\t```bash\n1042\t# 提取JUnit失败用例的failure_reason\n1043\t# 从 target/surefire-reports/TEST-*.xml 的 / 提取异常类型+首行,截断到200字符\n1044\tfor xml_file in $UNIT_TEST_RESULTS; do\n1045\t xmllint --xpath \'//testcase[failure or error]\' "$xml_file" 2>/dev/null\n1046\tdone\n1047\t\n1048\t# 提取Cucumber失败场景的error_message首行\n1049\tjq \'[.[].elements[] | select(.status=="failed") | {case_id: .name, reason: ((.error_message // "unknown") | split("\\n")[0])}]\' \\\n1050\t "$CUCUMBER_REPORT" 2>/dev/null\n1051\t```\n1052\t\n1053\t### 7.1.5 解析Claude测试结果 🆕v3.7\n1054\t\n1055\t**解析Prompt验证报告**:\n1056\t```bash\n1057\t# 解析prompt-validator.py输出\n1058\tPROMPT_REPORT="test-results/claude/prompt-validation.log"\n1059\t\n1060\tif grep -q "总体结果.*PASS" "$PROMPT_REPORT"; then\n1061\t PROMPT_PASSED=1\n1062\telse\n1063\t PROMPT_PASSED=0\n1064\tfi\n1065\t```\n1066\t\n1067\t**解析Agent测试报告**:\n1068\t```bash\n1069\t# 解析agent-tester.py输出\n1070\tAGENT_REPORT="test-results/claude/agent-test.log"\n1071\t\n1072\tif [ -f "$AGENT_REPORT" ]; then\n1073\t AGENT_PASSED=$(grep -c "PASS" "$AGENT_REPORT" || echo 0)\n1074\t AGENT_FAILED=$(grep -c "FAIL" "$AGENT_REPORT" || echo 0)\n1075\telse\n1076\t AGENT_PASSED=0\n1077\t AGENT_FAILED=0\n1078\tfi\n1079\t```\n1080\t\n1081\t**Claude测试汇总**:\n1082\t```bash\n1083\tCLAUDE_TOTAL=$((PROMPT_PASSED + AGENT_PASSED + PROMPT_FAILED + AGENT_FAILED))\n1084\tCLAUDE_STATUS=$([ $PROMPT_PASSED -eq 1 ] && [ $AGENT_FAILED -eq 0 ] && echo "通过" || echo "失败")\n1085\t```\n1086\t\n1087\t### 7.2 生成验证结果报告\n1088\t\n1089\t**报告模板(传统代码开发)**:\n1090\t```markdown\n1091\t# {需求名} 自动化测试验证结果\n1092\t\n1093\t## 测试概览\n1094\t\n1095\t| 项目 | 值 |\n1096\t|-----|-----|\n1097\t| **测试时间** | {timestamp} |\n1098\t| **项目类型** | {Java/Python/Go} |\n1099\t| **执行模式** | 标准模式 / 全量回归模式 |\n1100\t\n1101\t## 测试结果汇总\n1102\t\n1103\t| 测试类型 | 总数 | 通过 | 失败 | 通过率 |\n1104\t|---------|:----:|:----:|:----:|:------:|\n1105\t| 单元测试 | {total} | ✅ {passed} | ❌ {failed} | {rate}% |\n1106\t| Cucumber测试 | {total} | ✅ {passed} | ❌ {failed} | {rate}% |\n1107\t| 性能测试 | {total} | ✅ {passed} | ❌ {failed} | {rate}% |\n1108\t| 远程API测试 | {total} | ✅ {passed} | ❌ {failed} | {rate}% |\n1109\t| 前端E2E测试 | {total} | ✅ {passed} | ❌ {failed} | {rate}% |\n1110\t| **总计** | **{total}** | **✅ {passed}** | **❌ {failed}** | **{rate}%** |\n1111\t\n1112\t**报告模板**:\n1113\t```markdown\n1114\t# {需求名} 自动化测试验证结果\n1115\t\n1116\t## 测试概览\n1117\t\n1118\t| 项目 | 值 |\n1119\t|-----|-----|\n1120\t| **测试时间** | {timestamp} |\n1121\t| **项目类型** | {Java/Python/Go} |\n1122\t| **执行模式** | 标准模式 / 全量回归模式 |\n1123\t\n1124\t## 测试结果汇总\n1125\t\n1126\t| 测试类型 | 总数 | 通过 | 失败 | 通过率 |\n1127\t|---------|:----:|:----:|:----:|:------:|\n1128\t| 单元测试 | {total} | ✅ {passed} | ❌ {failed} | {rate}% |\n1129\t| Cucumber测试 | {total} | ✅ {passed} | ❌ {failed} | {rate}% |\n1130\t| 性能测试 | {total} | ✅ {passed} | ❌ {failed} | {rate}% |\n1131\t| 远程API测试 | {total} | ✅ {passed} | ❌ {failed} | {rate}% |\n1132\t| 前端E2E测试 | {total} | ✅ {passed} | ❌ {failed} | {rate}% |\n1133\t| **总计** | **{total}** | **✅ {passed}** | **❌ {failed}** | **{rate}%** |\n1134\t\n1135\t## 代码覆盖率 🆕\n1136\t\n1137\t| 指标 | 值 | 说明 |\n1138\t|-----|-----|------|\n1139\t| 指令覆盖率 | {instruction}% | 代码指令执行比例 |\n1140\t| 分支覆盖率 | {branch}% | 条件分支覆盖比例 |\n1141\t| 行覆盖率 | {line}% | 代码行覆盖比例 |\n1142\t| 方法覆盖率 | {method}% | 方法覆盖比例 |\n1143\t| 类覆盖率 | {class}% | 类覆盖比例 |\n1144\t\n1145\t**覆盖率报告路径**:`{coverage_report_path}`\n1146\t\n1147\t## 详细测试结果\n1148\t\n1149\t### 1. 单元测试结果\n1150\t\n1151\t| 测试类 | 测试方法 | 状态 | 耗时 | 失败原因 |\n1152\t|-------|---------|:----:|-----:|---------|\n1153\t| {TestClass} | {testMethod} | ✅/❌ | {ms} | {failure_reason或-} 🆕v4.8 |\n1154\t\n1155\t### 2. Cucumber场景测试结果\n1156\t\n1157\t| Feature | Scenario | 状态 | 耗时 | 失败原因 |\n1158\t|--------|---------|:----:|-----:|---------|\n1159\t| {Feature} | {Scenario} | ✅/❌ | {ms} | {failure_reason或-} 🆕v4.8 |\n1160\t\n1161\t### 3. 性能测试结果\n1162\t\n1163\t| 测试场景 | 目标值 | 实际值 | 状态 | 说明 | 失败原因 |\n1164\t|---------|-------|-------|:----:|-----|---------|\n1165\t| {场景} | {target} | {actual} | ✅/❌ | {description} | {failure_reason或-} 🆕v4.8 |\n1166\t\n1167\t### 4. 远程API测试结果\n1168\t\n1169\t| API用例 | 端点 | 状态 | 响应时间 | 失败原因 |\n1170\t|--------|-----|:----:|---------:|---------|\n1171\t| {用例} | {endpoint} | ✅/❌ | {ms} | {failure_reason或-} 🆕v4.8 |\n1172\t\n1173\t### 5. 前端E2E测试结果 🆕\n1174\t\n1175\t| 测试用例 | 页面 | 状态 | 耗时 | 失败原因 |\n1176\t|---------|-----|:----:|-----:|---------|\n1177\t| {用例} | {page} | ✅/❌ | {ms} | {failure_reason或-} 🆕v4.8 |\n1178\t\n1179\t---\n1180\t\n1181\t### 7.2a Claude测试报告模板 🆕v3.7\n1182\t\n1183\t**Claude开发模式报告**:\n1184\t```markdown\n1185\t# {需求名} Claude验证报告\n1186\t\n1187\t## 验证概览\n1188\t\n1189\t| 项目 | 值 |\n1190\t|-----|-----|\n1191\t| **验证时间** | {timestamp} |\n1192\t| **Claude产物类型** | {Agent/Skill/Command} |\n1193\t| **产物路径** | {.claude/agents/xxx/xxx.md} |\n1194\t| **验证模式** | Claude开发模式 |\n1195\t\n1196\t## 验证结果汇总\n1197\t\n1198\t| 测试类型 | 总数 | 通过 | 失败 | 通过率 |\n1199\t|---------|:----:|:----:|:----:|:------:|\n1200\t| Prompt语法验证 | 1 | ✅ {prompt_status} | ❌ {prompt_failed} | {rate}% |\n1201\t| Agent调用测试 | {agent_total} | ✅ {agent_passed} | ❌ {agent_failed} | {rate}% |\n1202\t| **总计** | **{total}** | **✅ {passed}** | **❌ {failed}** | **{rate}%** |\n1203\t\n1204\t## 详细验证结果\n1205\t\n1206\t### 1. Prompt语法验证\n1207\t\n1208\t| 检查项 | 状态 | 说明 |\n1209\t|:------:|:----:|------|\n1210\t| YAML头部格式 | ✅/❌ | {description} |\n1211\t| 产物类型识别 | ✅/❌ | {description} |\n1212\t| 必填字段 | ✅/❌ | {description} |\n1213\t| 版本号格式 | ✅/❌ | {description} |\n1214\t| Markdown语法 | ✅/❌ | {description} |\n1215\t\n1216\t**总体结果**: {PASS/FAIL}\n1217\t\n1218\t### 2. Agent调用测试(仅Agent类型)\n1219\t\n1220\t| 测试项 | 状态 | 说明 |\n1221\t|-------|:----:|------|\n1222\t| Agent加载 | ✅/❌ | {description} |\n1223\t| 调用兼容性 | ✅/❌ | {description} |\n1224\t| 输出格式 | ✅/❌ | {description} |\n1225\t\n1226\t**总体结果**: {PASS/FAIL}\n1227\t\n1228\t---\n1229\t\n1230\t## 验证结论\n1231\t\n1232\t{根据测试结果给出验证结论和建议}\n1233\t\n1234\t---\n1235\t\n1236\t```\n1237\t\n1238\t## 缺陷详细报告\n1239\t\n1240\t### 缺陷统计\n1241\t\n1242\t| 严重程度 | 数量 | 占比 | 状态 |\n1243\t|---------|:----:|:----:|:----:|\n1244\t| 🔴 P0 阻塞性 | {p0_count} | {p0_percent}% | ❌ |\n1245\t| 🟠 P1 严重 | {p1_count} | {p1_percent}% | ❌ |\n1246\t| 🟡 P2 一般 | {p2_count} | {p2_percent}% | ⚠️ |\n1247\t| 🟢 P3 轻微 | {p3_count} | {p3_percent}% | ℹ️ |\n1248\t\n1249\t### 缺陷详情\n1250\t\n1251\t| ID | 严重程度 | Feature | 场景 | 错误信息 |\n1252\t|----|:--------:|---------|------|---------|\n1253\t| {n} | 🔴 P0 | {Feature} | {Scenario} | {error} |\n1254\t\n1255\t## 测试结论\n1256\t\n1257\t### 测试结论\n1258\t\n1259\t- [ ] ✅ **通过**:所有测试通过,可以发版\n1260\t- [ ] ❌ **失败**:存在阻塞性缺陷,需要修复后重测\n1261\t- [ ] ⚠️ **有风险**:存在非阻塞性缺陷,评估风险后决定\n1262\t\n1263\t### 建议\n1264\t\n1265\t{基于测试结果的建议}\n1266\t```\n1267\t\n1268\t---\n1269\t\n1270\t## 质量标准\n1271\t\n1272\t### 测试执行必须满足:\n1273\t\n1274\t| 标准 | 说明 |\n1275\t|-----|------|\n1276\t| **完整性** | 所有类型的测试都必须执行 |\n1277\t| **准确性** | 测试结果必须准确反映实际状态 |\n1278\t| **可追溯** | 测试结果必须可追溯到具体测试用例 |\n1279\t| **有报告** | 必须生成完整的测试验证结果报告 |\n1280\t\n1281\t---\n1282\t\n1283\t## 注意事项\n1284\t\n1285\t1. **编译验证**:执行测试前必须先验证项目可编译\n1286\t2. **测试存在性检查**:执行前必须检查测试类是否存在\n1287\t3. **错误处理**:测试失败不应阻断后续测试执行\n1288\t4. **报告生成**:无论测试结果如何,都必须生成完整报告\n1289\t5. **覆盖率要求**:建议代码覆盖率不低于80%\n1290\t\n1291\t---\n1292\t\n1293\t## 输出示例\n1294\t\n1295\t```markdown\n1296\t# 自动化测试验证结果\n1297\t\n1298\t## 测试概览\n1299\t\n1300\t| 项目 | 值 |\n1301\t|-----|-----|\n1302\t| **测试时间** | 2026-03-10 14:30:00 |\n1303\t| **项目类型** | Java |\n1304\t\n1305\t## 测试结果汇总\n1306\t\n1307\t| 测试类型 | 总数 | 通过 | 失败 | 通过率 |\n1308\t|---------|:----:|:----:|:----:|:------:|\n1309\t| 单元测试 | 25 | 24 | 1 | 96% |\n1310\t| Cucumber测试 | 10 | 10 | 0 | 100% |\n1311\t| 性能测试 | 3 | 3 | 0 | 100% |\n1312\t| **总计** | **38** | **37** | **1** | **97%** |\n1313\t\n1314\t## 测试结论\n1315\t\n1316\t✅ **通过**:大部分测试通过,存在1个非阻塞性缺陷\n1317\t```\n1318\t\n1319\t---\n1320\t\n1321\t## 🧬 Gene 召回机制(自进化注入)\n1322\t\n1323\t> 方案 D++++++ §14.7 + §13.4 + GEP测试阶段接入实施方案。本段落由 GEP(Gene Evolution Plan)驱动,执行前召回匹配 Gene 策略,执行后回流结果用于进化。\n1324\t\n1325\t### project_name 取值规则(三级优先级)\n1326\t\n1327\t调用 gep_recall/gep_record_outcome 时,project_name/project_path/version_id 按以下优先级取值:\n1328\t1. **Prompt 上下文显式字段**(【项目路径】【项目名】【版本ID】)—— stage-hooks 直接调度时有\n1329\t2. **调用方透传** —— 调用方若在 prompt/args 透传\n1330\t3. **cwd basename 兜底** —— 上述均无时:`project_name`=cwd 路径 basename,`project_path`=cwd,`version_id`=留空(MCP schema 中 version_id 可选)\n1331\t\n1332\t### 执行前:召回 Gene 策略\n1333\t\n1334\t在执行测试前,调用 clawrelay-api 召回匹配的 Gene 策略(通过 biz-sync MCP 工具 `gep_recall` 调用,或直接 curl):\n1335\t\n1336\t```bash\n1337\tcurl -X POST http://localhost:50009/gep/recall \\\n1338\t -H "Content-Type: application/json" \\\n1339\t -d \'{\n1340\t "skill_name": "test-executor",\n1341\t "project_name": "<项目路径basename,按取值规则>",\n1342\t "project_path": "<项目路径,按取值规则>",\n1343\t "version_id": "<版本ID,按取值规则,可为空>",\n1344\t "signals": ["test_execution", "run", "assert", "result"],\n1345\t "context": "自动化测试执行"\n1346\t }\'\n1347\t```\n1348\t\n1349\t将返回的 `strategy_segment` 段落注入本次测试执行流程(用 `` ... `` 标记),作为额外规范清单。\n1350\t\n1351\t**信号(signals)选择指南**(根据本次测试执行的特征选择):\n1352\t- `["test_execution", "run", "assert", "result"]` - 自动化测试执行(默认)\n1353\t- `["test_execution", "failure_reason", "retry", "event_type"]` - 失败原因与重试\n1354\t- `["test", "verify", "behavior"]` - 测试验证相关\n1355\t- `["analyze", "architecture", "execution_flow"]` - 架构分析相关\n1356\t\n1357\t**容错语义**(§17.3):gep_recall 超时(3s) → 返回空 Gene,正常执行(不阻塞)。\n1358\t\n1359\t### 执行后:回流结果\n1360\t\n1361\t测试执行完成后,必须调用 `gep_record_outcome` 回流结果(通过 biz-sync MCP 工具调用,或直接 curl):\n1362\t\n1363\t```bash\n1364\tcurl -X POST http://localhost:50009/gep/record_outcome \\\n1365\t -H "Content-Type: application/json" \\\n1366\t -d \'{\n1367\t "gene_id": "<召回的Gene ID,冷启动期为空>",\n1368\t "skill_name": "test-executor",\n1369\t "project_name": "<项目路径basename,按取值规则>",\n1370\t "project_path": "<项目路径,按取值规则>",\n1371\t "version_id": "<版本ID,按取值规则,可为空>",\n1372\t "success": ,\n1373\t "signals_found": [...],\n1374\t "fixes_applied": [...],\n1375\t "files_changed": [...]\n1376\t }\'\n1377\t```\n1378\t\n1379\t**容错语义**(§17.3):gep_record_outcome 超时(2s) → 丢弃,不阻塞返回(fail-open)。\n1380\t\n1381\t### 召回的 Gene 应用方式\n1382\t\n1383\t召回的 Gene 策略段落注入后,作为**额外规范清单**对待:\n1384\t- Gene 的 `strategy` 字段每一条作为测试执行规范(如"必须记录失败原因与 event_type")\n1385\t- Gene 的 `antiPatterns` 字段作为反向验证(如"禁止静默吞测试失败")\n1386\t\n1387\t若召回多个 Gene,按 `priority`(P0 > P1 > P2)排序后依次应用。\n1388\t'}] + +**AI**: +需要看第5.5步"代码与脚本合法性验证"的完整内容,确认它是否实际执行单元测试。... + + +## 交互记录 (2026-07-29T08:54:09.139Z) + +**用户**: +Caveat: The messages below were generated by the user while running local commands. DO NOT respond to these messages or otherwise consider them in your response unless the user explicitly asks you to. + +**AI**: +[思考] 现在我有了清晰的答案。让我梳理test-code-generator是否会执行单元测试: + +## 关键证据 + +### 1. SKILL 定位(第37行) +"你是基于Cucumber BDD的自动化测试代码生成专家,专注于**生成**可执行的测试代码。" +- 明确是"生成",不是"执行"。 + +### 2. 核心能力表(57-70行) +- "Cucumber场景测试 - 基于Feature文件**生成**BDD风格测试" +- "单元测试 - 为核心方法**生成**单元测试(含Mock)" +- "代码与脚本验证 - 编译验证+脚本语法检查(block模式)" +- 没有任何"执行单元测试"的能力描述。 + +### 3. 测试生成流程图(159-197行) +流程: ... -> U[第5步: 测试代码合并] -> V[第5.5步: 代码与脚本合法性验证] -> W{验证通过?} -> X[更新test-status.json] -> I[结束] +- 流程中没有"执行单元测试"步骤,5.5步是合法性验证,通过后直接更新test-status.json结束。 + +### 4. 第5.5步详细内容(2587-2943行) +验证范围明确: +- Java: `mvn test-compile -q` (编译,不是执行) +- Python: `python -m py_compile ` (语法检查) +- Go: `go build ./...` (编译) +- Shell: `bash -n ` (语法检查,明确写"不执行") +- JMeter: XML格式验证 +- Locust: `python -m py_compile` (语法检查) + +关键:`mvn test-compile` 是**编译测试代码**,不是`mvn test`(执行测试)。`bash -n`明确是"语法检查(不执行)"。 + +### 5. 第0.7步 Claude开发模式(1329-1333行) +"✅ 直接执行的内容(由test-executor完成)": +- prompt-validator.py +- agent-tester.py +- agent-behavior-tester.py +明确写"由test-executor完成"执行。 + +### 6. Stage 7 映射表(stage-hooks.md) +`7 | 测试执行 | test-code-generator(Skill)->test-executor(Skill)` +- 明确: test-code-generator 生成, test-executor 执行。两者串行,职责分离。 + +## 结论 + +**test-code-generator 不会执行单元测试。** 它只负责: +1. **生成**测试代码(Cucumber Step Definitions + Runner + 单元测试类 + 性能脚本 + 远程curl脚本) +2. **验证合法性**(编译验证 `mvn test-compile` / 语法检查 `bash -n` / `py_compile`),这是静态验证,不是运行测试 + +**真正执行单元测试的是 test-executor Skill**(Stage 7 的下游)。 + +唯一需要注意的细节:`mvn test-compile` 会编译测试代码到 target/test-classes,但不会运行测试。这是编译阶段,不是执行阶段。 + +我可以给出明确的答案了。这是一个事实查询,我已经读了实际文件,基于证据回答。不需要AskUserQuestion,不需要写文档,直接回答。 + +让我组织一个简洁、有据可查的回答。引用具体行号。... + + +## 交互记录 (2026-07-29T08:54:09.134Z) + +**用户**: +/exit + exit + + +**AI**: +不会。`test-code-generator` 只**生成**测试代码并做**编译/语法验证**,不执行单元测试。真正执行测试的是 `test-executor`。 + +## 证据(均来自 `test-code-generator/SKILL.md` 实际内容) + +**1. Skill 定位明确是"生成"**(SKILL.md:37) +> 你是基于Cucumber BDD的自动化测试代码生成专家,专注于**生成**可执行的测试代码。 + +**2. 核心能力表无"执行"项**(SKILL.md:57-70) +- 单元测试 → "为核心方法**生成**单元测试(含Mock)" +- 代码与脚本验证 → "**编译验证**+脚本语法检查(block模式)" +- 没有任何"执行/运行测试"的能力声明。 + +**3. 流程图终点是"更新 test-status.json -> 结束",没有运行测试步骤**(SKILL.md:182-196) +``` +第5步: 测试代码合并 → 第5.5步: 代码与脚本合法性验证 → 验证通过? → 更新test-status.json → 结束 +``` + +**4. 第5.5步的"验证"全是静态检查,不是运行测试**(SKILL.md:2595-2604) + +| 文件类型 | 验证命令 | 性质 | +|---------|---------|------| +| Java | `mvn test-compile -q` | **编译**测试代码(非 `mvn test`) | +| Python | `python -m py_compile ` | 语法检查 | +| Go | `go build ./...` | 编译 | +| Shell | `bash -n ` | 语法检查(SKILL.md:2714 明确写"不执行") | +| JMeter | XML 格式验证 | 静态校验 | + +关键区别:`mvn test-compile` 只把测试代码编译到 `target/test-classes`,**不会运行**任何 `@Test` 方法;`bash -n` 是纯语法解析。 + +**5. Claude 开发模式下也明确标注执行由 test-executor 完成**(SKILL.md:1329-1333) +> ✅ 直接执行的内容(**由 test-executor 完成**):prompt-validator.py / agent-tester.py / agent-behavior-tester.py + +**6. Stage 7 映射表体现职责分离**(`stage-hooks.md` 阶段Agent映射表) +> `7 | 测试执行 | test-code-generator(Skill) -> test-executor(Skill)` + +两者串行:`test-code-generator` 负责生成代码 + 编译验证,`test-executor` 负责真正跑测试并产出 `event_type`(test_passed/test_failed/bug_fixed)。 + +## 结论 + +| Skill | 职责 | 是否执行单元测试 | +|-------|------|:--------------:| +| `test-code-generator` | 生成 Cucumber/JUnit/pytest 代码 + 编译语法验证 | ❌ 否 | +| `test-executor` | 运行测试 + 产出 event_type | ✅ 是 | + +所以如果你看到 `mvn test-compile` 通过,那只代表测试代码"能编译通过",并不代表测试"跑过且通过"。真正跑测试发生在 Stage 7 下游的 `test-executor`。... + + +## 交互记录 (2026-07-29T08:54:09.134Z) + +**用户**: +Goodbye! + +**AI**: +[思考] 用户问 test-executor 是否只执行单元测试。我需要读 test-executor 的实际内容来回答,遵循 memory `verify-against-actual-agent-content`。 + +让我读 .claude/skills/test-executor/SKILL.md。... + diff --git a/docs/project-knowledge/sessions/agent_requirement-design_fd4df847/session_index.json b/docs/project-knowledge/sessions/agent_requirement-design_fd4df847/session_index.json new file mode 100644 index 0000000000000000000000000000000000000000..4d956be39b1db28d6c1ca4ea64175a082582e28a --- /dev/null +++ b/docs/project-knowledge/sessions/agent_requirement-design_fd4df847/session_index.json @@ -0,0 +1,6 @@ +{ + "session_id": "agent_requirement-design_fd4df847", + "start_time": "2026-07-27T09:22:25.393Z", + "rounds": 23, + "last_update": "2026-07-29T08:54:09.134Z" +} \ No newline at end of file diff --git a/docs/stage3-design-reuse-constraint-plan.md b/docs/stage3-design-reuse-constraint-plan.md new file mode 100644 index 0000000000000000000000000000000000000000..30b19791efea51223a8294fe394c4753b052e5cd --- /dev/null +++ b/docs/stage3-design-reuse-constraint-plan.md @@ -0,0 +1,147 @@ +# 设计阶段 5 个 des-xxx Agent 新增"存量代码与数据复用约束"改造方案 + +## 一、背景与决策 + +**问题**:代码开发阶段对简单需求过度设计——新增大量类/方法、db 不复用已有表而新建表。 + +**根因核查结论**(前 7 轮对话已确认): +- des-new-feature 第1步明确"从零设计、不复用现有业务组件"(:661-668),但这是**全新功能**的合理策略 → **不修改**。 +- 其余 5 个 des-xxx(enhance/fix-bug/optimize/refactor/integrate)**均无明确的"优先复用现有代码和 db"约束**;db 层 6 个 agent 普遍缺复用闸门。 +- 代码开发阶段 4 种后端语言 agent 的数据访问层术语不同:Java=Mapper/Repository(DAO)、Go=Repository、TypeScript=Repository(TypeORM)/Prisma、**Python 无 DAO 概念**(Service 直接操作 Model)。 + +**用户决策**: +- des-new-feature 保持不动(全新功能从零合理)。 +- 其余 5 个 agent 新增约束:"在不影响存量代码逻辑前提下,复用已有 service 和数据访问层代码;约束数据访问层即约束 db 设计"。 +- 约束术语按语言适配(Python 用 Model,不用 DAO)。 + +## 二、改造范围 + +| Agent | 改动 | 当前版本 | 目标版本 | +|---|---|---|---| +| des-new-feature | ❌ 不修改 | 4.10 | 4.10 | +| des-enhance-feature | ✅ 新增约束(整合现有) | 4.10 | 4.11 | +| des-fix-bug | ✅ 新增约束 | 4.10 | 4.11 | +| des-optimize | ✅ 新增约束 | 4.10 | 4.11 | +| des-refactor | ✅ 新增约束 | 4.10 | 4.11 | +| des-integrate | ✅ 新增约束 | 4.10 | 4.11 | + +版本天花板:current_version 4.10 → 4.11(5 个 agent 已达天花板 4.10,修改必须提天花板)。 + +## 三、统一约束文本(插入 5 个 agent) + +插入位置:每个 agent 的 `## 设计流程` 章节之前(即 `## 📝 代码边界规则` 章节之后)。 + +插入锚点行号(`## 设计流程` 所在行,在其前插入): +- des-enhance-feature: :340 +- des-fix-bug: :403 +- des-optimize: :339 +- des-integrate: :507 +- des-refactor: :446 + +**约束章节内容**(统一模板,仅开头"{类型说明}"按 agent 替换): + +```markdown +## 🚨 存量代码与数据复用约束(P0级强制执行) + +> 适用范围:本 Agent 处理的需求均为基于存量系统的{类型说明},必须在不影响存量代码逻辑的前提下,优先复用已有的业务层与数据访问层代码,避免过度新建类/方法/表。 +> 注:全新功能(NEW,由 des-new-feature 处理)从零设计,不受本约束限制。 + +### 1. 业务层(Service)复用 +- ✅ 优先在现有 Service 中扩展方法(不修改现有方法签名与行为),仅当现有 Service 无法承载时才新增 Service。 +- ❌ 禁止为可用现有方法承载的需求新建重复 Service。 + +### 2. 数据访问层复用(按项目技术栈选用术语) +| 语言 | 数据访问层 | 复用要求 | +|---|---|---| +| Java | Mapper(MyBatis)/Repository(JPA) | 复用现有 Mapper/Repository,不新建访问已有表的 DAO | +| Go | Repository | 复用现有 Repository | +| TypeScript | Repository(TypeORM)/Prisma | 复用现有 Repository/Prisma Service | +| Python | Model(SQLAlchemy)(无独立DAO层,Service直接操作Model) | 复用现有 Model,不新建映射已有表的 Model | + +⚠️ **约束数据访问层即约束 db 设计**:访问已有表的代码必须复用,不得新建重复的数据访问实现或重复的表映射。 + +### 3. db 设计复用 +- ✅ 新增表前必须评估是否可复用/扩展现有表(加字段优先于建新表)。 +- ✅ 确需新建表时,须在设计文档中说明无法复用现有表的理由。 +- ❌ 禁止为可由现有表承载的数据新建重复表。 + +### 4. 复用决策记录 +- 设计文档须列出"复用决策表":现有资产(Service / 数据访问层 / 表)→ 复用 / 扩展 / 新建 → 理由。 +- 涉及复用判定的关键决策,通过 AskUserQuestion 与用户确认(设计阶段为主会话,可交互)。 +``` + +**类型说明替换**: +- des-enhance-feature:功能增强 +- des-fix-bug:缺陷修复 +- des-optimize:性能/代码优化 +- des-refactor:架构重构 +- des-integrate:系统集成 + +## 四、各 agent 额外改动 + +### 1. frontmatter 版本升级(5 个 agent 统一) +- `version: 4.10` → `version: 4.11` +- `last_updated: 2026-07-16` → `2026-07-17` +- changelog 顶部新增: + ``` + v4.11 - 2026-07-17 + - 🚨 P0新增「存量代码与数据复用约束」章节:不影响存量前提下优先复用已有 Service 与数据访问层;约束数据访问层即约束 db 设计;新增表前评估复用现有表 + - 数据访问层术语按语言适配(Java=Mapper/Repository, Go/TypeScript=Repository, Python=Model,Python 无 DAO 概念) + ``` + +### 2. des-enhance-feature 整合(避免与现有约束冲突/重复) +des-enhance 现有约束保留(作为 ENHANCE 类型的步骤细化,与新 P0 总纲一致、互为补充): +- :730-732 第4步"在现有Service添加新方法、不修改签名" → 保留 +- :761 第2.5步"复用现有Adapter" → 保留(外部依赖维度,与新约束的数据访问层维度不重叠) +- :818 第5步"数据模型变更(变更字段表格)" → 保留 + +在 des-enhance 新约束章节末尾追加一句衔接: +> 本约束与第4步设计策略(扩展现有 Service 不修改签名)、第2.5步(复用现有 Adapter)、第5步(数据模型变更)一致,互为补充。 + +## 五、版本管理流程(CLAUDE.md P0 强制) + +```bash +# 1. 提版本天花板 4.10 -> 4.11(5 个 agent 已达天花板,必须先提天花板) +python .claude/dev-tools/version-manager/release-init.py --version 4.11 + +# 2. 修改 5 个 agent 文件(Edit 新增约束章节 + frontmatter version/changelog) + +# 3. 批量升级修改的 agent 版本号(确认 5 个 agent -> 4.11) +python .claude/dev-tools/version-manager/batch-upgrade-changed.py --version 4.11 + +# 4. 同步版本锁文件 +python .claude/dev-tools/version-manager/sync-lock.py + +# 5. 合规性检查(必须通过:所有 agent 版本 <= current_version 4.11) +python .claude/dev-tools/version-compliance-checker/check.py + +# 6. 提交(触发 pre-commit-check-enhanced.py hook) +git add . && git commit -m "..." +``` + +## 六、验证清单 + +- [ ] 5 个 agent 均新增「存量代码与数据复用约束」章节,位置在「代码边界规则」后、「设计流程」前 +- [ ] 5 个 agent 约束文本的"{类型说明}"已正确替换 +- [ ] des-enhance 约束章节末尾有衔接句,现有 :730-732/:761/:818 未被删除 +- [ ] 5 个 agent frontmatter version=4.11,changelog 含 v4.11 条目 +- [ ] des-new-feature 未被修改(保持 4.10) +- [ ] release-init 4.11 后 current_version=4.11,status=development +- [ ] sync-lock.py 输出 5 个 des agent 版本=4.11,des-new-feature=4.10 +- [ ] version-compliance-checker/check.py 通过(无版本超天花板) +- [ ] git commit pre-commit hook 通过 + +## 七、风险与回滚 + +**风险**: +1. release-init 4.11 会将开发版本从 4.10 推进到 4.11。若 4.10 有未发布的正式变更,需先确认 4.10 是否需要正式 release。当前 status=development,4.10 未 released,release-init 4.11 直接推进开发版本,符合"按需升级"。 +2. des-enhance 新约束与现有 :730-732 措辞部分重叠(均讲"扩展现有 Service")。已通过"总纲+细化"定位处理,并在衔接句明确关系,不冲突。 +3. 约束文本含 4 语言术语表格,对单语言项目略显冗余,但保证 des-xxx(语言无关)通用性。可接受。 + +**回滚**:若改造有问题,`git revert` 本次 commit 即可恢复 5 个 agent 到 4.10。 + +## 八、不涉及 +- des-new-feature:不改(全新功能从零策略合理) +- 开发阶段 code-developer agent:不改(复用由设计文档约束传导,developer P0 忠于设计文档,设计文档含复用约束即生效) +- enforce-checklist.py:不适用(本任务改 agent prompt .md,非 Python 工具实施,无 spec doc / try-except) +- 模板联动更新:本次仅新增 agent 约束章节,不改模板字段结构,非 M/L 级模板变更,不触发模板联动