@fitlab-ai/agent-infra 0.5.3 → 0.5.5

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 (69) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/lib/defaults.json +1 -0
  4. package/package.json +1 -1
  5. package/templates/.agents/rules/issue-pr-commands.github.en.md +35 -10
  6. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +35 -10
  7. package/templates/.agents/rules/issue-sync.github.en.md +118 -28
  8. package/templates/.agents/rules/issue-sync.github.zh-CN.md +112 -22
  9. package/templates/.agents/rules/milestone-inference.github.en.md +13 -6
  10. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +13 -6
  11. package/templates/.agents/rules/pr-sync.github.en.md +3 -1
  12. package/templates/.agents/rules/pr-sync.github.zh-CN.md +3 -1
  13. package/templates/.agents/scripts/platform-adapters/platform-sync.github.js +1118 -0
  14. package/templates/.agents/scripts/validate-artifact.js +51 -802
  15. package/templates/.agents/skills/analyze-task/SKILL.en.md +2 -2
  16. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +2 -2
  17. package/templates/.agents/skills/analyze-task/config/verify.json +1 -1
  18. package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
  19. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
  20. package/templates/.agents/skills/block-task/config/verify.json +1 -1
  21. package/templates/.agents/skills/cancel-task/SKILL.en.md +6 -6
  22. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +6 -6
  23. package/templates/.agents/skills/cancel-task/config/verify.json +1 -1
  24. package/templates/.agents/skills/commit/SKILL.en.md +14 -2
  25. package/templates/.agents/skills/commit/SKILL.zh-CN.md +14 -2
  26. package/templates/.agents/skills/commit/config/verify.json +2 -1
  27. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +23 -0
  28. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +23 -0
  29. package/templates/.agents/skills/complete-task/SKILL.en.md +2 -2
  30. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +2 -2
  31. package/templates/.agents/skills/complete-task/config/verify.json +1 -1
  32. package/templates/.agents/skills/create-issue/SKILL.en.md +3 -1
  33. package/templates/.agents/skills/create-issue/SKILL.zh-CN.md +3 -1
  34. package/templates/.agents/skills/create-issue/config/verify.json +1 -1
  35. package/templates/.agents/skills/create-issue/reference/label-and-type.en.md +6 -1
  36. package/templates/.agents/skills/create-issue/reference/label-and-type.zh-CN.md +6 -1
  37. package/templates/.agents/skills/create-pr/SKILL.en.md +4 -4
  38. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +4 -4
  39. package/templates/.agents/skills/create-pr/config/verify.json +3 -1
  40. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +9 -6
  41. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +9 -6
  42. package/templates/.agents/skills/create-release-note/SKILL.en.md +27 -2
  43. package/templates/.agents/skills/create-release-note/SKILL.zh-CN.md +27 -2
  44. package/templates/.agents/skills/create-task/config/verify.json +1 -1
  45. package/templates/.agents/skills/implement-task/SKILL.en.md +4 -4
  46. package/templates/.agents/skills/implement-task/SKILL.zh-CN.md +4 -4
  47. package/templates/.agents/skills/implement-task/config/verify.json +1 -2
  48. package/templates/.agents/skills/import-codescan/config/verify.json +1 -1
  49. package/templates/.agents/skills/import-dependabot/config/verify.json +1 -1
  50. package/templates/.agents/skills/import-issue/SKILL.en.md +1 -1
  51. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +1 -1
  52. package/templates/.agents/skills/import-issue/config/verify.json +1 -1
  53. package/templates/.agents/skills/plan-task/SKILL.en.md +2 -2
  54. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -2
  55. package/templates/.agents/skills/plan-task/config/verify.json +1 -1
  56. package/templates/.agents/skills/refine-task/SKILL.en.md +2 -4
  57. package/templates/.agents/skills/refine-task/SKILL.zh-CN.md +2 -4
  58. package/templates/.agents/skills/refine-task/config/verify.json +1 -2
  59. package/templates/.agents/skills/refine-title/SKILL.en.md +5 -1
  60. package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +5 -1
  61. package/templates/.agents/skills/restore-task/config/verify.json +1 -1
  62. package/templates/.agents/skills/review-task/SKILL.en.md +2 -2
  63. package/templates/.agents/skills/review-task/SKILL.zh-CN.md +2 -2
  64. package/templates/.agents/skills/review-task/config/verify.json +1 -1
  65. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +2 -1
  66. package/templates/.github/scripts/sync-labels-to-set.sh +110 -0
  67. package/templates/.github/workflows/metadata-sync.yml +118 -0
  68. package/templates/.github/workflows/pr-label.yml +66 -0
  69. package/templates/.github/workflows/status-label.yml +20 -30
