@fitlab-ai/agent-infra 0.3.0 → 0.3.2

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 (51) hide show
  1. package/README.md +368 -51
  2. package/README.zh-CN.md +369 -52
  3. package/bin/cli.js +1 -1
  4. package/lib/version.js +2 -1
  5. package/package.json +1 -1
  6. package/templates/.agents/README.md +12 -0
  7. package/templates/.agents/README.zh-CN.md +12 -0
  8. package/templates/.agents/skills/analyze-task/SKILL.md +106 -105
  9. package/templates/.agents/skills/check-task/SKILL.md +108 -94
  10. package/templates/.agents/skills/check-task/SKILL.zh-CN.md +12 -0
  11. package/templates/.agents/skills/close-codescan/SKILL.md +64 -63
  12. package/templates/.agents/skills/close-dependabot/SKILL.md +71 -70
  13. package/templates/.agents/skills/commit/SKILL.md +19 -4
  14. package/templates/.agents/skills/commit/SKILL.zh-CN.md +19 -4
  15. package/templates/.agents/skills/complete-task/SKILL.md +11 -1
  16. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +11 -1
  17. package/templates/.agents/skills/create-issue/SKILL.md +302 -0
  18. package/templates/.agents/skills/create-issue/SKILL.zh-CN.md +302 -0
  19. package/templates/.agents/skills/create-pr/SKILL.md +140 -5
  20. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +140 -5
  21. package/templates/.agents/skills/create-release-note/SKILL.md +18 -11
  22. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +18 -11
  23. package/templates/.agents/skills/create-task/SKILL.md +80 -78
  24. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +7 -6
  25. package/templates/.agents/skills/implement-task/SKILL.md +7 -2
  26. package/templates/.agents/skills/implement-task/SKILL.zh-CN.md +7 -2
  27. package/templates/.agents/skills/import-codescan/SKILL.md +54 -53
  28. package/templates/.agents/skills/import-dependabot/SKILL.md +57 -56
  29. package/templates/.agents/skills/import-issue/SKILL.md +58 -58
  30. package/templates/.agents/skills/init-labels/SKILL.md +8 -0
  31. package/templates/.agents/skills/init-labels/SKILL.zh-CN.md +8 -0
  32. package/templates/.agents/skills/plan-task/SKILL.md +151 -149
  33. package/templates/.agents/skills/refine-task/SKILL.md +147 -137
  34. package/templates/.agents/skills/refine-task/SKILL.zh-CN.md +10 -2
  35. package/templates/.agents/skills/review-task/SKILL.md +196 -186
  36. package/templates/.agents/skills/review-task/SKILL.zh-CN.md +13 -4
  37. package/templates/.agents/skills/sync-issue/SKILL.md +252 -272
  38. package/templates/.agents/skills/sync-issue/SKILL.zh-CN.md +26 -47
  39. package/templates/.agents/skills/sync-pr/SKILL.md +274 -82
  40. package/templates/.agents/skills/sync-pr/SKILL.zh-CN.md +251 -59
  41. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +1 -1
  42. package/templates/.claude/CLAUDE.md +13 -0
  43. package/templates/.claude/CLAUDE.zh-CN.md +13 -0
  44. package/templates/.claude/commands/create-issue.md +8 -0
  45. package/templates/.claude/commands/create-issue.zh-CN.md +8 -0
  46. package/templates/.gemini/commands/_project_/create-issue.toml +8 -0
  47. package/templates/.gemini/commands/_project_/create-issue.zh-CN.toml +8 -0
  48. package/templates/.opencode/commands/create-issue.md +11 -0
  49. package/templates/.opencode/commands/create-issue.zh-CN.md +11 -0
  50. package/templates/AGENTS.md +13 -0
  51. package/templates/AGENTS.zh-CN.md +13 -0
@@ -1,23 +1,24 @@
1
1
  ---
2
2
  name: sync-issue
3
3
  description: >
4
- 将任务处理进度同步到对应的 GitHub Issue 评论。
5
- 当用户要求同步进度到 Issue 时触发。参数:task-id issue-number。
4
+ Sync task progress to comments on the related GitHub Issue.
5
+ Triggered when the user asks to sync progress to an Issue.
6
+ Argument: task-id or issue-number.
6
7
  ---
7
8
 
8
- # 同步进度到 Issue
9
+ # Sync Progress to Issue
9
10
 
10
- 将任务处理进度同步到关联的 GitHub Issue。参数:task-id issue-number
11
+ Sync task progress to the related GitHub Issue. Argument: task-id or issue-number.
11
12
 
12
- ## 执行流程
13
+ ## Execution Flow
13
14
 
14
- ### 1. 解析参数
15
+ ### 1. Parse the Argument
15
16
 
16
- 识别用户提供的参数:
17
- - 纯数字(如 `123`)或 `#` + 数字(如 `#123`)-> 视为 issue number
18
- - `TASK-` 开头 -> 视为 task-id(现有格式)
17
+ Identify the argument provided by the user:
18
+ - plain number (`123`) or `#` + number (`#123`) -> treat as an issue number
19
+ - Starts with `TASK-` -> treat as a task-id (current format)
19
20
 
20
- 如果参数是 issue number,使用 Bash 搜索关联任务(注意:`.agent-workspace` 是隐藏目录,Grep/Glob 工具会跳过,必须使用 Bash):
21
+ If the argument is an issue number, use Bash to search for the related task (note: `.agent-workspace` is a hidden directory, so Grep/Glob tools may skip it; you must use Bash):
21
22
 
22
23
  ```bash
23
24
  grep -rl "^issue_number: {issue-number}$" \
@@ -27,44 +28,44 @@ grep -rl "^issue_number: {issue-number}$" \
27
28
  2>/dev/null | head -1
28
29
  ```
29
30
 
