@fitlab-ai/agent-infra 0.5.8 → 0.5.9

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 (40) hide show
  1. package/README.md +44 -4
  2. package/README.zh-CN.md +44 -4
  3. package/lib/sandbox/commands/vm.js +7 -1
  4. package/lib/sandbox/constants.js +3 -0
  5. package/lib/sandbox/engine.js +38 -3
  6. package/lib/sandbox/runtimes/base.dockerfile +9 -2
  7. package/package.json +3 -1
  8. package/templates/.agents/rules/create-issue.en.md +5 -0
  9. package/templates/.agents/rules/create-issue.github.en.md +178 -0
  10. package/templates/.agents/rules/create-issue.github.zh-CN.md +178 -0
  11. package/templates/.agents/rules/create-issue.zh-CN.md +5 -0
  12. package/templates/.agents/rules/issue-sync.github.en.md +1 -1
  13. package/templates/.agents/rules/issue-sync.github.zh-CN.md +1 -1
  14. package/templates/.agents/rules/milestone-inference.github.en.md +2 -2
  15. package/templates/.agents/rules/milestone-inference.github.zh-CN.md +2 -2
  16. package/templates/.agents/scripts/platform-adapters/platform-sync.github.js +46 -1
  17. package/templates/.agents/skills/create-task/SKILL.en.md +69 -11
  18. package/templates/.agents/skills/create-task/SKILL.zh-CN.md +70 -12
  19. package/templates/.agents/skills/create-task/config/verify.json +6 -1
  20. package/templates/.agents/skills/implement-task/reference/implementation-rules.en.md +7 -12
  21. package/templates/.agents/skills/implement-task/reference/implementation-rules.zh-CN.md +7 -12
  22. package/templates/.agents/skills/import-issue/SKILL.en.md +1 -1
  23. package/templates/.agents/skills/import-issue/SKILL.zh-CN.md +1 -1
  24. package/templates/.agents/skills/refine-task/reference/fix-workflow.en.md +2 -2
  25. package/templates/.agents/skills/refine-task/reference/fix-workflow.zh-CN.md +2 -2
  26. package/templates/.agents/skills/test/SKILL.en.md +45 -6
  27. package/templates/.agents/skills/test/SKILL.zh-CN.md +45 -6
  28. package/templates/.agents/skills/create-issue/SKILL.en.md +0 -118
  29. package/templates/.agents/skills/create-issue/SKILL.zh-CN.md +0 -118
  30. package/templates/.agents/skills/create-issue/config/verify.json +0 -30
  31. package/templates/.agents/skills/create-issue/reference/label-and-type.en.md +0 -71
  32. package/templates/.agents/skills/create-issue/reference/label-and-type.zh-CN.md +0 -71
  33. package/templates/.agents/skills/create-issue/reference/template-matching.en.md +0 -17
  34. package/templates/.agents/skills/create-issue/reference/template-matching.zh-CN.md +0 -17
  35. package/templates/.claude/commands/create-issue.en.md +0 -8
  36. package/templates/.claude/commands/create-issue.zh-CN.md +0 -8
  37. package/templates/.gemini/commands/_project_/create-issue.en.toml +0 -8
  38. package/templates/.gemini/commands/_project_/create-issue.zh-CN.toml +0 -8
  39. package/templates/.opencode/commands/create-issue.en.md +0 -11
  40. package/templates/.opencode/commands/create-issue.zh-CN.md +0 -11
package/README.md CHANGED
@@ -236,6 +236,47 @@ agent-infra is intentionally simple: a bootstrap CLI creates the seed configurat
236
236
  └───────────────────────────────────────────────────────┘