@@ -2,38 +2,114 @@
2
2
 
3
3
  在任务技能需要更新 GitHub Issue 时先读取本文件。
4
4
 
5
- ## status: label 直设
5
+ ## Upstream 仓库检测
6
6
 
7
- 如果 task.md 中存在有效的 `issue_number`(非空、非 `N/A`),且 Issue 状态为 `OPEN`,则替换所有 `status:` label 并设置目标值:
7
+ 外部开发者在 fork 仓库中执行 `gh` 命令时,默认目标会指向 fork,而不是原始仓库。所有后续 `gh issue` `gh api "repos/..."` 操作都必须先检测 upstream 仓库,并统一复用 `upstream_repo`。
8
8
 
9
9
  ```bash
10
- state=$(gh issue view {issue-number} --json state --jq '.state' 2>/dev/null)
10
+ upstream_repo=$(gh api "repos/$(gh repo view --json nameWithOwner -q .nameWithOwner)" \
11
+ --jq 'if .fork then .parent.full_name else .full_name end' 2>/dev/null)
12
+ ```
13
+
14
+ - 非 fork 仓库:返回当前仓库自身的 `full_name`
15
+ - fork 仓库:返回父仓库的 `full_name`
16
+ - 后续所有 `gh issue` 命令统一使用 `-R "$upstream_repo"`
17
+ - 后续所有 `gh api "repos/..."` 命令统一使用 `"repos/$upstream_repo/..."`
18
+
19
+ ## 权限检测
20
+
21
+ 所有需要写权限的操作都先对 upstream 仓库做一次权限检测。检测失败时按无权限处理,确保安全降级。
22
+
23
+ ```bash
24
+ repo_perms=$(gh api "repos/$upstream_repo" --jq '.permissions' 2>/dev/null || echo '{}')
25
+ has_triage=$(printf '%s' "$repo_perms" | grep -q '"triage":true' 2>/dev/null && echo true || echo false)
26
+ has_push=$(printf '%s' "$repo_perms" | grep -q '"push":true' 2>/dev/null && echo true || echo false)
27
+ ```
28
+
29
+ 操作与权限映射:
30
+
31
+ | 操作 | 所需权限 | 说明 |
32
+ |------|---------|------|
33
+ | 设置/移除 label | `has_triage` | triage 是最低权限 |
34
+ | 设置/移除 milestone | `has_triage` | 同上 |
35
+ | 编辑 Issue body | `has_triage` | 需求复选框同步使用 |
36
+ | 设置 Issue Type | `has_push` | 需要 write 权限 |
37
+ | 设置 assignee | 不检测 | 无权限时直接跳过 |
38
+ | 发布/更新评论 | 无需检测 | 公开仓库中认证用户可执行 |
39
+
40
+ ## 降级行为定义
41
+
42
+ | 层级 | 操作类型 | 有权限 | 无权限 |
43
+ |------|---------|--------|--------|
44
+ | 静默降级 | label / milestone / Issue Type | 直接执行 `gh` 命令,同时更新 task 留言 | 跳过 `gh` 直接操作,仅更新 task 留言,由 bot 补位 |
45
+ | 直接跳过 | assignee | 直接执行 `gh` 命令 | 不做任何替代 |
46
+ | 正常执行 | 评论 | 正常执行 | 正常执行 |
47
+
48
+ 关键原则:
49
+
50
+ - 无论是否有写权限,task 留言同步都必须继续执行
51
+ - 权限不足只影响直接写 Issue 元数据的步骤,不中断整个技能
52
+ - 现有 `2>/dev/null || true` 容错模式保持不变
53
+
54
+ ## 外部开发者锁定机制
55
+
56
+ 维护者(`has_triage=true`)不受限制。外部开发者(`has_triage=false`)在开始任务前,必须先检查 Issue 上是否已有当前任务的 `task` 留言作者。
57
+
58
+ ```bash
59
+ task_comment_author=$(gh api "repos/$upstream_repo/issues/{issue-number}/comments" \
60
+ --paginate --jq '[.[] | select(.body | test("<!-- sync-issue:{task-id}:task -->")) | .user.login] | first' \
61
+ 2>/dev/null || echo "")
62
+ current_user=$(gh api user --jq '.login' 2>/dev/null || echo "")
63
+ ```
64
+
65
+ 判定规则:
66
+
67
+ - 没有 `task` 留言:允许开始
68
+ - `task` 留言作者等于当前用户:允许继续
69
+ - `task` 留言作者不等于当前用户:立即停止,并提示先与维护者协调,避免多人同时接手同一任务
70
+
71
+ ## status label 设置
72
+
73
+ 算法说明:下面的流程与 `.github/scripts/sync-labels-to-set.sh` 保持一致(集合差集)。本章节是 AI Agent 侧的等价实现(`target_set = {"{target-status-label}"}` 的特例)。修改任一侧时,必须同步另一侧,避免 Agent 与 Bot 的行为漂移。
74
+
75
+ 如果 task.md 中存在有效的 `issue_number`(非空、非 `N/A`),且 Issue 状态为 `OPEN`,则按幂等差集方式将 `status:` label 同步到目标值:
76
+
77
+ ```bash
78
+ state=$(gh issue view {issue-number} -R "$upstream_repo" --json state --jq '.state' 2>/dev/null)
11
79
  if [ "$state" = "OPEN" ]; then
12
- gh issue view {issue-number} --json labels \
13
- --jq '.labels[].name | select(startswith("status:"))' 2>/dev/null \
14
- | while IFS= read -r label; do
15
- [ -z "$label" ] && continue
16
- gh issue edit {issue-number} --remove-label "$label" 2>/dev/null || true
17
- done
18
- gh issue edit {issue-number} --add-label "{target-status-label}" 2>/dev/null || true
80
+ current_status_labels=$(gh issue view {issue-number} -R "$upstream_repo" \
81
+ --json labels --jq '.labels[].name | select(startswith("status:"))' 2>/dev/null || true)
82
+ printf '%s\n' "$current_status_labels" | while IFS= read -r label; do
83
+ [ -z "$label" ] && continue
84
+ if [ "$label" != "{target-status-label}" ] && [ "$has_triage" = "true" ]; then
85
+ gh issue edit {issue-number} -R "$upstream_repo" --remove-label "$label" 2>/dev/null || true
86
+ fi
87
+ done
88
+ if [ "$has_triage" = "true" ] && ! printf '%s\n' "$current_status_labels" | grep -qxF "{target-status-label}"; then
89
+ gh issue edit {issue-number} -R "$upstream_repo" --add-label "{target-status-label}" 2>/dev/null || true
90
+ fi
19
91
  fi
20
92
  ```