30
- - 如果返回文件路径(如 `.agent-workspace/completed/TASK-xxx/task.md`),从路径中提取 `{task-id}` 和任务目录,继续执行步骤 2
31
- - 如果无返回,提示 `No task found associated with Issue #{issue-number}`
31
+ - If a file path is returned (for example `.agent-workspace/completed/TASK-xxx/task.md`), extract `{task-id}` and the task directory from the path, then continue to Step 2
32
+ - If nothing is returned, output `No task found associated with Issue #{issue-number}`
32
33
 
33
- 如果参数是 task-id,继续执行步骤 2 的现有逻辑。
34
+ If the argument is a task-id, continue with the normal Step 2 flow.
34
35
 
35
- ### 2. 验证任务存在
36
+ ### 2. Verify the Task Exists
36
37
 
37
- 对于 `task-id` 路径,按优先顺序搜索任务:
38
+ For a `task-id`, search for the task in this order:
38
39
  - `.agent-workspace/active/{task-id}/task.md`
39
40
  - `.agent-workspace/blocked/{task-id}/task.md`
40
41
  - `.agent-workspace/completed/{task-id}/task.md`
41
42
 
42
- 注意:`{task-id}` 格式为 `TASK-{yyyyMMdd-HHmmss}`,例如 `TASK-20260306-143022`
43
+ Note: `{task-id}` format is `TASK-{yyyyMMdd-HHmmss}`, for example `TASK-20260306-143022`
43
44
 
44
- 如果步骤 1 已通过 issue number 找到匹配任务,则直接使用该任务目录继续后续步骤,无需再次扫描。
45
+ If Step 1 already found a matching task through the issue number, use that task directory directly for the remaining steps without scanning again.
45
46
 
46
- ### 3. 读取任务信息
47
+ ### 3. Read Task Information
47
48
 
48
- task.md 中提取:
49
- - `issue_number`(必需 —— 如果缺失,提示用户)
49
+ Extract from task.md:
50
+ - `issue_number` (required; if missing, prompt the user)
50
51
  - `type`
51
- - 任务标题、描述、状态
52
- - `current_step`、`created_at`、`updated_at`、`last_synced_at`(如存在)
52
+ - task title, description, and status
53
+ - `current_step`, `created_at`, `updated_at`, and `last_synced_at` (if present)
53
54
 
54
- ### 4. 读取上下文文件
55
+ ### 4. Read Context Files
55
56
 
56
- 检查并读取(如存在):
57
- - 最高轮次的 `analysis.md` / `analysis-r{N}.md` - 需求分析
58
- - 最高轮次的 `plan.md` / `plan-r{N}.md` - 技术方案
59
- - `implementation.md`、`implementation-r*.md` - 实现报告
60
- - `refinement.md`、`refinement-r*.md` - 修复报告
61
- - `review.md`、`review-r*.md` - 审查报告
57
+ Check and read these files if they exist:
58
+ - highest-round `analysis.md` / `analysis-r{N}.md` - requirements analysis
59
+ - highest-round `plan.md` / `plan-r{N}.md` - technical plan
60
+ - `implementation.md`, `implementation-r*.md` - implementation reports
61
+ - `refinement.md`, `refinement-r*.md` - refinement reports
62
+ - `review.md`, `review-r*.md` - review reports
62
63
 
63
- ### 5. 探测交付状态
64
+ ### 5. Detect Delivery Status
64
65
 
65
- 依次执行以下探测;任一步失败时,降级到“模式 C:开发中”,不要编造无法确认的信息。
66
+ Run the following checks in order. If any step fails, fall back to "Mode C: In development". Do not invent anything you cannot verify.
66
67
 
67
- 在开始探测前,先获取仓库坐标和绝对 URL 前缀:
68
+ Before starting detection, first resolve repository coordinates and the absolute URL prefix:
68
69
 
69
70
  ```bash
70
71
  repo="$(gh repo view --json nameWithOwner --jq '.nameWithOwner')"
@@ -72,203 +73,171 @@ owner="${repo%%/*}"
72
73
  repo_url="https://github.com/$repo"
73
74
  ```
74
75
 
75
- **a) 提取 commit hash**
76
+ **a) Extract the commit hash**
76
77
 
77
- task.md `## Activity Log` 中匹配最后一条 `**Commit** by` 记录,活动日志格式固定为:
78
+ Match the last `**Commit** by` record in `## Activity Log` in task.md. The Activity Log format is:
78
79
 
79
80
  ```text
80
81
  **Commit** by {agent} — {hash} {subject}
81
82
  ```
82
83
 
83
- 提取第一个词作为 commit hash;如果找不到,标记为“无 commit”。
84
+ Extract the first word as the commit hash. If none is found, mark it as "no commit".
84
85
 
85
- **b) 检测 commit 是否在受保护分支上**
86
+ **b) Detect whether the commit is on a protected branch**
86
87
 
87
- 如果存在 commit hash,执行:
88
+ If a commit hash exists, run:
88
89
 
89
90
  ```bash
90
91
  git branch -a --contains {commit-hash} 2>/dev/null
91
92
  ```
92
93
 
93
- 判断规则:
94
- - 输出包含 `main` `master` -> 已合入主分支,记录分支名
95
- - 输出匹配 `{major}.{minor}.x` 模式的分支名 -> 已合入版本分支,记录分支名
96
- - 都不匹配 -> 未合入受保护分支
94
+ Decision rules:
95
+ - output contains `main` or `master` -> merged into the main branch; record the branch name
96
+ - output matches a `{major}.{minor}.x` branch name -> merged into a release branch; record the branch name
97
+ - neither matches -> not merged into a protected branch
97
98
 
98
- **c) 检测关联 PR**
99
+ **c) Detect the linked PR**
99
100
 
100
- 检查 task.md `pr_number` 字段;如果存在,执行:
101
+ Check the `pr_number` field in task.md. If it exists, run:
101
102
 
102
103
  ```bash
103
104
  gh pr view {pr-number} --json state,mergedAt
104
105
  ```
105
106
 
