@fitlab-ai/agent-infra 0.4.4 → 0.5.0

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 (49) hide show
  1. package/README.md +16 -2
  2. package/README.zh-CN.md +16 -2
  3. package/bin/cli.js +19 -0
  4. package/lib/defaults.json +17 -0
  5. package/lib/init.js +1 -0
  6. package/lib/log.js +5 -10
  7. package/lib/merge.js +465 -0
  8. package/lib/sandbox/commands/create.js +1047 -0
  9. package/lib/sandbox/commands/enter.js +31 -0
  10. package/lib/sandbox/commands/ls.js +70 -0
  11. package/lib/sandbox/commands/rebuild.js +102 -0
  12. package/lib/sandbox/commands/rm.js +211 -0
  13. package/lib/sandbox/commands/vm.js +101 -0
  14. package/lib/sandbox/config.js +79 -0
  15. package/lib/sandbox/constants.js +113 -0
  16. package/lib/sandbox/dockerfile.js +95 -0
  17. package/lib/sandbox/engine.js +93 -0
  18. package/lib/sandbox/index.js +64 -0
  19. package/lib/sandbox/runtimes/ai-tools.dockerfile +26 -0
  20. package/lib/sandbox/runtimes/base.dockerfile +30 -0
  21. package/lib/sandbox/runtimes/java17.dockerfile +3 -0
  22. package/lib/sandbox/runtimes/java21.dockerfile +3 -0
  23. package/lib/sandbox/runtimes/node20.dockerfile +3 -0
  24. package/lib/sandbox/runtimes/node22.dockerfile +3 -0
  25. package/lib/sandbox/runtimes/python3.dockerfile +3 -0
  26. package/lib/sandbox/shell.js +48 -0
  27. package/lib/sandbox/task-resolver.js +35 -0
  28. package/lib/sandbox/tools.js +131 -0
  29. package/lib/update.js +16 -2
  30. package/package.json +5 -1
  31. package/templates/.agents/rules/commit-and-pr.md +30 -0
  32. package/templates/.agents/rules/commit-and-pr.zh-CN.md +30 -0
  33. package/templates/.agents/rules/issue-sync.md +12 -2
  34. package/templates/.agents/rules/issue-sync.zh-CN.md +12 -2
  35. package/templates/.agents/rules/task-management.md +28 -0
  36. package/templates/.agents/rules/task-management.zh-CN.md +28 -0
  37. package/templates/.agents/scripts/validate-artifact.js +40 -0
  38. package/templates/.agents/skills/archive-tasks/SKILL.md +6 -3
  39. package/templates/.agents/skills/archive-tasks/SKILL.zh-CN.md +6 -3
  40. package/templates/.agents/skills/archive-tasks/scripts/archive-tasks.sh +91 -8
  41. package/templates/.agents/skills/create-task/SKILL.md +6 -0
  42. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +6 -0
  43. package/templates/.agents/skills/create-task/config/verify.json +1 -0
  44. package/templates/.agents/skills/import-issue/SKILL.md +2 -0
  45. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +2 -0
  46. package/templates/.agents/skills/import-issue/config/verify.json +1 -0
  47. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +18 -1
  48. package/templates/.agents/templates/task.md +5 -4
  49. package/templates/.agents/templates/task.zh-CN.md +5 -4
@@ -88,12 +88,16 @@ Use this format:
88
88
  <!-- sync-issue:{task-id}:{file-stem} -->
89
89
  ## {artifact-title}
90
90
 
91
+ > **{agent}** · {task-id}
92
+
91
93
  {artifact body}
92
94
 
93
95
  ---
94
- *Generated by AI · Internal tracking: {task-id}*
96
+ *Generated by {agent} · Internal tracking: {task-id}*
95
97
  ```
96
98
 
99
+ `{agent}` is the name of the AI agent currently executing the skill (for example `claude`, `codex`, or `gemini`).
100
+
97
101
  `summary` comments need extra handling:
98
102
  - find an existing `<!-- sync-issue:{task-id}:summary -->` comment ID first
99
103
  - create the comment when none exists
@@ -133,6 +137,8 @@ task.md comment format:
133
137
  <!-- sync-issue:{task-id}:task -->
134
138
  ## Task File
135
139
 
140
+ > **{agent}** · {task-id}
141
+
136
142
  <details><summary>Metadata (frontmatter)</summary>
137
143
 
138
144
  ​```yaml
