@fitlab-ai/agent-infra 0.6.5 → 0.7.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (208) hide show
  1. package/README.md +51 -25
  2. package/README.zh-CN.md +49 -23
  3. package/bin/cli.ts +1 -1
  4. package/dist/bin/cli.js +1 -1
  5. package/dist/lib/builtin-tuis.js +45 -0
  6. package/dist/lib/defaults.json +4 -0
  7. package/dist/lib/init.js +65 -23
  8. package/dist/lib/prompt.js +49 -1
  9. package/dist/lib/sandbox/commands/create.js +4 -2
  10. package/dist/lib/sandbox/commands/enter.js +15 -4
  11. package/dist/lib/sandbox/commands/list-running.js +153 -0
  12. package/dist/lib/sandbox/commands/ls.js +24 -45
  13. package/dist/lib/sandbox/commands/rebuild.js +7 -13
  14. package/dist/lib/sandbox/commands/rm.js +2 -0
  15. package/dist/lib/sandbox/config.js +3 -0
  16. package/dist/lib/sandbox/image-prune.js +18 -0
  17. package/dist/lib/sandbox/index.js +2 -1
  18. package/dist/lib/sandbox/runtimes/ai-tools.dockerfile +10 -6
  19. package/dist/lib/sandbox/task-resolver.js +18 -0
  20. package/dist/lib/sandbox/tools.js +213 -8
  21. package/dist/lib/update.js +70 -18
  22. package/lib/builtin-tuis.ts +55 -0
  23. package/lib/defaults.json +4 -0
  24. package/lib/init.ts +97 -35
  25. package/lib/prompt.ts +54 -1
  26. package/lib/sandbox/commands/create.ts +10 -2
  27. package/lib/sandbox/commands/enter.ts +14 -4
  28. package/lib/sandbox/commands/list-running.ts +188 -0
  29. package/lib/sandbox/commands/ls.ts +28 -49
  30. package/lib/sandbox/commands/rebuild.ts +12 -14
  31. package/lib/sandbox/commands/rm.ts +3 -0
  32. package/lib/sandbox/config.ts +7 -0
  33. package/lib/sandbox/image-prune.ts +23 -0
  34. package/lib/sandbox/index.ts +2 -1
  35. package/lib/sandbox/runtimes/ai-tools.dockerfile +10 -6
  36. package/lib/sandbox/task-resolver.ts +23 -1
  37. package/lib/sandbox/tools.ts +248 -9
  38. package/lib/update.ts +85 -30
  39. package/package.json +1 -1
  40. package/templates/.agents/QUICKSTART.en.md +1 -1
  41. package/templates/.agents/QUICKSTART.zh-CN.md +1 -1
  42. package/templates/.agents/README.en.md +111 -2
  43. package/templates/.agents/README.zh-CN.md +111 -2
  44. package/templates/.agents/rules/create-issue.en.md +1 -1
  45. package/templates/.agents/rules/create-issue.github.en.md +1 -1
  46. package/templates/.agents/rules/create-issue.github.zh-CN.md +1 -1
  47. package/templates/.agents/rules/create-issue.zh-CN.md +1 -1
  48. package/templates/.agents/rules/issue-sync.github.en.md +6 -5
  49. package/templates/.agents/rules/issue-sync.github.zh-CN.md +6 -5
  50. package/templates/.agents/rules/milestone-inference.github.en.md +2 -2
  51. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +2 -2
  52. package/templates/.agents/rules/no-mid-flow-questions.en.md +57 -0
  53. package/templates/.agents/rules/no-mid-flow-questions.zh-CN.md +57 -0
  54. package/templates/.agents/rules/pr-sync.github.en.md +4 -5
  55. package/templates/.agents/rules/pr-sync.github.zh-CN.md +4 -5
  56. package/templates/.agents/rules/task-management.en.md +9 -6
  57. package/templates/.agents/rules/task-management.zh-CN.md +9 -6
  58. package/templates/.agents/rules/task-short-id.en.md +141 -0
  59. package/templates/.agents/rules/task-short-id.zh-CN.md +124 -0
  60. package/templates/.agents/rules/testing-discipline.en.md +2 -2
  61. package/templates/.agents/rules/testing-discipline.zh-CN.md +2 -2
  62. package/templates/.agents/scripts/task-short-id.js +713 -0
  63. package/templates/.agents/scripts/validate-artifact.js +1 -1
  64. package/templates/.agents/skills/analyze-task/SKILL.en.md +20 -4
  65. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +20 -5
  66. package/templates/.agents/skills/block-task/SKILL.en.md +12 -0
  67. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +12 -1
  68. package/templates/.agents/skills/cancel-task/SKILL.en.md +12 -0
  69. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +12 -1
  70. package/templates/.agents/skills/check-task/SKILL.en.md +47 -32
  71. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +46 -32
  72. package/templates/.agents/skills/close-codescan/SKILL.en.md +11 -0
  73. package/templates/.agents/skills/close-codescan/SKILL.zh-CN.md +11 -0
  74. package/templates/.agents/skills/close-dependabot/SKILL.en.md +11 -0
  75. package/templates/.agents/skills/close-dependabot/SKILL.zh-CN.md +11 -0
  76. package/templates/.agents/skills/code-task/SKILL.en.md +121 -0
  77. package/templates/.agents/skills/{implement-task → code-task}/SKILL.zh-CN.md +55 -25
  78. package/templates/.agents/skills/{implement-task → code-task}/config/verify.en.json +4 -4
  79. package/templates/.agents/skills/{implement-task → code-task}/config/verify.zh-CN.json +4 -4
  80. package/templates/.agents/skills/{implement-task → code-task}/reference/branch-management.zh-CN.md +2 -2
  81. package/templates/.agents/skills/{implement-task/reference/implementation-rules.en.md → code-task/reference/code-rules.en.md} +6 -6
  82. package/templates/.agents/skills/{implement-task/reference/implementation-rules.zh-CN.md → code-task/reference/code-rules.zh-CN.md} +3 -3
  83. package/templates/.agents/skills/code-task/reference/dual-mode.en.md +69 -0
  84. package/templates/.agents/skills/code-task/reference/dual-mode.zh-CN.md +69 -0
  85. package/templates/.agents/skills/{refine-task/reference/fix-workflow.en.md → code-task/reference/fix-mode.en.md} +12 -12
  86. package/templates/.agents/skills/{refine-task/reference/fix-workflow.zh-CN.md → code-task/reference/fix-mode.zh-CN.md} +8 -8
  87. package/templates/.agents/skills/code-task/reference/output-template.en.md +20 -0
  88. package/templates/.agents/skills/code-task/reference/output-template.zh-CN.md +20 -0
  89. package/templates/.agents/skills/{implement-task → code-task}/reference/report-template.en.md +4 -4
  90. package/templates/.agents/skills/{implement-task → code-task}/reference/report-template.zh-CN.md +3 -3
  91. package/templates/.agents/skills/code-task/scripts/detect-mode.js +370 -0
  92. package/templates/.agents/skills/commit/SKILL.en.md +6 -2
  93. package/templates/.agents/skills/commit/SKILL.zh-CN.md +6 -2
  94. package/templates/.agents/skills/commit/reference/task-status-update.en.md +10 -6
  95. package/templates/.agents/skills/commit/reference/task-status-update.zh-CN.md +10 -6
  96. package/templates/.agents/skills/complete-task/SKILL.en.md +17 -3
  97. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +17 -4
  98. package/templates/.agents/skills/create-pr/SKILL.en.md +21 -1
  99. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +21 -1
  100. package/templates/.agents/skills/create-task/SKILL.en.md +14 -0
  101. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +14 -1
  102. package/templates/.agents/skills/import-codescan/SKILL.en.md +15 -1
  103. package/templates/.agents/skills/import-codescan/SKILL.zh-CN.md +15 -1
  104. package/templates/.agents/skills/import-dependabot/SKILL.en.md +16 -2
  105. package/templates/.agents/skills/import-dependabot/SKILL.zh-CN.md +16 -2
  106. package/templates/.agents/skills/import-issue/SKILL.en.md +17 -3
  107. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +17 -3
  108. package/templates/.agents/skills/plan-task/SKILL.en.md +8 -4
  109. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +8 -5
  110. package/templates/.agents/skills/restore-task/SKILL.en.md +16 -3
  111. package/templates/.agents/skills/restore-task/SKILL.zh-CN.md +16 -4
  112. package/templates/.agents/skills/review-analysis/SKILL.en.md +80 -0
  113. package/templates/.agents/skills/review-analysis/SKILL.zh-CN.md +105 -0
  114. package/templates/.agents/skills/review-analysis/config/verify.en.json +51 -0
  115. package/templates/.agents/skills/review-analysis/config/verify.zh-CN.json +51 -0
  116. package/templates/.agents/skills/review-analysis/reference/output-templates.en.md +87 -0
  117. package/templates/.agents/skills/review-analysis/reference/output-templates.zh-CN.md +87 -0
  118. package/templates/.agents/skills/review-analysis/reference/report-template.en.md +90 -0
  119. package/templates/.agents/skills/review-analysis/reference/report-template.zh-CN.md +91 -0
  120. package/templates/.agents/skills/review-analysis/reference/review-criteria.en.md +47 -0
  121. package/templates/.agents/skills/review-analysis/reference/review-criteria.zh-CN.md +47 -0
  122. package/templates/.agents/skills/{review-task → review-code}/SKILL.en.md +15 -9
  123. package/templates/.agents/skills/{review-task → review-code}/SKILL.zh-CN.md +19 -10
  124. package/templates/.agents/skills/{review-task → review-code}/config/verify.en.json +7 -5
  125. package/templates/.agents/skills/{review-task → review-code}/config/verify.zh-CN.json +6 -4
  126. package/templates/.agents/skills/{review-task → review-code}/reference/output-templates.en.md +21 -17
  127. package/templates/.agents/skills/{review-task → review-code}/reference/output-templates.zh-CN.md +19 -15
  128. package/templates/.agents/skills/{review-task → review-code}/reference/report-template.en.md +5 -6
  129. package/templates/.agents/skills/review-code/reference/report-template.zh-CN.md +91 -0
  130. package/templates/.agents/skills/review-code/reference/review-criteria.en.md +48 -0
  131. package/templates/.agents/skills/{review-task → review-code}/reference/review-criteria.zh-CN.md +10 -4
  132. package/templates/.agents/skills/review-plan/SKILL.en.md +80 -0
  133. package/templates/.agents/skills/review-plan/SKILL.zh-CN.md +105 -0
  134. package/templates/.agents/skills/{refine-task → review-plan}/config/verify.en.json +14 -10
  135. package/templates/.agents/skills/{refine-task → review-plan}/config/verify.zh-CN.json +14 -10
  136. package/templates/.agents/skills/review-plan/reference/output-templates.en.md +87 -0
  137. package/templates/.agents/skills/review-plan/reference/output-templates.zh-CN.md +87 -0
  138. package/templates/.agents/skills/review-plan/reference/report-template.en.md +90 -0
  139. package/templates/.agents/skills/{review-task → review-plan}/reference/report-template.zh-CN.md +3 -3
  140. package/templates/.agents/skills/review-plan/reference/review-criteria.en.md +47 -0
  141. package/templates/.agents/skills/review-plan/reference/review-criteria.zh-CN.md +47 -0
  142. package/templates/.agents/skills/test/SKILL.en.md +2 -2
  143. package/templates/.agents/skills/test/SKILL.zh-CN.md +13 -31
  144. package/templates/.agents/skills/update-agent-infra/SKILL.en.md +1 -0
  145. package/templates/.agents/skills/update-agent-infra/SKILL.zh-CN.md +1 -0
  146. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +113 -21
  147. package/templates/.agents/templates/task.en.md +4 -3
  148. package/templates/.agents/templates/task.zh-CN.md +3 -2
  149. package/templates/.agents/workflows/bug-fix.en.yaml +126 -80
  150. package/templates/.agents/workflows/bug-fix.zh-CN.yaml +90 -44
  151. package/templates/.agents/workflows/feature-development.en.yaml +115 -70
  152. package/templates/.agents/workflows/feature-development.zh-CN.yaml +92 -47
  153. package/templates/.agents/workflows/refactoring.en.yaml +123 -78
  154. package/templates/.agents/workflows/refactoring.zh-CN.yaml +89 -44
  155. package/templates/.claude/commands/code-task.en.md +8 -0
  156. package/templates/.claude/commands/code-task.zh-CN.md +8 -0
  157. package/templates/.claude/commands/review-analysis.en.md +8 -0
  158. package/templates/.claude/commands/review-analysis.zh-CN.md +8 -0
  159. package/templates/.claude/commands/review-code.en.md +8 -0
  160. package/templates/.claude/commands/review-code.zh-CN.md +8 -0
  161. package/templates/.claude/commands/review-plan.en.md +8 -0
  162. package/templates/.claude/commands/review-plan.zh-CN.md +8 -0
  163. package/templates/.gemini/commands/_project_/archive-tasks.zh-CN.toml +1 -1
  164. package/templates/.gemini/commands/_project_/code-task.en.toml +8 -0
  165. package/templates/.gemini/commands/_project_/code-task.zh-CN.toml +8 -0
  166. package/templates/.gemini/commands/_project_/init-labels.zh-CN.toml +1 -1
  167. package/templates/.gemini/commands/_project_/init-milestones.zh-CN.toml +1 -1
  168. package/templates/.gemini/commands/_project_/review-analysis.en.toml +8 -0
  169. package/templates/.gemini/commands/_project_/review-analysis.zh-CN.toml +8 -0
  170. package/templates/.gemini/commands/_project_/review-code.en.toml +8 -0
  171. package/templates/.gemini/commands/_project_/review-code.zh-CN.toml +8 -0
  172. package/templates/.gemini/commands/_project_/review-plan.en.toml +8 -0
  173. package/templates/.gemini/commands/_project_/review-plan.zh-CN.toml +8 -0
  174. package/templates/.opencode/commands/code-task.en.md +11 -0
  175. package/templates/.opencode/commands/code-task.zh-CN.md +11 -0
  176. package/templates/.opencode/commands/review-analysis.en.md +11 -0
  177. package/templates/.opencode/commands/review-analysis.zh-CN.md +11 -0
  178. package/templates/.opencode/commands/review-code.en.md +11 -0
  179. package/templates/.opencode/commands/review-code.zh-CN.md +11 -0
  180. package/templates/.opencode/commands/review-plan.en.md +11 -0
  181. package/templates/.opencode/commands/review-plan.zh-CN.md +11 -0
  182. package/templates/.agents/skills/implement-task/SKILL.en.md +0 -173
  183. package/templates/.agents/skills/implement-task/reference/output-template.en.md +0 -20
  184. package/templates/.agents/skills/implement-task/reference/output-template.zh-CN.md +0 -20
  185. package/templates/.agents/skills/refine-task/SKILL.en.md +0 -153
  186. package/templates/.agents/skills/refine-task/SKILL.zh-CN.md +0 -153
  187. package/templates/.agents/skills/refine-task/reference/report-template.en.md +0 -64
  188. package/templates/.agents/skills/refine-task/reference/report-template.zh-CN.md +0 -64
  189. package/templates/.agents/skills/review-task/reference/review-criteria.en.md +0 -42
  190. package/templates/.claude/commands/implement-task.en.md +0 -8
  191. package/templates/.claude/commands/implement-task.zh-CN.md +0 -8
  192. package/templates/.claude/commands/refine-task.en.md +0 -8
  193. package/templates/.claude/commands/refine-task.zh-CN.md +0 -8
  194. package/templates/.claude/commands/review-task.en.md +0 -8
  195. package/templates/.claude/commands/review-task.zh-CN.md +0 -8
  196. package/templates/.gemini/commands/_project_/implement-task.en.toml +0 -8
  197. package/templates/.gemini/commands/_project_/implement-task.zh-CN.toml +0 -8
  198. package/templates/.gemini/commands/_project_/refine-task.en.toml +0 -8
  199. package/templates/.gemini/commands/_project_/refine-task.zh-CN.toml +0 -8
  200. package/templates/.gemini/commands/_project_/review-task.en.toml +0 -8
  201. package/templates/.gemini/commands/_project_/review-task.zh-CN.toml +0 -8
  202. package/templates/.opencode/commands/implement-task.en.md +0 -11
  203. package/templates/.opencode/commands/implement-task.zh-CN.md +0 -11
  204. package/templates/.opencode/commands/refine-task.en.md +0 -11
  205. package/templates/.opencode/commands/refine-task.zh-CN.md +0 -11
  206. package/templates/.opencode/commands/review-task.en.md +0 -11
  207. package/templates/.opencode/commands/review-task.zh-CN.md +0 -11
  208. /package/templates/.agents/skills/{implement-task → code-task}/reference/branch-management.en.md +0 -0