106
- 根据返回结果识别 PR `OPEN`、`MERGED` 还是其他状态。
107
+ Use the result to determine whether the PR is `OPEN`, `MERGED`, or another state.
107
108
 
108
- **d) 检测 Issue 状态**
109
+ **d) Determine the delivery mode**
109
110
 
110
- 执行:
111
+ Choose the summary mode with this priority:
111
112
 
112
- ```bash
113
- gh issue view {issue-number} --json state
114
- ```
115
-
116
- 记录 Issue 当前是 `OPEN` 还是 `CLOSED`。
117
-
118
- **e) 综合判定交付模式**
119
-
120
- 按以下优先级确定摘要模式:
121
-
122
- | 条件 | 模式 |
123
- |------|------|
124
- | commit 已在受保护分支上 | 模式 A:已完成 |
125
- | 有 PR,且状态为 `OPEN` 或 `MERGED` | 模式 B:PR 阶段 |
126
- | 其他情况 | 模式 C:开发中 |
113
+ | Condition | Mode |
114
+ |---|---|
115
+ | commit is already on a protected branch | Mode A: Completed |
116
+ | PR exists and its state is `OPEN` or `MERGED` | Mode B: PR stage |
117
+ | anything else | Mode C: In development |
127
118
 
128
- 优先级必须为 `模式 A > 模式 B > 模式 C`。即使存在 PR,只要 commit 已在受保护分支上,也按“已完成”处理。
119
+ The priority must be `Mode A > Mode B > Mode C`. Even if a PR exists, treat it as "Completed" when the commit is already on a protected branch.
129
120
 
130
- 后续所有 commit / PR 链接必须使用绝对 URL:
121
+ All later commit and PR links must use absolute URLs:
131
122
  - `https://github.com/{owner}/{repo}/commit/{commit-hash}`
132
123
  - `https://github.com/{owner}/{repo}/pull/{pr-number}`
133
124
 
134
- 不要再使用 `../../commit/...` `../../pull/...` 这类相对路径。
125
+ Do not use relative paths such as `../../commit/...` or `../../pull/...`.
135
126
 
136
- ### 6. 同步 Labels Issue Type
127
+ ### 6. Sync Labels and Issue Type
137
128
 
138
- 基于步骤 5 的探测结果同步 Issue labels。
129
+ Sync Issue labels based on the detection result from Step 5.
139
130
 
140
- **a) 检查 label 体系是否已初始化**
131
+ **a) Check whether the label system has been initialized**
141
132
 
142
- 执行:
133
+ Run:
143
134
 
144
135
  ```bash
145
136
  gh label list --search "type:" --limit 1 --json name --jq 'length'
146
137
  ```
147
138
 
148
- 判断规则:
149
- - 返回 `0` -> 说明标准 label 体系缺失。先执行 `init-labels` 技能(幂等),然后重新执行本步骤
150
- - 返回非 `0` -> 继续后续 label 同步
151
-
152
- **b) 同步 type label**
153
-
154
- 根据 task.md 的 `type` 字段按下表映射:
155
-
156
- | task.md type | GitHub label |
157
- |---|---|
158
- | bug、bugfix | `type: bug` |
159
- | feature | `type: feature` |
160
- | enhancement | `type: enhancement` |
161
- | documentation | `type: documentation` |
162
- | dependency-upgrade | `type: dependency-upgrade` |
163
- | task | `type: task` |
164
- | 其他(含 refactoring 等) | 跳过 |
165
-
166
- 如果映射到具体 label,执行:
167
-
168
- ```bash
169
- gh issue edit {issue-number} --add-label "{type-label}"
170
- ```
171
-
172
- 未映射到标准 type label 时跳过,不创建新 label。
139
+ Decision rules:
140
+ - returns `0` -> the standard label system is missing; run the `init-labels` skill first (idempotent), then retry this step
141
+ - returns non-zero -> continue with label sync
173
142
 
174
- **c) 同步 status label**
143
+ **b) Sync the `status:` label**
175
144
 
176
- 先读取 Issue 上已有的 `status:` labels
145
+ First read existing `status:` labels on the Issue:
177
146
 
178
147
  ```bash
179
148
  gh issue view {issue-number} --json labels --jq '.labels[].name | select(startswith("status:"))'
180
149
  ```
181
150
 
182
- 对每个已有的 `status:` label 执行移除:
151
+ Remove each existing `status:` label:
183
152
 
184
153
  ```bash
185
154
  gh issue edit {issue-number} --remove-label "{status-label}"
186
155
  ```
187
156
 
188
- 然后按以下优先级决定是否添加新的 `status:` label
157
+ Then decide whether to add a new `status:` label using this priority:
189
158
 
190
- | 条件 | 动作 |
159
+ | Condition | Action |
191
160
  |---|---|
192
- | 任务位于 `blocked/` 目录 | 添加 `status: blocked` |
193
- | 模式 A:已完成 | 不添加新的 status label |
194
- | 模式 BPR MERGED | 不添加新的 status label |
195
- | 模式 BPR OPEN | 添加 `status: in-progress` |
196
- | 模式 C + `current_step` ∈ {`requirement-analysis`, `technical-design`} | 添加 `status: pending-design-work` |
197
- | 模式 C + `current_step` ∈ {`implementation`, `code-review`, `refinement`} | 添加 `status: in-progress` |
161
+ | task is under the `blocked/` directory | add `status: blocked` |
162
+ | Mode A: Completed | do not add a new status label |
163
+ | Mode B: PR is MERGED | do not add a new status label |
164
+ | Mode B: PR is OPEN | add `status: in-progress` |
165
+ | Mode C + `current_step` ∈ {`requirement-analysis`, `technical-design`} | add `status: pending-design-work` |
166
+ | Mode C + `current_step` ∈ {`implementation`, `code-review`, `refinement`} | add `status: in-progress` |
198
167
 
199
- 如果需要添加新 label,执行:
168
+ If a new label needs to be added, run:
200
169
 
