@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
package/lib/update.ts CHANGED
@@ -3,6 +3,8 @@ import path from 'node:path';
3
3
  import { info, ok, err } from './log.ts';
4
4
  import { resolveTemplateDir } from './paths.ts';
5
5
  import { renderFile, copySkillDir, KNOWN_PLATFORMS } from './render.ts';
6
+ import { isPathOwnedByDisabledTUI, resolveEnabledTUIs } from './builtin-tuis.ts';
7
+ import type { BuiltinTUIId } from './builtin-tuis.ts';
6
8
 
7
9
  type FileRegistry = {
8
10
  managed: string[];
@@ -15,14 +17,19 @@ type UpdateConfig = {
15
17
  org: string;
16
18
  language: string;
17
19
  platform?: { type?: string };
20
+ requiresPullRequest?: boolean;
18
21
  sandbox?: Record<string, unknown>;
22
+ task?: { shortIdLength: number };
19
23
  labels?: Record<string, unknown>;
20
24
  files?: Partial<FileRegistry>;
25
+ tuis?: unknown;
21
26
  };
22
27
 
23
28
  type Defaults = {
24
29
  platform: { type: string };
30
+ requiresPullRequest: boolean;
25
31
  sandbox: Record<string, unknown>;
32
+ task: { shortIdLength: number };
26
33
  labels: Record<string, unknown>;
27
34
  files: FileRegistry;
28
35
  };
@@ -43,7 +50,7 @@ function isPathOwnedByOtherPlatform(relativePath: string, platformType: string):
43
50
  return candidate !== platformType;
44
51
  }
45
52
 