@@ -146,7 +152,7 @@ task.md comment format:
146
152
  {task.md body after frontmatter}
147
153
 
148
154
  ---
149
- *Generated by AI · Internal tracking: {task-id}*
155
+ *Generated by {agent} · Internal tracking: {task-id}*
150
156
  ```
151
157
 
152
158
  When restoring, extract the frontmatter from the `<details>` block and reassemble with the body to recover the original `task.md`.
@@ -159,6 +165,10 @@ Title mapping:
159
165
  - Scan `task.md`, `analysis*.md`, `plan*.md`, `implementation*.md`, `review*.md`, and `refinement*.md` in the task directory
160
166
  - Check whether each `{file-stem}` was already published by its hidden marker; publish only missing artifacts
161
167
  - Backfill only appends missing comments; never delete or reorder existing comments
168
+ - Resolve `{agent}` for backfilled comments in this order:
169
+ 1. Match the artifact filename in Activity Log (for example `→ analysis.md`) and extract the executor from `by {agent}`
170
+ 2. If no match is found, fall back to `assigned_to` in task.md frontmatter
171
+ 3. If `assigned_to` is also unavailable, use the current backfilling agent
162
172
  - Derive the previous and next neighbors from Activity Log order and add this note below the title:
163
173
 
164
174
  ```markdown
@@ -88,12 +88,16 @@ gh api "repos/{owner}/{repo}/issues/{issue-number}/comments" \
88
88
  <!-- sync-issue:{task-id}:{file-stem} -->
89
89
  ## {artifact-title}
90
90
 
91
+ > **{agent}** · {task-id}
92
+
91
93
  {artifact body}
92
94
 
93
95
  ---
94
- *由 AI 自动生成 · 内部追踪:{task-id}*
96
+ *由 {agent} 自动生成 · 内部追踪:{task-id}*
95
97
  ```
96
98
 
99
+ 其中 `{agent}` 使用当前执行该技能的 AI 代理名称(如 `claude`、`codex`、`gemini`)。
100
+
97
101
  `summary` 评论需要额外处理:
98
102
  - 先查找已有 `<!-- sync-issue:{task-id}:summary -->` 评论的 ID
99
103
  - 不存在则创建
@@ -133,6 +137,8 @@ task.md 评论格式:
133
137
  <!-- sync-issue:{task-id}:task -->
134
138
  ## 任务文件
135
139
 
140
+ > **{agent}** · {task-id}
141
+
136
142
  <details><summary>元数据 (frontmatter)</summary>
137
143
 
138
144
  ​```yaml
@@ -146,7 +152,7 @@ task.md 评论格式:
146
152
  {task.md body after frontmatter}
147
153
 
148
154
  ---
149
- *由 AI 自动生成 · 内部追踪:{task-id}*
155
+ *由 {agent} 自动生成 · 内部追踪:{task-id}*
150
156
  ```
151
157
 
152
158
  还原时,从 `<details>` 块中提取 frontmatter,与正文拼合恢复为原始 `task.md`。
@@ -159,6 +165,10 @@ task.md 评论格式:
159
165
  - 扫描任务目录中的 `task.md`、`analysis*.md`、`plan*.md`、`implementation*.md`、`review*.md`、`refinement*.md`
160
166
  - 对每个 `{file-stem}` 用隐藏标记检查是否已发布;未发布则补发,已发布则跳过
161
167
  - 补发只追加缺失评论,不删除或重排已有评论
168
+ - 补发评论的 `{agent}` 按以下顺序确定:
169
+ 1. 从 Activity Log 中匹配对应产物文件名(如 `→ analysis.md`),提取 `by {agent}` 中的执行者
170
+ 2. 若未匹配到,则回退到 task.md frontmatter 的 `assigned_to`
171
+ 3. 若 `assigned_to` 也不可用,则使用当前执行补发的 agent
162
172
  - 位置说明从 Activity Log 推导时间线中的前后邻居,并加在评论标题下方:
163
173
 
164
174
  ```markdown