201
170
  ```bash
202
171
  gh issue edit {issue-number} --add-label "{status-label}"
203
172
  ```
204
173
 
205
- **d) 同步 in: label**
174
+ **c) Sync the `in:` label**
206
175
 
207
- 从实现报告(优先)或 `analysis.md` 中提取受影响文件路径:
208
- - 优先读取 `implementation.md` `implementation-r*.md` 中 `## 修改文件` / `## 新建文件` 的文件列表
209
- - 如果实现报告不存在,则回退到分析报告中的受影响文件列表
176
+ Extract affected file paths from implementation reports first, or from `analysis.md` as a fallback:
177
+ - prefer file paths listed under `## Modified Files`, especially `### New Files` / `### Modified Files`, in `implementation.md` and `implementation-r{N}.md`
178
+ - if no implementation report exists, fall back to the affected file list in the analysis report
210
179
 
211
- 对每个文件路径:
212
- 1. 取第一级目录作为模块名
213
- 2. 去重
214
- 3. 检查仓库中是否存在对应 label
180
+ For each file path:
181
+ 1. take the first-level directory as the module name
182
+ 2. deduplicate
183
+ 3. check whether the corresponding label exists in the repository:
215
184
 
216
185
  ```bash
217
186
  gh label list --search "in: {module}" --limit 10 --json name --jq '.[].name'
218
187
  ```
219
188
 
220
- 4. 只有存在精确匹配的 `in: {module}` label 时才执行:
189
+ 4. only when the exact `in: {module}` label exists, run:
221
190
 
222
191
  ```bash
223
192
  gh issue edit {issue-number} --add-label "in: {module}"
224
193
  ```
225
194
 
226
- 5. **只添加,不移除**现有的 `in:` labels
195
+ 5. **Only add; do not remove** existing `in:` labels
227
196
 
228
- **e) 同步 Issue Type 字段**
197
+ **d) Sync the Issue Type field**
229
198
 
230
- 根据 task.md `type` 字段映射 GitHub 原生 Issue Type
199
+ Map the `type` field in task.md to the native GitHub Issue Type:
231
200
 
232
201
  | task.md type | GitHub Issue Type |
233
202
  |---|---|
234
- | `bug`、`bugfix` | `Bug` |
235
- | `feature`、`enhancement` | `Feature` |
236
- | `task`、`documentation`、`dependency-upgrade`、`chore`、`docs`、`refactor`、`refactoring` 及其他值 | `Task` |
203
+ | `bug`, `bugfix` | `Bug` |
204
+ | `feature`, `enhancement` | `Feature` |
205
+ | `task`, `documentation`, `dependency-upgrade`, `chore`, `docs`, `refactor`, `refactoring`, and any other value | `Task` |
237
206
 
238
- 先查询组织可用的 Issue Types
207
+ First query the Issue Types available in the organization:
239
208
 
240
209
  ```bash
241
210
  gh api "orgs/$owner/issue-types" --jq '.[].name'
242
211
  ```
243
212
 
244
- 然后仅在目标类型存在时执行:
213
+ Then execute this only when the target type exists:
245
214
 
246
215
  ```bash
247
216
  gh api "repos/$repo/issues/{issue-number}" -X PATCH -f type="{name}"
248
217
  ```
249
218
 
250
- 容错要求:
251
- - 如果 API 返回 `404`、仓库 owner 不是组织,或仓库未启用 Issue Types,记录 `Issue Type: skipped (not enabled)` 并继续,不要让整个同步失败
252
- - 如果目标类型不存在,记录 `Issue Type: skipped (type not available)`
253
- - 不要尝试创建新的 Issue Type;只使用组织中已存在的类型名称
219
+ Fault-tolerance requirements:
220
+ - If the API returns `404`, the repo owner is not an organization, or Issue Types are not enabled for the repo, record `Issue Type: skipped (not enabled)` and continue; do not fail the whole sync
221
+ - If the target type does not exist, record `Issue Type: skipped (type not available)`
222
+ - Do not try to create new Issue Types; only use names that already exist in the organization
254
223
 
255
- ### 7. 同步 Development
224
+ ### 7. Sync Development
256
225
 
257
- 如果 task.md 包含 `pr_number`,确保 PR body 关联当前 Issue
226
+ If task.md contains `pr_number`, ensure the PR body links the current Issue.
258
227
 
259
- 1. 读取 PR body
228
+ 1. Read the PR body:
260
229
 
261
230
  ```bash
262
231
  gh pr view {pr-number} --json body --jq '.body // ""'
263
232
  ```
264
233
 
265
- 2. 检查 body 是否已经包含以下任一关键词:
234
+ 2. Check whether the body already contains any of:
266
235
  - `Closes #{issue-number}`
267
236
  - `Fixes #{issue-number}`
268
237
  - `Resolves #{issue-number}`
269
238
 
270
- 3. 如果已存在任一关键词,跳过更新
271
- 4. 如果不存在,在 body 末尾追加:
239
+ 3. If any keyword already exists, skip the update
240
+ 4. Otherwise append this to the end of the body:
272
241
 
273
242
  ```bash
274
243
  gh pr edit {pr-number} --body "$(cat <<'EOF'
@@ -279,85 +248,85 @@ EOF
279
248
  )"
280
249
  ```
281
250
 
282
- 5. 如果 task.md 不包含 `pr_number`,记录为 `Development: N/A`
251
+ 5. If task.md does not contain `pr_number`, record `Development: N/A`
283
252
 
284
- ### 8. 同步 Milestone
253
+ ### 8. Sync the Milestone
285
254
 
286
- 根据 Issue 当前状态、任务显式配置和分支策略,为 Issue 关联线里程碑。
255
+ Assign a line milestone to the Issue based on the current Issue state, explicit task configuration, and branch strategy.
287
256
 
288
- **a) 检查 Issue 是否已有 Milestone**
257
+ **a) Check whether the Issue already has a milestone**
289
258
 