46
- function syncFileRegistry(config: UpdateConfig, platformType: string) {
53
+ function syncFileRegistry(config: UpdateConfig, platformType: string, enabledTUIs: Set<BuiltinTUIId>) {
47
54
  config.files ||= {};
48
55
  const before = JSON.stringify({
49
56
  files: {
@@ -65,6 +72,7 @@ function syncFileRegistry(config: UpdateConfig, platformType: string) {
65
72
 
66
73
  for (const entry of defaults.files.managed) {
67
74
  if (isPathOwnedByOtherPlatform(entry, platformType)) continue;
75
+ if (isPathOwnedByDisabledTUI(entry, enabledTUIs)) continue;
68
76
  if (!allExisting.includes(entry)) {
69
77
  config.files.managed.push(entry);
70
78
  added.managed.push(entry);
@@ -72,6 +80,7 @@ function syncFileRegistry(config: UpdateConfig, platformType: string) {
72
80
  }
73
81
  for (const entry of defaults.files.merged) {
74
82
  if (isPathOwnedByOtherPlatform(entry, platformType)) continue;
83
+ if (isPathOwnedByDisabledTUI(entry, enabledTUIs)) continue;
75
84
  if (!allExisting.includes(entry)) {
76
85
  config.files.merged.push(entry);
77
86
  added.merged.push(entry);
@@ -116,6 +125,7 @@ async function cmdUpdate(): Promise<void> {
116
125
  const config = JSON.parse(fs.readFileSync(CONFIG_PATH, 'utf8')) as UpdateConfig;
117
126
  const { project, org, language } = config;
118
127
  const platformType = config.platform?.type || defaults.platform.type;
128
+ const enabledTUIs = resolveEnabledTUIs(config.tuis);
119
129
  const replacements = { project, org };
120
130
 
121
131
  info(`Updating seed files for: ${project}`);
@@ -148,36 +158,44 @@ async function cmdUpdate(): Promise<void> {
148
158
  // Ignore missing legacy script from pre-ESM installs.
149
159
  }
150
160
 
151
- // update Claude command
152
- renderFile(
153
- path.join(templateDir, '.claude', 'commands', claudeSrc),
154
- path.join('.claude', 'commands', 'update-agent-infra.md'),
155
- replacements
156
- );
157
- ok('Updated .claude/commands/update-agent-infra.md');
161
+ // update Claude command (only if enabled)
162
+ if (enabledTUIs.has('claude-code')) {
163
+ renderFile(
164
+ path.join(templateDir, '.claude', 'commands', claudeSrc),
165
+ path.join('.claude', 'commands', 'update-agent-infra.md'),
166
+ replacements
167
+ );
168
+ ok('Updated .claude/commands/update-agent-infra.md');
169
+ }
158
170
 
159
- // update Gemini command
160
- renderFile(
161
- path.join(templateDir, '.gemini', 'commands', '_project_', geminiSrc),
162
- path.join('.gemini', 'commands', project, 'update-agent-infra.toml'),
163
- replacements
164
- );
165
- ok(`Updated .gemini/commands/${project}/update-agent-infra.toml`);
171
+ // update Gemini command (only if enabled)
172
+ if (enabledTUIs.has('gemini-cli')) {
173
+ renderFile(
174
+ path.join(templateDir, '.gemini', 'commands', '_project_', geminiSrc),
175
+ path.join('.gemini', 'commands', project, 'update-agent-infra.toml'),
176
+ replacements
177
+ );
178
+ ok(`Updated .gemini/commands/${project}/update-agent-infra.toml`);
179
+ }
166
180
 
167
- // update OpenCode command
168
- renderFile(
169
- path.join(templateDir, '.opencode', 'commands', opencodeSrc),
170
- path.join('.opencode', 'commands', 'update-agent-infra.md'),
171
- replacements
172
- );
173
- ok('Updated .opencode/commands/update-agent-infra.md');
181
+ // update OpenCode command (only if enabled)
182
+ if (enabledTUIs.has('opencode')) {
183
+ renderFile(
184
+ path.join(templateDir, '.opencode', 'commands', opencodeSrc),
185
+ path.join('.opencode', 'commands', 'update-agent-infra.md'),
186
+ replacements
187
+ );
188
+ ok('Updated .opencode/commands/update-agent-infra.md');
189
+ }
174
190
 
175
191
  // sync file registry
176
- const { added, changed } = syncFileRegistry(config, platformType);
192
+ const { added, changed } = syncFileRegistry(config, platformType, enabledTUIs);
177
193
  const hasNewEntries = added.managed.length > 0 || added.merged.length > 0;
178
194
  const platformAdded = !config.platform;
179
195
  const sandboxAdded = !config.sandbox;
196
+ const taskAdded = !config.task;
180
197
  const labelsAdded = !config.labels;
198
+ const requiresPullRequestAdded = config.requiresPullRequest === undefined;
181
199
  let configChanged = changed;
182
200
 
183
201
  if (platformAdded) {
@@ -190,11 +208,21 @@ async function cmdUpdate(): Promise<void> {
190
208
  configChanged = true;
191
209
  }
192
210
 
211
+ if (taskAdded) {
212
+ config.task = structuredClone(defaults.task);
213
+ configChanged = true;
214
+ }
215
+
193
216
  if (labelsAdded) {
194
217
  config.labels = structuredClone(defaults.labels);
195
218
  configChanged = true;
196
219
  }
197
220
 
221
+ if (requiresPullRequestAdded) {
222
+ config.requiresPullRequest = defaults.requiresPullRequest;
223
+ configChanged = true;
224
+ }
225
+
198
226
  if (configChanged) {
199
227
  console.log('');
200
228
  if (hasNewEntries) {
@@ -205,28 +233,40 @@ async function cmdUpdate(): Promise<void> {
205
233
  for (const entry of added.merged) {
206
234
  ok(` merged: ${entry}`);
207
235
  }
208
- } else if (platformAdded || sandboxAdded || labelsAdded) {
236
+ } else if (platformAdded || sandboxAdded || taskAdded || labelsAdded || requiresPullRequestAdded) {
209
237
  if (platformAdded) {
210
238
  info(`Default platform config added to ${CONFIG_PATH}.`);
211
239
  }
212
240
  if (sandboxAdded) {
213
241
  info(`Default sandbox config added to ${CONFIG_PATH}.`);
214
242
  }
243
+ if (taskAdded) {
244
+ info(`Default task.shortIdLength=${defaults.task.shortIdLength} added to ${CONFIG_PATH}.`);
245
+ }
215
246
  if (labelsAdded) {
216
247
  info(`Default labels.in config added to ${CONFIG_PATH}.`);
217
248
  }
249
+ if (requiresPullRequestAdded) {
250
+ info(`Default requiresPullRequest=${defaults.requiresPullRequest} added to ${CONFIG_PATH}.`);
251
+ }
218
252
  } else {
219
253
  info(`File registry changed in ${CONFIG_PATH}.`);
220
254
  }
221
255
  if (hasNewEntries && sandboxAdded) {
222
256
  info(`Default sandbox config added to ${CONFIG_PATH}.`);
223
257
  }
258
+ if (hasNewEntries && taskAdded) {
259
+ info(`Default task.shortIdLength=${defaults.task.shortIdLength} added to ${CONFIG_PATH}.`);
260
+ }
224
261
  if (hasNewEntries && labelsAdded) {
225
262
  info(`Default labels.in config added to ${CONFIG_PATH}.`);
226
263
  }
227
264
  if (hasNewEntries && platformAdded) {
228
265
  info(`Default platform config added to ${CONFIG_PATH}.`);
229
266
  }
267
+ if (hasNewEntries && requiresPullRequestAdded) {
268
+ info(`Default requiresPullRequest=${defaults.requiresPullRequest} added to ${CONFIG_PATH}.`);
269
+ }
230
270
  fs.writeFileSync(CONFIG_PATH, JSON.stringify(config, null, 2) + '\n', 'utf8');
231
271
  ok(`Updated ${CONFIG_PATH}`);
232
272
  }
@@ -235,12 +275,27 @@ async function cmdUpdate(): Promise<void> {
235
275
  console.log('');
236
276
  ok('Seed files updated successfully!');
237
277
  console.log('');
238
- console.log(' Next step: run the full update in your AI TUI:');
239
- console.log('');
240
- console.log(' Claude Code / OpenCode: /update-agent-infra');
241
- console.log(` Gemini CLI: /${project}:update-agent-infra`);
242
- console.log(' Codex CLI: $update-agent-infra');
243
- console.log('');
278
+ if (enabledTUIs.size === 0) {
279
+ console.log(' No built-in TUI enabled (tuis: []).');
280
+ console.log(` Configure "customTUIs" in ${CONFIG_PATH} if needed.`);
281
+ console.log('');
282
+ } else {
283
+ console.log(' Next step: run the full update in your AI TUI:');
284
+ console.log('');
285
+ const claudeOrOpencode: string[] = [];
286
+ if (enabledTUIs.has('claude-code')) claudeOrOpencode.push('Claude Code');
287
+ if (enabledTUIs.has('opencode')) claudeOrOpencode.push('OpenCode');
288
+ if (claudeOrOpencode.length > 0) {
289
+ console.log(` ${claudeOrOpencode.join(' / ')}: /update-agent-infra`);
290
+ }
291
+ if (enabledTUIs.has('gemini-cli')) {
292
+ console.log(` Gemini CLI: /${project}:update-agent-infra`);
293
+ }
294
+ if (enabledTUIs.has('codex')) {
295
+ console.log(' Codex CLI: $update-agent-infra');
296
+ }
297
+ console.log('');
298
+ }
244
299
  }
245
300
 
246
301
  export { cmdUpdate };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fitlab-ai/agent-infra",
3
- "version": "0.6.5",
3
+ "version": "0.7.1",
4
4
  "description": "Bootstrap tool for AI multi-tool collaboration infrastructure — works with Claude Code, Codex, Gemini CLI, and OpenCode",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -164,7 +164,7 @@ The receiving AI should read this document first to get up to speed.
164
164
 
165
165
  ### 1. One AI Per Phase
166
166
 
167
- Don't have multiple AIs working on the same files simultaneously. Follow the sequential workflow: analyze, design, implement, review, fix, commit.
167
+ Don't have multiple AIs working on the same files simultaneously. Follow the sequential workflow: analysis → analysis-review → design design-review → code → code-review → commit (when any review finds issues, re-run the matching upstream stage).
168
168
 
169
169
  ### 2. Always Create Handoff Documents
170
170
 
@@ -164,7 +164,7 @@ cp .agents/templates/handoff.md .agents/workspace/active/handoff-task-001-phase2
164
164
 
165
165
  ### 1. 每个阶段一个 AI
166
166
 
167
- 不要让多个 AI 同时处理相同的文件。遵循顺序工作流:分析、设计、实现、审查、修复、提交。
167
+ 不要让多个 AI 同时处理相同的文件。遵循顺序工作流:分析 → 分析审查 → 设计 → 设计审查 → 编码 → 代码审查 → 提交(任一审查发现问题时,回到同名上游阶段重跑)。
168
168
 
169
169
  ### 2. 始终创建交接文档
170
170
 
@@ -210,6 +210,38 @@ The `files` field in `.agents/.airc.json` groups project files into three catego
210
210
 
211
211
  `ejected` entries support literal paths or globs, using the same matching rules as `merged`.
212
212
 
213
+ ## Built-in TUI Selection
214
+
215
+ Use the top-level `.agents/.airc.json` `tuis` array to pick which built-in TUIs (`claude-code`, `codex`, `gemini-cli`, `opencode`) agent-infra should install command files for and keep in sync.
216
+
217
+ | Value | Meaning |
218
+ |-------|---------|
219
+ | `tuis` missing or `null` | All four built-in TUIs are enabled (backward-compatible default for legacy `.airc.json` predating this field). |
220
+ | `tuis: []` | No built-in TUI is managed. Use this when the project only relies on `customTUIs` and does not need any built-in command files installed. |
221
+ | `tuis: [<subset>]` | Only the listed TUIs are managed. Unknown ids are ignored. |
222
+
223
+ `ai init` includes an interactive multi-select for this field:
224
+
225
+ - Press Enter to accept the default (all built-in TUIs enabled).
226
+ - Type comma-separated numbers or ids (e.g. `1,3` or `claude-code,opencode`) to keep a subset.
227
+ - Type `none` to explicitly disable every built-in TUI (typically combined with a `customTUIs` entry added later).
228
+ - Invalid input (duplicate, out-of-range, unknown id, whitespace-only) aborts init with a non-zero exit code.
229
+
230
+ ### Side effects of disabling a TUI
231
+
232
+ When you disable a built-in TUI (either via `ai init` or by hand-editing `.airc.json`), the next `ai update` / `update-agent-infra` will:
233
+
234
+ - skip seed command writes for that TUI (e.g. `.gemini/commands/<project>/update-agent-infra.toml`);
235
+ - skip the TUI's owned default entries when backfilling `files.managed` / `files.merged`;
236
+ - **clean up existing files** under the TUI's owned path prefix (`.claude/`, `.codex/`, `.gemini/`, `.opencode/`) — these are listed in `report.managed.removed`, mirroring the cleanup behavior when switching `platform`.
237
+
238
+ To opt a specific file out of this cleanup, list it in `files.ejected`; ejected entries owned by disabled TUIs are preserved as-is and are not re-created by sync.
239
+
240
+ ### Relation to other config fields
241
+
242
+ - `tuis` controls **which TUI command files agent-infra writes and maintains**. It is independent from `sandbox.tools`, which controls **which CLIs the sandbox image installs**. Toggling one does not affect the other; the README for `sandbox.tools` lives in the Sandbox section.
243
+ - `tuis` is independent from `customTUIs` (see below). CustomTUI command files are not removed when you disable a built-in TUI, even if the customTUI's `dir` falls under that TUI's owned prefix (e.g. a customTUI configured with `dir: ".codex/commands"` is preserved when `codex` is disabled).
244
+
213
245
  ## Custom TUI Configuration
214
246
 
215
247
  Use the top-level `.agents/.airc.json` `customTUIs` array when your team uses an AI TUI that is not one of the built-in command targets. This config lets agent-infra show the correct next-step commands and generate command files for project custom skills by learning from an existing command in the custom TUI directory.
@@ -224,8 +256,8 @@ Supported `invoke` placeholders:
224
256
 
225
257
  | Placeholder | Replaced with | Example |
226
258
  |-------------|---------------|---------|
227
- | `${skillName}` | The skill command name, such as `review-task` or `commit`. | `<your-cli> ${skillName}` -> `<your-cli> review-task` |
228
- | `${projectName}` | The `.airc.json` `project` value. Use this for namespaced commands. | `/${projectName}:${skillName}` -> `/agent-infra:review-task` |
259
+ | `${skillName}` | The skill command name, such as `review-code` or `commit`. | `<your-cli> ${skillName}` -> `<your-cli> review-code` |
260
+ | `${projectName}` | The `.airc.json` `project` value. Use this for namespaced commands. | `/${projectName}:${skillName}` -> `/agent-infra:review-code` |
229
261
 
230
262
  Non-namespaced custom TUI:
231
263
 
@@ -258,6 +290,83 @@ Namespaced custom TUI:
258
290
 
259
291
  `customTUIs` should contain one entry per custom TUI. To let `update-agent-infra` generate command files for custom skills, keep at least one existing command file in `dir` that references a built-in skill path such as `.agents/skills/analyze-task/SKILL.md`; agent-infra uses that file as the format reference.
260
292
 
293
+ ## Sandbox Custom Tools
294
+
295
+ `customTUIs` (above) generates slash-command files but does not change the sandbox image. To install a non-npm TUI (pip / cargo / curl-based / pre-built binary) into the sandbox image and live-mount its credentials, declare it under `sandbox.customTools` in `.agents/.airc.json`. Built-in tools (`claude-code`, `codex`, `opencode`, `gemini-cli`) keep working unchanged.
296
+
297
+ ### Required fields
298
+
299
+ | Field | Meaning |
300
+ |-------|---------|
301
+ | `id` | Lowercase id matching `^[a-z0-9][a-z0-9-]*$`. Referenced from `sandbox.tools`. Must not collide with a built-in id. |
302
+ | `install` | Install descriptor. `{ "type": "npm", "cmd": "<npm package spec>" }` runs `npm install -g <cmd>`. `{ "type": "shell", "cmd": "<shell>" }` runs the shell command(s) as `devuser` during image build. `cmd` must be non-empty. |
303
+
304
+ Minimal entry — the contract for getting a tool into the image is just these two fields:
305
+
306
+ ```json
307
+ {
308
+ "sandbox": {
309
+ "tools": ["my-shell-tool"],
310
+ "customTools": [
311
+ {
312
+ "id": "my-shell-tool",
313
+ "install": { "type": "shell", "cmd": "curl -fsSL https://example.com/install.sh | bash" }
314
+ }
315
+ ]
316
+ }
317
+ }
318
+ ```
319
+
320
+ ### Optional integration fields
321
+
322
+ Add only the fields your tool actually needs. Omit them and the loader fills sensible defaults; provide them and the loader uses your value. Provide an explicit empty string and the loader rejects it (preventing silent install-verification bypass).
323
+
324
+ | Field | Default when omitted | When to provide |
325
+ |-------|---------------------|-----------------|
326
+ | `name` | `id` | A friendlier display name in sandbox reports / hints. |
327
+ | `containerMount` | `/home/devuser/.<id>` | Your tool stores its config / state somewhere other than `~/.<id>`. Must be an absolute path. |
328
+ | `versionCmd` | `which <id>` | The installed binary name differs from `id` (e.g. id `anthropic-claude`, binary `claude`); set `"claude --version"` so sandbox-create can verify the install. |
329
+ | `setupHint` | `Run \`<id>\` inside the container to set up.` | The setup story is non-obvious and worth a one-liner. |
330
+ | `envVars` | (none) | Your tool reads config from a path the env points to (e.g. `XDG_CONFIG_HOME`-style or a custom `*_CONFIG` env). Shape: `Record<string, string>`. |
331
+ | `hostPreSeedFiles` / `hostPreSeedDirs` | (none) | Seed the tool's sandbox dir from host files / directories on first launch. |
332
+ | `pathRewriteFiles` | (none) | Seeded files contain absolute host paths that need rewriting to container paths. |
333
+ | `hostLiveMounts` | (none) | Share host credentials live (e.g. OAuth tokens) with the container. Read-write. |
334
+ | `postSetupCmds` | (none) | Run commands inside the container after first setup (e.g. symlinks). |
335
+
336
+ > **`sandboxBase` is not user-configurable.** The loader always assigns `~/.agent-infra/sandboxes/<id>` so `ai sandbox rm` / `prune` can find tool state. Any `sandboxBase` value in `customTools` entries is silently ignored.
337
+
338
+ Real-world example — `anthropic-claude` as a user-defined id with binary name `claude` and host credential live-mount:
339
+
340
+ ```json
341
+ {
342
+ "sandbox": {
343
+ "tools": ["claude-code", "anthropic-claude"],
344
+ "customTools": [
345
+ {
346
+ "id": "anthropic-claude",
347
+ "install": { "type": "npm", "cmd": "@anthropic-ai/claude-code@stable" },
348
+ "versionCmd": "claude --version",
349
+ "hostLiveMounts": [
350
+ { "hostPath": "~/.claude/.credentials.json", "containerSubpath": ".credentials.json" }
351
+ ]
352
+ }
353
+ ]
354
+ }
355
+ }
356
+ ```
357
+
358
+ ### Trust boundary and execution context
359
+
360
+ - `install.cmd` runs as user `devuser` (non-root) during `docker build`. It can write to the container's filesystem but cannot escape to the host. The trust model is the same as for the `sandbox.dockerfile` escape hatch — you own the `.airc.json` in your repo, so you own what runs at build time.
361
+ - Because the build runs as `devuser`, shell installs cannot `sudo` / `apt-get`. Available options for non-npm distributions:
362
+ - User-scope installers landing in `~/.local/bin`, `~/.cargo/bin`, `~/.npm-global/bin` (e.g. `pipx`, `cargo install`, `curl … | bash` with `INSTALL_DIR=$HOME/.local/bin`).
363
+ - When you genuinely need root or system packages, fall back to the existing `sandbox.dockerfile` field and own the full Dockerfile.
364
+ - Changing `install.cmd` (or any field that participates in the image signature) triggers exactly one image rebuild on the next `ai sandbox` invocation.
365
+
366
+ ### Interaction with `sandbox.dockerfile`
367
+
368
+ When you set `sandbox.dockerfile` to point at your own Dockerfile, agent-infra still passes both `AI_TOOL_PACKAGES` (space-separated npm package specs) and `AI_TOOLS_SHELL_INSTALL_B64` (base64-encoded shell install script) as `--build-arg`. Your custom Dockerfile decides whether to consume them; if it does not declare the matching `ARG`, the shell installs for `customTools` are silently skipped — taking over the Dockerfile means taking over the install path.
369
+
261
370
  ## Skill Authoring Conventions
262
371
 
263
372
  When writing or updating `.agents/skills/*/SKILL.md` files and their templates, keep step numbering consistent:
@@ -210,6 +210,38 @@ args: "<task-id>" # 可选
210
210
 
211
211
  `ejected` 条目支持字面路径或 glob,匹配规则与 `merged` 相同。
212
212
 
213
+ ## 内建 TUI 选择
214
+
215
+ `.agents/.airc.json` 顶层 `tuis` 数组用于决定 agent-infra 应当为哪些内建 TUI(`claude-code`、`codex`、`gemini-cli`、`opencode`)安装并维护命令文件。
216
+
217
+ | 取值 | 含义 |
218
+ |------|------|
219
+ | `tuis` 缺失或为 `null` | 启用全部四个内建 TUI(向后兼容默认,适用于本字段引入之前的 `.airc.json`) |
220
+ | `tuis: []` | 不维护任何内建 TUI。适用于只依赖 `customTUIs`、不需要安装任何内建命令文件的项目 |
221
+ | `tuis: [<子集>]` | 仅维护列出的 TUI;未知 id 会被忽略 |
222
+
223
+ `ai init` 会通过交互式多选询问该字段:
224
+
225
+ - 直接回车 = 接受默认值(全部内建 TUI 启用)。
226
+ - 输入逗号分隔的编号或 id(如 `1,3` 或 `claude-code,opencode`)= 只保留子集。
227
+ - 输入 `none` = 明确不启用任何内建 TUI(通常配合后续在 `customTUIs` 添加条目使用)。
228
+ - 非法输入(重复、超界、未知 id、纯空白)会让 init 以非零退出码终止。
229
+
230
+ ### 取消某个 TUI 的副作用
231
+
232
+ 通过 `ai init` 或手工编辑 `.airc.json` 取消某个内建 TUI 后,下一次 `ai update` / `update-agent-infra` 会:
233
+
234
+ - 跳过该 TUI 的 seed 命令文件写入(例如 `.gemini/commands/<project>/update-agent-infra.toml`);
235
+ - 在回填 `files.managed` / `files.merged` 时跳过该 TUI owned 的默认条目;
236
+ - **物理清理**该 TUI owned 路径前缀(`.claude/`、`.codex/`、`.gemini/`、`.opencode/`)下的已有文件——清理列表会出现在 `report.managed.removed`,与切换 `platform` 时的清理行为一致。
237
+
238
+ 若希望保留某个具体文件,把它加入 `files.ejected`:被 ejected 的、属于已取消 TUI 的条目会保持原状,sync 不会重新创建也不会删除。
239
+
240
+ ### 与其他配置字段的关系
241
+
242
+ - `tuis` 控制 **agent-infra 写入与维护哪些 TUI 的命令文件**,与 `sandbox.tools`(控制**沙箱镜像里安装哪些 CLI**)相互独立。两者互不影响;`sandbox.tools` 的说明见 Sandbox 一节。
243
+ - `tuis` 与 `customTUIs`(见下)相互独立。取消某个内建 TUI 时 customTUI 命令文件不会被清理,即便 customTUI 的 `dir` 落在该 TUI 的 owned 前缀下(例如 `dir: ".codex/commands"` 的 customTUI 在 `codex` 被取消时仍会保留)。
244
+
213
245
  ## 自定义 TUI 配置
214
246
 
215
247
  当团队使用的 AI TUI 不属于内置命令目标时,可以在 `.agents/.airc.json` 顶层配置 `customTUIs` 数组。该配置用于让 agent-infra 输出正确的下一步命令,并通过学习自定义 TUI 目录中的既有命令文件,为项目自定义 skill 生成同格式命令。
@@ -224,8 +256,8 @@ args: "<task-id>" # 可选
224
256
 
225
257
  | 占位符 | 替换为 | 示例 |
226
258
  |--------|--------|------|
227
- | `${skillName}` | skill 命令名,例如 `review-task` 或 `commit`。 | `<your-cli> ${skillName}` -> `<your-cli> review-task` |
228
- | `${projectName}` | `.airc.json` 中的 `project` 值,适用于带命名空间的命令。 | `/${projectName}:${skillName}` -> `/agent-infra:review-task` |
259
+ | `${skillName}` | skill 命令名,例如 `review-code` 或 `commit`。 | `<your-cli> ${skillName}` -> `<your-cli> review-code` |
260
+ | `${projectName}` | `.airc.json` 中的 `project` 值,适用于带命名空间的命令。 | `/${projectName}:${skillName}` -> `/agent-infra:review-code` |
229
261
 
230
262
  不带命名空间的自定义 TUI:
231
263
 
@@ -258,6 +290,83 @@ args: "<task-id>" # 可选
258
290
 
259
291
  `customTUIs` 每个条目对应一个自定义 TUI。若希望 `update-agent-infra` 为自定义 skill 生成命令文件,请在 `dir` 中保留至少一个引用内置 skill 路径的既有命令文件,例如 `.agents/skills/analyze-task/SKILL.md`;agent-infra 会以该文件作为格式参考。
260
292
 
293
+ ## 沙箱自定义工具(Sandbox Custom Tools)
294
+
295
+ 上文 `customTUIs` 只负责生成 slash-command 文件,**不影响沙箱镜像**。如果要把一个非 npm 分发的 TUI(pip / cargo / curl 脚本 / 裸二进制)装进沙箱镜像、并 live-mount 它的凭证目录,需要在 `.agents/.airc.json` 的 `sandbox.customTools` 中声明。内建的四个工具(`claude-code` / `codex` / `opencode` / `gemini-cli`)行为保持不变。
296
+
297
+ ### 必填字段
298
+
299
+ | 字段 | 含义 |
300
+ |------|------|
301
+ | `id` | 小写 id,匹配 `^[a-z0-9][a-z0-9-]*$`;由 `sandbox.tools` 引用;不可与内建 id 冲突。 |
302
+ | `install` | 安装描述符。`{ "type": "npm", "cmd": "<npm 包规范>" }` 执行 `npm install -g <cmd>`;`{ "type": "shell", "cmd": "<shell>" }` 在镜像构建阶段以 `devuser` 执行 shell。`cmd` 必须非空。 |
303
+
304
+ 最小入口——把一个工具装进镜像所需的契约只有这两个字段:
305
+
306
+ ```json
307
+ {
308
+ "sandbox": {
309
+ "tools": ["my-shell-tool"],
310
+ "customTools": [
311
+ {
312
+ "id": "my-shell-tool",
313
+ "install": { "type": "shell", "cmd": "curl -fsSL https://example.com/install.sh | bash" }
314
+ }
315
+ ]
316
+ }
317
+ }
318
+ ```
319
+
320
+ ### 可选集成字段
321
+
322
+ 只在你的工具真正需要时才加。**省略**则 loader 用合理默认值;**显式提供**则用你给的值;**显式给空串**会被拒绝(防止安装验证被绕过)。
323
+
324
+ | 字段 | 省略时的默认值 | 什么时候应该提供 |
325
+ |------|---------------|----------------|
326
+ | `name` | `id` | 想在沙箱报告 / 提示里显示更友好的名称。 |
327
+ | `containerMount` | `/home/devuser/.<id>` | 工具的配置 / 状态目录不在 `~/.<id>` 而在别处。必须是绝对路径。 |
328
+ | `versionCmd` | `which <id>` | 安装后的可执行文件名与 `id` 不同(例如 id 是 `anthropic-claude`,二进制名是 `claude`);填 `"claude --version"` 让 sandbox-create 能验证安装。 |
329
+ | `setupHint` | `Run \`<id>\` inside the container to set up.` | setup 流程不一目了然,值得用一行说明。 |
330
+ | `envVars` | (无) | 工具通过环境变量找配置(如 `XDG_CONFIG_HOME` 风格或自定义 `*_CONFIG` 变量)。形状:`Record<string, string>`。 |
331
+ | `hostPreSeedFiles` / `hostPreSeedDirs` | (无) | 首次启动时从宿主复制文件 / 目录到工具沙箱配置目录。 |
332
+ | `pathRewriteFiles` | (无) | seed 进来的文件里有宿主绝对路径,需要改写为容器路径。 |
333
+ | `hostLiveMounts` | (无) | 把宿主凭证(如 OAuth token)实时挂进容器,读写共享。 |
334
+ | `postSetupCmds` | (无) | 首次安装完成后在容器内执行命令(如建符号链接)。 |
335
+
336
+ > **`sandboxBase` 不由用户配置。** loader 永远使用 `~/.agent-infra/sandboxes/<id>`,这样 `ai sandbox rm` / `prune` 才能找到工具状态目录。`customTools` 条目里写的任何 `sandboxBase` 都会被静默忽略。
337
+
338
+ 实际场景示例——`anthropic-claude` 作为用户自定义 id,二进制名是 `claude`,并把宿主凭证 live-mount 进来:
339
+
340
+ ```json
341
+ {
342
+ "sandbox": {
343
+ "tools": ["claude-code", "anthropic-claude"],
344
+ "customTools": [
345
+ {
346
+ "id": "anthropic-claude",
347
+ "install": { "type": "npm", "cmd": "@anthropic-ai/claude-code@stable" },
348
+ "versionCmd": "claude --version",
349
+ "hostLiveMounts": [
350
+ { "hostPath": "~/.claude/.credentials.json", "containerSubpath": ".credentials.json" }
351
+ ]
352
+ }
353
+ ]
354
+ }
355
+ }
356
+ ```
357
+
358
+ ### 信任边界与执行身份
359
+
360
+ - `install.cmd` 在 `docker build` 阶段以 `devuser`(非 root)身份执行,只能写容器内文件系统,不能逃逸到宿主。信任模型与现有 `sandbox.dockerfile` 一致:你是 `.airc.json` 的作者,本次构建做什么由你负责。
361
+ - 因为不是 root,shell 安装无法 `sudo` / `apt-get`。非 npm 分发的几条可用路径:
362
+ - 用户态安装器,落到 `~/.local/bin`、`~/.cargo/bin`、`~/.npm-global/bin`(如 `pipx`、`cargo install`、`curl … | bash` 配合 `INSTALL_DIR=$HOME/.local/bin`)。
363
+ - 确实需要 root / 系统包时,仍走原有 `sandbox.dockerfile` 字段,接管整个 Dockerfile。
364
+ - 修改 `install.cmd` 或任何参与镜像签名的字段,下次 `ai sandbox` 命令会触发一次镜像重建。
365
+
366
+ ### 与 `sandbox.dockerfile` 的交互
367
+
368
+ 当 `sandbox.dockerfile` 指向自定义 Dockerfile 时,agent-infra 仍会把 `AI_TOOL_PACKAGES`(空格分隔的 npm 包规范)和 `AI_TOOLS_SHELL_INSTALL_B64`(base64 编码的 shell 安装脚本)作为 `--build-arg` 传入。你的自定义 Dockerfile 若未声明对应 `ARG`,shell 安装路径会被 docker build 静默忽略——这是接管 Dockerfile 后的应有代价。
369
+
261
370
  ## Skill 编写规范
262
371
 
263
372
  编写或维护 `.agents/skills/*/SKILL.md` 及其模板时,步骤编号遵循以下规则:
@@ -2,4 +2,4 @@
2
2
 
3
3
  This code platform does not provide an Issue creation rule.
4
4
 
5
- `create-task` skips the cascade Issue creation step on this platform; the local `task.md` remains a valid artifact. If you later want to bind the task to an Issue, manually write `issue_number` into `task.md` and the subsequent skills (`commit` / `refine-task` / `complete-task`, etc.) will pick up Issue metadata syncing through the existing cascade rules.
5
+ `create-task` skips the cascade Issue creation step on this platform; the local `task.md` remains a valid artifact. If you later want to bind the task to an Issue, manually write `issue_number` into `task.md` and the subsequent skills (`commit` / `code-task` / `complete-task`, etc.) will pick up Issue metadata syncing through the existing cascade rules.
@@ -5,7 +5,7 @@ After `create-task` writes the local `task.md`, follow this rule to cascade Issu
5
5
  ## Boundary
6
6
 
7
7
  - Issue title and body must come from `task.md` only
8
- - Do not read `analysis.md`, `plan.md`, `implementation.md`, or any review artifact
8
+ - Do not read `analysis.md`, `review-analysis.md`, `plan.md`, `review-plan.md`, `code.md`, or any review-code artifact
9
9
  - Persistent outputs are limited to the remote Issue and the `issue_number` written back to `task.md`
10
10
  - If Issue creation fails, do not roll back `task.md`; the current task remains valid for the workflow, and the user can later manually fill `issue_number` so other skills' cascade sync takes over
11
11
 
@@ -5,7 +5,7 @@
5
5
  ## 行为边界
6
6
 
7
7
  - Issue 标题和正文只能来自 `task.md`
8
- - 不读取 `analysis.md`、`plan.md`、`implementation.md` 或审查产物
8
+ - 不读取 `analysis.md`、`review-analysis.md`、`plan.md`、`review-plan.md`、`code.md` 或代码审查产物
9
9
  - 持久产物只有:远端 Issue + `task.md` 中回写的 `issue_number`
10
10
  - Issue 创建失败时不回滚 `task.md`;当前 task 仍可继续后续工作流,未来可由用户手动写入 `issue_number`,让其它技能的级联同步接管
11
11
 
@@ -2,4 +2,4 @@
2
2
 
3
3
  当前代码平台未提供 Issue 创建规则。
4
4
 
5
- `create-task` 在本平台上会跳过级联创建 Issue 步骤;本地 `task.md` 仍然是有效产物。如果将来需要把任务绑定到一个 Issue,可手动在 `task.md` 中写入 `issue_number`,后续技能(`commit` / `refine-task` / `complete-task` 等)会按既有的级联同步规则自动接管 Issue 元数据更新。
5
+ `create-task` 在本平台上会跳过级联创建 Issue 步骤;本地 `task.md` 仍然是有效产物。如果将来需要把任务绑定到一个 Issue,可手动在 `task.md` 中写入 `issue_number`,后续技能(`commit` / `code-task` / `complete-task` 等)会按既有的级联同步规则自动接管 Issue 元数据更新。
@@ -123,7 +123,7 @@ When a skill creates or imports an Issue, automatically add the current executor
123
123
 
124
124
  ## `in:` Label Sync
125
125
 
126
- > **Trigger timing**: run `in:` label sync only after code is committed (the `commit` skill). Do not run it during `implement-task` or `refine-task`. During `create-pr`, only copy the labels from the Issue to the PR without recomputing them.
126
+ > **Trigger timing**: run `in:` label sync only after code is committed (the `commit` skill). Do not run it during `code-task`. During `create-pr`, only copy the labels from the Issue to the PR without recomputing them.
127
127
 
128
128
  Read the `labels.in` mapping from `.agents/.airc.json`.
129
129
 
@@ -262,7 +262,7 @@ task comment sync always runs and is never downgraded.
262
262
 
263
263
  ## Backfill Rules (run before `/complete-task` archives)
264
264
 
265
- - Scan `task.md`, `analysis*.md`, `plan*.md`, `implementation*.md`, `review*.md`, and `refinement*.md` in the task directory
265
+ - Scan `task.md`, `analysis*.md`, `review-analysis*.md`, `plan*.md`, `review-plan*.md`, `code*.md`, and `review-code*.md` in the task directory
266
266
  - Check whether each `{file-stem}` was already published by its hidden marker; publish only missing artifacts
267
267
  - Backfill only appends missing comments and never deletes or reorders existing comments
268
268
  - Resolve `{agent}` for backfilled comments in this order:
@@ -281,10 +281,11 @@ Title mapping:
281
281
 
282
282
  - `task` -> `Task File`
283
283
  - `analysis` / `analysis-r{N}` -> `Requirements Analysis` / `Requirements Analysis (Round {N})`
284
+ - `review-analysis` / `review-analysis-r{N}` -> `Requirements Analysis Review (Round 1)` / `Requirements Analysis Review (Round {N})`
284
285
  - `plan` / `plan-r{N}` -> `Technical Plan` / `Technical Plan (Round {N})`
285
- - `implementation` / `implementation-r{N}` -> `Implementation Report (Round 1)` / `Implementation Report (Round {N})`
286
- - `review` / `review-r{N}` -> `Review Report (Round 1)` / `Review Report (Round {N})`
287
- - `refinement` / `refinement-r{N}` -> `Refinement Report (Round 1)` / `Refinement Report (Round {N})`
286
+ - `review-plan` / `review-plan-r{N}` -> `Technical Plan Review (Round 1)` / `Technical Plan Review (Round {N})`
287
+ - `code` / `code-r{N}` -> `Code Report (Round 1)` / `Code Report (Round {N})`
288
+ - `review-code` / `review-code-r{N}` -> `Code Review (Round 1)` / `Code Review (Round {N})`
288
289
  - `summary` -> `Delivery Summary`
289
290
 
290
291
  Backfilled comments are also not gated by `has_triage` or `has_push`.
@@ -123,7 +123,7 @@ fi
123
123
 
124
124
  ## `in:` label 同步
125
125
 
126
- > **触发时机**:`in:` label 同步应在代码提交后(commit 技能)执行,不在 implement-task 或 refine-task 阶段执行。create-pr 阶段仅从 Issue 复制到 PR,不重新计算。
126
+ > **触发时机**:`in:` label 同步应在代码提交后(commit 技能)执行,不在 code-task 阶段执行。create-pr 阶段仅从 Issue 复制到 PR,不重新计算。
127
127
 
128
128
  读取 `.agents/.airc.json` 的 `labels.in` 映射。
129
129
 
@@ -262,7 +262,7 @@ task 留言同步始终执行,不受权限降级影响。
262
262
 
263
263
  ## 补发规则(`/complete-task` 归档前执行)
264
264
 
265
- - 扫描任务目录中的 `task.md`、`analysis*.md`、`plan*.md`、`implementation*.md`、`review*.md`、`refinement*.md`
265
+ - 扫描任务目录中的 `task.md`、`analysis*.md`、`review-analysis*.md`、`plan*.md`、`review-plan*.md`、`code*.md`、`review-code*.md`
266
266
  - 对每个 `{file-stem}` 用隐藏标记检查是否已发布;未发布则补发,已发布则跳过
267
267
  - 补发只追加缺失评论,不删除或重排已有评论
268
268
  - 补发评论的 `{agent}` 按以下顺序确定:
@@ -281,10 +281,11 @@ task 留言同步始终执行,不受权限降级影响。
281
281
 
282
282
  - `task` -> `任务文件`
283
283
  - `analysis` / `analysis-r{N}` -> `需求分析` / `需求分析(Round {N})`
284
+ - `review-analysis` / `review-analysis-r{N}` -> `需求分析审查(Round 1)` / `需求分析审查(Round {N})`
284
285
  - `plan` / `plan-r{N}` -> `技术方案` / `技术方案(Round {N})`
285
- - `implementation` / `implementation-r{N}` -> `实现报告(Round 1)` / `实现报告(Round {N})`
286
- - `review` / `review-r{N}` -> `审查报告(Round 1)` / `审查报告(Round {N})`
287
- - `refinement` / `refinement-r{N}` -> `修复报告(Round 1)` / `修复报告(Round {N})`
286
+ - `review-plan` / `review-plan-r{N}` -> `技术方案审查(Round 1)` / `技术方案审查(Round {N})`
287
+ - `code` / `code-r{N}` -> `实现报告(Round 1)` / `实现报告(Round {N})`
288
+ - `review-code` / `review-code-r{N}` -> `代码审查(Round 1)` / `代码审查(Round {N})`
288
289
  - `summary` -> `交付摘要`
289
290
 
290
291
  补发评论同样不受 `has_triage` / `has_push` 限制。
@@ -1,6 +1,6 @@
1
1
  # Milestone Inference Rules
2
2
 
3
- Read this file before the `create-task` platform rule, `implement-task`, or `create-pr` handles a milestone.
3
+ Read this file before the `create-task` platform rule, `code-task`, or `create-pr` handles a milestone.
4
4
 
5
5
  ## General Principles
6
6
 
@@ -56,7 +56,7 @@ fi
56
56
 
57
57
  If `has_triage=false`, inference returns empty, or `gh issue edit` fails, skip and continue without blocking the `import-issue` workflow.
58
58
 
59
- ## Phase 2: `implement-task`
59
+ ## Phase 2: `code-task`
60
60
 
61
61
  Goal: narrow the Issue milestone from a release line to a concrete version when implementation starts.
62
62