@@ -0,0 +1,28 @@
1
+ # General Rules - Task Management
2
+
3
+ ## Task Intent Detection
4
+
5
+ Map user intent to the corresponding workflow command:
6
+ - "analyze issue #123" -> `import-issue`
7
+ - "analyze task TASK-20260306-143022" -> `analyze-task`
8
+ - "design a plan" -> `plan-task`
9
+ - "implement" or "build" -> `implement-task`
10
+ - "review" -> `review-task`
11
+ - "fix review feedback" -> `refine-task`
12
+
13
+ ## Task State Management
14
+
15
+ - Update the corresponding `task.md` immediately after every workflow command
16
+ - At minimum, synchronize `current_step`, `updated_at`, `assigned_to`, and the current-round artifact reference
17
+ - Activity Log entries are append-only and must never overwrite history
18
+
19
+ ## Required State Updates by Command
20
+
21
+ - `import-issue`: update `current_step`, `updated_at`, `assigned_to`
22
+ - `analyze-task`: update `current_step`, `updated_at`, `assigned_to`
23
+ - `plan-task`: update `current_step`, `updated_at`
24
+ - `implement-task`: update `current_step`, `updated_at`
25
+ - `review-task`: update `current_step`, `updated_at`
26
+ - `refine-task`: update `current_step`, `updated_at`
27
+ - `complete-task`: update `status`, `completed_at`, `updated_at`
28
+ - `block-task`: update `status`, `blocked_at`, `blocked_reason`
@@ -0,0 +1,28 @@
1
+ # 通用规则 - 任务管理
2
+
3
+ ## 任务语义识别
4
+
5
+ 根据用户意图自动映射到对应工作流命令:
6
+ - “分析 issue #123” -> `import-issue`
7
+ - “分析任务 TASK-20260306-143022” -> `analyze-task`
8
+ - “设计方案” -> `plan-task`
9
+ - “实施/实现” -> `implement-task`
10
+ - “审查” -> `review-task`
11
+ - “修复审查问题” -> `refine-task`
12
+
13
+ ## 任务状态管理
14
+
15
+ - 每次执行工作流命令后,必须立即更新对应任务的 `task.md`
16
+ - 至少同步 `current_step`、`updated_at`、`assigned_to`,以及本轮产物引用
17
+ - Activity Log 只能追加,不能覆盖历史记录
18
+
19
+ ## 常见命令的状态更新要求
20
+
21
+ - `import-issue`:更新 `current_step`、`updated_at`、`assigned_to`
22
+ - `analyze-task`:更新 `current_step`、`updated_at`、`assigned_to`
23
+ - `plan-task`:更新 `current_step`、`updated_at`
24
+ - `implement-task`:更新 `current_step`、`updated_at`
25
+ - `review-task`:更新 `current_step`、`updated_at`
26
+ - `refine-task`:更新 `current_step`、`updated_at`
27
+ - `complete-task`:更新 `status`、`completed_at`、`updated_at`
28
+ - `block-task`:更新 `status`、`blocked_at`、`blocked_reason`
@@ -33,6 +33,7 @@ const DEFAULT_RETRY_DELAYS_MS = [3000, 10000];
33
33
  const DEFAULT_FRESHNESS_MINUTES = 30;
34
34
  const DATE_TIME_PATTERN = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
35
35
  const ACTIVITY_LOG_PATTERN = /^- (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) — \*\*(.+?)\*\* by (.+?) — (.+)$/;
36
+ const BRANCH_SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
36
37
 
37
38
  const scriptPath = fileURLToPath(import.meta.url);
38
39
  const repoRoot = path.resolve(path.dirname(scriptPath), "..", "..");
@@ -190,6 +191,11 @@ function checkTaskMeta({ taskDir, config }) {
190
191
  }
191
192
  }
192
193
 
194
+ const branchValidationError = validateTaskBranch(metadata);
195
+ if (branchValidationError) {
196
+ return failResult("task-meta", branchValidationError);
197
+ }
198
+
193
199
  const expectedStep = config.expected_step;