290
- 执行:
259
+ Run:
291
260
 
292
261
  ```bash
293
262
  gh issue view {issue-number} --json milestone --jq '.milestone.title // empty'
294
263
  ```
295
264
 
296
- 如果返回非空,保留现有里程碑并记录 `Milestone: {existing} (preserved)`,跳过后续里程碑同步步骤。
265
+ If the result is non-empty, preserve the existing milestone and record `Milestone: {existing} (preserved)`, then skip the remaining milestone-sync steps.
297
266
 
298
- **b) 检查 task.md 是否显式指定 milestone**
267
+ **b) Check whether task.md explicitly sets `milestone`**
299
268
 
300
- 如果 task.md frontmatter 中存在非空 `milestone` 字段,优先使用该值作为目标里程碑。
301
- 此字段应填写线里程碑标题或 `General Backlog`,不要自动指定具体版本里程碑。
269
+ If the frontmatter in task.md contains a non-empty `milestone` field, use it as the target milestone.
270
+ This field should contain a line milestone title or `General Backlog`; do not automatically set a specific version milestone here.
302
271
 
303
- **c) 推断目标线里程碑**
272
+ **c) Infer the target line milestone**
304
273
 
305
- task.md 未显式指定 `milestone` 时,按以下顺序推断:
274
+ When task.md does not explicitly set `milestone`, infer it in this order:
306
275
 
307
- 1. 检测当前分支:
276
+ 1. Detect the current branch:
308
277
 
309
278
  ```bash
310
279
  git branch --show-current
311
280
  ```
312
281
 
313
- - 如果分支名匹配 `{major}.{minor}.x`,目标里程碑为同名线里程碑 `{major}.{minor}.x`
282
+ - If the branch name matches `{major}.{minor}.x`, the target milestone is the same line milestone `{major}.{minor}.x`
314
283
 
315
- 2. 如果当前分支是 `main` `master`,检测现有版本分支:
284
+ 2. If the current branch is `main` or `master`, detect existing release branches:
316
285
 
317
286
  ```bash
318
287
  git branch -a | grep -oE '[0-9]+\.[0-9]+\.x' | sort -V | tail -1
319
288
  ```
320
289
 
321
- - 如果存在最高版本分支 `X.Y.x`,则目标里程碑为 `(X+1).0.x`
322
- - 如果不存在版本分支,则读取最新 tag
290
+ - If the highest release branch is `X.Y.x`, the target milestone is `(X+1).0.x`
291
+ - If no release branch exists, read the latest tag:
323
292
 
324
293
  ```bash
325
294
  git tag --list 'v*' --sort=-v:refname | head -1
326
295
  ```
327
296
 
328
- - 当最新 tag 存在且可解析为 `X.Y.Z` 时,目标里程碑为 `X.Y.x`
297
+ - When the latest tag exists and can be parsed as `X.Y.Z`, the target milestone is `X.Y.x`
329
298
 
330
- 3. 如果以上规则都无法得出结果,回退到 `General Backlog`
299
+ 3. If none of the above yields a result, fall back to `General Backlog`
331
300
 
332
- **d) 查找目标里程碑编号**
301
+ **d) Find the target milestone number**
333
302
 
334
- 执行:
303
+ Run:
335
304
 
336
305
  ```bash
337
306
  gh api "repos/$repo/milestones" --paginate \
338
307
  --jq '.[] | select(.title=="{target}") | .number'
339
308
  ```
340
309
 
341
- - 如果目标里程碑不存在,则降级到查找 `General Backlog`
342
- - 如果 `General Backlog` 也不存在,则记录 `Milestone: skipped (not found)` 并跳过关联
310
+ - If the target milestone does not exist, fall back to `General Backlog`
311
+ - If `General Backlog` also does not exist, record `Milestone: skipped (not found)` and skip assignment
343
312
 
344
- **e) 关联 Issue 到里程碑**
313
+ **e) Assign the Issue to the milestone**
345
314
 
346
- 一旦找到目标里程碑编号,执行:
315
+ Once a target milestone number is found, run:
347
316
 
348
317
  ```bash
349
318
  gh api "repos/$repo/issues/{issue-number}" -X PATCH -F milestone={milestone-number}
350
319
  ```
351
320
 
352
- 记录:
353
- - `Milestone: {target} (assigned)`
321
+ Record:
322
+ - `Milestone: {target} (assigned)` or
354
323
  - `Milestone: General Backlog (fallback)`
355
324
 
356
- ### 9. 拉取已有评论并构建已发布文件集合
325
+ ### 9. Fetch Existing Comments and Build the Published Artifact Set
357
326
 
358
- 一次性拉取 Issue 的全部评论,并基于隐藏标识构建“已发布文件 stem 集合”,同时在本地构建待发布的产物时间线。
327
+ Fetch all Issue comments in one pass, then build the set of published artifact stems from hidden markers and construct the local timeline of artifacts to publish.
359
328
 
360
- 先拉取评论(保留 comment id body):
329
+ First fetch comments (preserving comment id and body):
361
330
 
362
331
  ```bash
363
332
  comments_jsonl="$(mktemp)"
@@ -367,38 +336,38 @@ gh api "repos/$repo/issues/{issue-number}/comments" \
367
336
  --jq '.[] | {id, body}' > "$comments_jsonl"
368
337
  ```
369
338
 
370
- `task.md` Activity Log 中提取所有以 `→ {filename}` 结尾的记录。
339
+ Extract all Activity Log records in `task.md` that end with `→ {filename}`.
371
340
 
372
- 解析规则:
373
- - 使用正则 `/→\s+(\S+\.md)\s*$/` 提取文件名
374
- - 去掉 `.md` 后缀得到 `{file-stem}`
375
- - Activity Log 中的出现顺序构建产物时间线
376
- - `summary` 仍作为最后一个固定产物追加到时间线末尾
377
- - `summary` 始终排在最末
341
+ Parsing rules:
342
+ - Use the regex `/→\s+(\S+\.md)\s*$/` to extract filenames
343
+ - remove the `.md` suffix to get `{file-stem}`
344
+ - build the artifact timeline in Activity Log order
345
+ - append `summary` as a fixed final artifact at the end of the timeline
346
+ - `summary` is always last
378
347
 