@@ -24,7 +24,7 @@
24
24
 
25
25
  env-blocked 项不在修复范围。处理规则:
26
26
  - 不要为这些项编写代码改动
27
- - 在 refinement 报告的「环境性遗留处理」段落原样列出,标注「不在 AI 修复范围」
27
+ - 在 code 报告的「环境性遗留处理」段落原样列出,标注「不在 AI 修复范围」
28
28
  - 不要在 unresolved 段落里重复列出(避免视觉计数翻倍)
29
29
  - 这些项的去向:维护者在 PR description 中以「待人工验证」清单承接
30
30
 
@@ -38,7 +38,7 @@ env-blocked 项不在修复范围。处理规则:
38
38
 
39
39
  ## 运行测试验证
40
40
 
41
- refinement 报告前,运行项目测试的 **core 子集**做最终验证,确保所有必需测试仍然通过。如果项目没有分层 script,回退到完整项目测试命令。
41
+ code 报告前,运行项目测试的 **core 子集**做最终验证,确保所有必需测试仍然通过。如果项目没有分层 script,回退到完整项目测试命令。
42
42
 
43
43
  ## 选择下一步分支
44
44
 
@@ -62,13 +62,13 @@ env-blocked 项不在修复范围。处理规则:
62
62
  - [如 env-blocked > 0] 环境性遗留跳过:{数量}
