@fitlab-ai/agent-infra 0.5.3 → 0.5.4

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 (65) hide show
  1. package/README.md +1 -1
  2. package/README.zh-CN.md +1 -1
  3. package/package.json +1 -1
  4. package/templates/.agents/rules/issue-pr-commands.github.en.md +25 -9
  5. package/templates/.agents/rules/issue-pr-commands.github.zh-CN.md +25 -9
  6. package/templates/.agents/rules/issue-sync.github.en.md +111 -23
  7. package/templates/.agents/rules/issue-sync.github.zh-CN.md +105 -17
  8. package/templates/.agents/rules/milestone-inference.github.en.md +13 -6
  9. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +13 -6
  10. package/templates/.agents/rules/pr-sync.github.en.md +3 -1
  11. package/templates/.agents/rules/pr-sync.github.zh-CN.md +3 -1
  12. package/templates/.agents/scripts/platform-adapters/platform-sync.github.js +1080 -0
  13. package/templates/.agents/scripts/validate-artifact.js +51 -802
  14. package/templates/.agents/skills/analyze-task/SKILL.en.md +2 -2
  15. package/templates/.agents/skills/analyze-task/SKILL.zh-CN.md +2 -2
  16. package/templates/.agents/skills/analyze-task/config/verify.json +1 -1
  17. package/templates/.agents/skills/block-task/SKILL.en.md +2 -2
  18. package/templates/.agents/skills/block-task/SKILL.zh-CN.md +2 -2
  19. package/templates/.agents/skills/block-task/config/verify.json +1 -1
  20. package/templates/.agents/skills/cancel-task/SKILL.en.md +6 -6
  21. package/templates/.agents/skills/cancel-task/SKILL.zh-CN.md +6 -6
  22. package/templates/.agents/skills/cancel-task/config/verify.json +1 -1
  23. package/templates/.agents/skills/commit/SKILL.en.md +14 -2
  24. package/templates/.agents/skills/commit/SKILL.zh-CN.md +14 -2
  25. package/templates/.agents/skills/commit/config/verify.json +2 -1
  26. package/templates/.agents/skills/commit/reference/issue-metadata-sync.en.md +23 -0
  27. package/templates/.agents/skills/commit/reference/issue-metadata-sync.zh-CN.md +23 -0
  28. package/templates/.agents/skills/complete-task/SKILL.en.md +2 -2
  29. package/templates/.agents/skills/complete-task/SKILL.zh-CN.md +2 -2
  30. package/templates/.agents/skills/complete-task/config/verify.json +1 -1
  31. package/templates/.agents/skills/create-issue/SKILL.en.md +3 -1
  32. package/templates/.agents/skills/create-issue/SKILL.zh-CN.md +3 -1
  33. package/templates/.agents/skills/create-issue/config/verify.json +1 -1
  34. package/templates/.agents/skills/create-issue/reference/label-and-type.en.md +6 -1
  35. package/templates/.agents/skills/create-issue/reference/label-and-type.zh-CN.md +6 -1
  36. package/templates/.agents/skills/create-pr/SKILL.en.md +4 -4
  37. package/templates/.agents/skills/create-pr/SKILL.zh-CN.md +4 -4
  38. package/templates/.agents/skills/create-pr/config/verify.json +1 -1
  39. package/templates/.agents/skills/create-pr/reference/pr-body-template.en.md +9 -5
  40. package/templates/.agents/skills/create-pr/reference/pr-body-template.zh-CN.md +9 -5
  41. package/templates/.agents/skills/create-task/config/verify.json +1 -1
  42. package/templates/.agents/skills/implement-task/SKILL.en.md +4 -4
  43. package/templates/.agents/skills/implement-task/SKILL.zh-CN.md +4 -4
  44. package/templates/.agents/skills/implement-task/config/verify.json +1 -2
  45. package/templates/.agents/skills/import-codescan/config/verify.json +1 -1
  46. package/templates/.agents/skills/import-dependabot/config/verify.json +1 -1
  47. package/templates/.agents/skills/import-issue/SKILL.en.md +1 -1
  48. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +1 -1
  49. package/templates/.agents/skills/import-issue/config/verify.json +1 -1
  50. package/templates/.agents/skills/plan-task/SKILL.en.md +2 -2
  51. package/templates/.agents/skills/plan-task/SKILL.zh-CN.md +2 -2
  52. package/templates/.agents/skills/plan-task/config/verify.json +1 -1
  53. package/templates/.agents/skills/refine-task/SKILL.en.md +2 -4
  54. package/templates/.agents/skills/refine-task/SKILL.zh-CN.md +2 -4
  55. package/templates/.agents/skills/refine-task/config/verify.json +1 -2
  56. package/templates/.agents/skills/refine-title/SKILL.en.md +5 -1
  57. package/templates/.agents/skills/refine-title/SKILL.zh-CN.md +5 -1
  58. package/templates/.agents/skills/restore-task/config/verify.json +1 -1
  59. package/templates/.agents/skills/review-task/SKILL.en.md +2 -2
  60. package/templates/.agents/skills/review-task/SKILL.zh-CN.md +2 -2
  61. package/templates/.agents/skills/review-task/config/verify.json +1 -1
  62. package/templates/.agents/skills/update-agent-infra/scripts/sync-templates.js +1 -1
  63. package/templates/.github/workflows/metadata-sync.yml +127 -0
  64. package/templates/.github/workflows/pr-label.yml +75 -0
  65. package/templates/.github/workflows/status-label.yml +12 -8