237
237
  ```
238
238
 
239
+ <a id="platform-support"></a>
240
+
241
+ ## Platform Support
242
+
243
+ agent-infra runs on macOS and Linux. The CLI itself only needs Node.js (>=18); container-related features (`ai sandbox *`) additionally need Docker.
244
+
245
+ ### macOS
246
+
247
+ - `ai init`, `ai sync`, etc.: works out of the box after `npm install -g @fitlab-ai/agent-infra` (or Homebrew).
248
+ - `ai sandbox *`: requires Colima, OrbStack, or Docker Desktop. Colima is the default engine on macOS — when it is selected and the `colima` command is missing, agent-infra auto-installs and starts Colima via Homebrew on first run. To use OrbStack or Docker Desktop instead, set `sandbox.engine` in `.agents/.airc.json`.
249
+
250
+ ### Linux
251
+
252
+ - `ai init`, `ai sync`, etc.: works out of the box after `npm install -g @fitlab-ai/agent-infra`.
253
+ - `ai sandbox *`: requires Docker Engine on the host. Quick setup:
254
+
255
+ ```bash
256
+ # 1. Install Docker Engine — see https://docs.docker.com/engine/install/
257
+ # 2. Start the daemon and enable on boot
258
+ sudo systemctl enable --now docker
259
+ # 3. Skip 'sudo' for docker: add yourself to the docker group
260
+ sudo usermod -aG docker $USER && newgrp docker
261
+ ```
262
+
263
+ Validate with `docker info` — it should succeed without sudo.
264
+
265
+ GPG signing works when the host `gpg-agent` and signing key are available; if key sync fails, `ai sandbox create` falls back to a sanitized Git config so commits still work without host signing state.
266
+
267
+ #### Known limitations on Linux
268
+
269
+ These configurations are not actively tested in this release:
270
+
271
+ - **Rootless Docker**: Track [#256](https://github.com/fitlab-ai/agent-infra/issues/256).
272
+ - **Podman** instead of Docker: Track [#257](https://github.com/fitlab-ai/agent-infra/issues/257).
273
+ - **SELinux-enforcing** hosts (Fedora / RHEL) may need manual mount labels: Track [#258](https://github.com/fitlab-ai/agent-infra/issues/258).
274
+ - `ai sandbox vm` is a no-op on Linux. Linux uses native Docker directly with no VM to manage; use `ai sandbox create`, `ai sandbox exec`, `ai sandbox ls`, `ai sandbox rebuild`, `ai sandbox rm` directly.
275
+
276
+ ### Windows
277
+
278
+ WSL2 support is tracked in [#184](https://github.com/fitlab-ai/agent-infra/issues/184).
279
+
239
280
  <a id="what-you-get"></a>
240
281
 
241
282
  ## What You Get
@@ -268,7 +309,7 @@ agent-infra ships with **a rich set of built-in AI skills**. They are organized
268
309
 
269
310
  | Skill | Description | Parameters | Recommended use case |
270
311
  |-------|-------------|------------|----------------------|
271
- | `create-task` | Create a task scaffold from a natural-language request. | `description` | Start a new feature, bug-fix, or improvement from scratch. |
312
+ | `create-task` | Create a task scaffold from a natural-language request and cascade Issue creation through the platform rule when available. | `description` | Start a new feature, bug-fix, or improvement from scratch. |
272
313
  | `import-issue` | Import a GitHub Issue into the local task workspace. | `issue-number` | Convert an existing Issue into an actionable task folder. |
273
314
  | `analyze-task` | Produce a requirement analysis artifact for an existing task. | `task-id` | Capture scope, risks, and impacted files before designing. |
274
315
  | `plan-task` | Write the technical implementation plan with a review checkpoint. | `task-id` | Define the approach after analysis is complete. |
@@ -293,7 +334,6 @@ agent-infra ships with **a rich set of built-in AI skills**. They are organized
293
334
 
294
335
  | Skill | Description | Parameters | Recommended use case |
295
336
  |-------|-------------|------------|----------------------|
296
- | `create-issue` | Create a GitHub Issue from a task file. | `task-id` | Push a local task into GitHub tracking. |
297
337
  | `create-pr` | Open a Pull Request to an inferred or explicit target branch. | `task-id` (optional), `target-branch` (optional) | Publish reviewed changes for merge, with optional explicit task linkage after a fresh session. |
298
338
 
299
339
  <a id="code-quality"></a>
@@ -499,7 +539,7 @@ The simplest end-to-end delivery loop looks like this:
499
539
 
500
540
  ```text
501
541
  import-issue #42 Import task from GitHub Issue
502
- (or: create-task "add dark mode") Or create a task from a description
542
+ (or: create-task "add dark mode") Or create a task from a description; Issue creation cascades when the platform rule supports it
503
543
  |
504
544
  | --> get task ID, e.g. T1
505
545
  v
@@ -545,7 +585,7 @@ The generated `.agents/.airc.json` file is the central contract between the boot
545
585
  "project": "my-project",
546
586
  "org": "my-org",
547
587
  "language": "en",