63
63
  - 所有测试通过:{是/否}
64
64
  - 审查输入:{review-artifact}
65
- - 修复产物:{refinement-artifact}
65
+ - 修复产物:{code-artifact}
66
66
 
67
67
  下一步 - 重新审查或提交:
68
68
  - 重新审查(始终推荐):
69
- - Claude Code / OpenCode:/review-task {task-id}
70
- - Gemini CLI:/agent-infra:review-task {task-id}
71
- - Codex CLI:$review-task {task-id}
69
+ - Claude Code / OpenCode:/review-code {task-id}
70
+ - Gemini CLI:/agent-infra:review-code {task-id}
71
+ - Codex CLI:$review-code {task-id}
72
72
  - 直接提交(可选;仅在所有问题已解决且风险可控时):
73
73
  - Claude Code / OpenCode:/commit
74
74
  - Gemini CLI:/agent-infra:commit
@@ -77,9 +77,9 @@ env-blocked 项不在修复范围。处理规则:
77
77
 
78
78
  ## 注意事项
79
79
 
80
- 1. **前置条件**:必须存在审查产物(`review.md` 或 `review-r{N}.md`)
80
+ 1. **前置条件**:必须存在代码审查产物(`review-code.md` 或 `review-code-r{N}.md`)
81
81
  2. **禁止自动提交**:不要执行 `git commit`