379
- 仅当 Activity Log 引用的文件当前存在于任务目录中时,才纳入待发布集合;缺失文件跳过,不报错。
348
+ Only include files that still exist in the task directory in the publish set. Skip missing files without error.
380
349
 
381
- 每条同步评论的第一行必须插入隐藏标识:
350
+ The first line of every sync comment must include a hidden marker:
382
351
 
383
352
  ```html
384
353
  <!-- sync-issue:{task-id}:{file-stem} -->
385
354
  ```
386
355
 
387
- 其中 `{file-stem}` 为去掉 `.md` 后缀后的文件名,例如 `analysis`、`plan`、`implementation`、`implementation-r2`、`review-r3`;`summary` 仍使用字面量 `summary`。
356
+ Where `{file-stem}` is the filename without the `.md` suffix, for example `analysis`, `plan`, `implementation`, `implementation-r2`, or `review-r3`. `summary` still uses the literal `summary`.
388
357
 
389
- 时间线示例:
358
+ Timeline example:
390
359
  `analysis → plan → implementation → review → refinement → analysis-r2 → plan-r2 → implementation-r2 → review-r2 → summary`
391
360
 
392
- 对每个 `{file-stem}`,用本地检索判断是否已发布:
361
+ For each `{file-stem}`, determine whether it has already been published with a local check:
393
362
 
394
363
  ```bash
395
364
  grep -qF "<!-- sync-issue:{task-id}:{file-stem} -->" "$comments_jsonl"
396
365
  ```
397
366
 
398
- - 匹配到:该产物已发布,后续默认跳过
399
- - 未匹配:该产物尚未发布,可以创建新评论
367
+ - match found: this artifact has already been published and should be skipped by default
368
+ - no match: this artifact has not been published yet and can create a new comment
400
369
 
401
- `summary` 产物,额外提取评论 id 以便后续更新:
370
+ For the `summary` artifact, also extract the comment id for later updates:
402
371
 
403
372
  ```bash
404
373
  summary_comment_id="$(
@@ -407,92 +376,92 @@ summary_comment_id="$(
407
376
  )"
408
377
  ```
409
378
 
410
- 幂等要求:
411
- - 第一次执行时,只发布当前已存在产物对应的文件评论
412
- - 第二次执行时,必须跳过已发布文件,只补发新增产物(例如 `implementation-r2`、`review-r2`)
413
- - 如果所有产物文件评论都已发布,且 `summary` 内容没有变化,则本次不发布任何新评论
414
- - 如果 `summary` 已发布但交付状态发生变化,只更新原评论,不新增第二条 summary 评论
379
+ Before finishing Step 9, precompute `has_unpublished_artifacts` from the published/unpublished results above: whether any non-`summary` artifact remains unpublished. Keep this value fixed during Step 10. It is only used to decide whether `summary` should be updated in place or deleted and rebuilt at the end.
380
+
381
+ Idempotency requirements:
382
+ - On the first run, publish comments only for artifacts that currently exist
383
+ - On the second run, skip already published files and only publish new artifacts (for example `implementation-r2`, `review-r2`)
384
+ - If all artifact file comments have already been published and the `summary` content has not changed, publish no new comments
385
+ - If `summary` is already published but the delivery state has changed: delete the old `summary` and recreate it at the end when new artifacts are published this run; otherwise update the existing comment in place when no new artifacts are published
415
386
 
416
- ### 10. 按时间线逐条发布上下文文件
387
+ ### 10. Publish Context Files One by One in Timeline Order
417
388
 
418
- 按步骤 9 生成的已排序产物列表逐条处理,不要再使用固定 5 步骤,也不要把同类型多轮次产物合并到一条评论。
389
+ Process the sorted artifact list from Step 9 one item at a time. Do not fall back to a fixed 5-step order, and do not merge multiple rounds of the same artifact type into a single comment.
419
390
 
420
- **a) 为每个产物准备评论内容**
391
+ **a) Prepare comment content for each artifact**
421
392
 
422
- - `analysis`:发布 `analysis.md` 原文
423
- - `plan`:发布 `plan.md` 原文
424
- - `analysis-r{N}`、`plan-r{N}`:每个文件各自发布一条评论,正文直接使用对应产物原文
425
- - `implementation`、`implementation-r{N}`:每个文件各自发布一条评论,正文直接使用对应实现报告原文
426
- - `refinement`、`refinement-r{N}`:每个文件各自发布一条评论,正文直接使用对应修复报告原文
427
- - `review`、`review-r{N}`:每个文件各自发布一条评论,正文直接使用对应审查报告原文
428
- - `summary`:生成精简交付摘要,只包含当前交付状态与 GitHub 上可访问的绝对链接
393
+ - `analysis`: publish the full text of `analysis.md`
394
+ - `plan`: publish the full text of `plan.md`
395
+ - `analysis-r{N}`, `plan-r{N}`: publish one comment per file, using the artifact's original content as the comment body
396
+ - `implementation`, `implementation-r{N}`: publish one comment per file, using the corresponding implementation report as-is
397
+ - `refinement`, `refinement-r{N}`: publish one comment per file, using the corresponding refinement report as-is
398
+ - `review`, `review-r{N}`: publish one comment per file, using the corresponding review report as-is
399
+ - `summary`: generate a concise delivery summary that includes only the current delivery state and absolute GitHub links
429
400
 
430
- `summary` 外,其余产物都应发布原文,不要再次压缩成摘要。
401
+ All artifacts except `summary` must publish the original content directly. Do not compress them into another summary.
431
402
 