21
93
 
22
94
  使用 `while IFS= read -r label` 按行处理,可避免 `status: in-progress` 这类含空格 label 被 shell 按空格拆开。
23
95
 
96
+ 如果 `has_triage=false`,则跳过直接设置 label,只更新 task 留言,由 bot 根据最新 task 元数据补位。
97
+
24
98
  如果 `gh` 命令失败,跳过并继续,不中断技能执行。
25
99
 
26
100
  ## Assignee 同步
27
101
 
28
102
  当技能创建或导入 Issue 时,自动将当前执行者添加为 assignee:
29
103
 
30
- - `create-issue`:在 `gh issue create` 命令中使用 `--assignee @me` 参数
31
- - `import-issue`:导入后执行 `gh issue edit {issue-number} --add-assignee @me 2>/dev/null || true`
104
+ - `create-issue`:在 `gh issue create` 命令中使用 `--assignee @me` 参数,并附带 `-R "$upstream_repo"`
105
+ - `import-issue`:导入后执行 `gh issue edit {issue-number} -R "$upstream_repo" --add-assignee @me 2>/dev/null || true`
32
106
 
33
- `@me` 由 `gh` CLI 自动解析为当前认证用户。此操作是幂等的(重复添加不会报错)。如果命令失败(如权限不足),跳过并继续。
107
+ `@me` 由 `gh` CLI 自动解析为当前认证用户。此操作是幂等的(重复添加不会报错)。如果命令失败(如权限不足),直接跳过,不做任何替代。
34
108
 