82
82
  3. **范围约束**:只修复审查中列出的问题
83
83
  4. **分歧处理**:如果不同意审查意见,要在报告里明确记录
84
- 5. **重新审查**:修复后始终推荐执行 `review-task`
84
+ 5. **重新审查**:修复后始终推荐执行 `review-code`
85
85
  6. **一致性**:最新审查产物、Activity Log 记录和修复报告必须引用同一轮次
@@ -0,0 +1,20 @@
1
+ # Output Template
2
+
3
+ When reporting that implementation is complete, use the following standard format:
4
+
5
+ ```text
6
+ Task {task-id} code implementation complete.
7
+
8
+ Summary:
9
+ - Implementation round: Round {code-round}
10
+ - Files modified: {count}
11
+ - All tests passed: {yes/no}
12
+
13
+ Output files:
14
+ - Code report: .agents/workspace/active/{task-id}/{code-artifact}
15
+
16
+ Next step - code review:
17
+ - Claude Code / OpenCode: /review-code {task-id}
18
+ - Gemini CLI: /{{project}}:review-code {task-id}
19
+ - Codex CLI: $review-code {task-id}
20
+ ```
@@ -0,0 +1,20 @@
1
+ # 输出模板
2
+
3
+ 向用户汇报实现完成时,使用以下标准格式:
4
+
5
+ ```text
6
+ 任务 {task-id} 实现完成。
7
+
8
+ 摘要:
9
+ - 实现轮次:Round {code-round}
10
+ - 修改文件:{数量}
11
+ - 所有测试通过:{是/否}
12
+
13
+ 产出文件:
14
+ - 实现报告:.agents/workspace/active/{task-id}/{code-artifact}
15
+
16
+ 下一步 - 代码审查:
17
+ - Claude Code / OpenCode:/review-code {task-id}
18
+ - Gemini CLI:/agent-infra:review-code {task-id}
19
+ - Codex CLI:$review-code {task-id}
20
+ ```
@@ -1,14 +1,14 @@
1
- # Implementation Report Template
1
+ # Code Report Template
2
2
 
3
- Use this structure when creating `implementation.md` or `implementation-r{N}.md`.
3
+ Use this structure when creating `code.md` or `code-r{N}.md`.
4
4
 
5
5
  ## Output Template
6
6
 
7
7
  ```markdown
8
8
  # Implementation Report
9
9
 
10
- - **Implementation Round**: Round {implementation-round}
11
- - **Artifact File**: `{implementation-artifact}`
10
+ - **Implementation Round**: Round {code-round}
11
+ - **Artifact File**: `{code-artifact}`
12
12
 
13
13
  ## State Check
14
14
 
@@ -1,14 +1,14 @@
1
1
  # 实现报告模板
2
2
 
3
- 创建 `implementation.md` 或 `implementation-r{N}.md` 时,使用以下结构。
3
+ 创建 `code.md` 或 `code-r{N}.md` 时,使用以下结构。
4
4
 
5
5
  ## 输出模板
6
6
 
7
7
  ```markdown
8
8
  # 实现报告
9
9
 
10
- - **实现轮次**: Round {implementation-round}
11
- - **产物文件**: `{implementation-artifact}`
10
+ - **实现轮次**: Round {code-round}
11
+ - **产物文件**: `{code-artifact}`
12
12
 
13
13
  ## 状态核对
14
14
 
