ai-dev-flow 3.10.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- ai_dev_flow/__init__.py +5 -0
- ai_dev_flow/__main__.py +6 -0
- ai_dev_flow/checkpoint.py +65 -0
- ai_dev_flow/cli.py +598 -0
- ai_dev_flow/config.py +404 -0
- ai_dev_flow/data/pipeline.yaml +193 -0
- ai_dev_flow/data/profiles/java-spring.yml +140 -0
- ai_dev_flow/data/recipes/steps/00-init-project.yaml +168 -0
- ai_dev_flow/data/recipes/steps/01-refine-requirement.yaml +117 -0
- ai_dev_flow/data/recipes/steps/02-analysis.yaml +97 -0
- ai_dev_flow/data/recipes/steps/03-design.yaml +91 -0
- ai_dev_flow/data/recipes/steps/03.5-decompose.yaml +120 -0
- ai_dev_flow/data/recipes/steps/05-build.yaml +72 -0
- ai_dev_flow/data/recipes/steps/06-review.yaml +115 -0
- ai_dev_flow/data/recipes/steps/07-delivery.yaml +76 -0
- ai_dev_flow/data/recipes/steps/task-template.yaml +74 -0
- ai_dev_flow/error_handler.py +122 -0
- ai_dev_flow/executor.py +406 -0
- ai_dev_flow/git_ops.py +187 -0
- ai_dev_flow/knowledge_accumulator.py +121 -0
- ai_dev_flow/logger.py +84 -0
- ai_dev_flow/sandbox.py +291 -0
- ai_dev_flow/semantic_summarizer.py +351 -0
- ai_dev_flow/snapshot.py +210 -0
- ai_dev_flow/state.py +87 -0
- ai_dev_flow/task_context.py +134 -0
- ai_dev_flow/task_graph.py +841 -0
- ai_dev_flow/task_state.py +151 -0
- ai_dev_flow/watchdog.py +120 -0
- ai_dev_flow-3.10.0.dist-info/METADATA +171 -0
- ai_dev_flow-3.10.0.dist-info/RECORD +35 -0
- ai_dev_flow-3.10.0.dist-info/WHEEL +5 -0
- ai_dev_flow-3.10.0.dist-info/entry_points.txt +2 -0
- ai_dev_flow-3.10.0.dist-info/licenses/LICENSE +21 -0
- ai_dev_flow-3.10.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
version: "1.0.0"
|
|
2
|
+
title: "阶段 3.5 - 任务拆分"
|
|
3
|
+
description: "将工程方案拆分为原子化的独立执行任务,每个任务可独立在新 AI 会话中执行"
|
|
4
|
+
instructions: |
|
|
5
|
+
你是任务拆分专家。基于已确认的工程方案,将实施工作拆分为原子化的独立任务。
|
|
6
|
+
|
|
7
|
+
拆分原则:
|
|
8
|
+
1. 每个任务必须足够小,能在 20-60 个 AI turn 内完成
|
|
9
|
+
2. 每个任务只做一个明确的事情(单一职责)
|
|
10
|
+
3. 任务之间通过文件依赖,不通过对话上下文
|
|
11
|
+
4. 基础设施层先于应用层,数据库变更加业务代码
|
|
12
|
+
5. 每个任务必须附带 context_notes——足够让一个全新 AI 会话理解要做什么
|
|
13
|
+
parameters:
|
|
14
|
+
- key: requirement
|
|
15
|
+
input_type: string
|
|
16
|
+
requirement: required
|
|
17
|
+
description: "精炼需求文件路径"
|
|
18
|
+
- key: input_analysis
|
|
19
|
+
input_type: string
|
|
20
|
+
requirement: required
|
|
21
|
+
description: "需求分析报告路径"
|
|
22
|
+
- key: input_plan
|
|
23
|
+
input_type: string
|
|
24
|
+
requirement: required
|
|
25
|
+
description: "工程方案路径"
|
|
26
|
+
- key: profile
|
|
27
|
+
input_type: string
|
|
28
|
+
requirement: required
|
|
29
|
+
description: "项目画像文件路径"
|
|
30
|
+
- key: project_root
|
|
31
|
+
input_type: string
|
|
32
|
+
requirement: required
|
|
33
|
+
description: "项目根目录"
|
|
34
|
+
- key: output_tasks
|
|
35
|
+
input_type: string
|
|
36
|
+
requirement: required
|
|
37
|
+
description: "任务文件输出路径 (YAML)"
|
|
38
|
+
prompt: |
|
|
39
|
+
阅读以下文档并扫描项目代码,将实施工作拆分为原子化任务,输出到 {{ output_tasks }}:
|
|
40
|
+
|
|
41
|
+
1. 需求文档:{{ requirement }}
|
|
42
|
+
2. 需求分析:{{ input_analysis }}
|
|
43
|
+
3. 工程方案:{{ input_plan }}
|
|
44
|
+
4. 项目画像:{{ profile }}
|
|
45
|
+
5. 扫描项目代码:{{ project_root }}
|
|
46
|
+
|
|
47
|
+
## 拆分原则
|
|
48
|
+
|
|
49
|
+
1. **原子性**:每个任务做一件事,有明确的输入和输出文件
|
|
50
|
+
2. **可控规模**:每个任务预计 20-60 个 AI turn
|
|
51
|
+
3. **依赖清晰**:用 depends_on 明确前置任务
|
|
52
|
+
4. **文件可传递**:列出 input_files(需要读取的文件)和 output_files(需要生成的文件)
|
|
53
|
+
5. **上下文自包含**:context_notes 必须足够详细,让新 AI 会话仅凭它就能理解该任务的全部意图和约束
|
|
54
|
+
6. **基础设施优先**:数据库 Schema、公共模块、配置变更先于业务逻辑
|
|
55
|
+
|
|
56
|
+
## 每个任务必须包含
|
|
57
|
+
|
|
58
|
+
- id: 唯一标识(如 task-db-schema, task-user-api)
|
|
59
|
+
- name: 中文任务名
|
|
60
|
+
- description: 具体做什么(1-2句话)
|
|
61
|
+
- category: infrastructure | backend-api | frontend | database | config | test
|
|
62
|
+
- estimated_turns: 预估 turns(20-60)
|
|
63
|
+
- priority: P0 | P1 | P2
|
|
64
|
+
- depends_on: 前置任务 ID 列表(可为空)
|
|
65
|
+
- input_files: 需要读取的现有文件路径(项目根目录的相对路径)
|
|
66
|
+
- output_files: 需要创建或修改的文件路径
|
|
67
|
+
- context_notes: 实现上下文说明(这是**最关键**的字段!必须包含:技术选型、关键约束、接口约定、与上下游的契约)
|
|
68
|
+
- reference_docs: 参考的设计文档名(如 "03-plan.md")
|
|
69
|
+
- parallel_group: 可并行组名(可选,独立任务使用相同组名表示可并行)
|
|
70
|
+
|
|
71
|
+
## 输出格式
|
|
72
|
+
|
|
73
|
+
将任务列表以 YAML 格式写入 {{ output_tasks }}:
|
|
74
|
+
|
|
75
|
+
```yaml
|
|
76
|
+
version: "1.0"
|
|
77
|
+
project: "项目名"
|
|
78
|
+
created_at: "当前ISO时间"
|
|
79
|
+
total_estimated_turns: <总和>
|
|
80
|
+
tasks:
|
|
81
|
+
- id: task-xxx
|
|
82
|
+
name: "任务名"
|
|
83
|
+
description: "具体描述"
|
|
84
|
+
category: backend-api
|
|
85
|
+
estimated_turns: 40
|
|
86
|
+
priority: P0
|
|
87
|
+
depends_on: []
|
|
88
|
+
parallel_group: "group1"
|
|
89
|
+
input_files:
|
|
90
|
+
- "src/main/resources/application.yml"
|
|
91
|
+
- "pom.xml"
|
|
92
|
+
output_files:
|
|
93
|
+
- "src/main/java/com/example/XxxService.java"
|
|
94
|
+
- "src/main/java/com/example/XxxController.java"
|
|
95
|
+
context_notes: |
|
|
96
|
+
详细实现说明:
|
|
97
|
+
- 技术选型:Spring Boot + MyBatis
|
|
98
|
+
- 关键约束:不能修改已有接口路径
|
|
99
|
+
- 接口约定:POST /api/v1/xxx,JSON 格式
|
|
100
|
+
reference_docs:
|
|
101
|
+
- "03-plan.md"
|
|
102
|
+
retry_limit: 2
|
|
103
|
+
timeout_minutes: 15
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## 完成后
|
|
107
|
+
|
|
108
|
+
输出:
|
|
109
|
+
```
|
|
110
|
+
=== 任务拆分完成 ===
|
|
111
|
+
任务总数: N
|
|
112
|
+
预估总 turns: M
|
|
113
|
+
P0 任务数: X
|
|
114
|
+
可并行组: [group1, group2]
|
|
115
|
+
```
|
|
116
|
+
extensions:
|
|
117
|
+
- type: builtin
|
|
118
|
+
name: developer
|
|
119
|
+
timeout: 600
|
|
120
|
+
bundled: true
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
version: "1.0.0"
|
|
2
|
+
title: "阶段 5 - 编译 + 测试验证"
|
|
3
|
+
description: "自动编译项目并运行现有测试"
|
|
4
|
+
instructions: |
|
|
5
|
+
你是一个构建验证工程师。
|
|
6
|
+
|
|
7
|
+
你的任务是在代码变更后自动编译项目,并运行现有测试用例。
|
|
8
|
+
确保代码可编译通过、现有功能不被破坏。
|
|
9
|
+
|
|
10
|
+
parameters:
|
|
11
|
+
- key: project_root
|
|
12
|
+
input_type: string
|
|
13
|
+
requirement: required
|
|
14
|
+
description: "项目根目录"
|
|
15
|
+
- key: profile
|
|
16
|
+
input_type: string
|
|
17
|
+
requirement: required
|
|
18
|
+
description: "项目画像文件路径"
|
|
19
|
+
- key: output_result
|
|
20
|
+
input_type: string
|
|
21
|
+
requirement: required
|
|
22
|
+
description: "构建结果输出路径"
|
|
23
|
+
|
|
24
|
+
prompt: |
|
|
25
|
+
基于以下信息执行编译和测试验证:
|
|
26
|
+
|
|
27
|
+
1. 项目代码仓库:{{ project_root }}
|
|
28
|
+
2. 项目画像:{{ profile }}
|
|
29
|
+
|
|
30
|
+
## 执行步骤
|
|
31
|
+
|
|
32
|
+
### 1. 编译
|
|
33
|
+
- 根据项目类型(从 profile.yml 读取)执行编译命令
|
|
34
|
+
- 如果 profile.yml 中有 build 命令,直接使用
|
|
35
|
+
- 如果 profile.yml 中没有,根据项目类型推测编译命令
|
|
36
|
+
|
|
37
|
+
### 2. 运行测试
|
|
38
|
+
- 如果 profile.yml 中有 test 命令,执行
|
|
39
|
+
- 如果没有 test 命令,搜索项目中现有的测试框架配置并尝试运行
|
|
40
|
+
- 如果找不到测试配置,记录"未找到测试,跳过"
|
|
41
|
+
|
|
42
|
+
### 3. 处理编译失败
|
|
43
|
+
- 如果编译失败,列出所有错误位置和原因
|
|
44
|
+
- 尝试修复编译错误(确保与工程方案一致的前提下)
|
|
45
|
+
- 如果修复后仍然失败,记录失败详情到 {{ output_result }},停止
|
|
46
|
+
|
|
47
|
+
## 输出
|
|
48
|
+
|
|
49
|
+
将结果写入 {{ output_result }}:
|
|
50
|
+
|
|
51
|
+
```markdown
|
|
52
|
+
# 构建验证结果
|
|
53
|
+
|
|
54
|
+
## 编译
|
|
55
|
+
- 状态:通过/失败
|
|
56
|
+
- 错误列表(如有):
|
|
57
|
+
- 文件:行号 - 错误信息
|
|
58
|
+
|
|
59
|
+
## 测试
|
|
60
|
+
- 状态:通过/失败/未运行
|
|
61
|
+
- 测试结果明细
|
|
62
|
+
|
|
63
|
+
## 总结
|
|
64
|
+
- 构建是否通过
|
|
65
|
+
- 是否可以进入下一阶段
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
extensions:
|
|
69
|
+
- type: builtin
|
|
70
|
+
name: developer
|
|
71
|
+
timeout: 600
|
|
72
|
+
bundled: true
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
version: "1.0.0"
|
|
2
|
+
title: "阶段 6 - 审查(代码 + 安全)"
|
|
3
|
+
description: "合并代码审查和安全审查,核对待办项"
|
|
4
|
+
instructions: |
|
|
5
|
+
你是一个代码审查 + 安全审查专家。
|
|
6
|
+
|
|
7
|
+
同时做代码审查和安全审查,一次性输出完整的审查报告。
|
|
8
|
+
不涉及文件修改,只做审查。
|
|
9
|
+
|
|
10
|
+
parameters:
|
|
11
|
+
- key: project_root
|
|
12
|
+
input_type: string
|
|
13
|
+
requirement: required
|
|
14
|
+
description: "项目根目录"
|
|
15
|
+
- key: requirement
|
|
16
|
+
input_type: string
|
|
17
|
+
requirement: required
|
|
18
|
+
description: "精炼后的需求文件路径"
|
|
19
|
+
- key: input_analysis
|
|
20
|
+
input_type: string
|
|
21
|
+
requirement: required
|
|
22
|
+
description: "需求分析报告路径"
|
|
23
|
+
- key: input_engineering_plan
|
|
24
|
+
input_type: string
|
|
25
|
+
requirement: required
|
|
26
|
+
description: "工程方案路径"
|
|
27
|
+
- key: input_change_list
|
|
28
|
+
input_type: string
|
|
29
|
+
requirement: required
|
|
30
|
+
description: "变更清单路径"
|
|
31
|
+
- key: input_build_result
|
|
32
|
+
input_type: string
|
|
33
|
+
requirement: required
|
|
34
|
+
description: "构建结果路径"
|
|
35
|
+
- key: profile
|
|
36
|
+
input_type: string
|
|
37
|
+
requirement: required
|
|
38
|
+
description: "项目画像文件路径"
|
|
39
|
+
- key: output_review
|
|
40
|
+
input_type: string
|
|
41
|
+
requirement: required
|
|
42
|
+
description: "审查报告输出路径"
|
|
43
|
+
|
|
44
|
+
prompt: |
|
|
45
|
+
基于以下文件进行审查:
|
|
46
|
+
|
|
47
|
+
1. 精炼需求:{{ requirement }}
|
|
48
|
+
2. 需求分析:{{ input_analysis }}
|
|
49
|
+
3. 工程方案:{{ input_engineering_plan }}
|
|
50
|
+
4. 变更清单:{{ input_change_list }}
|
|
51
|
+
5. 构建结果:{{ input_build_result }}
|
|
52
|
+
6. 项目画像:{{ profile }}
|
|
53
|
+
7. 项目代码仓库:{{ project_root }}
|
|
54
|
+
|
|
55
|
+
## 执行规则
|
|
56
|
+
|
|
57
|
+
1. 仅输出审查报告到 {{ output_review }},禁止修改任何项目源代码文件(.java/.py/.ts/.js/.go 等)。
|
|
58
|
+
2. 禁止编写任何源代码,只做审查分析。
|
|
59
|
+
3. 只做审查,输出报告。
|
|
60
|
+
|
|
61
|
+
## 审查内容
|
|
62
|
+
|
|
63
|
+
将结果写入 {{ output_review }},包含以下章节:
|
|
64
|
+
|
|
65
|
+
### A. 代码审查
|
|
66
|
+
|
|
67
|
+
#### A1. 变更与需求一致性
|
|
68
|
+
逐条核对变更清单中的每个修改是否对应需求文档中的功能点:
|
|
69
|
+
- [ ] 功能 A — 已实现/未实现/部分实现
|
|
70
|
+
- [ ] 功能 B — 已实现/未实现/部分实现
|
|
71
|
+
|
|
72
|
+
#### A2. 变更与工程方案一致性
|
|
73
|
+
核对实际代码变更是否与工程方案一致:
|
|
74
|
+
- [ ] 接口定义一致
|
|
75
|
+
- [ ] 数据模型一致
|
|
76
|
+
- [ ] 无未列入方案的变更
|
|
77
|
+
|
|
78
|
+
#### A3. 代码质量
|
|
79
|
+
- 编码规范一致性
|
|
80
|
+
- 命名规范
|
|
81
|
+
- 注释完整度
|
|
82
|
+
- 重复代码
|
|
83
|
+
|
|
84
|
+
### B. 安全审查
|
|
85
|
+
|
|
86
|
+
#### B1. 暴露面
|
|
87
|
+
- 新增接口是否有鉴权
|
|
88
|
+
- 是否有敏感信息泄露风险
|
|
89
|
+
- 是否有未授权访问路径
|
|
90
|
+
|
|
91
|
+
#### B2. 注入安全
|
|
92
|
+
- SQL 注入
|
|
93
|
+
- 命令注入
|
|
94
|
+
- XSS
|
|
95
|
+
|
|
96
|
+
#### B3. 凭据处理
|
|
97
|
+
- 密码/密钥是否硬编码
|
|
98
|
+
- 敏感配置是否泄露
|
|
99
|
+
|
|
100
|
+
#### B4. 风险等级
|
|
101
|
+
- critical(必须修复)
|
|
102
|
+
- high(强烈建议修复)
|
|
103
|
+
- medium(建议修复)
|
|
104
|
+
- low(可忽略)
|
|
105
|
+
|
|
106
|
+
### C. 总结
|
|
107
|
+
- 审查结论:通过/有条件通过/不通过
|
|
108
|
+
- 需要修复的问题列表
|
|
109
|
+
- 是否建议合并
|
|
110
|
+
|
|
111
|
+
extensions:
|
|
112
|
+
- type: builtin
|
|
113
|
+
name: developer
|
|
114
|
+
timeout: 600
|
|
115
|
+
bundled: true
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
version: "1.0.0"
|
|
2
|
+
title: "阶段 7 - 交付"
|
|
3
|
+
description: "输出变更清单,管线结束"
|
|
4
|
+
instructions: |
|
|
5
|
+
你是交付管理助手。
|
|
6
|
+
|
|
7
|
+
汇总全流程产出,输出简洁的交付清单。
|
|
8
|
+
不做代码修改。
|
|
9
|
+
|
|
10
|
+
parameters:
|
|
11
|
+
- key: requirement
|
|
12
|
+
input_type: string
|
|
13
|
+
requirement: required
|
|
14
|
+
description: "精炼后的需求文件路径"
|
|
15
|
+
- key: input_change_list
|
|
16
|
+
input_type: string
|
|
17
|
+
requirement: required
|
|
18
|
+
description: "变更清单路径"
|
|
19
|
+
- key: input_build_result
|
|
20
|
+
input_type: string
|
|
21
|
+
requirement: required
|
|
22
|
+
description: "构建结果路径"
|
|
23
|
+
- key: input_review
|
|
24
|
+
input_type: string
|
|
25
|
+
requirement: required
|
|
26
|
+
description: "审查报告路径"
|
|
27
|
+
- key: output_delivery
|
|
28
|
+
input_type: string
|
|
29
|
+
requirement: required
|
|
30
|
+
description: "交付清单输出路径"
|
|
31
|
+
|
|
32
|
+
prompt: |
|
|
33
|
+
基于以下文件生成交付清单:
|
|
34
|
+
|
|
35
|
+
1. 精炼需求:{{ requirement }}
|
|
36
|
+
2. 变更清单:{{ input_change_list }}
|
|
37
|
+
3. 构建结果:{{ input_build_result }}
|
|
38
|
+
4. 审查报告:{{ input_review }}
|
|
39
|
+
|
|
40
|
+
## 执行规则
|
|
41
|
+
|
|
42
|
+
1. 仅生成交付清单到 {{ output_delivery }},禁止编写任何源代码文件(.java/.py/.ts/.js/.go 等)。
|
|
43
|
+
2. 禁止修改项目中的任何文件(交付清单除外)。
|
|
44
|
+
|
|
45
|
+
## 输出
|
|
46
|
+
|
|
47
|
+
将交付清单写入 {{ output_delivery }}:
|
|
48
|
+
|
|
49
|
+
```markdown
|
|
50
|
+
# 交付清单
|
|
51
|
+
|
|
52
|
+
## 需求
|
|
53
|
+
(需求名称和简要说明)
|
|
54
|
+
|
|
55
|
+
## 变更文件
|
|
56
|
+
- 新增:N 个文件
|
|
57
|
+
- 修改:N 个文件
|
|
58
|
+
- 删除:N 个文件
|
|
59
|
+
|
|
60
|
+
## 构建验证
|
|
61
|
+
- 编译:通过/失败
|
|
62
|
+
- 测试:通过/失败/未运行
|
|
63
|
+
|
|
64
|
+
## 审查结论
|
|
65
|
+
- 代码审查:通过/有条件通过/不通过
|
|
66
|
+
- 安全审查:无风险/有风险(见报告)
|
|
67
|
+
|
|
68
|
+
## 待办(如有)
|
|
69
|
+
- [ ] 需要后续处理的遗留问题
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
extensions:
|
|
73
|
+
- type: builtin
|
|
74
|
+
name: developer
|
|
75
|
+
timeout: 300
|
|
76
|
+
bundled: true
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
version: "1.0.0"
|
|
2
|
+
title: "Task - {{ task_name }}"
|
|
3
|
+
description: "执行单个原子开发任务。仅依赖文件上下文,不依赖对话记忆。"
|
|
4
|
+
instructions: |
|
|
5
|
+
你正在执行一个独立的原子开发任务。
|
|
6
|
+
你拥有完成任务所需的全部上下文(已通过参数注入)。
|
|
7
|
+
不要超出任务范围。不要修改 output_files 之外的文件。
|
|
8
|
+
|
|
9
|
+
parameters:
|
|
10
|
+
- key: task_name
|
|
11
|
+
input_type: string
|
|
12
|
+
requirement: required
|
|
13
|
+
description: "任务名称"
|
|
14
|
+
- key: task_description
|
|
15
|
+
input_type: string
|
|
16
|
+
requirement: required
|
|
17
|
+
description: "任务描述"
|
|
18
|
+
- key: project_root
|
|
19
|
+
input_type: string
|
|
20
|
+
requirement: required
|
|
21
|
+
description: "项目根目录"
|
|
22
|
+
- key: profile
|
|
23
|
+
input_type: string
|
|
24
|
+
requirement: required
|
|
25
|
+
description: "项目画像文件路径"
|
|
26
|
+
- key: context_file
|
|
27
|
+
input_type: string
|
|
28
|
+
requirement: required
|
|
29
|
+
description: "完整的任务上下文文件路径"
|
|
30
|
+
|
|
31
|
+
prompt: |
|
|
32
|
+
## 你的任务:{{ task_name }}
|
|
33
|
+
|
|
34
|
+
{{ task_description }}
|
|
35
|
+
|
|
36
|
+
## 项目信息
|
|
37
|
+
|
|
38
|
+
项目根目录:{{ project_root }}
|
|
39
|
+
项目画像:{{ profile }}
|
|
40
|
+
|
|
41
|
+
## 执行规则
|
|
42
|
+
|
|
43
|
+
1. 首先读取 {{ context_file }},其中包含本任务的完整上下文(技术选型、约束、参考文档内容等)。
|
|
44
|
+
2. 只修改本任务指定的文件。不要修改任何其他文件。
|
|
45
|
+
3. 不要向用户提问。如有不确定的地方,记录下来并停止。
|
|
46
|
+
4. 不要做全局重构、批量重命名、或格式化清理。
|
|
47
|
+
5. 保持现有代码风格和命名习惯。
|
|
48
|
+
|
|
49
|
+
## 完成后
|
|
50
|
+
|
|
51
|
+
确认所有 output_files 已正确创建/修改后,**必须**在文件末尾追加以下段落,然后输出任务完成标记。
|
|
52
|
+
|
|
53
|
+
### 产出要求
|
|
54
|
+
|
|
55
|
+
在每个修改/创建的源代码文件末尾,追加 `## Key Decisions` 段落(作为注释),记录:
|
|
56
|
+
- 关键设计决策及原因
|
|
57
|
+
- 与现有代码的集成约定
|
|
58
|
+
- 需要注意的约束条件
|
|
59
|
+
|
|
60
|
+
### 任务完成标记
|
|
61
|
+
|
|
62
|
+
最后输出:
|
|
63
|
+
|
|
64
|
+
=== TASK COMPLETE ===
|
|
65
|
+
Task: {{ task_name }}
|
|
66
|
+
Files modified:
|
|
67
|
+
- path/to/file1 (变更摘要)
|
|
68
|
+
- path/to/file2 (变更摘要)
|
|
69
|
+
|
|
70
|
+
extensions:
|
|
71
|
+
- type: builtin
|
|
72
|
+
name: developer
|
|
73
|
+
timeout: 600
|
|
74
|
+
bundled: true
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
"""错误处理 - 4 选项交互。"""
|
|
2
|
+
|
|
3
|
+
import logging
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
from enum import Enum
|
|
6
|
+
|
|
7
|
+
logger = logging.getLogger("ai-dev-flow")
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class Action(Enum):
|
|
11
|
+
RETRY = "retry"
|
|
12
|
+
FIX = "fix"
|
|
13
|
+
NOTE_EXIT = "note_exit"
|
|
14
|
+
SKIP = "skip"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class TaskAction(Enum):
|
|
18
|
+
RETRY_TASK = "retry_task"
|
|
19
|
+
SKIP_TASK = "skip_task"
|
|
20
|
+
ABORT_GRAPH = "abort_graph"
|
|
21
|
+
NOTE_EXIT = "note_exit"
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
SEPARATOR = "=" * 60
|
|
25
|
+
|
|
26
|
+
ci_mode = False
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def set_ci_mode(enabled: bool) -> None:
|
|
30
|
+
global ci_mode
|
|
31
|
+
ci_mode = enabled
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def handle_error(ai_dev_dir: Path) -> Action:
|
|
35
|
+
"""显示错误菜单,返回用户选择的操作。"""
|
|
36
|
+
if ci_mode:
|
|
37
|
+
print("\n [CI] 阶段执行失败,自动跳过...")
|
|
38
|
+
return Action.SKIP
|
|
39
|
+
print()
|
|
40
|
+
print(SEPARATOR)
|
|
41
|
+
print(" 阶段执行失败")
|
|
42
|
+
print(SEPARATOR)
|
|
43
|
+
print()
|
|
44
|
+
print(" 1) retry — 原地重试该阶段")
|
|
45
|
+
print(" 2) fix — 手动修改后按任意键重试")
|
|
46
|
+
print(" 3) write note — 写说明笔记,保存并退出")
|
|
47
|
+
print(" 4) skip — 跳过该阶段,标记为完成")
|
|
48
|
+
print()
|
|
49
|
+
|
|
50
|
+
while True:
|
|
51
|
+
choice = input(" 选择 (1/2/3/4): ").strip()
|
|
52
|
+
|
|
53
|
+
if choice == "1":
|
|
54
|
+
return Action.RETRY
|
|
55
|
+
elif choice == "2":
|
|
56
|
+
input(" 修改完成后按 Enter 重试...")
|
|
57
|
+
return Action.RETRY
|
|
58
|
+
elif choice == "3":
|
|
59
|
+
note = input(" 写说明: ").strip()
|
|
60
|
+
if note:
|
|
61
|
+
note_path = ai_dev_dir / ".pipeline_note"
|
|
62
|
+
note_path.write_text(note, encoding="utf-8")
|
|
63
|
+
logger.info("笔记已保存,下次运行时会提示")
|
|
64
|
+
return Action.NOTE_EXIT
|
|
65
|
+
elif choice == "4":
|
|
66
|
+
confirm = input(" 确认跳过? 这会标记该阶段为已完成 (y/N): ").strip().lower()
|
|
67
|
+
if confirm == "y":
|
|
68
|
+
return Action.SKIP
|
|
69
|
+
else:
|
|
70
|
+
print(" 无效输入,请输入 1/2/3/4")
|
|
71
|
+
|
|
72
|
+
|
|
73
|
+
def handle_task_error(task_id: str, task_name: str, retries: int,
|
|
74
|
+
retry_limit: int, ai_dev_dir: Path) -> TaskAction:
|
|
75
|
+
"""任务级错误处理菜单。返回用户选择的操作。"""
|
|
76
|
+
if ci_mode:
|
|
77
|
+
if retries < retry_limit:
|
|
78
|
+
print(f"\n [CI] Task {task_id} 失败 ({retries}/{retry_limit}),自动重试...")
|
|
79
|
+
return TaskAction.RETRY_TASK
|
|
80
|
+
else:
|
|
81
|
+
print(f"\n [CI] Task {task_id} 失败 (已达上限),自动跳过...")
|
|
82
|
+
return TaskAction.SKIP_TASK
|
|
83
|
+
print()
|
|
84
|
+
print(SEPARATOR)
|
|
85
|
+
print(f" Task Failed: {task_name} ({task_id})")
|
|
86
|
+
print(f" Retries: {retries}/{retry_limit}")
|
|
87
|
+
print(SEPARATOR)
|
|
88
|
+
print()
|
|
89
|
+
if retries < retry_limit:
|
|
90
|
+
print(" 1) retry task — 重新执行此任务")
|
|
91
|
+
else:
|
|
92
|
+
print(" 1) retry task — (已达重试上限)")
|
|
93
|
+
print(" 2) skip task — 跳过此任务,继续后续")
|
|
94
|
+
print(" 3) abort — 终止任务图,保存进度")
|
|
95
|
+
print(" 4) write note — 写说明笔记并退出")
|
|
96
|
+
print()
|
|
97
|
+
|
|
98
|
+
while True:
|
|
99
|
+
choice = input(" 选择 (1/2/3/4): ").strip()
|
|
100
|
+
|
|
101
|
+
if choice == "1":
|
|
102
|
+
if retries >= retry_limit:
|
|
103
|
+
print(" 已达重试上限,请选择其他选项")
|
|
104
|
+
continue
|
|
105
|
+
return TaskAction.RETRY_TASK
|
|
106
|
+
elif choice == "2":
|
|
107
|
+
confirm = input(" 确认跳过? 该任务产出将缺失 (y/N): ").strip().lower()
|
|
108
|
+
if confirm == "y":
|
|
109
|
+
return TaskAction.SKIP_TASK
|
|
110
|
+
elif choice == "3":
|
|
111
|
+
confirm = input(" 确认终止任务图? (y/N): ").strip().lower()
|
|
112
|
+
if confirm == "y":
|
|
113
|
+
return TaskAction.ABORT_GRAPH
|
|
114
|
+
elif choice == "4":
|
|
115
|
+
note = input(" 写说明: ").strip()
|
|
116
|
+
if note:
|
|
117
|
+
note_path = ai_dev_dir / ".pipeline_note"
|
|
118
|
+
note_path.write_text(note, encoding="utf-8")
|
|
119
|
+
logger.info("笔记已保存")
|
|
120
|
+
return TaskAction.NOTE_EXIT
|
|
121
|
+
else:
|
|
122
|
+
print(" 无效输入,请输入 1/2/3/4")
|