548
- "templateVersion": "v0.5.8",
588
+ "templateVersion": "v0.5.9",
549
589
  "templates": {
550
590
  "sources": [
551
591
  { "type": "local", "path": "~/private-templates" }
package/README.zh-CN.md CHANGED
@@ -236,6 +236,47 @@ agent-infra 的结构刻意保持简单:引导 CLI 负责生成种子配置,
236
236
  └───────────────────────────────────────────────────────┘
237
237
  ```
238
238
 
239
+ <a id="platform-support"></a>
240
+
241
+ ## 平台支持
242
+
243
+ agent-infra 支持 macOS 和 Linux。CLI 本身只需要 Node.js (>=18);容器相关功能(`ai sandbox *`)额外需要 Docker。
244
+
245
+ ### macOS
246
+
247
+ - `ai init`、`ai sync` 等:执行 `npm install -g @fitlab-ai/agent-infra`(或 Homebrew 安装)后开箱即用。
248
+ - `ai sandbox *`:需要 Colima、OrbStack 或 Docker Desktop。macOS 默认引擎是 Colima —— 当选用 Colima 且宿主机没有 `colima` 命令时,agent-infra 会在首次运行时通过 Homebrew 自动安装并启动。如需使用 OrbStack 或 Docker Desktop,请在 `.agents/.airc.json` 中设置 `sandbox.engine`。
249
+
250
+ ### Linux
251
+
252
+ - `ai init`、`ai sync` 等:执行 `npm install -g @fitlab-ai/agent-infra` 后开箱即用。
253
+ - `ai sandbox *`:需要宿主机已安装 Docker Engine。三步配置:
254
+
255
+ ```bash
256
+ # 1. 安装 Docker Engine —— 见 https://docs.docker.com/engine/install/
257
+ # 2. 启动 daemon 并设置开机自启
258
+ sudo systemctl enable --now docker
259
+ # 3. 让当前用户免 sudo 跑 docker:加入 docker 组
260
+ sudo usermod -aG docker $USER && newgrp docker
261
+ ```
262
+
263
+ 验证:执行 `docker info` 应在不带 sudo 的情况下成功。
264
+
265
+ 当宿主机 `gpg-agent` 和签名 key 可用时,GPG signing 可正常工作;如果 key 同步失败,`ai sandbox create` 会回退到清理后的 Git config,让提交仍可在没有宿主签名状态的情况下继续。
266
+
267
+ #### Linux 已知限制
268
+
269
+ 下列场景在本期未做主动验证:
270
+
271
+ - **Rootless Docker**:后续跟踪 [#256](https://github.com/fitlab-ai/agent-infra/issues/256)。
272
+ - 用 **Podman** 替代 Docker:后续跟踪 [#257](https://github.com/fitlab-ai/agent-infra/issues/257)。
273
+ - **SELinux enforcing** 宿主机(Fedora / RHEL)可能需要手动加挂载标签:后续跟踪 [#258](https://github.com/fitlab-ai/agent-infra/issues/258)。
274
+ - `ai sandbox vm` 在 Linux 上是空操作。Linux 直接使用 native Docker,没有 VM 需要管理;请直接使用 `ai sandbox create`、`ai sandbox exec`、`ai sandbox ls`、`ai sandbox rebuild`、`ai sandbox rm`。
275
+
276
+ ### Windows
277
+
278
+ WSL2 支持在 [#184](https://github.com/fitlab-ai/agent-infra/issues/184) 跟踪。
279
+
239
280
  <a id="what-you-get"></a>
240
281
 
241
282
  ## 安装效果
@@ -268,7 +309,7 @@ agent-infra 提供 **丰富的内置 AI skills**。它们按使用场景分组
268
309
 
269
310
  | Skill | 描述 | 参数 | 推荐场景 |
270
311
  |-------|------|------|---------|
271
- | `create-task` | 根据自然语言请求创建任务骨架。 | `description` | 从零开始记录新功能、缺陷或改进需求。 |
312
+ | `create-task` | 根据自然语言请求创建任务骨架,并在平台规则可用时级联创建 Issue。 | `description` | 从零开始记录新功能、缺陷或改进需求。 |
272
313
  | `import-issue` | 将 GitHub Issue 导入本地任务工作区。 | `issue-number` | 把已有 Issue 转成可执行的任务目录。 |
273
314
  | `analyze-task` | 为已有任务输出需求分析产物。 | `task-id` | 在设计前明确范围、风险和受影响文件。 |
274
315
  | `plan-task` | 编写技术实施方案,并设置人工审查检查点。 | `task-id` | 分析完成后定义具体实现路径。 |
@@ -293,7 +334,6 @@ agent-infra 提供 **丰富的内置 AI skills**。它们按使用场景分组
293
334
 
294
335
  | Skill | 描述 | 参数 | 推荐场景 |
295
336
  |-------|------|------|---------|
296
- | `create-issue` | 根据任务文件创建 GitHub Issue。 | `task-id` | 需要把本地任务同步到 GitHub 跟踪时。 |
297
337
  | `create-pr` | 向推断出的目标分支或显式指定分支创建 Pull Request。 | `task-id`(可选)、`target-branch`(可选) | 变更准备合入时创建 PR;清空上下文后也可显式传入任务关联。 |
298
338
 
299
339
  <a id="code-quality"></a>
@@ -499,7 +539,7 @@ agent-infra 内置 **4 个预置工作流**。其中 3 个共享同一条分阶
499
539
 
500
540
  ```text
501
541
  import-issue #42 从 GitHub Issue 导入任务
502
- (或: create-task "添加暗色模式") 或直接从描述创建任务
542
+ (或: create-task "添加暗色模式") 或直接从描述创建任务;平台规则支持时会级联创建 Issue
503
543
  |
504
544
  | --> 得到任务 ID,例如 T1
505
545
  v
@@ -545,7 +585,7 @@ import-issue #42 从 GitHub Issue 导入任务
545
585
  "project": "my-project",
546
586
  "org": "my-org",
547
587
  "language": "en",
548
- "templateVersion": "v0.5.8",
588
+ "templateVersion": "v0.5.9",
549
589
  "templates": {
550
590
  "sources": [
551
591
  { "type": "local", "path": "~/private-templates" }
@@ -15,7 +15,13 @@ import { runOk, runSafe } from '../shell.js';
15
15
 
16
16
  const USAGE = `Usage: ai sandbox vm <status|start|stop> [--cpu <n>] [--memory <n>]`;
17
17
 
18
- function ensureManagedVm(engine) {
18
+ export function ensureManagedVm(engine) {
19
+ if (engine === 'native') {
20
+ throw new Error(
21
+ "Linux native Docker does not use a managed VM. Use 'ai sandbox create' directly."
22
+ );
23
+ }
24
+
19
25
  if (!isManagedEngine(engine)) {
20
26
  throw new Error(`VM management is unavailable for engine '${engineDisplayName(engine)}'.`);
21
27
  }
@@ -88,6 +88,9 @@ export function parsePositiveIntegerOption(value, optionName) {
88
88
  }
89
89
 
90
90
  export function detectHostResources() {
91
+ // Resource hints are for engines that pre-allocate a managed VM. macOS uses
92
+ // sysctl for Colima defaults, while the generic fallback supports WSL2 or
93
+ // other direct callers that need conservative CPU and memory defaults.
91
94
  if (process.platform === 'darwin') {
92
95
  try {
93
96
  const hostCpu = Number(execFileSync('sysctl', ['-n', 'hw.ncpu'], { encoding: 'utf8' }).trim());
@@ -132,6 +132,43 @@ export async function ensureDockerDesktop(
132
132
  }
133
133
  }
134
134
 
135
+ export async function ensureNativeDocker(
136
+ _config,
137
+ _onMessage,
138
+ { runOkFn = runOk, runSafeFn = runSafe } = {}
139
+ ) {
140
+ if (!runOkFn('which', ['docker'])) {
141
+ throw new Error([
142
+ 'Docker is not installed.',
143
+ 'Install Docker Engine for your distribution: https://docs.docker.com/engine/install/',
144
+ 'Then start the daemon with: sudo systemctl enable --now docker',
145
+ 'If you want to run Docker without sudo, add your user to the docker group: sudo usermod -aG docker $USER'
146
+ ].join('\n'));
147
+ }
148
+
149
+ if (runOkFn('docker', ['info'])) {
150
+ return;
151
+ }
152
+
153
+ const serverVersion = runSafeFn('docker', ['version', '--format', '{{.Server.Version}}']);
154
+ if (!serverVersion) {
155
+ throw new Error([
156
+ 'Docker daemon is not running or is unreachable.',
157
+ 'Start it with: sudo systemctl start docker',
158
+ 'Enable it on boot with: sudo systemctl enable docker',
159
+ 'If you use rootless or remote Docker, verify DOCKER_HOST points at a reachable socket.',
160
+ 'Then retry: ai sandbox create <branch>'
161
+ ].join('\n'));
162
+ }
163
+
164
+ throw new Error([
165
+ 'Docker is installed, but the current user may lack permission to use the daemon.',
166
+ 'Add your user to the docker group: sudo usermod -aG docker $USER',
167
+ 'Open a new login shell or run: newgrp docker',
168
+ 'For rootless Docker, make sure DOCKER_HOST points at the rootless daemon socket.'
169
+ ].join('\n'));
170
+ }
171
+
135
172
  export async function ensureDocker(config, onMessage) {
136
173
  const engine = detectEngine(config);
137
174
 
@@ -151,9 +188,7 @@ export async function ensureDocker(config, onMessage) {
151
188
  }
152
189
 
153
190
  if (engine === 'native') {
154
- if (!runOk('docker', ['info'])) {
155
- throw new Error('Docker daemon is not running. Please start Docker first.');
156
- }
191
+ await ensureNativeDocker(config, onMessage);
157
192
  return;
158
193
  }
159
194
 
@@ -7,8 +7,15 @@ ENV TZ=Asia/Shanghai
7
7
 
8
8
  ARG HOST_UID=1000
9
9
  ARG HOST_GID=1000
10
- RUN (groupadd -g ${HOST_GID} devuser || true) && \
11
- useradd -u ${HOST_UID} -g ${HOST_GID} -m -s /bin/bash devuser
10
+ # Root host uid 0 collides with container root; -o lets devuser share uid 0
11
+ # while keeping a real passwd entry that USER devuser can resolve.
12
+ RUN if [ "${HOST_UID}" = "0" ]; then \
13
+ (groupadd -o -g ${HOST_GID} devuser || true) && \
14
+ useradd -o -u ${HOST_UID} -g ${HOST_GID} -m -s /bin/bash devuser; \
15
+ else \
16
+ (groupadd -g ${HOST_GID} devuser || true) && \
17
+ useradd -u ${HOST_UID} -g ${HOST_GID} -m -s /bin/bash devuser; \
18
+ fi
12
19
 
13
20
  RUN apt-get update && apt-get install -y \
14
21
  curl wget git vim file \
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fitlab-ai/agent-infra",
3
- "version": "0.5.8",
3
+ "version": "0.5.9",
4
4
  "description": "Bootstrap tool for AI multi-tool collaboration infrastructure — works with Claude Code, Codex, Gemini CLI, and OpenCode",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -48,6 +48,8 @@
48
48
  "build": "node scripts/build-inline.js",
49
49
  "demo:regen": "sh scripts/demo-regen.sh",
50
50
  "prepare": "git config core.hooksPath .git-hooks || true",
51
+ "test:smoke": "node scripts/build-inline.js --check && node --test tests/templates/*.test.js tests/core/airc.test.js tests/core/release.test.js tests/core/metadata-sync-workflow.test.js tests/core/pr-label-workflow.test.js tests/core/status-label-workflow.test.js tests/core/test-tier-coverage.test.js tests/cli/lib.test.js tests/cli/sync-templates.test.js tests/scripts/sync-templates-platform-gating.test.js",
52
+ "test:core": "node scripts/build-inline.js --check && node --test tests/templates/*.test.js tests/core/airc.test.js tests/core/release.test.js tests/core/metadata-sync-workflow.test.js tests/core/pr-label-workflow.test.js tests/core/status-label-workflow.test.js tests/core/test-tier-coverage.test.js tests/cli/lib.test.js tests/cli/sync-templates.test.js tests/scripts/sync-templates-platform-gating.test.js tests/cli/cli.test.js tests/cli/merge.test.js tests/cli/sandbox.test.js tests/core/custom-skills.test.js tests/core/custom-tuis.test.js tests/core/demo-regen.test.js tests/scripts/find-existing-task.test.js tests/scripts/platform-adapter-defaults.test.js",
51
53
  "test": "node scripts/build-inline.js --check && node --test tests/cli/*.test.js tests/templates/*.test.js tests/core/*.test.js tests/scripts/*.test.js",
52
54
  "prepublishOnly": "node scripts/build-inline.js --check && node --test tests/cli/*.test.js tests/templates/*.test.js tests/core/*.test.js tests/scripts/*.test.js"
53
55
  }
@@ -0,0 +1,5 @@
1
+ # Issue Creation
2
+
3
+ This code platform does not provide an Issue creation rule.
4
+
5
+ `create-task` skips the cascade Issue creation step on this platform; the local `task.md` remains a valid artifact. If you later want to bind the task to an Issue, manually write `issue_number` into `task.md` and the subsequent skills (`commit` / `refine-task` / `complete-task`, etc.) will pick up Issue metadata syncing through the existing cascade rules.
@@ -0,0 +1,178 @@
1
+ # Issue Creation
2
+
3
+ After `create-task` writes the local `task.md`, follow this rule to cascade Issue creation. This rule is referenced internally by `create-task` SKILL.md only; do not invoke it standalone.
4
+
5
+ ## Boundary
6
+
7
+ - Issue title and body must come from `task.md` only
8
+ - Do not read `analysis.md`, `plan.md`, `implementation.md`, or any review artifact
9
+ - Persistent outputs are limited to the remote Issue and the `issue_number` written back to `task.md`
10
+ - If Issue creation fails, do not roll back `task.md`; the current task remains valid for the workflow, and the user can later manually fill `issue_number` so other skills' cascade sync takes over
11
+
12
+ ## Steps
13
+
14
+ ### 1. Verify Prerequisites
15
+
16
+ - `.agents/workspace/active/{task-id}/task.md` must exist
17
+ - Read `.agents/rules/issue-pr-commands.md` first and run its authentication and platform detection commands to confirm `gh auth status` and the current repository are usable
18
+ - Read `.agents/rules/issue-sync.md` first and complete `upstream_repo`, `has_triage`, and `has_push` detection; reuse these variables for every later `gh issue` and repo-level `gh api` call
19
+ - If `task.md` already has a non-empty, non-`N/A` `issue_number`, halt the cascade immediately: return "Task already linked to Issue #{n}, skipping creation" to `create-task` and let it decide how to continue
20
+
21
+ ### 2. Extract Task Information
22
+
23
+ Pull the following from `task.md`:
24
+
25
+ - Task title (the first `# ` heading, stripped of `任务:` / `Task:` prefixes)
26
+ - The `## Description` / `## 描述` section
27
+ - The `## Requirements` / `## 需求` section
28
+ - frontmatter fields `type` and (optionally) `milestone`
29
+
30
+ Build the Issue title:
31
+
32
+ | task.md `type` | Conventional Commits type |
33
+ |---|---|
34
+ | `feature` | `feat` |
35
+ | `bugfix`, `bug` | `fix` |
36
+ | `refactor`, `refactoring` | `refactor` |
37
+ | `docs`, `documentation` | `docs` |
38
+ | `chore`, `task`, others | `chore` |
39
+
40
+ Scope inference: read known module names from `.agents/.airc.json`'s `labels.in` field, then semantically match them against the task title and description; omit `scope` when there is no clear hit. Final title: `{cc_type}({scope}): {task_title}` or `{cc_type}: {task_title}` (preserve the task title verbatim — do not translate or rewrite).
41
+
42
+ ### 3. Build the Issue Body
43
+
44
+ Issue Form detection: follow the "Issue Template Detection" section in `.agents/rules/issue-pr-commands.md` to scan `.github/ISSUE_TEMPLATE/*.yml` (excluding `config.yml`).
45
+
46
+ #### Scenario A: A matching template was detected
47
+
48
+ Pick the form whose `name` (or filename) best matches the task type (e.g., a task with `type: bugfix` prefers a form whose name contains `bug`); if no match, fall back to a generic form like `other.yml`; if none, take the first form in the directory.
49
+
50
+ Populate the form by following the field-handling rules in `.agents/rules/issue-pr-commands.md` § "Issue Template Detection":
51
+
52
+ - `textarea` / `input` fields: use `attributes.label` as a markdown heading and pull values from task.md
53
+ - `markdown` fields: skip (these are description blurbs)
54
+ - `dropdown` / `checkboxes` fields: skip
55
+
56
+ Recommended field-to-source mapping:
57
+
58
+ | Template field hint | Source in task.md |
59
+ |---|---|
60
+ | `summary`, `title` | task title |
61
+ | `description`, `problem`, `what happened`, `issue-description`, `current-content` | task description |
62
+ | `solution`, `requirements`, `steps`, `suggested-content`, `impact`, `context`, `alternatives`, `expected` | requirements list (preserve checked / unchecked state as-is) |
63
+ | Other `textarea` / `input` fields | task description, or `N/A` if missing |
64
+
65
+ Whenever task.md does not provide a usable value, write `N/A`.
66
+
67
+ #### Scenario B: No template, or template parsing failed
68
+
69
+ Fall back to the default body:
70
+
71
+ ```markdown
72
+ ## Description
73
+
74
+ {task description, or N/A if missing}
75
+
76
+ ## Requirements
77
+
78
+ - [ ] {requirement-1}
79
+ - [ ] {requirement-2}
80
+ ```
81
+
82
+ If the requirements list is empty, write `N/A` in that section.
83
+
84
+ ### 4. Resolve labels / Issue Type / milestone
85
+
86
+ #### labels (rough pass)
87
+
88
+ - Call `gh api "repos/$upstream_repo/labels?per_page=100" --jq '.[].name'` to fetch the actual labels in the repo (cache as a set)
89
+ - Pick the "expected type label" using the mapping below, keeping only those that exist in the repo set:
90
+
91
+ | task.md `type` | label |
92
+ |---|---|
93
+ | `bug`, `bugfix` | `type: bug` |
94
+ | `feature` | `type: feature` |
95
+ | `enhancement` | `type: enhancement` |
96
+ | `docs`, `documentation` | `type: documentation` |
97
+ | `dependency-upgrade` | `type: dependency-upgrade` |
98
+ | `task`, `chore` | `type: task` |
99
+ | `refactor`, `refactoring` | `type: enhancement` |
100
+ | others | skip |
101
+
102
+ - `in:` labels (rough pass — when in doubt, leave it out): semantically match the task title and description against module names from `labels.in`; explicit mention or strong implication → add `in: {module}`; vague or uncertain → skip. `in:` labels also require the label to actually exist in the repo.
103
+
104
+ If the final label set is empty, omit the `--label` argument.
105
+
106
+ #### Issue Type fallback
107
+
108
+ | task.md `type` | Issue Type |
109
+ |---|---|
110
+ | `bug`, `bugfix` | `Bug` |
111
+ | `feature`, `enhancement` | `Feature` |
112
+ | `task`, `documentation`, `dependency-upgrade`, `chore`, `docs`, `refactor`, `refactoring`, others | `Task` |
113
+
114
+ When applying the Issue Type, follow the "Set Issue Type" command in `.agents/rules/issue-pr-commands.md`; first call `gh api orgs/{owner}/issue-types` to list the org's actually available Types, and only set the inferred value when it is present in that list. Failure to set is non-blocking.
115
+
116
+ #### milestone
117
+
118
+ Infer per `.agents/rules/milestone-inference.md` § "Stage 1: `create-task` (when the platform rule creates the Issue)". When the inference is empty or the repo lacks a matching milestone, omit the milestone.
119
+
120
+ ### 5. Call the GitHub CLI to Create the Issue
121
+
122
+ Run the "Create Issue" command from `.agents/rules/issue-pr-commands.md`:
123
+
124
+ ```bash
125
+ gh issue create -R "$upstream_repo" \
126
+ --title "{title}" \
127
+ --body "{body}" \
128
+ --assignee @me \
129
+ {label-args} \
130
+ {milestone-arg}
131
+ ```
132
+
133
+ - `{label-args}` is expanded from the result of §4 into multiple `--label "..."`; if empty, omit the entire argument
134
+ - `{milestone-arg}` is only expanded to `--milestone "..."` when `has_triage=true` and milestone is non-empty; otherwise omit
135
+ - `--assignee @me` requires no permission probe; on failure, skip silently
136
+
137
+ Permission downgrade follows `.agents/rules/issue-sync.md`: `has_triage=false` skips label / milestone settings; `has_push=false` skips Issue Type setting; the rest continues.
138
+
139
+ After success, parse the Issue number from the output (match only the `https://.../issues/(\d+)` URL form; do not use a loose regex). If parsing fails, halt the cascade and propagate the error back to `create-task`.
140
+
141
+ ### 6. Set Issue Type (Optional)
142
+
143
+ Execute only when `has_push=true` and the Issue Type inferred in §4 is in the org's actually available list:
144
+
145
+ ```bash
146
+ gh api "repos/$upstream_repo/issues/{issue-number}" -X PATCH \
147
+ -f type="{issue-type}" --silent
148
+ ```
149
+
150
+ Failure is non-blocking.
151
+
152
+ ### 7. Write Back task.md
153
+
154
+ Update task.md:
155
+
156
+ - Write `issue_number: {n}` into the frontmatter (replace if it exists; append at the end of the frontmatter otherwise)
157
+ - Update `updated_at` to the current time (command: `date "+%Y-%m-%d %H:%M:%S%:z"`)
158
+ - Append to the `## 活动日志` / `## Activity Log` section:
159
+ ```
160
+ - {YYYY-MM-DD HH:mm:ss±HH:MM} — **Create Issue** by {agent} — Created GitHub Issue #{n}
161
+ ```
162
+
163
+ ### 8. Return the Result
164
+
165
+ Hand the following back to the caller `create-task`:
166
+
167
+ - Issue number `{n}`
168
+ - Issue URL (prefer the URL printed by `gh issue create`; fall back to `https://github.com/$upstream_repo/issues/{n}`)
169
+ - The labels / milestone / Issue Type that were actually applied
170
+
171
+ `create-task` uses these to pick the "Scenario A: Issue created" output branch and continue with task comment sync and status label setup.
172
+
173
+ ## Error Handling
174
+
175
+ - Auth failure / command unavailable: return a structured `{code: "AUTH_FAILED", message}` to `create-task`; do not modify task.md
176
+ - Network timeout / DNS failure: `{code: "NETWORK", message}`
177
+ - Template parsing failure, Issue number parsing failure, other anomalies: `{code: "VALIDATION", message}`
178
+ - All failures keep task.md untouched; `create-task` takes the "Scenario C: failure fallback" output branch and prompts the user to retry manually or fill `issue_number` later
@@ -0,0 +1,178 @@
1
+ # Issue 创建
2
+
3
+ 当 `create-task` 完成本地 `task.md` 落盘后,按本规则级联创建 Issue。本规则仅由 `create-task` SKILL.md 内部引用,不应独立调用。
4
+
5
+ ## 行为边界
6
+
7
+ - Issue 标题和正文只能来自 `task.md`
8
+ - 不读取 `analysis.md`、`plan.md`、`implementation.md` 或审查产物
9
+ - 持久产物只有:远端 Issue + `task.md` 中回写的 `issue_number`
10
+ - Issue 创建失败时不回滚 `task.md`;当前 task 仍可继续后续工作流,未来可由用户手动写入 `issue_number`,让其它技能的级联同步接管
11
+
12
+ ## 执行步骤
13
+
14
+ ### 1. 验证前置条件
15
+
16
+ - `.agents/workspace/active/{task-id}/task.md` 必须存在
17
+ - 先读取 `.agents/rules/issue-pr-commands.md`,按其中的认证与平台检测命令验证 `gh auth status` 和当前仓库可用
18
+ - 先读取 `.agents/rules/issue-sync.md`,完成 `upstream_repo`、`has_triage`、`has_push` 检测;后续所有 `gh issue` 与 repo 级 `gh api` 调用都复用这些变量
19
+ - 如果 `task.md` 中 `issue_number` 已存在且既不为空也不为 `N/A`,立即停止级联:返回"任务已绑定 Issue #{n},跳过创建"信息给 `create-task`,由调用方决定如何继续
20
+
21
+ ### 2. 提取任务信息
22
+
23
+ 从 `task.md` 提取以下字段:
24
+
25
+ - 任务标题(首个 `# ` 标题,去掉 `任务:` / `Task:` 前缀)
26
+ - `## Description` / `## 描述` 段落
27
+ - `## Requirements` / `## 需求` 段落
28
+ - frontmatter 中的 `type` 与(可选的)`milestone`
29
+
30
+ 构造 Issue 标题:
31
+
32
+ | task.md `type` | Conventional Commits type |
33
+ |---|---|
34
+ | `feature` | `feat` |
35
+ | `bugfix`, `bug` | `fix` |
36
+ | `refactor`, `refactoring` | `refactor` |
37
+ | `docs`, `documentation` | `docs` |
38
+ | `chore`, `task` 或其它 | `chore` |
39
+
40
+ scope 推断:从 `.agents/.airc.json` 的 `labels.in` 字段读取已知模块名,再与任务标题/描述做语义匹配;没有清晰命中时省略 scope。最终标题:`{cc_type}({scope}): {task_title}` 或 `{cc_type}: {task_title}`(任务标题保留原文,不要翻译或改写)。
41
+
42
+ ### 3. 构建 Issue 正文
43
+
44
+ Issue 模板检测:按 `.agents/rules/issue-pr-commands.md` 的 "Issue 模板检测" 规则扫描 `.github/ISSUE_TEMPLATE/*.yml`(排除 `config.yml`)。
45
+
46
+ #### 场景 A:检测到匹配模板
47
+
48
+ 按模板顶层 `name` 与任务类型挑选最匹配的 form(如任务 `type: bugfix` 优先选名称含 `bug` 的模板);找不到匹配时,回退到通用 form(如 `other.yml`),仍找不到时取目录中第一个 form。
49
+
50
+ 按 `.agents/rules/issue-pr-commands.md` 中 "Issue 模板检测" 章节的字段处理规则填充 form:
51
+
52
+ - `textarea` / `input` 字段:使用 `attributes.label` 作为 markdown 标题,从 task.md 取值
53
+ - `markdown` 字段:跳过(说明文案)
54
+ - `dropdown` / `checkboxes` 字段:跳过
55
+
56
+ 字段值映射(建议):
57
+
58
+ | 模板字段提示 | task.md 来源 |
59
+ |---|---|
60
+ | `summary`, `title` | 任务标题 |
61
+ | `description`, `problem`, `what happened`, `issue-description`, `current-content` | 任务描述 |
62
+ | `solution`, `requirements`, `steps`, `suggested-content`, `impact`, `context`, `alternatives`, `expected` | 需求列表(已勾选与未勾选混合,原样保留) |
63
+ | 其它 `textarea` / `input` 字段 | 任务描述;缺失时填 `N/A` |
64
+
65
+ 任何字段在 task.md 中找不到合适值时,写入 `N/A`。
66
+
67
+ #### 场景 B:无模板或解析失败
68
+
69
+ 回退到默认正文:
70
+
71
+ ```markdown
72
+ ## Description
73
+
74
+ {任务描述;缺失时填 N/A}
75
+
76
+ ## Requirements
77
+
78
+ - [ ] {requirement-1}
79
+ - [ ] {requirement-2}
80
+ ```
81
+
82
+ 需求列表为空时,整段写 `N/A`。
83
+
84
+ ### 4. 解析 labels / Issue Type / milestone
85
+
86
+ #### labels(粗选)
87
+
88
+ - 调用 `gh api "repos/$upstream_repo/labels?per_page=100" --jq '.[].name'` 获取仓库实际存在的 label 列表(缓存为 set)
89
+ - 按以下映射挑出"应有的 type label",仅保留仓库 set 中实际存在的:
90
+
91
+ | task.md `type` | label |
92
+ |---|---|
93
+ | `bug`, `bugfix` | `type: bug` |
94
+ | `feature` | `type: feature` |
95
+ | `enhancement` | `type: enhancement` |
96
+ | `docs`, `documentation` | `type: documentation` |
97
+ | `dependency-upgrade` | `type: dependency-upgrade` |
98
+ | `task`, `chore` | `type: task` |
99
+ | `refactor`, `refactoring` | `type: enhancement` |
100
+ | 其它 | 跳过 |
101
+
102
+ - `in:` label(粗选,宁缺毋滥):根据任务标题与描述对 `labels.in` 中的模块名做语义匹配;明确提及或强烈暗示 → 添加 `in: {module}`;模糊或不确定 → 不添加。`in:` label 同样要求仓库实际存在。
103
+
104
+ 最终 label 集合若为空,省略 `--label` 参数。
105
+
106
+ #### Issue Type fallback
107
+
108
+ | task.md `type` | Issue Type |
109
+ |---|---|
110
+ | `bug`, `bugfix` | `Bug` |
111
+ | `feature`, `enhancement` | `Feature` |
112
+ | `task`, `documentation`, `dependency-upgrade`, `chore`, `docs`, `refactor`, `refactoring` 及其它 | `Task` |
113
+
114
+ 实际设置时按 `.agents/rules/issue-pr-commands.md` 的 "设置 Issue Type" 命令;先调 `gh api orgs/{owner}/issue-types` 列出 org 实际可用的 Type,仅当推断值在列表中时才设置;设置失败不阻断流程。
115
+
116
+ #### milestone
117
+
118
+ 按 `.agents/rules/milestone-inference.md` 的 "阶段 1:`create-task`(平台规则创建 Issue 时)" 规则推断;推断结果为空或仓库无对应 milestone 时省略。
119
+
120
+ ### 5. 调用 GitHub CLI 创建 Issue
121
+
122
+ 按 `.agents/rules/issue-pr-commands.md` 中的 "创建 Issue" 命令执行:
123
+
124
+ ```bash
125
+ gh issue create -R "$upstream_repo" \
126
+ --title "{title}" \
127
+ --body "{body}" \
128
+ --assignee @me \
129
+ {label-args} \
130
+ {milestone-arg}
131
+ ```
132
+
133
+ - `{label-args}` 由 §4 计算结果展开为多个 `--label "..."`;为空则整体省略
134
+ - `{milestone-arg}` 仅当 `has_triage=true` 且 milestone 非空时展开为 `--milestone "..."`;否则整体省略
135
+ - `--assignee @me` 不做权限预判,失败时静默跳过
136
+
137
+ 权限降级规则按 `.agents/rules/issue-sync.md`:`has_triage=false` 时跳过 label / milestone 设置;`has_push=false` 时跳过 Issue Type 设置;其余流程继续。
138
+
139
+ 创建成功后从输出中解析 Issue 编号(仅匹配 `https://.../issues/(\d+)` URL 形式,不要使用宽松正则);解析失败时停止级联并把错误传回 `create-task`。
140
+
141
+ ### 6. 设置 Issue Type(可选)
142
+
143
+ 仅当 `has_push=true` 且 §4 推断的 Issue Type 在 org 实际可用列表中时执行:
144
+
145
+ ```bash
146
+ gh api "repos/$upstream_repo/issues/{issue-number}" -X PATCH \
147
+ -f type="{issue-type}" --silent
148
+ ```
149
+
150
+ 设置失败不阻断流程。
151
+
152
+ ### 7. 回写 task.md
153
+
154
+ 更新 task.md:
155
+
156
+ - 把 `issue_number: {n}` 写入 frontmatter(已存在则替换;不存在则在 frontmatter 末尾追加)
157
+ - 更新 `updated_at` 为当前时间(命令:`date "+%Y-%m-%d %H:%M:%S%:z"`)
158
+ - 在 `## 活动日志` / `## Activity Log` 段落追加:
159
+ ```
160
+ - {YYYY-MM-DD HH:mm:ss±HH:MM} — **Create Issue** by {agent} — Created GitHub Issue #{n}
161
+ ```
162
+
163
+ ### 8. 返回结果
164
+
165
+ 把以下信息回传给调用方 `create-task`:
166
+
167
+ - Issue 编号 `{n}`
168
+ - Issue URL(首选 `gh issue create` 输出中的 URL;缺失时拼 `https://github.com/$upstream_repo/issues/{n}`)
169
+ - 实际应用的 labels / milestone / Issue Type
170
+
171
+ `create-task` 据此选择"场景 A:已创建 Issue"输出分支并继续执行后续 task 评论同步与 status label 设置。
172
+
173
+ ## 错误处理
174
+
175
+ - 认证失败 / 命令不可用:返回结构化错误 `{code: "AUTH_FAILED", message}` 给 `create-task`,不修改 task.md
176
+ - 网络超时 / DNS 失败:`{code: "NETWORK", message}`
177
+ - 模板解析失败、Issue 编号解析失败、其它异常:`{code: "VALIDATION", message}`
178
+ - 任意失败均不回滚 task.md;`create-task` 走"场景 C 失败兜底"输出,提示用户手动重试或在事后写入 `issue_number`
@@ -0,0 +1,5 @@
1
+ # Issue 创建
2
+
3
+ 当前代码平台未提供 Issue 创建规则。
4
+
5
+ `create-task` 在本平台上会跳过级联创建 Issue 步骤;本地 `task.md` 仍然是有效产物。如果将来需要把任务绑定到一个 Issue,可手动在 `task.md` 中写入 `issue_number`,后续技能(`commit` / `refine-task` / `complete-task` 等)会按既有的级联同步规则自动接管 Issue 元数据更新。