@@ -0,0 +1,370 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+ import process from "node:process";
4
+
5
+ function main() {
6
+ const taskDir = process.argv[2];
7
+ if (!taskDir) {
8
+ writeResult({
9
+ mode: "error",
10
+ code_max: 0,
11
+ rev_max: 0,
12
+ verdict: null,
13
+ next_round: null,
14
+ next_artifact: null,
15
+ review_artifact: null,
16
+ message: "Task directory argument is required."
17
+ }, 2);
18
+ return;
19
+ }
20
+
21
+ try {
22
+ const resolvedTaskDir = path.resolve(taskDir);
23
+ const taskId = path.basename(resolvedTaskDir);
24
+ const entries = fs.readdirSync(resolvedTaskDir);
25
+ const codeMax = maxRound(entries, "code");
26
+ const revMax = maxRound(entries, "review-code");
27
+
28
+ if (codeMax === 0) {
29
+ writeResult({
30
+ mode: "init",
31
+ code_max: codeMax,
32
+ rev_max: revMax,
33
+ verdict: null,
34
+ next_round: 1,
35
+ next_artifact: "code.md",
36
+ review_artifact: null,
37
+ message: "No prior code artifact. Starting initial implementation (round 1 -> code.md)."
38
+ }, 0);
39
+ return;
40
+ }
41
+
42
+ // replan-precedes-unreviewed-code:
43
+ // 第 8 分支(replan)必须在第 2 分支(revMax < codeMax → error)之前评估。
44
+ // 依据 task.md 盲区 B 修法 B1:「不论 review-code 状态如何(包括未审)」,
45
+ // 只要最新 review-plan 已批准且 mtime > code,就进入新一轮实现。
46
+ const planMax = maxRound(entries, "plan");
47
+ const reviewPlanMax = maxRound(entries, "review-plan");
48
+ const replanCheck = checkPlanAheadOfCode({
49
+ resolvedTaskDir,
50
+ codeMax,
51
+ planMax,
52
+ reviewPlanMax
53
+ });
54
+ if (replanCheck.replan) {
55
+ const nextRound = codeMax + 1;
56
+ const nextArtifact = artifactName("code", nextRound);
57
+ writeResult({
58
+ mode: "init",
59
+ code_max: codeMax,
60
+ rev_max: revMax,
61
+ verdict: null,
62
+ next_round: nextRound,
63
+ next_artifact: nextArtifact,
64
+ review_artifact: replanCheck.reviewPlanArtifact,
65
+ message: `Latest ${replanCheck.reviewPlanArtifact} is approved and its mtime is newer than the latest code artifact. Entering replan-driven init (round ${nextRound} -> ${nextArtifact}).`
66
+ }, 0);
67
+ return;
68
+ }
69
+
70
+ if (revMax < codeMax) {
71
+ const expected = artifactName("review-code", codeMax);
72
+ writeResult({
73
+ mode: "error",
74
+ code_max: codeMax,
75
+ rev_max: revMax,
76
+ verdict: null,
77
+ next_round: null,
78
+ next_artifact: null,
79
+ review_artifact: expected,
80
+ message: `Code round ${codeMax} has no matching review-code artifact (${expected} expected). Run /review-code ${taskId} first.`
81
+ }, 2);
82
+ return;
83
+ }
84
+
85
+ if (revMax > codeMax) {
86
+ writeResult({
87
+ mode: "error",
88
+ code_max: codeMax,
89
+ rev_max: revMax,
90
+ verdict: null,
91
+ next_round: null,
92
+ next_artifact: null,
93
+ review_artifact: artifactName("review-code", revMax),
94
+ message: `Inconsistent state: review-code round ${revMax} > code round ${codeMax}. Manual inspection required.`
95
+ }, 2);
96
+ return;
97
+ }
98
+
99
+ const reviewArtifact = artifactName("review-code", revMax);
100
+ const verdictResult = parseVerdict(path.join(resolvedTaskDir, reviewArtifact));
101
+ if (!verdictResult.ok) {
102
+ writeResult({
103
+ mode: "error",
104
+ code_max: codeMax,
105
+ rev_max: revMax,
106
+ verdict: verdictResult.verdict ?? null,
107
+ next_round: null,
108
+ next_artifact: null,
109
+ review_artifact: reviewArtifact,
110
+ message: verdictResult.message
111
+ }, 2);
112
+ return;
113
+ }
114
+
115
+ const verdict = verdictResult.verdict;
116
+ if (verdict === "Approved") {
117
+ writeResult({
118
+ mode: "refused",
119
+ code_max: codeMax,
120
+ rev_max: revMax,
121
+ verdict,
122
+ next_round: null,
123
+ next_artifact: null,
124
+ review_artifact: reviewArtifact,
125
+ message: `Latest ${reviewArtifact} verdict is Approved with no findings. Nothing to fix. Run /commit to proceed.`
126
+ }, 1);
127
+ return;
128
+ }
129
+
130
+ if (verdict === "Rejected") {
131
+ writeResult({
132
+ mode: "refused",
133
+ code_max: codeMax,
134
+ rev_max: revMax,
135
+ verdict,
136
+ next_round: null,
137
+ next_artifact: null,
138
+ review_artifact: reviewArtifact,
139
+ message: `Latest ${reviewArtifact} verdict is Rejected. This requires a fresh implementation strategy; re-plan or discuss with maintainers before re-running /code-task ${taskId}.`
140
+ }, 1);
141
+ return;
142
+ }
143
+
144
+ const nextRound = codeMax + 1;
145
+ const nextArtifact = artifactName("code", nextRound);
146
+ const optional = verdict === "Approved-with-issues";
147
+ writeResult({
148
+ mode: "fix",
149
+ code_max: codeMax,
150
+ rev_max: revMax,
151
+ verdict,
152
+ next_round: nextRound,
153
+ next_artifact: nextArtifact,
154
+ review_artifact: reviewArtifact,
155
+ message: optional
156
+ ? `Latest ${reviewArtifact} approved with non-blocking findings. Entering optional fix mode (round ${nextRound} -> ${nextArtifact}).`
157
+ : `Latest ${reviewArtifact} requests changes. Entering required fix mode (round ${nextRound} -> ${nextArtifact}).`
158
+ }, 0);
159
+ } catch (error) {
160
+ writeResult({
161
+ mode: "error",
162
+ code_max: 0,
163
+ rev_max: 0,
164
+ verdict: null,
165
+ next_round: null,
166
+ next_artifact: null,
167
+ review_artifact: null,
168
+ message: `Mode detection failed: ${error instanceof Error ? error.message : String(error)}`
169
+ }, 2);
170
+ }
171
+ }
172
+
173
+ function maxRound(entries, stem) {
174
+ let max = 0;
175
+ for (const entry of entries) {
176
+ if (entry === `${stem}.md`) {
177
+ max = Math.max(max, 1);
178
+ continue;
179
+ }
180
+
181
+ const match = entry.match(new RegExp(`^${escapeRegExp(stem)}-r(\\d+)\\.md$`));
182
+ if (match) {
183
+ max = Math.max(max, Number(match[1]));
184
+ }
185
+ }
186
+ return max;
187
+ }
188
+
189
+ function artifactName(stem, round) {
190
+ return round === 1 ? `${stem}.md` : `${stem}-r${round}.md`;
191
+ }
192
+
193
+ function checkPlanAheadOfCode({ resolvedTaskDir, codeMax, planMax, reviewPlanMax }) {
194
+ if (planMax === 0 || reviewPlanMax === 0) {
195
+ return { replan: false };
196
+ }
197
+
198
+ // plan 和 review-plan 轮次独立递增(plan-r5 可被 review-plan-r4 批准),不能假设同号。
199
+ // 用最新 review-plan 产物的「审查输入」/「Review Input」段落里引用的 plan 文件名
200
+ // 作为真正被批准的 plan;若该 plan 文件名不等于目录里最新 plan-rN.md,
201
+ // 说明最新 plan 还未被审查,不触发 replan。
202
+ const reviewPlanArtifact = artifactName("review-plan", reviewPlanMax);
203
+ const reviewPlanPath = path.join(resolvedTaskDir, reviewPlanArtifact);
204
+ if (!fs.existsSync(reviewPlanPath)) {
205
+ return { replan: false };
206
+ }
207
+
208
+ const reviewedPlan = parseReviewedPlan(reviewPlanPath);
209
+ if (!reviewedPlan) {
210
+ return { replan: false };
211
+ }
212
+ const latestPlanArtifact = artifactName("plan", planMax);
213
+ if (reviewedPlan !== latestPlanArtifact) {
214
+ return { replan: false };
215
+ }
216
+
217
+ // review-plan 的「通过 + 主要/次要建议」(Approved-with-issues)仍是已批准,
218
+ // 区别于 review-code(Approved-with-issues 触发 optional fix)。replan 检测对
219
+ // review-plan 放宽到 Approved + Approved-with-issues 二者均放行。
220
+ const APPROVED_PLAN_VERDICTS = new Set(["Approved", "Approved-with-issues"]);
221
+ const reviewVerdict = parseVerdict(reviewPlanPath);
222
+ if (!reviewVerdict.ok || !APPROVED_PLAN_VERDICTS.has(reviewVerdict.verdict)) {
223
+ return { replan: false };
224
+ }
225
+
226
+ const codeArtifact = artifactName("code", codeMax);
227
+ const codeStat = safeStat(path.join(resolvedTaskDir, codeArtifact));
228
+ const reviewPlanStat = safeStat(reviewPlanPath);
229
+ if (!codeStat || !reviewPlanStat) {
230
+ return { replan: false };
231
+ }
232
+
233
+ // 严格 `>`:同秒回退到既有 7 分支逻辑(保守,参见 plan-r5.md Q2 决议)
234
+ if (reviewPlanStat.mtimeMs > codeStat.mtimeMs) {
235
+ return { replan: true, reviewPlanArtifact };
236
+ }
237
+ return { replan: false };
238
+ }
239
+
240
+ function parseReviewedPlan(reviewPlanPath) {
241
+ let content;
242
+ try {
243
+ content = fs.readFileSync(reviewPlanPath, "utf8");
244
+ } catch {
245
+ return null;
246
+ }
247
+ const lines = content.split(/\r?\n/);
248
+ const headerPattern = /^[-*]\s*\*\*(?:审查输入|Review Input)\*\*[::]/;
249
+ const planFilePattern = /`(plan(?:-r\d+)?\.md)`/;
250
+ let inHeader = false;
251
+ for (const line of lines) {
252
+ if (headerPattern.test(line)) {
253
+ inHeader = true;
254
+ const inline = line.match(planFilePattern);
255
+ if (inline) return inline[1];
256
+ continue;
257
+ }
258
+ if (!inHeader) continue;
259
+ if (/^\s*[-*]\s/.test(line)) {
260
+ const match = line.match(planFilePattern);
261
+ if (match) return match[1];
262
+ continue;
263
+ }
264
+ if (line.trim() === "") continue;
265
+ break;
266
+ }
267
+ return null;
268
+ }
269
+
270
+ function safeStat(filePath) {
271
+ try {
272
+ return fs.statSync(filePath);
273
+ } catch {
274
+ return null;
275
+ }
276
+ }
277
+
278
+ function parseVerdict(reviewPath) {
279
+ if (!fs.existsSync(reviewPath)) {
280
+ return { ok: false, verdict: null, message: `Review artifact not found: ${path.basename(reviewPath)}` };
281
+ }
282
+
283
+ const content = fs.readFileSync(reviewPath, "utf8");
284
+ const summary = extractSection(content, ["审查摘要", "Review Summary"]);
285
+ const fileName = path.basename(reviewPath);
286
+ if (!summary) {
287
+ return { ok: false, verdict: null, message: `cannot locate review summary section in ${fileName}` };
288
+ }
289
+
290
+ const verdictMatch = summary.match(/^[-*]?\s*\*\*(?:总体结论|Overall Verdict)\*\*[::]\s*(.+?)\s*$/im);
291
+ if (!verdictMatch) {
292
+ return { ok: false, verdict: null, message: `cannot parse verdict in ${fileName}` };
293
+ }
294
+
295
+ const verdict = normalizeVerdict(verdictMatch[1]);
296
+ if (!verdict) {
297
+ return {
298
+ ok: false,
299
+ verdict: null,
300
+ message: `unrecognized verdict '${verdictMatch[1].trim()}' in ${fileName}`
301
+ };
302
+ }
303
+
304
+ if (verdict !== "Approved") {
305
+ return { ok: true, verdict };
306
+ }
307
+
308
+ const findingsMatch = summary.match(/^[-*]?\s*\*\*(?:发现(AI 可处理)|Findings \(AI-actionable\))\*\*[::]\s*(.+?)\s*$/im);
309
+ if (!findingsMatch) {
310
+ return { ok: false, verdict, message: `cannot parse findings count in ${fileName}` };
311
+ }
312
+
313
+ const counts = findingsMatch[1].match(/(\d+)\s*(?:阻塞项|blockers?).*?(\d+)\s*(?:主要|majors?).*?(\d+)\s*(?:次要|minors?)/i);
314
+ if (!counts) {
315
+ return { ok: false, verdict, message: `cannot parse findings count in ${fileName}` };
316
+ }
317
+
318
+ const [, blockers, majors, minors] = counts.map(Number);
319
+ return {
320
+ ok: true,
321
+ verdict: blockers === 0 && majors === 0 && minors === 0 ? "Approved" : "Approved-with-issues"
322
+ };
323
+ }
324
+
325
+ function normalizeVerdict(raw) {
326
+ const value = String(raw).trim().toLowerCase();
327
+ if (value === "通过" || value === "approved") {
328
+ return "Approved";
329
+ }
330
+ if (value === "需要修改" || value === "changes requested") {
331
+ return "Changes Requested";
332
+ }
333
+ if (value === "拒绝" || value === "rejected") {
334
+ return "Rejected";
335
+ }
336
+ return "";
337
+ }
338
+
339
+ function extractSection(content, names) {
340
+ const lines = content.split(/\r?\n/);
341
+ const nameSet = new Set(names);
342
+ const start = lines.findIndex((line) => {
343
+ const match = line.trim().match(/^##\s+(.+?)\s*$/);
344
+ return match ? nameSet.has(match[1]) : false;
345
+ });
346
+
347
+ if (start === -1) {
348
+ return "";
349
+ }
350
+
351
+ const sectionLines = [];
352
+ for (let index = start + 1; index < lines.length; index += 1) {
353
+ if (/^##\s+/.test(lines[index])) {
354
+ break;
355
+ }
356
+ sectionLines.push(lines[index]);
357
+ }
358
+ return sectionLines.join("\n");
359
+ }
360
+
361
+ function writeResult(result, code) {
362
+ process.stdout.write(`${JSON.stringify(result, null, 2)}\n`);
363
+ process.exitCode = code;
364
+ }
365
+
366
+ function escapeRegExp(value) {
367
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
368
+ }
369
+
370
+ main();
@@ -17,6 +17,10 @@ When updating related `task.md` frontmatter, read `.agents/rules/version-stamp.m
17
17
  | "`git add -A` is faster." | `git add -A` and `git add .` are forbidden; stage only explicitly listed files to avoid including unrelated changes. |
18
18
  | "This file has a copyright header, but the year can wait." | If you changed it, update the copyright year using `date +%Y`; this is a hard pre-commit check. |
19
19
 
20
+ ## Task id short ref
21
+
22
+ > If `{task-id}` begins with `#`, follow the "SKILL parameter resolver" section of `.agents/rules/task-short-id.md`; treat `{task-id}` as the resolved full `TASK-YYYYMMDD-HHMMSS` form for every downstream command.
23
+
20
24
  ## 1. Check Local Modifications (CRITICAL)
21
25
 
22
26
  Before any edit, inspect:
@@ -59,8 +63,8 @@ date "+%Y-%m-%d %H:%M:%S%:z"
59
63
  Append the Commit Activity Log entry and choose exactly one next-step case:
60
64
  - final commit -> `complete-task {task-id}`
61
65
  - more work remains -> update task.md and stop
62
- - ready for review -> `review-task {task-id}`
63
- - ready for PR -> `create-pr`
66
+ - ready for review -> `review-code {task-id}`
67
+ - ready for PR (only when the project enables the PR flow, i.e. `requiresPullRequest !== false`) -> `create-pr`
64
68
 
65
69
  ## 6. Sync Issue Metadata When Applicable
66
70
 
@@ -17,6 +17,10 @@ description: "提交当前变更到 Git"
17
17
  | 「`git add -A` 更省事」 | 禁止 `git add -A`/`git add .`;只暂存明确列出的文件,避免带入无关改动。 |
18
18
  | 「改了带版权头的文件,年份先不动」 | 改了就更新版权年份(动态取 `date +%Y`),这是提交前的硬性检查。 |
19
19
 
20
+ ## 任务入参短号别名
21
+
22
+ > 如果 `{task-id}` 入参以 `#` 开头,先读取 `.agents/rules/task-short-id.md` 的「SKILL 入参解析」段执行解析;后续命令视 `{task-id}` 为解析后的全长 `TASK-YYYYMMDD-HHMMSS` 形式。
23
+
20
24
  ## 1. 检查本地修改(关键)
21
25
 
22
26
  在任何编辑前先检查:
@@ -59,8 +63,8 @@ date "+%Y-%m-%d %H:%M:%S%:z"
59
63
  追加 Commit 的 Activity Log,并且只能选择一个下一步分支:
60
64
  - 最终提交 -> `complete-task {task-id}`
61
65
  - 还有后续工作 -> 更新 task.md 后停止
62
- - 准备审查 -> `review-task {task-id}`
63
- - 准备创建 PR -> `create-pr`
66
+ - 准备审查 -> `review-code {task-id}`
67
+ - 准备创建 PR(仅项目启用 PR 流程,即 `requiresPullRequest !== false`)-> `create-pr`
64
68
 
65
69
  ## 6. 同步 Issue 元数据(按需)
66
70
 
@@ -20,9 +20,11 @@ For every task-related commit, append this Activity Log entry in `task.md`:
20
20
 
21
21
  Before selecting the next step, verify:
22
22
  - `current_step` and the latest workflow progress in `task.md`
23
- - whether the latest `review.md` / `review-r{N}.md` passed without findings
23
+ - whether the latest `review-code.md` / `review-code-r{N}.md` passed without findings
24
24
  - whether there are still pending fixes, review work, or PR creation steps
25
25
 
26
+ **Gate read (project-level PR flow policy)**: Before running this step, read `.agents/.airc.json`'s `requiresPullRequest` field. Treat missing or `true` as "PR flow enabled" (default); treat explicit `false` as "PR flow disabled". All branches that depend on this field follow the same rule.
27
+
26
28
  Choose exactly one case:
27
29
 
28
30
  | Decision Basis | Required Case |
@@ -30,17 +32,19 @@ Choose exactly one case:
30
32
  | all workflow steps completed + latest review approved with no findings + all tests passed | Case 1: final commit |
31
33
  | unfinished steps, pending fixes, or waiting on others still exist | Case 2: more work remains |
32
34
  | this commit prepares the task for code review | Case 3: ready for review |
33
- | code is committed, review is done, and the next step is PR creation | Case 4: ready for PR |
35
+ | code is committed, review is done, **and the project enables the PR flow**, with PR creation as the next step | Case 4: ready for PR |
34
36
 
35
37
  Never apply more than one case. Match the single next-step branch first, then update the task.
36
38
 
39
+ **Gate downgrade**: When `requiresPullRequest === false`, Case 4 must never be entered; commits that would otherwise fall into Case 4 collapse into Case 1 (final commit -> `/complete-task`).
40
+
37
41
  ### Case 1: Final Commit
38
42
 
39
43
  Prerequisites:
40
44
  - [ ] all code committed
41
45
  - [ ] all tests passed
42
46
  - [ ] code review approved
43
- - [ ] all workflow steps completed
47
+ - [ ] all workflow steps completed (for the `pr_tasks` list under each yaml `commit` step, count those items toward completion only when `requiresPullRequest !== false`)
44
48
 
45
49
  Required next-step commands:
46
50
 
@@ -71,9 +75,9 @@ Required next-step commands:
71
75
 
72
76
  ```text
73
77
  Next step - code review:
74
- - Claude Code / OpenCode: /review-task {task-id}
75
- - Gemini CLI: /agent-infra:review-task {task-id}
76
- - Codex CLI: $review-task {task-id}
78
+ - Claude Code / OpenCode: /review-code {task-id}
79
+ - Gemini CLI: /agent-infra:review-code {task-id}
80
+ - Codex CLI: $review-code {task-id}
77
81
  ```
78
82
 
79
83
  ### Case 4: Ready for PR
@@ -20,9 +20,11 @@ date "+%Y-%m-%d %H:%M:%S%:z"
20
20
 
21
21
  在决定下一步之前,先确认:
22
22
  - `task.md` 中的 `current_step` 和最新工作流进度
23
- - 最新的 `review.md` / `review-r{N}.md` 是否无问题通过
23
+ - 最新的 `review-code.md` / `review-code-r{N}.md` 是否无问题通过
24
24
  - 是否仍然存在待修复项、待审查工作或待创建 PR 的步骤
25
25
 
26
+ **门控读取(项目级 PR 流程策略)**:在执行本步骤前,读取 `.agents/.airc.json` 的 `requiresPullRequest` 字段;当字段缺失或为 `true` 时视为「启用 PR 流程」(默认),仅当显式为 `false` 时视为「关闭 PR 流程」。所有依赖该字段的分支按此规则判定。
27
+
26
28
  必须且只能选择一个分支:
27
29
 
28
30
  | 判断依据 | 必选分支 |
@@ -30,17 +32,19 @@ date "+%Y-%m-%d %H:%M:%S%:z"
30
32
  | 所有工作流步骤都已完成 + 最新审查无问题通过 + 所有测试通过 | 场景 1:最终提交 |
31
33
  | 仍有未完成步骤、待修复项或等待他人的动作 | 场景 2:还有后续工作 |
32
34
  | 这次提交是为了把任务交给代码审查 | 场景 3:准备进入审查 |
33
- | 代码已提交、审查已完成,下一步是创建 PR | 场景 4:准备创建 PR |
35
+ | 代码已提交、审查已完成,且**项目启用 PR 流程**,下一步是创建 PR | 场景 4:准备创建 PR |
34
36
 
35
37
  绝对不要同时套用多个分支。先匹配唯一的下一步分支,再更新任务。
36
38
 
39
+ **门控降级**:当 `requiresPullRequest === false` 时,场景 4 永远不被进入;原本会落入场景 4 的提交统一收敛到场景 1(最终提交 → `/complete-task`)。
40
+
37
41
  ### 场景 1:最终提交
38
42
 
39
43
  前置条件:
40
44
  - [ ] 所有代码都已提交
41
45
  - [ ] 所有测试通过
42
46
  - [ ] 代码审查已通过
43
- - [ ] 所有工作流步骤已完成
47
+ - [ ] 所有工作流步骤已完成(对 yaml `commit` 步骤的 `pr_tasks` 列表,仅在 `requiresPullRequest !== false` 时计入)
44
48
 
45
49
  必带下一步命令:
46
50
 
@@ -71,9 +75,9 @@ date "+%Y-%m-%d %H:%M:%S%:z"
71
75
 
72
76
  ```text
73
77
  下一步 - 代码审查:
74
- - Claude Code / OpenCode: /review-task {task-id}
75
- - Gemini CLI: /agent-infra:review-task {task-id}
76
- - Codex CLI: $review-task {task-id}
78
+ - Claude Code / OpenCode: /review-code {task-id}
79
+ - Gemini CLI: /agent-infra:review-code {task-id}
80
+ - Codex CLI: $review-code {task-id}
77
81
  ```
78
82
 
79
83
  ### 场景 4:准备创建 PR