35
109
  ## `in:` label 同步
36
110
 
111
+ > **触发时机**:`in:` label 同步应在代码提交后(commit 技能)执行,不在 implement-task 或 refine-task 阶段执行。create-pr 阶段仅从 Issue 复制到 PR,不重新计算。
112
+
37
113
  读取 `.agents/.airc.json` 的 `labels.in` 映射。
38
114
 
39
115
  ```bash
@@ -48,15 +124,18 @@ git diff {base-branch}...HEAD --name-only
48
124
  2. 对每个文件按目录前缀匹配 `labels.in` 中的值,得到"应有的 `in:` labels"集合
49
125
  3. 查询 Issue/PR 当前的 `in:` labels
50
126
  4. 差集比较:
51
- - 应有但没有 `gh issue edit {issue-number} --add-label "in: {module}" 2>/dev/null || true`
52
- - 有但不应有 `gh issue edit {issue-number} --remove-label "in: {module}" 2>/dev/null || true`
127
+ - 应有但没有:仅当 `has_triage=true` 时执行 `gh issue edit {issue-number} -R "$upstream_repo" --add-label "in: {module}" 2>/dev/null || true`
128
+ - 有但不应有:仅当 `has_triage=true` 时执行 `gh issue edit {issue-number} -R "$upstream_repo" --remove-label "in: {module}" 2>/dev/null || true`
53
129
 
54
130
  ### 无映射时(只增不删回退)
55
131
 
56
132
  如果 `.airc.json` 中不存在 `labels.in` 或为空对象:
133
+
57
134
  1. 查询仓库已有 `in:` labels
58
135
  2. 从改动文件提取第一级目录
59
- 3. 仅添加匹配的 label,不移除已有 `in:` label
136
+ 3. 仅当 `has_triage=true` 时添加匹配的 label,不移除已有 `in:` label
137
+
138
+ 如果 `has_triage=false`,则跳过直接修改 `in:` label,只保留 task 留言同步,由后续自动化补位。
60
139
 
61
140
  ## 产物评论发布
62
141
 
@@ -69,7 +148,7 @@ git diff {base-branch}...HEAD --name-only
69
148
  发布前先检查是否已存在同标记评论:
70
149
 
71
150
  ```bash
72
- gh api "repos/{owner}/{repo}/issues/{issue-number}/comments" \
151
+ gh api "repos/$upstream_repo/issues/{issue-number}/comments" \
73
152
  --paginate --jq '.[].body' \
74
153
  | grep -qF "<!-- sync-issue:{task-id}:{file-stem} -->"
75
154
  ```
@@ -99,20 +178,23 @@ gh api "repos/{owner}/{repo}/issues/{issue-number}/comments" \
99
178
  其中 `{agent}` 使用当前执行该技能的 AI 代理名称(如 `claude`、`codex`、`gemini`)。
100
179
 
101
180
  `summary` 评论需要额外处理:
181
+
102
182
  - 先查找已有 `<!-- sync-issue:{task-id}:summary -->` 评论的 ID
103
183
  - 不存在则创建
104
- - 已存在且正文有变化时,使用 `gh api "repos/{owner}/{repo}/issues/comments/{comment-id}" -X PATCH -f body=...` 原地更新
184
+ - 已存在且正文有变化时,使用 `gh api "repos/$upstream_repo/issues/comments/{comment-id}" -X PATCH -f body=...` 原地更新
105
185
 
106
186
  ```bash