@@ -19,6 +19,6 @@
19
19
  "expected_action_pattern": "Import Dependabot Alert",
20
20
  "freshness_minutes": 30
21
21
  },
22
- "github-sync": null
22
+ "platform-sync": null
23
23
  }
24
24
  }
@@ -17,7 +17,7 @@ Import the specified GitHub Issue and create a task. Argument: issue number.
17
17
 
18
18
  ### 1. Retrieve Issue Information
19
19
 
20
- Read `.agents/rules/issue-pr-commands.md` first, then use its "Read an Issue" command to load the Issue data.
20
+ Read `.agents/rules/issue-pr-commands.md` first, follow its prerequisite steps to complete authentication and code-hosting platform detection, then load the Issue data with its "Read an Issue" command.
21
21
 
22
22
  Extract: issue number, title, description, and labels.
23
23
  Use the Issue title as-is for the task title (preserve the Issue's original language).
@@ -17,7 +17,7 @@ description: "从 GitHub Issue 导入并创建任务"
17
17
 
18
18
  ### 1. 获取 Issue 信息
19
19
 
20
- 执行前先读取 `.agents/rules/issue-pr-commands.md`,并按其中的 “读取 Issue” 命令获取 Issue 信息。
20
+ 执行前先读取 `.agents/rules/issue-pr-commands.md`,并按其中的前置步骤完成认证和代码托管平台检测;随后按其中的 “读取 Issue” 命令获取 Issue 信息。
21
21
 
22
22
  提取:issue 编号、标题、描述、标签。
23
23
  任务标题直接使用 Issue 的原始标题(保持 Issue 标题的原始语言)。
@@ -20,7 +20,7 @@
20
20
  "expected_action_pattern": "Import Issue",
21
21
  "freshness_minutes": 30
22
22
  },
23
- "github-sync": {
23
+ "platform-sync": {
24
24
  "when": "issue_number_exists",
25
25
  "issue_must_exist": true
26
26
  }
@@ -97,8 +97,8 @@ Update `.agents/workspace/active/{task-id}/task.md`:
97
97
  ```
98
98
 
99
99
  If task.md contains a valid `issue_number`, perform these sync actions (skip and continue on any failure):
100
- - Read `.agents/rules/issue-sync.md` before syncing
101
- - Set `status: pending-design-work`
100
+ - Read `.agents/rules/issue-sync.md` before syncing, and complete upstream repository detection plus permission detection
101
+ - Set `status: pending-design-work` by following issue-sync.md
102
102
  - Publish the `{plan-artifact}` comment
103
103
  - Create or update the `<!-- sync-issue:{task-id}:task -->` comment (follow the task.md comment sync rule in issue-sync.md)
104
104
 
@@ -97,8 +97,8 @@ date "+%Y-%m-%d %H:%M:%S%:z"
97
97
  ```
98
98
 
99
99
  如果 task.md 中存在有效的 `issue_number`,执行以下同步操作(任一失败则跳过并继续):
100
- - 执行前先读取 `.agents/rules/issue-sync.md`
101
- - 设置 `status: pending-design-work`
100
+ - 执行前先读取 `.agents/rules/issue-sync.md`,完成 upstream 仓库检测和权限检测
101
+ - 按 issue-sync.md 设置 `status: pending-design-work`
102
102
  - 发布 `{plan-artifact}` 评论
103
103
  - 创建或更新 `<!-- sync-issue:{task-id}:task -->` 评论(按 issue-sync.md 的 task.md 评论同步规则)
104
104
 
@@ -31,7 +31,7 @@
31
31
  "expected_action_pattern": "Technical Design \\(Round \\d+\\)",
32
32
  "freshness_minutes": 30
33
33
  },
