<NN>: <Ticket title>

原创2026-09-11 17:48:37315 阅读
文章标签:AI 技能AI 插件

:

What to build: the end-to-end behaviour this ticket makes work, from the user's perspective, not a layer-by-layer implementation list.

Blocked by: the numbers/titles of the tickets that gate this one, or "None (can start immediately)".

Status: ready-for-agent

  • [ ] Acceptance criterion 1
  • [ ] Acceptance criterion 2

### 真实 tracker 的 issue 模板

```markdown
## Parent

A reference to the parent issue on the tracker (if the source was an existing issue, otherwise omit this section).

## What to build

The end-to-end behaviour this ticket makes work, from the user's perspective, not layer-by-layer implementation.

## Acceptance criteria

- [ ] Criterion 1
- [ ] Criterion 2

## Blocked by

- A reference to each blocking ticket, or "None (can start immediately)".

两个模板的共性要点:

  • "What to build" 从用户视角写端到端行为,而不是按层列实现清单;
  • 避免在 ticket 里写具体文件路径或代码片段——它们过时太快。唯一的例外:如果 prototype 产出的某个片段(状态机、reducer、schema、类型形状)比散文更精确地编码了一个决策,可以内联它并简短注明来自 prototype,且只保留决策密集的部分,而不是一个可运行的 demo。

八、不同 Tracker 的落地细节:本地 / GitHub / GitLab

/setup-matt-pocock-skills 支持的三种 tracker 各自有明确的约定文件,to-tickets 的发布步骤("publish to the issue tracker"、"fetch the relevant ticket")在三种模式下语义不同:

本地 Markdown(issue-tracker-local.md)

  • 每个功能一个目录:.scratch/<feature-slug>/;spec 固定为 .scratch/<feature-slug>/spec.md;
  • 实现 ticket 一个文件一个 ticket:.scratch/<feature-slug>/issues/<NN>-<slug>.md,从 01 编号;
  • triage 状态记录在文件顶部附近的 Status: 行(角色字符串见 triage-labels.md);
  • 评论与对话历史追加到文件底部 ## Comments 标题之下。

值得注意:该技能曾把本地 ticket 写进根级 tickets.md 单文件,后被证实是 bug——并行 agent 同时写入一个共享文件会竞争。因此本地模式现在强制"每个 ticket 一个文件",且 NN 前缀是真实的 ticket ID,使 /implement 03 可以直接引用编号而无需重打长标题。

GitHub(issue-tracker-github.md)

  • 用 gh CLI 操作:gh issue create --title "..." --body "..."(多行正文用 heredoc);
  • 读取:gh issue view <number> --comments;列表:gh issue list --state open --json ...;
  • 阻塞关系优先用 GitHub 原生 issue dependencies(在 child 上通过 gh api --method POST repos/<owner>/<repo>/issues/<child>/dependencies/blocked_by -F issue_id=<blocker-db-id> 添加边,注意 <blocker-db-id> 是数字数据库 id,用 gh api ... --jq .id 取,不是 #number 或 node_id);不可用时回退为正文顶部的 Blocked by: #<n>, #<n> 行。ticket 在其每个 blocker 都被关闭后解除阻塞;
  • frontier 查询:列出 map 的开放子 issue,剔除有未关闭 blocker(issue_dependencies_summary.blocked_by > 0)或已有 assignee 的,按 map 顺序取第一个;
  • 认领:gh issue edit <n> --add-assignee @me;解决:评论答案后 gh issue close <n>,再向 map 的 Decisions-so-far 追加上下文指针。

GitLab(issue-tracker-gitlab.md)

  • 用 glab CLI:创建 glab issue create --title "..." --description "...";读取 glab issue view <number> --comments(机器可读加 -F json);GitLab 把评论称为 "notes",用 glab issue note <number> --message "...";
  • 关闭时 glab issue close 不接受附带评论,所以要先 glab issue note 发说明再关闭;
  • 阻塞关系优先用 GitLab 原生 blocking link:glab issue note <child> --message "/blocked_by #<blocker>"。原生 blocking link 是 Premium/Ultimate 功能,免费版回退为描述顶部的 Blocked by: #<n>, #<n> 行;
  • GitLab 的 issue 与 MR 编号空间分离,#42 一旦确定 surface 就没有歧义。

Triage 标签词汇

无论哪种 tracker,五个规范角色都映射到真实标签字符串(表来自 triage-labels.md):

规范角色 默认标签 含义
needs-triage needs-triage 维护者需要评估
needs-info needs-info 等待 reporter 补充信息
ready-for-agent ready-for-agent 完全明确,可供 AFK agent 直接实现
ready-for-human ready-for-human 需要人类实现
wontfix wontfix 不会处理

to-tickets 发布的 ticket 按构造即 agent-ready,因此默认打 ready-for-agent 标签;如果你所在 tracker 已使用别的标签名(如 bug:triage),可在配置文件中改右列以复用既有标签、避免重复创建。

九、FAQ:六个高频问题与对策

FAQ 部分 汇总了该技能实践中最常被报告的问题,写作者与使用者都值得提前知晓:

  1. 三行改动拆出十二个 ticket → 过度分解是最常见的摩擦点,模型默认原子化、丢失聚合。去 quiz 步骤要求合并;更根本的判断是"一个上下文窗口装得下就不需要本技能"。

  2. ticket 一层一个 → 垂直切片规则要防的正是这个。quiz 时每个 ticket 问"能 demo 什么",答不上来就是水平切片;可加 "demo path" 行矫正。

  3. GitHub 上 ticket 没建成 spec issue 的 sub-issue → 已知且未修复的边界情况。gh 从 v2.94 起原生支持 gh issue create --parent <n> 与 gh issue edit <parent> --add-sub-issue <n>,但直到 tracker 模板默认采用这些命令前,跑完后自己补父链接是可靠的做法。

  4. "Blocked by" 被写进了 issue 正文而不是真实 blocking link → 同类问题。GitHub 原生支持 gh issue create --blocked-by 12,15;因为 blocker 先发布,其编号在创建时总是可得。正文文本只是无原生边 trackers 的回退,不是默认。

  5. 本地 ticket 去哪了(v1.1 曾说根级 tickets.md) → 那是个 bug:共享单文件在并行 agent 写入时会竞争。现在改为每个 ticket 一个文件,依赖顺序编号,NN 前缀即真实 ticket ID。

  6. 读 spec 时一直截断 → 超大 spec 会超出 tracker issue 能干净回读的上限,agent 会反复用 tool call 抓取片段。不要在 /to-spec 与 /to-tickets 之间 clear 或 compact,同一上下文窗口内连续运行,spec 根本无需回取。

此外还有两条验收层面的经典陷阱:

  • 验收标准"什么都没评":有些标准在基线 commit 上就已成立、只能被别的 ticket 的工作满足、或只是复述请求。垂直切片本身能防住大部分("交付了原本不存在的行为"的切片在基线处按构造就是红的),但建议逐条自检:为每条标准命名一个"能证明它为假"的观察,并确认它在 implementer 起步的 commit 上是失败的;
  • ticket 发布后怎么运行:技能止步于工件,无自动派发。人工派发:看板数出"无未关闭 blocker"的 ticket 数量,开同样数量的 agent session,每个 ticket 一个全新上下文,之间清空;且 implement 完成时不一定可靠关闭/勾选 ticket,其状态由你更新。

十、It's working if:成功验收清单

来自 docs/engineering/to-tickets.md,判断一次运行是否成功:

  • 每个 ticket 都能回答"做完能 demo 什么?",且答案是行为,不是某一层;
  • 列表在发布前就以编号形式返回给你,每个都带 "Blocked by" 行;
  • 最顶部的 ticket 没有 blocker,可以立即开始;
  • ticket 正文里没有任何文件路径或行号(prototype 产生的片段除外);
  • 每个 ticket 读起来像一个全新 session 不用你在场就能独立完成;
  • 找到的 prefactor 排在序列最前面,而不是混进功能 ticket。

十一、它在技能链中的位置

to-tickets 是主构建链的一环(docs/engineering/to-tickets.md):

grill-with-docs → to-spec → to-tickets → implement → code-review
登录后查看全文
skills