107
- summary_comment_id=$(gh api "repos/{owner}/{repo}/issues/{issue-number}/comments" \
187
+ summary_comment_id=$(gh api "repos/$upstream_repo/issues/{issue-number}/comments" \
108
188
  --paginate --jq '.[] | select(.body | startswith("<!-- sync-issue:{task-id}:summary -->")) | .id' \
109
189
  | head -n 1)
110
- gh api "repos/{owner}/{repo}/issues/comments/{comment-id}" -X PATCH -f body="$(cat <<'EOF'
190
+ gh api "repos/$upstream_repo/issues/comments/{comment-id}" -X PATCH -f body="$(cat <<'EOF'
111
191
  {comment-body}
112
192
  EOF
113
193
  )"
114
194
  ```
115
195
 
196
+ 评论发布不受 `has_triage` / `has_push` 限制,认证用户可正常执行。
197
+
116
198
  ## task.md 评论同步
117
199
 
118
200
  隐藏标记:
@@ -158,8 +240,11 @@ task.md 评论格式:
158
240
  还原时,从 `<details>` 块中提取 frontmatter,与正文拼合恢复为原始 `task.md`。
159
241
 
160
242
  评论标题映射:
243
+
161
244
  - `task` -> `任务文件`
162
245
 
246
+ task 留言同步始终执行,不受权限降级影响。
247
+
163
248
  ## 补发规则(`/complete-task` 归档前执行)
164
249
 
165
250
  - 扫描任务目录中的 `task.md`、`analysis*.md`、`plan*.md`、`implementation*.md`、`review*.md`、`refinement*.md`
@@ -178,6 +263,7 @@ task.md 评论格式:
178
263
  - 如果只有前邻居或后邻居,仅保留存在的一侧说明;如果两侧都不存在,则不添加位置说明
179
264
 
180
265
  标题映射:
266
+
181
267
  - `task` -> `任务文件`
182
268
  - `analysis` / `analysis-r{N}` -> `需求分析` / `需求分析(Round {N})`
183
269
  - `plan` / `plan-r{N}` -> `技术方案` / `技术方案(Round {N})`
@@ -186,6 +272,8 @@ task.md 评论格式:
186
272
  - `refinement` / `refinement-r{N}` -> `修复报告(Round 1)` / `修复报告(Round {N})`
187
273
  - `summary` -> `交付摘要`
188
274
 
275
+ 补发评论同样不受 `has_triage` / `has_push` 限制。
276
+
189
277
  ## 需求复选框同步
190
278
 
191
279
  从 task.md 的 `## 需求` 段落提取已勾选的 `- [x]` 条目;如果没有,跳过。
@@ -193,10 +281,12 @@ task.md 评论格式:
193
281
  读取 Issue 当前正文:
194
282
 
195
283
  ```bash
196
- gh issue view {issue-number} --json body --jq '.body'
284
+ gh issue view {issue-number} -R "$upstream_repo" --json body --jq '.body'
197
285
  ```
198
286
 
199
- 按复选框文本匹配,将对应的 `- [ ] {text}` 单向替换为 `- [x] {text}`。只有正文实际变化时,才使用 `gh api` PATCH 更新完整 body。
287
+ 按复选框文本匹配,将对应的 `- [ ] {text}` 单向替换为 `- [x] {text}`。只有正文实际变化且 `has_triage=true` 时,才使用 `gh api` PATCH 更新完整 body。
288
+
289
+ 如果 `has_triage=false`,则跳过正文 PATCH,只更新 task 留言,由 bot 根据最新任务状态补位。
200
290
 
201
291
  ## Shell 安全规则
202
292
 
@@ -7,6 +7,7 @@ Read this file before `create-issue`, `implement-task`, or `create-pr` handles a
7
7
  - Narrow the milestone over the skill lifecycle: release line -> concrete version -> reuse
8
8
  - Every phase must fall back safely instead of blocking the skill
9
9
  - If `gh` is unavailable, unauthenticated, or the GitHub API call fails, skip milestone handling and continue
10
+ - Before any repository-scoped `gh api`, `gh issue edit`, or Issue lookup runs, the caller must resolve `upstream_repo` and `has_triage`
10
11
  - Only use milestones that actually exist in the repository; if a target milestone is unavailable, apply the fallback for that phase
11
12
 
12
13
  ## Branch Mode Detection