432
- 每条评论统一格式:
403
+ Use the same format for every comment:
433
404
 
434
405
  ```markdown
435
406
  <!-- sync-issue:{task-id}:{file-stem} -->
436
- ## {产物标题}
407
+ ## {artifact title}
437
408
 
438
- {原文内容或 summary 内容}
409
+ {original content or summary content}
439
410
 
440
411
  ---
441
- *由 AI 自动生成 · 内部追踪:{task-id}*
442
- ```
443
-
444
- 推荐标题映射:
445
- - `analysis` -> `需求分析`
446
- - `analysis-r2` -> `需求分析(Round 2)`
447
- - `analysis-r{N}` -> `需求分析(Round {N})`
448
- - `plan` -> `技术方案`
449
- - `plan-r2` -> `技术方案(Round 2)`
450
- - `plan-r{N}` -> `技术方案(Round {N})`
451
- - `implementation` -> `实现报告(Round 1)`
452
- - `implementation-r2` -> `实现报告(Round 2)`
453
- - `implementation-r{N}` -> `实现报告(Round {N})`
454
- - `refinement` -> `修复报告(Round 1)`
455
- - `refinement-r2` -> `修复报告(Round 2)`
456
- - `refinement-r{N}` -> `修复报告(Round {N})`
457
- - `review` -> `审查报告(Round 1)`
458
- - `review-r2` -> `审查报告(Round 2)`
459
- - `review-r{N}` -> `审查报告(Round {N})`
460
- - `summary` -> `交付摘要`
461
-
462
- `summary` 评论建议格式:
412
+ *Generated by AI · Internal tracking: {task-id}*
413
+ ```
414
+
415
+ Recommended title mapping:
416
+ - `analysis` -> `Requirements Analysis`
417
+ - `analysis-r2` -> `Requirements Analysis (Round 2)`
418
+ - `analysis-r{N}` -> `Requirements Analysis (Round {N})`
419
+ - `plan` -> `Technical Plan`
420
+ - `plan-r2` -> `Technical Plan (Round 2)`
421
+ - `plan-r{N}` -> `Technical Plan (Round {N})`
422
+ - `implementation` -> `Implementation Report (Round 1)`
423
+ - `implementation-r2` -> `Implementation Report (Round 2)`
424
+ - `implementation-r{N}` -> `Implementation Report (Round {N})`
425
+ - `refinement` -> `Refinement Report (Round 1)`
426
+ - `refinement-r2` -> `Refinement Report (Round 2)`
427
+ - `refinement-r{N}` -> `Refinement Report (Round {N})`
428
+ - `review` -> `Review Report (Round 1)`
429
+ - `review-r2` -> `Review Report (Round 2)`
430
+ - `review-r{N}` -> `Review Report (Round {N})`
431
+ - `summary` -> `Delivery Summary`
432
+
433
+ Recommended `summary` comment format:
463
434
 
464
435
  ```markdown
465
436
  <!-- sync-issue:{task-id}:summary -->
466
- ## 交付摘要
437
+ ## Delivery Summary
467
438
 
468
- **更新时间**:{当前时间}
469
- **状态**:{模式化状态描述}
439
+ **Updated at**: {current time}
440
+ **Status**: {formatted status description}
470
441
 
471
- | 类型 | 内容 |
442
+ | Type | Content |
472
443
  |---|---|
473
- | 分支 | `{branch N/A}` |
474
- | Commit | [`{commit-short}`](https://github.com/{owner}/{repo}/commit/{commit-hash}) `N/A` |
475
- | PR | [#{pr-number}](https://github.com/{owner}/{repo}/pull/{pr-number}) 或 `N/A` |
476
- | Issue | `{issue-state}` |
444
+ | Branch | `{branch or N/A}` |
445
+ | Commit | [`{commit-short}`](https://github.com/{owner}/{repo}/commit/{commit-hash}) or `N/A` |
477
446
 
478
447
  ---
479
- *由 AI 自动生成 · 内部追踪:{task-id}*
448
+ *Generated by AI · Internal tracking: {task-id}*
480
449
  ```
481
450
 
482
- 模式化状态描述要求:
483
- - 模式 A:`✅ 已完成,代码已合入 {branch}`
484
- - 模式 B:`PR 阶段,当前为 #{pr-number}(OPEN 或 MERGED)`
485
- - 模式 C:`开发中,当前步骤为 {current_step}`
451
+ Formatted status description rules:
452
+ - Mode A: `✅ Completed`
453
+ - Mode B: `PR stage`
454
+ - Mode C: `In development, current step is {current_step}`
486
455
 
487
- **b) 跳过已发布或缺失的产物**
456
+ **b) Skip already-published or missing artifacts**
488
457
 
489
- - 对于 `analysis.md`、`plan.md`、`implementation*.md`、`review*.md`:如果对应文件不存在,直接跳过,不报错
490
- - 对于任意产物:如果标识已存在,默认跳过
491
- - 对于 `summary`:即使标识已存在,也要重新生成候选内容,用于比较是否需要更新
458
+ - For `analysis.md`, `plan.md`, `implementation*.md`, and `review*.md`: skip directly if the corresponding file does not exist, without error
459
+ - For any artifact: skip by default if its marker already exists
460
+ - For `summary`: regenerate candidate content even if its marker already exists, so you can compare whether an update is needed
492
461
 
493
- **c) 发布新评论**
462
+ **c) Publish a new comment**
494
463
 
495
- 当产物尚未发布时,执行:
464
+ When an artifact has not been published yet, run:
496
465
 
497
466
  ```bash
498
467
  gh issue comment {issue-number} --body "$(cat <<'EOF'
@@ -501,69 +470,80 @@ EOF
501
470
  )"
502
471
  ```
503
472
 
504
- **d) 仅更新已有 summary 评论**
473
+ **d) Publish or rebuild the `summary` comment**
474
+
475
+ `summary` must always remain the last comment. Choose the handling strategy with these rules:
505
476
 