194
200
  if (expectedStep && metadata.current_step !== expectedStep) {
195
201
  return failResult(
@@ -232,6 +238,40 @@ function checkTaskMeta({ taskDir, config }) {
232
238
  return passResult("task-meta", `Task metadata valid (${requiredFields.length} required fields checked)`);
233
239
  }
234
240
 
241
+ function validateTaskBranch(metadata) {
242
+ if (isBlank(metadata.branch)) {
243
+ return null;
244
+ }
245
+
246
+ const projectName = loadProjectName();
247
+ const expectedPrefix = projectName ? `${projectName}-${metadata.type}-` : "";
248
+
249
+ if (expectedPrefix && !String(metadata.branch).startsWith(expectedPrefix)) {
250
+ return `Invalid branch: expected prefix '${expectedPrefix}', got '${metadata.branch}'`;
251
+ }
252
+
253
+ const slug = expectedPrefix ? String(metadata.branch).slice(expectedPrefix.length) : String(metadata.branch);
254
+ if (!BRANCH_SLUG_PATTERN.test(slug)) {
255
+ return `Invalid branch: '${metadata.branch}' must use kebab-case suffixes`;
256
+ }
257
+
258
+ return null;
259
+ }
260
+
261
+ function loadProjectName() {
262
+ const configPath = path.join(repoRoot, ".agents", ".airc.json");
263
+ if (!fs.existsSync(configPath)) {
264
+ return "";
265
+ }
266
+
267
+ try {
268
+ const config = JSON.parse(fs.readFileSync(configPath, "utf8"));
269
+ return String(config.project || "").trim();
270
+ } catch {
271
+ return "";
272
+ }
273
+ }
274
+
235
275
  function checkArtifact({ taskDir, config, artifactFile }) {
236
276
  const resolvedArtifact = resolveArtifactPath(taskDir, config.file_pattern, artifactFile);
237
277
  if (!resolvedArtifact.ok) {
@@ -5,7 +5,10 @@ description: "Archive completed tasks into a date-organized workspace directory"
5
5
 
6
6
  # Archive Completed Tasks
7
7
 
8
- Move completed tasks from `.agents/workspace/completed/` into `.agents/workspace/archive/YYYY/MM/DD/TASK-xxx/` and rebuild the archive index `manifest.md`.
8
+ Move completed tasks from `.agents/workspace/completed/` into `.agents/workspace/archive/YYYY/MM/DD/TASK-xxx/` and rebuild a three-level archive index:
9
+ - root manifest: `.agents/workspace/archive/manifest.md`
10
+ - yearly manifest: `.agents/workspace/archive/YYYY/manifest.md`
11
+ - monthly manifest: `.agents/workspace/archive/YYYY/MM/manifest.md`
9
12
 
10
13
  ## Execution Flow
11
14
 
@@ -29,7 +32,7 @@ The script is responsible for:
29
32
  - reading `completed_at` from `task.md` frontmatter and falling back to `updated_at`
30
33
  - moving task directories directly into `YYYY/MM/DD/TASK-xxx/` without compression
31
34
  - skipping already archived, missing, or malformed tasks
32
- - rebuilding `.agents/workspace/archive/manifest.md` from all archived tasks
35
+ - rebuilding root, yearly, and monthly manifests from all archived tasks
33
36
  - printing an archive and skip summary
34
37
 
35
38
  ### 3. Inform the user
@@ -37,4 +40,4 @@ The script is responsible for:
37
40
  Report:
38
41
  - how many tasks were archived
39
42
  - how many tasks were skipped and why
40
- - the path to `manifest.md`
43
+ - the path to the root manifest
@@ -5,7 +5,10 @@ description: "归档已完成任务到按日期组织的目录"
5
5
 
6
6
  # 归档已完成任务
7
7
 
8
- 将 `.agents/workspace/completed/` 中的已完成任务移动到 `.agents/workspace/archive/YYYY/MM/DD/TASK-xxx/`,并重建归档索引 `manifest.md`。
8
+ 将 `.agents/workspace/completed/` 中的已完成任务移动到 `.agents/workspace/archive/YYYY/MM/DD/TASK-xxx/`,并重建三级归档索引:
9
+ - 根 manifest:`.agents/workspace/archive/manifest.md`
10
+ - 年 manifest:`.agents/workspace/archive/YYYY/manifest.md`
11
+ - 月 manifest:`.agents/workspace/archive/YYYY/MM/manifest.md`
9
12
 
10
13
  ## 执行流程
11
14
 
@@ -29,7 +32,7 @@ bash .agents/skills/archive-tasks/scripts/archive-tasks.sh [--days N | --before
29
32
  - 解析 `task.md` frontmatter 中的 `completed_at`(缺失时回退到 `updated_at`)
30
33
  - 按 `YYYY/MM/DD/TASK-xxx/` 目录直接移动任务,不压缩
31
34
  - 跳过已归档、缺少元数据或不存在的任务
32
- - 全量重建 `.agents/workspace/archive/manifest.md`
35
+ - 全量重建根 // 月三级 manifest
33
36
  - 输出归档与跳过摘要
34
37
 
35
38
  ### 3. 告知用户
@@ -37,4 +40,4 @@ bash .agents/skills/archive-tasks/scripts/archive-tasks.sh [--days N | --before
37
40
  向用户汇报:
38
41
  - 本次归档的任务数量
39
42
  - 跳过的任务数量和原因
40
- - `manifest.md` 的路径
43
+ - manifest 的路径
@@ -208,6 +208,8 @@ should_archive_filtered_task() {
208
208
 
209
209
  rebuild_manifest() {
210
210
  entries_file="$tmpdir/manifest.tsv"
211
+ month_keys_file="$tmpdir/manifest-months.tsv"
212
+ year_keys_file="$tmpdir/manifest-years.tsv"
211
213
  generated_at=$(date "+%Y-%m-%d %H:%M:%S")
212
214
 
213
215
  mkdir -p "$ARCHIVE_DIR"
@@ -253,26 +255,107 @@ rebuild_manifest() {
253
255
  fi
254
256
  fi
255
257
 
256
- printf '%s\t%s\t%s\t%s\t%s\n' "$completed_at" "$task_id" "$title" "$task_type" "$relative_path" >> "$entries_file"
258
+ printf '%s\t%s\t%s\t%s\t%s\t%s\t%s\n' "$year" "$month" "$completed_at" "$task_id" "$title" "$task_type" "$relative_path" >> "$entries_file"
257
259
  done
258
260
  done
259
261
  done
260
262
  done
261
263
 
264
+ find "$ARCHIVE_DIR" -type f -name 'manifest.md' -exec rm -f {} \;
265
+
266
+ awk -F'\t' '{print $1 "\t" $2}' "$entries_file" | LC_ALL=C sort -u > "$month_keys_file"
267
+ awk -F'\t' '{print $1}' "$entries_file" | LC_ALL=C sort -u > "$year_keys_file"
268
+
269
+ while IFS="$(printf '\t')" read -r year month; do
270
+ [ -n "$year" ] || continue
271
+ [ -n "$month" ] || continue
272
+
273
+ month_entries_file="$tmpdir/manifest-${year}-${month}.tsv"
274
+ month_manifest_path="$ARCHIVE_DIR/$year/$month/manifest.md"
275
+
276
+ awk -F'\t' -v target_year="$year" -v target_month="$month" '
277
+ $1 == target_year && $2 == target_month {
278
+ print $3 "\t" $4 "\t" $5 "\t" $6 "\t" $7
279
+ }
280
+ ' "$entries_file" | LC_ALL=C sort -r > "$month_entries_file"
281
+
282
+ month_entry_count=$(wc -l < "$month_entries_file" | tr -d ' ')
283
+
284
+ {
285
+ echo "# Archive Manifest"
286
+ echo
287
+ echo "> Auto-generated by archive-tasks. Do not edit manually."
288
+ echo "> Last updated: $generated_at"
289
+ echo
290
+ echo "| Task ID | Title | Type | Completed | Path |"
291
+ echo "| --- | --- | --- | --- | --- |"
292
+
293
+ head -n 1000 "$month_entries_file" | while IFS="$(printf '\t')" read -r completed_at task_id title task_type relative_path; do
294
+ [ -n "$task_id" ] || continue
295
+ printf '| %s | %s | %s | %s | %s |\n' "$task_id" "$title" "$task_type" "$completed_at" "$relative_path"
296
+ done
297
+
298
+ if [ "$month_entry_count" -gt 1000 ]; then
299
+ echo
300
+ printf '> Showing 1000 of %s entries.\n' "$month_entry_count"
301
+ fi
302
+ } > "$month_manifest_path"
303
+ done < "$month_keys_file"
304
+
305
+ while IFS= read -r year; do
306
+ [ -n "$year" ] || continue
307
+
308
+ year_manifest_path="$ARCHIVE_DIR/$year/manifest.md"
309
+
310
+ {
311
+ echo "# Archive Manifest"
312
+ echo
313
+ echo "> Auto-generated by archive-tasks. Do not edit manually."
314
+ echo "> Last updated: $generated_at"
315
+ echo
316
+ echo "| Month | Tasks | Manifest |"
317
+ echo "| --- | --- | --- |"
318
+
319
+ awk -F'\t' -v target_year="$year" '
320
+ $1 == target_year {
321
+ counts[$2] += 1
322
+ }
323
+
324
+ END {
325
+ for (month in counts) {
326
+ print month "\t" counts[month]
327
+ }
328
+ }
329
+ ' "$entries_file" | LC_ALL=C sort -r | while IFS="$(printf '\t')" read -r month task_count; do
330
+ [ -n "$month" ] || continue
331
+ printf '| %s | %s | [%s/manifest.md](%s/manifest.md) |\n' "$month" "$task_count" "$month" "$month"
332
+ done
333
+ } > "$year_manifest_path"
334
+ done < "$year_keys_file"
335
+
262
336
  {
263
337
  echo "# Archive Manifest"
264
338
  echo
265
339
  echo "> Auto-generated by archive-tasks. Do not edit manually."
266
340
  echo "> Last updated: $generated_at"
267
341
  echo
268
- echo "| Task ID | Title | Type | Completed | Path |"
269
- echo "| --- | --- | --- | --- | --- |"
342
+ echo "| Year | Tasks | Manifest |"
343
+ echo "| --- | --- | --- |"
270
344
 
271
- if [ -s "$entries_file" ]; then
272
- LC_ALL=C sort -r "$entries_file" | while IFS="$(printf '\t')" read -r completed_at task_id title task_type relative_path; do
273
- printf '| %s | %s | %s | %s | %s |\n' "$task_id" "$title" "$task_type" "$completed_at" "$relative_path"
274
- done
275
- fi
345
+ awk -F'\t' '
346
+ {
347
+ counts[$1] += 1
348
+ }
349
+
350
+ END {
351
+ for (year in counts) {
352
+ print year "\t" counts[year]
353
+ }
354
+ }
355
+ ' "$entries_file" | LC_ALL=C sort -r | while IFS="$(printf '\t')" read -r year task_count; do
356
+ [ -n "$year" ] || continue
357
+ printf '| %s | %s | [%s/manifest.md](%s/manifest.md) |\n' "$year" "$task_count" "$year" "$year"
358
+ done
276
359
  } > "$MANIFEST_PATH"
277
360
  }
278
361
 
@@ -27,6 +27,10 @@ Extract from the natural-language description:
27
27
  - **Task title**: a concise title (maximum 50 characters), in the same language as the user's description - do not translate it to English or apply Conventional Commits formatting
28
28
  - **Task type**: `feature` | `bugfix` | `refactor` | `docs` | `chore` (infer from the description)
29
29
  - **Workflow**: `feature-development` | `bug-fix` | `refactoring` (infer from the type)
30
+ - **Branch name**: format `<project>-<type>-<slug>`
31
+ - `<project>` comes from the `project` field in `.agents/.airc.json`
32
+ - `<type>` is the inferred task type
33
+ - `<slug>` is a kebab-case slug built from 3-6 English keywords extracted from the task title
30
34
  - **Detailed description**: the cleaned-up original user request
31
35
 
32
36
  If the description is unclear, **ask the user to clarify first**.
@@ -64,6 +68,7 @@ Task metadata (`task.md` YAML front matter):
64
68
  ```yaml
65
69
  id: TASK-{yyyyMMdd-HHmmss}
66
70
  type: feature|bugfix|refactor|docs|chore
71
+ branch: <project>-<type>-<slug>
67
72
  workflow: feature-development|bug-fix|refactoring
68
73
  status: active
69
74
  created_at: {yyyy-MM-dd HH:mm:ss}
@@ -87,6 +92,7 @@ Update `.agents/workspace/active/{task-id}/task.md`:
87
92
  - `current_step`: requirement-analysis
88
93
  - `assigned_to`: {current AI agent}
89
94
  - `updated_at`: {current time}
95
+ - `## Context` -> `- **Branch**:`: update it to the generated branch name
90
96
  - **Append** to `## Activity Log` (do NOT overwrite previous entries):
91
97
  ```
92
98
  - {yyyy-MM-dd HH:mm:ss} — **Task Created** by {agent} — Task created from description
@@ -27,6 +27,10 @@ description: "根据自然语言描述创建任务"
27
27
  - **任务标题**:简洁标题(最多 50 个字符),使用中文——不要翻译为英文,不要套用 Conventional Commits 格式
28
28
  - **任务类型**:`feature` | `bugfix` | `refactor` | `docs` | `chore`(从描述推断)
29
29
  - **工作流**:`feature-development` | `bug-fix` | `refactoring`(从类型推断)
30
+ - **分支名**:格式 `<project>-<type>-<slug>`
31
+ - `<project>` 从 `.agents/.airc.json` 的 `project` 字段读取
32
+ - `<type>` 为推断出的任务类型
33
+ - `<slug>` 从任务标题提取 3-6 个英文关键词并转为 kebab-case
30
34
  - **详细描述**:整理后的用户原始描述
31
35
 
32
36
  如果描述不清晰,**先向用户确认**再继续。
@@ -64,6 +68,7 @@ date +%Y%m%d-%H%M%S
64
68
  ```yaml
65
69
  id: TASK-{yyyyMMdd-HHmmss}
66
70
  type: feature|bugfix|refactor|docs|chore
71
+ branch: <project>-<type>-<slug>
67
72
  workflow: feature-development|bug-fix|refactoring
68
73
  status: active
69
74
  created_at: {yyyy-MM-dd HH:mm:ss}
@@ -87,6 +92,7 @@ date "+%Y-%m-%d %H:%M:%S"
87
92
  - `current_step`:requirement-analysis
88
93
  - `assigned_to`:{当前 AI 代理}
89
94
  - `updated_at`:{当前时间}
95
+ - `## 上下文` 中的 `- **分支**:`:更新为生成的分支名
90
96
  - **追加**到 `## Activity Log`(不要覆盖之前的记录):
91
97
  ```
92
98
  - {yyyy-MM-dd HH:mm:ss} — **Task Created** by {agent} — Task created from description
@@ -5,6 +5,7 @@
5
5
  "required_fields": [
6
6
  "id",
7
7
  "type",
8
+ "branch",
8
9
  "workflow",
9
10
  "status",
10
11
  "created_at",
@@ -44,6 +44,7 @@ Task metadata:
44
44
  id: TASK-{yyyyMMdd-HHmmss}
45
45
  issue_number: <issue-number>
46
46
  type: feature|bugfix|refactor|docs|chore
47
+ branch: <project>-<type>-<slug>
47
48
  workflow: feature-development|bug-fix|refactoring
48
49
  status: active
49
50
  created_at: {yyyy-MM-dd HH:mm:ss}
@@ -65,6 +66,7 @@ Update `.agents/workspace/active/{task-id}/task.md`:
65
66
  - `current_step`: requirement-analysis
66
67
  - `assigned_to`: {current AI agent}
67
68
  - `updated_at`: {current time}
69
+ - `## Context` -> `- **Branch**:`: update it to the generated branch name
68
70
  - **Append** to `## Activity Log` (do NOT overwrite previous entries):
69
71
  ```
70
72
  - {yyyy-MM-dd HH:mm:ss} — **Import Issue** by {agent} — Issue #{number} imported
@@ -44,6 +44,7 @@ date +%Y%m%d-%H%M%S
44
44
  id: TASK-{yyyyMMdd-HHmmss}
45
45
  issue_number: <issue-number>
46
46
  type: feature|bugfix|refactor|docs|chore
47
+ branch: <project>-<type>-<slug>
47
48
  workflow: feature-development|bug-fix|refactoring
48
49
  status: active
49
50
  created_at: {yyyy-MM-dd HH:mm:ss}
@@ -65,6 +66,7 @@ date "+%Y-%m-%d %H:%M:%S"
65
66
  - `current_step`:requirement-analysis
66
67
  - `assigned_to`:{当前 AI 代理}
67
68
  - `updated_at`:{当前时间}
69
+ - `## 上下文` 中的 `- **分支**:`:更新为生成的分支名
68
70
  - **追加**到 `## Activity Log`(不要覆盖之前的记录):
69
71
  ```
70
72
  - {yyyy-MM-dd HH:mm:ss} — **Import Issue** by {agent} — Issue #{number} imported
@@ -5,6 +5,7 @@
5
5
  "required_fields": [
6
6
  "id",
7
7
  "type",
8
+ "branch",
8
9
  "workflow",
9
10
  "status",
10
11
  "created_at",
@@ -20,6 +20,23 @@ import path from 'node:path';
20
20
  import { fileURLToPath } from 'node:url';
21
21
 
22
22
  const DEFAULTS = {
23
+ "sandbox": {
24
+ "runtimes": [
25
+ "node20"
26
+ ],
27
+ "tools": [
28
+ "claude-code",
29
+ "codex",
30
+ "opencode",
31
+ "gemini-cli"
32
+ ],
33
+ "dockerfile": null,
34
+ "vm": {
35
+ "cpu": null,
36
+ "memory": null,
37
+ "disk": null
38
+ }
39
+ },
23
40
  "labels": {
24
41
  "in": {}
25
42
  },
@@ -57,7 +74,7 @@ const DEFAULTS = {
57
74
  }
58
75
  };
59
76
 
60
- const INSTALLER_VERSION = "v0.4.4";
77
+ const INSTALLER_VERSION = "v0.5.0";
61
78
 
62
79
  function norm(p) { return p.replace(/\\/g, '/'); }
63
80
 
@@ -1,12 +1,13 @@
1
1
  ---
2
2
  id: task-XXX
3
- type: feature # feature | bugfix | refactor | docs | review
3
+ type: feature # feature | bugfix | refactor | docs | review
4
+ branch: "" # <project>-<type>-<slug>
4
5
  workflow: feature-development # feature-development | bug-fix | code-review | refactoring
5
- status: open # open | in-progress | review | blocked | completed
6
+ status: open # open | in-progress | review | blocked | completed
6
7
  created_at: YYYY-MM-DD
7
8
  updated_at: YYYY-MM-DD
8
- current_step: analysis # analysis | design | implementation | review | fix | commit
9
- assigned_to: "" # claude | codex | gemini | opencode | human
9
+ current_step: analysis # analysis | design | implementation | review | fix | commit
10
+ assigned_to: "" # claude | codex | gemini | opencode | human
10
11
  ---
11
12
 
12
13
  # Task: [Title]
@@ -1,12 +1,13 @@
1
1
  ---
2
2
  id: task-XXX
3
- type: feature # feature | bugfix | refactor | docs | review
3
+ type: feature # feature | bugfix | refactor | docs | review
4
+ branch: "" # <project>-<type>-<slug>
4
5
  workflow: feature-development # feature-development | bug-fix | code-review | refactoring
5
- status: open # open | in-progress | review | blocked | completed
6
+ status: open # open | in-progress | review | blocked | completed
6
7
  created_at: YYYY-MM-DD
7
8
  updated_at: YYYY-MM-DD
8
- current_step: analysis # analysis | design | implementation | review | fix | commit
9
- assigned_to: "" # claude | codex | gemini | opencode | human
9
+ current_step: analysis # analysis | design | implementation | review | fix | commit
10
+ assigned_to: "" # claude | codex | gemini | opencode | human
10
11
  ---
11
12
 
12
13
  # 任务:[标题]