@@ -35,12 +36,14 @@ Priority:
35
36
  Suggested release-line query:
36
37
 
37
38
  ```bash
38
- gh api "repos/{owner}/{repo}/milestones?state=open&per_page=100" \
39
+ gh api "repos/$upstream_repo/milestones?state=open&per_page=100" \
39
40
  --jq '.[].title'
40
41
  ```
41
42
 
42
43
  Only match titles in `X.Y.x` format and choose the smallest major/minor pair numerically.
43
44
 
45
+ Direct milestone writes are triage-gated. When the caller detected `has_triage=false`, omit `--milestone` and continue.
46
+
44
47
  ## Phase 2: `implement-task`
45
48
 
46
49
  Goal: narrow the Issue milestone from a release line to a concrete version when implementation starts.
@@ -60,15 +63,17 @@ Sequence:
60
63
  4. When a target concrete version is found, run:
61
64
 
62
65
  ```bash
63
- gh issue edit {issue-number} --milestone "{version}"
66
+ if [ "$has_triage" = "true" ]; then
67
+ gh issue edit {issue-number} -R "$upstream_repo" --milestone "{version}"
68
+ fi
64
69
  ```
65
70
 
66
- 5. If the target milestone does not exist or the branch ancestry cannot be determined reliably, keep the original milestone unchanged
71
+ 5. If `has_triage=false`, the target milestone does not exist, or the branch ancestry cannot be determined reliably, keep the original milestone unchanged
67
72
 
68
73
  Suggested concrete-version query:
69
74
 
70
75
  ```bash
71
- gh api "repos/{owner}/{repo}/milestones?state=open&per_page=100" \
76
+ gh api "repos/$upstream_repo/milestones?state=open&per_page=100" \
72
77
  --jq '.[].title'
73
78
  ```
74
79
 
@@ -94,9 +99,11 @@ Sequence:
94
99
  2. If the Issue has a milestone, run:
95
100
 
96
101
  ```bash
97
- gh pr edit {pr-number} --milestone "{milestone}"
102
+ if [ "$has_triage" = "true" ]; then
103
+ gh pr edit {pr-number} --milestone "{milestone}"
104
+ fi
98
105
  ```
99
106
 
100
- 3. If the Issue has no milestone, skip PR milestone assignment
107
+ 3. If the Issue has no milestone, or `has_triage=false`, skip PR milestone assignment
101
108
 
102
109
  Do not infer a PR milestone separately from task.md, branch names, tags, or `General Backlog`.
@@ -7,6 +7,7 @@
7
7
  - milestone 在技能生命周期中逐步收窄:版本线 -> 具体版本 -> 复用
8
8
  - 任一步骤推断失败时都必须回退,不得阻塞技能执行
9
9
  - 如果 `gh` CLI 不可用、未认证,或 GitHub API 请求失败,跳过 milestone 处理并继续
10
+ - 在执行 repo 级 `gh api`、`gh issue edit` 或 Issue 查询前,调用方必须先完成 `upstream_repo` / `has_triage` 检测
10
11
  - 只使用仓库中实际存在的 milestone;目标 milestone 不存在时按各阶段 fallback 处理
11
12
 
12
13
  ## 分支模式检测
@@ -35,12 +36,14 @@ git branch -r | grep -v 'HEAD' | grep -E 'origin/[0-9]+\.[0-9]+\.x$'
35
36
  版本线查询建议:
36
37
 
37
38
  ```bash
38
- gh api "repos/{owner}/{repo}/milestones?state=open&per_page=100" \
39
+ gh api "repos/$upstream_repo/milestones?state=open&per_page=100" \
39
40
  --jq '.[].title'
40
41
  ```
41
42
 
42
43
  只匹配 `X.Y.x` 格式的标题;按 major、minor 数值升序取最小版本线。
43
44
 
45
+ Milestone 设置属于 `has_triage` 权限范围;如果调用方检测到 `has_triage=false`,则省略 `--milestone` 并继续。
46
+
44
47
  ## 阶段 2:`implement-task`
45
48
 
46
49
  目标:开始开发时,把 Issue milestone 从版本线收窄到具体版本。