34
- "github-sync": {
34
+ "platform-sync": {
35
35
  "when": "issue_number_exists",
36
36
  "expected_status_label": "status: pending-design-work",
37
37
  "expected_comment_marker": "<!-- sync-issue:{task-id}:{artifact-stem} -->",
@@ -60,10 +60,8 @@ Update task.md:
60
60
  `- {YYYY-MM-DD HH:mm:ss±HH:MM} — **Refinement (Round {N}, for {review-artifact})** by {agent} — Fixed {n} blockers, {n} major, {n} minor issues → {refinement-artifact}`
61
61
 
62
62
  If task.md contains a valid `issue_number`, perform these sync actions (skip and continue on any failure):
63
- - Read `.agents/rules/issue-sync.md` before syncing
64
- - Set `status: in-progress`
65
- - Refine `in:` labels from the branch diff by following `.agents/rules/issue-sync.md` (add/remove when a mapping exists, add-only when it does not)
66
- - Sync checked `## Requirements` items to the Issue body
63
+ - Read `.agents/rules/issue-sync.md` before syncing, and complete upstream repository detection plus permission detection
64
+ - Set `status: in-progress` by following issue-sync.md
67
65
  - Publish the `{refinement-artifact}` comment
68
66
  - Create or update the `<!-- sync-issue:{task-id}:task -->` comment (follow the task.md comment sync rule in issue-sync.md)
69
67
 
@@ -60,10 +60,8 @@ date "+%Y-%m-%d %H:%M:%S%:z"
60
60
  `- {YYYY-MM-DD HH:mm:ss±HH:MM} — **Refinement (Round {N}, for {review-artifact})** by {agent} — Fixed {n} blockers, {n} major, {n} minor issues → {refinement-artifact}`
61
61
 
62
62
  如果 task.md 中存在有效的 `issue_number`,执行以下同步操作(任一失败则跳过并继续):
63
- - 执行前先读取 `.agents/rules/issue-sync.md`
64
- - 设置 `status: in-progress`
65
- - 按 `.agents/rules/issue-sync.md` 的 `in:` label 同步规则,基于分支改动精修 `in:` label(有映射时可增可删,无映射时仅补充)
66
- - 同步 `## 需求` 中已勾选项到 Issue body
63
+ - 执行前先读取 `.agents/rules/issue-sync.md`,完成 upstream 仓库检测和权限检测
64
+ - 按 issue-sync.md 设置 `status: in-progress`
67
65
  - 发布 `{refinement-artifact}` 评论
68
66
  - 创建或更新 `<!-- sync-issue:{task-id}:task -->` 评论(按 issue-sync.md 的 task.md 评论同步规则)
69
67
 
@@ -25,13 +25,12 @@
25
25
  "expected_action_pattern": "Refinement \\(Round \\d+, for .+\\)",
26
26
  "freshness_minutes": 30
27
27
  },
28
- "github-sync": {
28
+ "platform-sync": {
29
29
  "when": "issue_number_exists",
30
30
  "expected_status_label": "status: in-progress",
31
31
  "expected_comment_marker": "<!-- sync-issue:{task-id}:{artifact-stem} -->",
32
32
  "verify_comment_content": true,
33
33
  "verify_task_comment_content": true,
34
- "sync_checked_requirements": true,
35
34
  "verify_issue_type": true,
36
35
  "verify_milestone": true
37
36
  }
@@ -11,7 +11,7 @@ Reformat the title of the specified Issue or PR to Conventional Commits format b
11
11
 
12
12
  ### 1. Identify Target and Fetch Information
13
13
 
14
- Read `.agents/rules/issue-pr-commands.md` before this step.
14
+ Read `.agents/rules/issue-pr-commands.md` before this step, and follow its prerequisite steps to complete authentication and code-hosting platform detection.
15
15
 
16
16
  Try to determine if the ID is an Issue or PR:
17
17
  - first fetch Issue data by following the "Read an Issue" command in the rule file
@@ -58,6 +58,8 @@ If the user confirms:
58
58
  - for an Issue, update the title by following the "Update Issues" command in `.agents/rules/issue-pr-commands.md`
59
59
  - for a PR, update the title by following the "Update PRs" command in `.agents/rules/issue-pr-commands.md`
60
60
 
61
+ Title changes require write permission. Follow the permission-degradation rules in `.agents/rules/issue-pr-commands.md` and `.agents/rules/issue-sync.md`; if permission is unavailable, skip the change and inform the user.
62
+
61
63
  ### 5. Inform User
62
64
 
63
65
  > **IMPORTANT**: All TUI command formats listed below must be output in full. Do not show only the format for the current AI agent.
@@ -66,6 +68,8 @@ If the skill updated an Issue title, explain that no extra sync command is requi
66
68
 
67
69
  If the skill updated a PR title, explain that `create-pr` now publishes the reviewer summary inline, so no extra sync command is needed; continue with the workflow skill that matches the task's current stage.
68
70
 
71
+ If title modification was skipped due to insufficient permissions, additionally remind the user that the suggested title can still be applied manually on the code-hosting platform page.
72
+
69
73
  ## Advantages
70
74
 
71
75
  This skill:
@@ -11,7 +11,7 @@ description: "重构 Issue/PR 标题为 Conventional Commits 格式"
11
11
 
12
12
  ### 1. 识别目标并获取信息
13
13
 
14
- 执行前先读取 `.agents/rules/issue-pr-commands.md`。
14
+ 执行前先读取 `.agents/rules/issue-pr-commands.md`,并按其中的前置步骤完成认证和代码托管平台检测。
15
15
 
16
16
  尝试判断 ID 是 Issue 还是 PR:
17
17
  - 先按规则文件中的“读取 Issue”命令获取 Issue 信息
@@ -58,6 +58,8 @@ Issue/PR #{id} 分析结果:
58
58
  - 对于 Issue:按 `.agents/rules/issue-pr-commands.md` 中的 “Issue 更新” 命令设置标题
59
59
  - 对于 PR:按 `.agents/rules/issue-pr-commands.md` 中的 “PR 更新” 命令设置标题
60
60
 
61
+ 标题修改需要写权限,按 `.agents/rules/issue-pr-commands.md` 与 `.agents/rules/issue-sync.md` 中的权限降级规则执行;无权限时跳过修改操作并告知用户。
62
+
61
63
  ### 5. 告知用户
62
64
 
63
65
  > **重要**:以下「下一步」中列出的所有 TUI 命令格式必须完整输出,不要只展示当前 AI 代理对应的格式。
@@ -66,6 +68,8 @@ Issue/PR #{id} 分析结果:
66
68
 
67
69
  如果修改了 PR 标题,提示 `create-pr` 已内联发布 reviewer 摘要,无需额外同步命令;后续按任务当前阶段继续执行对应工作流技能。
68
70
 
71
+ 如果因权限不足跳过了标题修改,额外提示用户建议标题仍可手动应用到代码托管平台页面。
72
+
69
73
  ## 优势
70
74
 
71
75
  本技能的优势:
@@ -19,6 +19,6 @@
19
19
  "expected_action_pattern": "Restore Task",
20
20
  "freshness_minutes": 30
21
21
  },
22
- "github-sync": null
22
+ "platform-sync": null
23
23
  }
