关于 to-issues
to-issues 将 PRD 和/或 SPEC 拆分为依赖顺序明确、可独立演示的 Issue,适合规划并交由 Agent 实现的团队。它强调端到端的垂直切片,并在发布前要求用户检查拆分结果。
主要功能
- 01定位 PRD 或 SPEC 输入
- 02先识别并安排预重构工作
- 03按可演示行为拆分垂直 Issue
- 04标明依赖并核验验收标准
- 05创建 GitHub Issue 或本地文件
适用场景
- 01将产品需求拆为可独立演示的任务
- 02为新会话中的 Agent 准备 Issue
- 03安排重构与功能工作的先后依赖
- 04将 Issue 保存到 GitHub 或本地
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ smallnest/ goal-workflow --skill to-issues安装后在 Claude Code 中输入/to-issues确认已加载。
详细介绍
to-issues — 将 PRD/SPEC 拆解为 Issues
将 PRD 和/或技术 SPEC 拆解为较小的 可独立演示 Issues,每个 Issue 的工作量都适合在一个全新的上下文窗口中完成,然后在你选择的平台上创建它们。本流程可独立使用——无需先运行 /prd。
此技能生成的每个 Issue 天然适合交给 Agent 执行:一个从未看过你的 PRD/SPEC 的全新会话,也能接手并完成它。
核心原则:示踪弹,而不是分层
这是最重要的一条规则,也是模型最常违反的一条。
- 横向切片只交付变更中的一层(一个工单包含所有 schema,另一个包含所有 API,第三个包含所有 UI)。必须等到所有层都完成后才有可用功能,而且每个工单的验收标准都得涉及其他工单负责的工作。这是模型最容易采用的默认做法——要避免。
- 纵向切片,也就是示踪弹,一次性交付贯穿所有层的一条精简但完整的路径(针对单一窄范围行为,包含 schema + API + UI + 测试)。它在交付后即可独立验证,并且包含自己负责评估的所有内容。
每个 Issue 的检验问题是:“完成后我能演示什么?” 如果答案是某一层(“数据库中有一个优先级列”),而不是某种行为(“用户可以设置任务的优先级,并看到设置持久化”),那就是横向切片——请重新切分。
**规模下限:**如果整个变更能放进一个上下文窗口,就根本不需要 Issues。请说明这一点,并直接引导用户使用 /goal。
将此技能与
/prd-to-spec放在同一个上下文窗口中。不要在它们之间清空或压缩上下文,否则必须重新获取 SPEC,而且内容可能会被截断。
工作内容
- 定位输入——查找 PRD 或 SPEC 文件(自动检测或由用户指定)
- 查找预先重构工作——找出“先让变更容易实现,再实现容易的变更”这类工作,并将其排在前面
- 拆解为纵向 Issues——将行为拆分为示踪弹工单,并添加阻塞关系
- 询问用户——展示带编号的列表,在发布前确认粒度、依赖关系和演示路径
- 选择平台——GitHub / Local
- 创建 Issues——先创建阻塞项并添加原生阻塞链接,然后打印摘要
步骤 1:定位输入
查找输入文档:
What should I base the Issues on?
A. Auto-detect: scan tasks/ for recent PRDs and SPECs
B. Specific PRD file (e.g., tasks/prd-priority-system.md)
C. Specific SPEC file (e.g., tasks/spec-priority-system.md)
D. Both PRD and SPEC (best: PRD for requirements, SPEC for technical contracts)
E. Paste requirements directly
如果使用自动检测,请列出可用文件并让用户选择。
如果 PRD 和 SPEC 都可用,请以 SPEC 的第 10.2 节(Issue Mapping)为主要指南,并参考 PRD 的 User Stories。如果只有 PRD,则直接根据 User Stories 生成 Issues。
步骤 2:优先查找预先重构工作
切分功能之前,先查找预先重构:用于让功能 Issues 更小、更安全的机械性基础工作,例如提取共享辅助函数、扩宽类型、添加接缝或移动文件。请将这些工作排在最前面,作为独立 Issue,以便依赖它们的功能工单保持精简。
如果没有此类工作,请跳过此步骤。不要凭空制造无意义的工作。
步骤 3:拆分为垂直 Issue
生成 Issue 列表。规则:
- 每个 Issue 都是一颗追踪弹——一条狭窄、完整、可演示的路径,贯穿它涉及的每一层。不要写成“X 的后端”,而要写成“针对一个用例,端到端实现 X”。
- 每个 Issue 都能在一个全新的上下文窗口中完成——单次 Agent 会话即可完成,无需你在场。
- 按行为拆分,而不是按层拆分——如果用户故事较大,就拆成 2-3 个范围更窄的行为,每个仍然是垂直切片,并明确标注阻塞关系。绝不能拆成一个后端工单和一个前端工单。
- 合并过小的故事——无法独立演示的 1-2 条简单验收条件,应合并到相关 Issue 中。
- 明确声明阻塞关系——每个 Issue 都要列出开始前必须完成的事项。这些关系正是该产物的意义所在。
- 按依赖顺序为 Issue 编号——先列阻塞项,这样实现者(或跟踪工具)总能找到可开始的任务。
- 如果有 SPEC——为每个 Issue 补充 SPEC 引用(API 合约、数据模型章节、错误处理)。但不要在正文中写入文件路径和行号——它们会过时;应改为描述行为和合约。
可证伪的验收条件。 对每条验收条件,指出什么观察结果能证明它不成立,并确认从实现者开始工作时的提交版本来看,该条件确实会失败。排除以下三种情况:在基准提交中已经成立的条件、只能通过其他 Issue 负责的工作才能满足的条件,以及仅仅复述需求的条件。垂直切片交付的是此前不存在的行为,因此按定义,它在基准提交中就应当不通过。
Issue 格式:
Issue #N: [Title — a behaviour, not a layer]
---
Description: [What behaviour this delivers, end to end, and why]
Demo path: [The one thing you can show working when this lands]
Acceptance Criteria:
- [ ] [Falsifiable — names an observation that fails at the base commit]
- [ ] ...
Blocked by: [None / Issue #X, #Y]
Priority: [high / medium / low]
SPEC Reference: [Section X.Y — contracts only, no file paths; only if SPEC available]
步骤 4:询问用户(不得跳过)
以编号列表的形式呈现拆分结果,并在发布任何内容前询问用户。过度拆分和意外的横向切分是最常见的两种问题——此步骤可以发现它们。
📋 Generated N Issues from [PRD/SPEC], in dependency order:
#1: Extract task-mutation helper (prefactoring) — Blocked by: none
#2: A user can set a task's priority and see it persist — Blocked by: #1
demo: open a task, pick High, reload, still High
#3: A user can filter the task list to one priority — Blocked by: #2
demo: select High, list shows only High tasks
#4: A user can sort the task list by priority — Blocked by: #2
demo: click Sort, tasks reorder High→Low
Review before I create anything:
- Granularity: too fine? "merge #3 and #4". Too coarse? "split #2".
- Demo path: any Issue whose demo is a layer, not a behaviour, is mis-sliced — tell me.
- Edges: are the "Blocked by" links real? Any missing or spurious?
- Adjust: "change #2 priority to high", "add an issue for a priority badge"
- Confirm: reply OK to proceed
创建任何 Issue 前,等待用户确认。
步骤 5:选择创建模式
Choose where to create these Issues:
A. GitHub (via gh CLI, with native blocking links and optional sub-issues)
B. Local (one markdown file per Issue, dependency-ordered)
Your choice:
步骤 6:按模式创建
模式 A:GitHub
**前提条件:**已安装并完成身份验证的 gh CLI;使用 --parent / --blocked-by 需要 v2.94+。
先创建阻塞项,确保在创建依赖它们的 Issue 前已有对应的 Issue 编号。记录每个返回的编号。
操作:
- 按依赖顺序逐个处理 Issue:
gh issue create \ --title "[Title]" \ --body "[Description + Demo path + Acceptance Criteria + SPEC Reference]" \ --label "priority: [priority]" \ --blocked-by [comma-separated blocker numbers, if any] \ --parent [spec issue number, if creating as sub-issues]- 使用原生
--blocked-by设置依赖关系。只有跟踪工具拒绝该标志时,才退回到在正文中添加“Blocked by #X”这一行。 - 如果 SPEC 位于 GitHub Issue 中,传入
--parent <spec_issue>,将这些 Issue 创建为其子 Issue。事后关联父 Issue:gh issue edit <parent> --add-sub-issue <n>。
- 使用原生
- 如果标签不存在,先创建标签,或跳过
--label标志。 - 报告已创建的 Issue 编号和 URL。
模式 B:本地
询问用户:
Where should I save the Issue files? (default: .autoresearch/issues/[feature-slug])
操作:
- 如果功能文件夹不存在,使用
mkdir -p创建。每个功能使用一个文件夹,可避免并行 Agent 在共享文件上发生竞争。 - 按依赖顺序为每个 Issue 保存为
NN-[slug].md(用零补齐;NN是实际工单 ID,因此/goal 03可以正常工作):# [Title — a behaviour] ## Description [What behaviour this delivers, end to end, and why] ## Demo path [The one thing you can show working when this lands] ## Acceptance Criteria - [ ] [Falsifiable criterion 1] - [ ] [Falsifiable criterion 2] ## Blocked by [None / #NN, #NN] ## Priority [high / medium / low] ## SPEC Reference [Section X.Y — contracts only; omit if no SPEC] - 按依赖顺序报告已创建的文件路径。
宽范围重构例外
有一种情况会打破示踪弹规则:宽范围重构——单个机械性变更(重命名列、重新定义共享符号的类型),其影响范围扩散到整个代码库,导致一次编辑破坏数千个调用点,且无法让任何垂直切片通过。
应按 扩展 → 迁移 → 收缩 的顺序处理:
- 扩展——在旧形式旁添加新形式,确保不会破坏任何内容。创建一个 Issue。
- 迁移——按影响范围(每个包、每个目录)分批迁移调用点,每批创建一个 Issue,且每个 Issue 都阻塞于扩展。由于旧形式仍然存在,CI 可以保持通过。
- 收缩——不再有调用方后,删除旧形式,创建一个阻塞于所有迁移批次的 Issue。
如果即使分批也无法单独保持通过,就让它们共用一个集成分支,并让所有批次都阻塞一个最终的集成并验证 Issue;只有到那时才能保证通过。
步骤 7:总结报告
✅ Issue creation complete!
Source: [PRD/SPEC path]
Mode: [GitHub / Local]
Issues created: N (in dependency order)
# | Title (behaviour) | Blocked by | Identifier
---|------------------------------------------|------------|------------
1 | Extract task-mutation helper | — | #42 / 01-*.md
2 | Set & persist task priority | #1 | #43 / 02-*.md
3 | Filter task list by priority | #2 | #44 / 03-*.md
4 | Sort task list by priority | #2 | #45 / 04-*.md
Frontier (no open blockers, start now): #1
💡 Dispatch is manual — one Issue per fresh session, cleared between them.
Count the Issues with no open blockers, open that many sessions, implement with /goal:
/goal 42 # GitHub mode
/goal 01-*.md # Local mode
Note: /goal may not auto-close the ticket — update its state yourself when done.
满足以下条件即表示有效
- 每个 Issue 都回答了“完成后我能演示什么?”——答案是一种行为,而不是一个层。
- 列表返回时已编号,且每个 Issue 都有实际的“阻塞于”行,并且尚未发布任何内容。
- 列表最顶部的 Issue 没有阻塞项,可以立即开始。
- Issue 正文中没有文件路径或行号(原型生成的代码片段除外)。
- 每个 Issue 都像是一个新会话可以在你不在场时独立完成的任务。
- 如果发现任何预重构工作,都应排在最前面,而不是混入功能 Issue。
- 每条验收标准都指出了一个在基础提交中会失败的可观察结果。
边缘情况与回退方案
| 场景 | 处理方式 |
|---|---|
| 整个变更能放进一个上下文窗口 | 说明这一点;跳过 Issue,直接指向 /goal |
| 在 tasks/ 中找不到 PRD/SPEC | 请用户提供文件路径或粘贴需求 |
| PRD 没有 User Stories | 改为根据 Functional Requirements 推导 Issue |
| SPEC 有 Issue Mapping(第 10.2 节) | 将其作为主要来源,并与 PRD 交叉核对 |
| 模型生成了每层一个 Issue | 在问答环节发现:演示内容是某一层的任何 Issue 都应重新切分为垂直切片 |
| 模型拆分过度(一个 3 行变更拆成 12 个工单) | 在问答环节要求合并;如果整个变更能放进一个窗口,则跳过 Issue |
| 宽范围机械性重构 | 使用上述扩展 → 迁移 → 收缩顺序 |
gh 太旧,不支持 --blocked-by / --parent | 回退为在正文中添加“阻塞于”行;建议将 gh 升级至 v2.94+ |
GitHub 模式下 gh CLI 未通过身份验证 | 显示错误,建议运行 gh auth login,并提供切换到本地模式的选项 |
| 本地模式下 Issue 文件夹不存在 | 自动创建按功能划分的文件夹 |
| 用户拒绝创建 Issue | 将按依赖关系排序的列表打印为文本摘要,供之后手动创建 |
与其他技能的关系
/prd → /prd-to-spec (optional) → /to-issues → /goal → /review-it → /ship-it
│ │ │ │
│ Requirements │ Technical design │ Vertical │ Implementation
│ (what) │ (how) │ tickets │ (code)
- /prd — 生成 PRD(此技能的输入)
- /prd-to-spec — 生成 SPEC(可选;与此技能放在同一上下文窗口中)
- /to-issues — 生成垂直切分的 Issue(此技能)
- /goal — 逐个实现 Issue,每个新会话处理一个