@@ -60,15 +63,17 @@ gh api "repos/{owner}/{repo}/milestones?state=open&per_page=100" \
60
63
  4. 找到目标具体版本后,执行:
61
64
 
62
65
  ```bash
63
- gh issue edit {issue-number} --milestone "{version}"
66
+ if [ "$has_triage" = "true" ]; then
67
+ gh issue edit {issue-number} -R "$upstream_repo" --milestone "{version}"
68
+ fi
64
69
  ```
65
70
 
66
- 5. 如果目标 milestone 不存在或无法可靠判断 -> 保持原 milestone 不变
71
+ 5. 如果 `has_triage=false`、目标 milestone 不存在,或无法可靠判断 -> 保持原 milestone 不变
67
72
 
68
73
  具体版本查询建议:
69
74
 
70
75
  ```bash
71
- gh api "repos/{owner}/{repo}/milestones?state=open&per_page=100" \
76
+ gh api "repos/$upstream_repo/milestones?state=open&per_page=100" \
72
77
  --jq '.[].title'
73
78
  ```
74
79
 
@@ -94,9 +99,11 @@ git merge-base --is-ancestor origin/main HEAD
94
99
  2. Issue 有 milestone -> 执行:
95
100
 
96
101
  ```bash
97
- gh pr edit {pr-number} --milestone "{milestone}"
102
+ if [ "$has_triage" = "true" ]; then
103
+ gh pr edit {pr-number} --milestone "{milestone}"
104
+ fi
98
105
  ```
99
106
 
100
- 3. Issue 没有 milestone -> 跳过,不设置 PR milestone
107
+ 3. Issue 没有 milestone,或 `has_triage=false` -> 跳过,不设置 PR milestone
101
108
 
102
109
  不要再使用 `task.md`、分支名、tag 或 `General Backlog` 为 PR 单独推断 milestone。
@@ -70,6 +70,8 @@ Use this canonical comment body template:
70
70
 
71
71
  Fetch existing comments through the Issues comments API, not the dedicated PR comments API.
72
72
 
73
+ Before this section runs, the caller must resolve `upstream_repo` by following `.agents/rules/issue-pr-commands.md` / `.agents/rules/issue-sync.md`.
74
+
73
75
  Process:
74
76
  1. Fetch existing PR comments and locate the comment ID that starts with `<!-- sync-pr:{task-id}:summary -->`
75
77
  2. When rendering the body, always write the current `git rev-parse HEAD` result into `<!-- last-commit: {git-head-sha} -->`
@@ -80,7 +82,7 @@ Process:
80
82
  When updating an existing comment, use:
81
83
 
82
84
  ```bash
83
- gh api "repos/{owner}/{repo}/issues/comments/{comment-id}" -X PATCH -f body="$(cat <<'EOF'
85
+ gh api "repos/$upstream_repo/issues/comments/{comment-id}" -X PATCH -f body="$(cat <<'EOF'
84
86
  {comment-body}
85
87
  EOF
86
88
  )"
@@ -70,6 +70,8 @@
70
70
 
71
71
  已有评论必须通过 Issues comments API 获取,而不是单独的 PR comments API。
72
72
 
73
+ 调用方在执行本章节前,必须先按 `.agents/rules/issue-pr-commands.md` / `.agents/rules/issue-sync.md` 完成 `upstream_repo` 检测。
74
+
73
75
  处理顺序:
74
76
  1. 获取 PR 上现有 comments,查找以 `<!-- sync-pr:{task-id}:summary -->` 开头的评论 ID
75
77
  2. 渲染评论正文时,始终写入当前 `git rev-parse HEAD` 的结果到 `<!-- last-commit: {git-head-sha} -->`
@@ -80,7 +82,7 @@
80
82
  更新已有评论时,使用如下模式:
81
83
 
82
84
  ```bash
83
- gh api "repos/{owner}/{repo}/issues/comments/{comment-id}" -X PATCH -f body="$(cat <<'EOF'
85
+ gh api "repos/$upstream_repo/issues/comments/{comment-id}" -X PATCH -f body="$(cat <<'EOF'
84
86
  {comment-body}
85
87
  EOF
86
88
  )"