24
24
  }
@@ -54,8 +54,8 @@ Update task.md and append:
54
54
  `- {YYYY-MM-DD HH:mm:ss±HH:MM} — **Code Review (Round {N})** by {agent} — Verdict: {Approved/Changes Requested/Rejected}, blockers: {n}, major: {n}, minor: {n} → {artifact-filename}`
55
55
 
56
56
  If task.md contains a valid `issue_number`, perform these sync actions (skip and continue on any failure):
57
- - Read `.agents/rules/issue-sync.md` before syncing
58
- - Set `status: in-progress`
57
+ - Read `.agents/rules/issue-sync.md` before syncing, and complete upstream repository detection plus permission detection
58
+ - Set `status: in-progress` by following issue-sync.md
59
59
  - Publish the `{review-artifact}` comment
60
60
  - Create or update the `<!-- sync-issue:{task-id}:task -->` comment (follow the task.md comment sync rule in issue-sync.md)
61
61
 
@@ -54,8 +54,8 @@ date "+%Y-%m-%d %H:%M:%S%:z"
54
54
  `- {YYYY-MM-DD HH:mm:ss±HH:MM} — **Code Review (Round {N})** by {agent} — Verdict: {Approved/Changes Requested/Rejected}, blockers: {n}, major: {n}, minor: {n} → {artifact-filename}`