506
- 如果 `summary` 标识已存在,且新生成内容与已有内容不同,则编辑原评论:
477
+ - `summary` does not exist: publish a new `summary` comment using Step 10c
478
+ - `summary` exists and `has_unpublished_artifacts=true`: delete the old `summary` comment first, then publish a new `summary` comment using Step 10c
479
+ - `summary` exists, `has_unpublished_artifacts=false`, and the newly generated content differs from the existing one: update the existing comment in place
480
+ - `summary` exists, `has_unpublished_artifacts=false`, and the content is the same: do nothing
481
+
482
+ To delete the old `summary` comment, run:
483
+
484
+ ```bash
485
+ gh api "repos/$repo/issues/comments/{summary_comment_id}" -X DELETE
486
+ ```
487
+
488
+ To update an existing `summary` comment in place, run:
507
489
 
508
490
  ```bash
509
- gh api "repos/$repo/issues/comments/{comment-id}" -X PATCH -f body="$(cat <<'EOF'
491
+ gh api "repos/$repo/issues/comments/{summary_comment_id}" -X PATCH -f body="$(cat <<'EOF'
510
492
  {comment-body}
511
493
  EOF
512
494
  )"
513
495
  ```
514
496
 
515
- 如果内容相同,则不做任何操作。
516
-
517
- **e) 零操作场景**
497
+ **e) No-op scenario**
518
498
 
519
- 如果所有产物都已同步,且 `summary` 无需更新:
520
- - 不发布任何新评论
521
- - 在最终告知用户时明确说明:`所有产物已同步,无新内容`
499
+ If all artifacts are already synced and `summary` does not need an update:
500
+ - publish no new comments
501
+ - explicitly tell the user at the end: `All artifacts are already synced, no new content`
522
502
 
523
- ### 11. 更新任务状态
503
+ ### 11. Update Task Status
524
504
 
525
- 获取当前时间:
505
+ Get the current time:
526
506
 
527
507
  ```bash
528
508
  date "+%Y-%m-%d %H:%M:%S"
529
509
  ```
530
510
 
531
- task.md 中添加或更新 `last_synced_at` 字段为 `{当前时间}`。
532
- - **追加**到 `## Activity Log`(不要覆盖之前的记录):
511
+ Add or update the `last_synced_at` field in task.md with `{current time}`.
512
+ - **Append** to `## Activity Log` (do NOT overwrite previous entries):
533
513
  ```
534
514
  - {yyyy-MM-dd HH:mm:ss} — **Sync to Issue** by {agent} — Progress synced to Issue #{issue-number}
535
515
  ```
536
516
 
537
- ### 12. 告知用户
517
+ ### 12. Inform User
538
518
 
539
519
  ```
540
- 进度已同步到 Issue #{issue-number}
520
+ Progress synced to Issue #{issue-number}.
541
521
 
542
- 同步结果:
543
- - 新发布评论:{数量}
544
- - 更新评论:{数量}
545
- - 已跳过步骤:{步骤列表或 `无`}
546
- - 当前状态:{状态}
547
- - Labels:type={type-label 或 skipped},status={status-label cleared}in:={新增数量}
548
- - Issue Type{Bug / Feature / Task / skipped}
549
- - Milestone{preserved / assigned / fallback / skipped}
550
- - Development{已追加 Closes 关联 / 已存在关联 / PR,跳过}
522
+ Sync result:
523
+ - New comments published: {count}
524
+ - Comments updated: {count}
525
+ - Steps skipped: {step list or `none`}
526
+ - Current status: {status}
527
+ - Labels: status={status-label or cleared}, in:={added count}
528
+ - Issue Type: {Bug / Feature / Task / skipped}
529
+ - Milestone: {preserved / assigned / fallback / skipped}
530
+ - Development: {Closes link appended / link already existed / no PR, skipped}
551
531
 
552
- 查看:https://github.com/{owner}/{repo}/issues/{issue-number}
532
+ View: https://github.com/{owner}/{repo}/issues/{issue-number}
553
533
 
554
- 如果本次没有发布或更新任何评论,请明确说明:所有步骤已同步,无新内容。
534
+ If no comments were published or updated in this run, clearly state: all steps are already synced, no new content.
555
535
  ```
556
536
 
557
- ## 注意事项
537
+ ## Notes
558
538
 
559
- 1. **需要 Issue 编号**:任务的 task.md 中必须有 `issue_number`。如果缺失,提示用户。
560
- 2. **受众**:`sync-issue` 技能面向利益相关者;`sync-pr` 技能面向代码审查者。关注点不同。
561
- 3. **同步时机**:在完成重要阶段(分析、设计、实现、审查)或被阻塞时同步。
562
- 4. **避免刷屏**:不要同步过于频繁。虽然本技能使用隐藏标识保证幂等,但仍应避免无意义重复同步。
539
+ 1. **Requires an issue number**: task.md must contain `issue_number`. If missing, prompt the user.
540
+ 2. **Audience**: `sync-issue` is for stakeholders, while `sync-pr` is for code reviewers. They have different focus areas.
541
+ 3. **When to sync**: sync after major stages (analysis, design, implementation, review) or when blocked.
542
+ 4. **Avoid noise**: do not sync too frequently. Although this skill uses hidden markers for idempotency, avoid meaningless repeated syncs.
563
543
 
564
- ## 错误处理
544
+ ## Error Handling
565
545
 
566
- - 任务未找到:提示 "Task {task-id} not found"
567
- - 缺少 Issue 编号:提示 "Task has no issue_number field"
568
- - Issue 未找到:提示 "Issue #{number} not found"
569
- - gh 认证失败:提示 "Please check GitHub CLI authentication"
546
+ - Task not found: output "Task {task-id} not found"
547
+ - Missing issue number: output "Task has no issue_number field"
548
+ - Issue not found: output "Issue #{number} not found"
549
+ - `gh` authentication failed: output "Please check GitHub CLI authentication"