55
55
 
56
56
  如果 task.md 中存在有效的 `issue_number`,执行以下同步操作(任一失败则跳过并继续):
57
- - 执行前先读取 `.agents/rules/issue-sync.md`
58
- - 设置 `status: in-progress`
57
+ - 执行前先读取 `.agents/rules/issue-sync.md`,完成 upstream 仓库检测和权限检测
58
+ - 按 issue-sync.md 设置 `status: in-progress`
59
59
  - 发布 `{review-artifact}` 评论
60
60
  - 创建或更新 `<!-- sync-issue:{task-id}:task -->` 评论(按 issue-sync.md 的 task.md 评论同步规则)
61
61
 
@@ -29,7 +29,7 @@
29
29
  "expected_action_pattern": "Code Review \\(Round \\d+\\)",
30
30
  "freshness_minutes": 30
31
31
  },
32
- "github-sync": {
32
+ "platform-sync": {
33
33
  "when": "issue_number_exists",
34
34
  "expected_status_label": "status: in-progress",
35
35
  "expected_comment_marker": "<!-- sync-issue:{task-id}:{artifact-stem} -->",
@@ -76,7 +76,7 @@ const DEFAULTS = {
76
76
  }
77
77
  };
78
78
 
79
- const INSTALLER_VERSION = "v0.5.3";
79
+ const INSTALLER_VERSION = "v0.5.4";
80
80
  const PACKAGE_NAME = '@fitlab-ai/agent-infra';
81
81
  // Add a new identifier here only after shipping matching .{platform}. template variants.
82
82
  const KNOWN_PLATFORMS = new Set(['github']);
@@ -0,0 +1,127 @@
1
+ name: Metadata Sync
2
+
3
+ on:
4
+ issue_comment:
5
+ types: [created, edited]
6
+
7
+ permissions:
8
+ issues: write
9
+
10
+ jobs:
11
+ sync-metadata:
12
+ runs-on: ubuntu-latest
13
+ if: ${{ !github.event.issue.pull_request }}
14
+ steps:
15
+ - name: Extract metadata from task comment
16
+ id: metadata
17
+ run: |
18
+ body=$(jq -r '.comment.body' "$GITHUB_EVENT_PATH")
19
+ if ! printf '%s' "$body" | grep -qE '<!-- sync-issue:TASK-[0-9]{8}-[0-9]{6}:task -->'; then
20
+ printf 'is_task_comment=false\n' >> "$GITHUB_OUTPUT"
21
+ exit 0
22
+ fi
23
+
24
+ frontmatter=$(printf '%s\n' "$body" \
25
+ | tr -d '\r' \
26
+ | awk '
27
+ BEGIN { capture = 0; separators = 0 }
28
+ $0 == "---" {
29
+ separators += 1
30
+ if (separators == 1) {
31
+ capture = 1
32
+ next
33
+ }
34
+ if (separators == 2) {
35
+ exit
36
+ }
37
+ }
38
+ capture { print }
39
+ ')
40
+
41
+ type=$(printf '%s\n' "$frontmatter" \
42
+ | sed -n 's/^type:[[:space:]]*//p' \
43
+ | head -n 1 \
44
+ | sed 's/[[:space:]]*#.*$//' \
45
+ | sed 's/^[[:space:]]*//; s/[[:space:]]*$//' \
46
+ | tr '[:upper:]' '[:lower:]')
47
+
48
+ milestone=$(printf '%s\n' "$frontmatter" \
49
+ | sed -n 's/^milestone:[[:space:]]*//p' \
50
+ | head -n 1 \
51
+ | sed 's/^[[:space:]]*//; s/[[:space:]]*$//')
52
+
53
+ printf 'is_task_comment=true\n' >> "$GITHUB_OUTPUT"
54
+ printf 'type=%s\n' "$type" >> "$GITHUB_OUTPUT"
55
+ printf 'milestone=%s\n' "$milestone" >> "$GITHUB_OUTPUT"
56
+
57
+ - name: Sync type label
58
+ if: steps.metadata.outputs.is_task_comment == 'true' && steps.metadata.outputs.type != ''
59
+ env:
60
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
61
+ ISSUE_NUMBER: ${{ github.event.issue.number }}
62
+ TYPE: ${{ steps.metadata.outputs.type }}
63
+ run: |
64
+ case "$TYPE" in
65
+ bug|bugfix) TYPE_LABEL="type: bug" ;;
66
+ feature) TYPE_LABEL="type: feature" ;;
67
+ enhancement|refactor|refactoring) TYPE_LABEL="type: enhancement" ;;
68
+ docs|documentation) TYPE_LABEL="type: documentation" ;;
69
+ dependency-upgrade) TYPE_LABEL="type: dependency-upgrade" ;;
70
+ task|chore) TYPE_LABEL="type: task" ;;
71
+ *) TYPE_LABEL="" ;;
72
+ esac
73
+
74
+ if [ -n "$TYPE_LABEL" ]; then
75
+ current_type_labels=$(gh issue view "$ISSUE_NUMBER" \
76
+ --repo "$GITHUB_REPOSITORY" \
77
+ --json labels --jq '.labels[].name | select(startswith("type:"))' \
78
+ 2>/dev/null || true)
79
+
80
+ printf '%s\n' "$current_type_labels" | while IFS= read -r label; do
81
+ [ -z "$label" ] && continue
82
+ if [ "$label" != "$TYPE_LABEL" ]; then
83
+ gh issue edit "$ISSUE_NUMBER" \
84
+ --repo "$GITHUB_REPOSITORY" \
85
+ --remove-label "$label" \
86
+ 2>/dev/null || true
87
+ fi
88
+ done || true
89
+
90
+ if ! printf '%s\n' "$current_type_labels" | grep -qxF "$TYPE_LABEL"; then
91
+ gh issue edit "$ISSUE_NUMBER" \
92
+ --repo "$GITHUB_REPOSITORY" \
93
+ --add-label "$TYPE_LABEL" \
94
+ 2>/dev/null || true
95
+ fi
96
+ fi
97
+
98
+ - name: Sync milestone
99
+ if: steps.metadata.outputs.is_task_comment == 'true' && steps.metadata.outputs.milestone != ''
100
+ env:
101
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
102
+ ISSUE_NUMBER: ${{ github.event.issue.number }}
103
+ MILESTONE: ${{ steps.metadata.outputs.milestone }}
104
+ run: |
105
+ gh issue edit "$ISSUE_NUMBER" \
106
+ --repo "$GITHUB_REPOSITORY" \
107
+ --milestone "$MILESTONE" \
108
+ 2>/dev/null || true
109
+
110
+ - name: Sync issue type
111
+ if: steps.metadata.outputs.is_task_comment == 'true' && steps.metadata.outputs.type != ''
112
+ env:
113
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
114
+ ISSUE_NUMBER: ${{ github.event.issue.number }}
115
+ TYPE: ${{ steps.metadata.outputs.type }}
116
+ run: |
117
+ case "$TYPE" in
118
+ bug|bugfix) ISSUE_TYPE="Bug" ;;
119
+ feature|enhancement) ISSUE_TYPE="Feature" ;;
120
+ *) ISSUE_TYPE="Task" ;;
121
+ esac
122
+
123
+ gh api "repos/$GITHUB_REPOSITORY/issues/$ISSUE_NUMBER" \
124
+ -X PATCH \
125
+ -f type="$ISSUE_TYPE" \
126
+ --silent \
127
+ 2>/dev/null || true
@@ -0,0 +1,75 @@
1
+ name: PR Label & Assignee
2
+
3
+ on:
4
+ pull_request_target:
5
+ types: [opened, synchronize]
6
+
7
+ permissions:
8
+ contents: read
9
+ issues: write
10
+ pull-requests: write
11
+
12
+ concurrency:
13
+ group: pr-label-${{ github.event.pull_request.number }}
14
+ cancel-in-progress: true
15
+
16
+ jobs:
17
+ label-and-assign:
18
+ runs-on: ubuntu-latest
19
+ steps:
20
+ - name: Checkout base branch
21
+ uses: actions/checkout@v4
22
+
23
+ - name: Sync in-labels
24
+ env:
25
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
26
+ PR_NUMBER: ${{ github.event.pull_request.number }}
27
+ run: |
28
+ changed_files=$(gh api "repos/$GITHUB_REPOSITORY/pulls/$PR_NUMBER/files" \
29
+ --paginate --jq '[.[].filename]')
30
+
31
+ should_labels=$(jq -rn \
32
+ --argjson files "$changed_files" \
33
+ --argjson mapping "$(jq '.labels.in // {}' .agents/.airc.json)" \
34
+ '$mapping
35
+ | to_entries
36
+ | map(select(.value | any(. as $prefix | $files | any(startswith($prefix)))))
37
+ | map("in: " + .key)
38
+ | .[]?')
39
+
40
+ current_labels=$(gh pr view "$PR_NUMBER" \
41
+ --repo "$GITHUB_REPOSITORY" \
42
+ --json labels --jq '.labels[].name | select(startswith("in: "))' \
43
+ 2>/dev/null || true)
44
+
45
+ printf '%s\n' "$should_labels" | while IFS= read -r label; do
46
+ [ -z "$label" ] && continue
47
+ if ! printf '%s\n' "$current_labels" | grep -qxF "$label"; then
48
+ gh pr edit "$PR_NUMBER" \
49
+ --repo "$GITHUB_REPOSITORY" \
50
+ --add-label "$label" 2>/dev/null || true
51
+ fi
52
+ done
53
+
54
+ printf '%s\n' "$current_labels" | while IFS= read -r label; do
55
+ [ -z "$label" ] && continue
56
+ if ! printf '%s\n' "$should_labels" | grep -qxF "$label"; then
57
+ gh pr edit "$PR_NUMBER" \
58
+ --repo "$GITHUB_REPOSITORY" \
59
+ --remove-label "$label" 2>/dev/null || true
60
+ fi
61
+ done
62
+
63
+ - name: Assign PR creator if unassigned
64
+ env:
65
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
66
+ PR_NUMBER: ${{ github.event.pull_request.number }}
67
+ CREATOR: ${{ github.event.pull_request.user.login }}
68
+ ASSIGNEES_JSON: ${{ toJSON(github.event.pull_request.assignees) }}
69
+ run: |
70
+ count=$(printf '%s' "$ASSIGNEES_JSON" | jq 'length')
71
+ if [ "$count" -eq 0 ]; then
72
+ gh pr edit "$PR_NUMBER" \
73
+ --repo "$GITHUB_REPOSITORY" \
74
+ --add-assignee "$CREATOR" 2>/dev/null || true
75
+ fi
@@ -40,19 +40,23 @@ jobs:
40
40
  GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
41
41
  ISSUE_NUMBER: ${{ github.event.issue.number }}
42
42
  run: |
43
- gh issue view "$ISSUE_NUMBER" \
43
+ current_status_labels=$(gh issue view "$ISSUE_NUMBER" \
44
44
  --repo "$GITHUB_REPOSITORY" \
45
45
  --json labels --jq '.labels[].name | select(startswith("status:"))' \
46
- 2>/dev/null \
47
- | while IFS= read -r label; do
48
- [ -z "$label" ] && continue
46
+ 2>/dev/null || true)
47
+ printf '%s\n' "$current_status_labels" | while IFS= read -r label; do
48
+ [ -z "$label" ] && continue
49
+ if [ "$label" != "status: waiting-for-triage" ]; then
49
50
  gh issue edit "$ISSUE_NUMBER" \
50
51
  --repo "$GITHUB_REPOSITORY" \
51
52
  --remove-label "$label"
52
- done || true
53
- gh issue edit "$ISSUE_NUMBER" \
54
- --repo "$GITHUB_REPOSITORY" \
55
- --add-label "status: waiting-for-triage"
53
+ fi
54
+ done || true
55
+ if ! printf '%s\n' "$current_status_labels" | grep -qxF "status: waiting-for-triage"; then
56
+ gh issue edit "$ISSUE_NUMBER" \
57
+ --repo "$GITHUB_REPOSITORY" \
58
+ --add-label "status: waiting-for-triage"
59
+ fi
56
60
 
57
61
  - name: Clean status labels on PR merge
58
62
  if: >-