关于 writing-plans
这项 Skill 用于编写逐项实施计划,包含文件范围、代码示例、测试和提交步骤,面向需要将工作交由 Agent 或工程师执行的开发者。
主要功能
- 01梳理文件及其职责
- 02拆分为可测试的任务
- 03列出实现与测试步骤
- 04检查计划中的遗漏和占位内容
- 05通过原生任务工具跟踪进度
适用场景
- 01为 Agent 执行准备功能计划
- 02将规格拆解为可提交的任务
- 03规划涉及多个文件的改动
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ pcvelz/ superpowers --skill writing-plans安装后在 Claude Code 中输入/writing-plans确认已加载。
详细介绍
编写计划
关键限制 — 请先阅读
在此技能的任何阶段,你都不得调用 EnterPlanMode 或 ExitPlanMode。 此技能在正常模式下运行,并通过 AskUserQuestion 管理自己的完成流程。调用 EnterPlanMode 会让会话陷入计划模式,导致 Write/Edit 受到限制。调用 ExitPlanMode 会破坏工作流,并跳过用户的执行选择。如果你想调用其中任意一个,请停下——改为遵循此技能的说明。
概述
编写全面的实施计划,假设工程师对我们的代码库一无所知,而且品味值得商榷。记录他们需要了解的一切:每项任务要修改哪些文件、需要编写什么代码、要检查哪些测试和文档,以及如何测试。将完整计划拆解为易于处理的小任务。遵循 DRY、YAGNI 和 TDD。频繁提交。
假设他们是熟练的开发者,但对我们的工具集或问题领域几乎一无所知。假设他们不太了解如何设计好的测试。
开始时宣布:“我将使用 writing-plans 技能来创建实施计划。”
上下文: 如果在隔离的工作树中工作,该工作树应在执行时通过 superpowers-extended-cc:using-git-worktrees 技能创建。
将计划保存到: docs/superpowers/plans/YYYY-MM-DD-<feature-name>.md
- (如用户对计划位置有偏好,则以用户偏好为准)
范围检查
如果规格说明涵盖多个彼此独立的子系统,那么在头脑风暴期间就应将其拆分为多个子项目规格说明。如果尚未拆分,请建议将其拆分为多个独立计划,每个子系统一个。每个计划都应独立产出可运行、可测试的软件。
文件结构
定义任务之前,先梳理将要创建或修改的文件,以及每个文件的职责。这一步将确定拆分方案。
- 设计边界清晰、接口明确的单元。每个文件都应有一个明确职责。
- 你最擅长推理自己能同时放入上下文中的代码;文件职责越集中,编辑就越可靠。优先选择小型、专注的文件,而不是承担过多工作的庞大文件。
- 会一起修改的文件应放在一起。按职责拆分,而非按技术层拆分。
- 在现有代码库中,遵循既有模式。如果代码库使用大型文件,不要擅自重构;但如果你要修改的文件已经变得难以驾驭,在计划中纳入拆分方案是合理的。
此结构将用于制定任务拆分方案。每项任务都应产出独立且有意义的变更。
必须先执行:初始化任务跟踪
在探索代码或编写计划之前,你必须:
- 调用
TaskList,检查头脑风暴阶段是否已有任务 - 如果已有任务:编写计划时补充实施细节
- 如果没有任务:编写计划时通过
TaskCreate创建任务
调用 TaskList 之前不得开始探索。 这也包括派遣后台或并行调查子 Agent——TaskList 调用快速且同步,因此必须先调用,再安排任何探索 Agent。
TaskList
任务粒度
每项任务都是一个连贯的工作单元,能够产出可测试、可提交的成果。
完整的粒度指南请参见 skills/shared/task-format-reference.md。
核心原则:TDD 循环应在任务内部完成,而不是拆成独立任务。任务应为“实现 X 并编写测试”——红绿重构步骤属于执行细节,不是任务边界。
范围检查:
- 能否独立验证?(如果不能 → 任务太小)
- 是否涉及多个关注点?(如果是 → 任务太大)
- 是否值得单独提交?(如果不值得 → 与相邻任务合并)
计划文档标题
每份计划都必须以此标题开头:
# [Feature Name] Implementation Plan
> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers-extended-cc:subagent-driven-development (recommended) or superpowers-extended-cc:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
**Goal:** [One sentence describing what this builds]
**Architecture:** [2-3 sentences about approach]
**Tech Stack:** [Key technologies/libraries]
**Spec:** [path to the spec/design doc this plan implements — the plan
argues from the spec, so the spec travels with it; executors read both]
## Global Constraints
[Binding requirements every task must respect — exact values, formats, cross-component relationships ("same layout as X", "matches Y"). Execution controllers hand these to every reviewer. "none" if none.]
**User decisions (already made):** [One line per decision the user made during brainstorming/planning, quotable. "none" if none.]
---
延后决定
如果计划安排了向用户提问的内容(DECIDE 列表、AskUserQuestion 步骤),每个问题都 MUST:
- 说明尽管标题中的决定已作出,为何该问题仍未解决。如果已有记录的决定能回答该问题,就根据记录作答——不要再次提问。
- 在选项说明中提供回答问题所需的事实:写明相关项目及其角色/状态(例如“过时的 GitHub 镜像,上次推送于 2026-03-25——与本地工具的开发主目录分开”),并说明每个选项下哪些内容不会改变。
- 不得提出与已有记录的决定相矛盾的建议。否则计划不合格(严重程度与存在占位内容相同)。
任务结构
### Task N: [Component Name]
**Goal:** [One sentence — what this task produces]
**Files:**
- Create: `exact/path/to/file.py`
- Modify: `exact/path/to/existing.py:123-145`
- Test: `tests/exact/path/to/test.py`
**Acceptance Criteria:**
- [ ] [Concrete, testable criterion]
- [ ] [Another criterion]
**Verify:** `exact test command` → expected output
**Steps:**
- [ ] **Step 1: Write the failing test**
```python
def test_specific_behavior():
result = function(input)
assert result == expected
```
- [ ] **Step 2: Run test to verify it fails**
Run: `pytest tests/path/test.py::test_name -v`
Expected: FAIL with "function not defined"
- [ ] **Step 3: Write minimal implementation**
```python
def function(input):
return expected
```
- [ ] **Step 4: Run test to verify it passes**
Run: `pytest tests/path/test.py::test_name -v`
Expected: PASS
- [ ] **Step 5: Commit**
```bash
git add tests/path/test.py src/path/file.py
git commit -m "feat: add specific feature"
```
不得使用占位内容
每个步骤都必须包含工程师所需的实际内容。以下均属计划不合格——绝不要这样写:
- “待定”“TODO”“稍后实现”“补充细节”
- “添加适当的错误处理”/“添加验证”/“处理边界情况”
- “为上述内容编写测试”(未提供实际测试代码)
- “与任务 N 类似”(重复写出代码——工程师可能会打乱任务顺序阅读)
- 只描述要做什么,却不说明怎么做的步骤(涉及代码的步骤必须提供代码块)
- 引用任何未在任务中定义的类型、函数或方法
自我检查
写完完整计划后,以全新的视角审视规范,并对照检查计划。这是你自己执行的检查清单——不是派遣子 Agent。
**1. 规范覆盖情况:**浏览规范的每个章节/要求。能否指出某个任务负责实现它?列出所有缺漏。
**2. 占位内容扫描:**搜索计划中的危险信号——包括上述“不得使用占位内容”部分列出的任何模式。修复它们。
**3. 类型一致性:**后续任务中使用的类型、方法签名和属性名称,是否与前面任务中的定义一致?例如,任务 3 中名为 clearLayers() 的函数,在任务 7 中却写成 clearFullLayers(),这就是一个错误。
如果发现问题,请直接修复。无需再次检查——修复后继续。如果发现某项规范要求没有对应任务,就添加该任务。
阶段门控执行说明(仅适用于已标记用户门控任务且尚未注册钩子的情况)
如果计划中有任何任务标记为 userGate: true,请检查用户是否已选择启用(扫描 Claude Code 合并的三个用户可编辑设置文件——项目的 settings.local.json 和 settings.json,以及用户的 ~/.claude/settings.json;缺失的文件会被静默跳过):
cat .claude/settings.local.json .claude/settings.json ~/.claude/settings.json 2>/dev/null | grep -q "post-task-complete-revalidate.sh"
如果管道以 0 退出(任一文件中已注册规范的用户门控钩子)→ 完全不显示提示。用户已启用该功能。
否则,在执行交接前显示以下简短提示(替换 {N} 和任务编号):
提醒 — 我将 {N} 个任务标记为用户门控任务(任务 #X、#Y、……)。计划本身可以端到端运行。如果你希望在关闭时自动执行门控检查,JSON 片段位于
README.md中——请将它们粘贴到.claude/settings.json(或settings.local.json)中。我可以帮你完成;直接告诉我即可。
内部参考(不要显示):~/.claude/plugins/marketplaces/superpowers-extended-cc-marketplace/README.md 中的章节 #force-re-validation-on-user-thrown-gate-close + #re-validate-gates-on-plan-complete-claims。钩子:hooks/examples/{post-task-complete-revalidate,stop-revalidate-user-gates}.sh。设计文档:docs/user-gate-flow.md。
如果没有标记任何用户门控任务,则完全不显示。不要将此转化为 AskUserQuestion。
执行方式交接
停止。你即将完成计划。不要调用 EnterPlanMode 或 ExitPlanMode。你必须调用下方的 AskUserQuestion。两者都禁止使用——EnterPlanMode 会让会话陷入其中,ExitPlanMode 会跳过用户的执行方式选择。你接下来唯一允许的操作是使用以下精确结构调用 AskUserQuestion:
AskUserQuestion:
question: "Plan complete and saved to docs/superpowers/plans/<filename>.md. How would you like to execute it?"
header: "Execution"
options:
- label: "Subagent-Driven (this session)"
description: "Runs here: fresh subagent per task, spec and quality review after every task. That review loop is what the other option gives up. Good default."
- label: "Parallel Session (separate)"
description: "You open a second session that runs executing-plans WITHOUT the per-task review loop, while this one stays alive to answer its questions. Choose it when this session is nearly out of context, or when the plan has no frontier tasks and a cheaper model should do the work."
**推荐一个选项:**在更合适选项的标签后追加“(推荐)”(将其列在第一位),并在其描述前加上一行理由。默认推荐 Subagent-Driven——审查循环正是其核心。只有在会话即将耗尽时才推荐 Parallel Session;任务数量绝不能成为推荐理由。成本由你的人工伙伴决定,不由你决定:在描述中提及成本,绝不要将其作为推荐理由。如果当前是 Fable/Opus 会话且没有前沿任务,请在 Parallel 的描述中说明适合使用哪个更便宜的模型(例如 Sonnet);如果有前沿任务,请说明哪个任务需要更强的模型,以便伙伴拆分运行。绝不要改写基础标签。
如果你正准备调用 ExitPlanMode,请停下——改为调用 AskUserQuestion。
停止。用户已经选择了执行方式。你现在必须使用 Skill 工具调用相应的技能。不要自行实现任务——不要读取文件、进行编辑或更新任务状态。你唯一允许的操作是调用下方的技能。如果选择了 Subagent-Driven:
调用 Skill 工具:superpowers-extended-cc:subagent-driven-development
- 该技能会处理所有事项:子 Agent 调度、审查和任务跟踪
- 你留在当前会话中担任协调者
- 不要直接开始处理任务
如果选择了 Parallel Session: 将以下精确提示词提供给用户,让其粘贴到工作树中新打开的会话中,并填入占位符。将提示词放在一个围栏代码块中,代码块内只包含提示词——围栏用于告知人工伙伴复制内容的起止位置。模型建议和备注放在围栏之后,绝不要放在其中:
Invoke superpowers-extended-cc:executing-plans for <plan path>. The plan author session "<this session's title>" is still running. On any ambiguity or design question, find it with ListAgents and ask it via SendMessage before guessing.
仅仅提示“run executing-plans”会丢失咨询关联——除非提示词中提及其发起者,否则新会话无法知道其存在。如果当前是 Fable/Opus 会话且没有前沿任务,请添加一行:使用更便宜的模型(例如 Sonnet)开启该会话。保留当前会话,以便回答问题。
原生任务集成参考
使用 Claude Code 的原生任务工具(v2.1.16+),在计划文档旁创建结构化任务。
创建原生任务
为计划中的每项任务创建一个对应的原生任务。在描述末尾以 json:metadata 代码围栏嵌入元数据——这是确保 TaskGet 能保留元数据的唯一方法(TaskCreate 接受 metadata 参数,但 TaskGet 不会返回该参数)。
用户设置的关卡——机械检测与标记
你必须对创建的每项任务都执行此检查。整个用户关卡流程中,这一步只需几秒,也是成本最低的部分。
步骤 1——扫描关卡措辞。 对以下每一项,以不区分大小写、尽可能按完整单词匹配的方式,搜索用户需求和任务的 Goal/Acceptance Criteria:
| 类别 | 关键词/模式 |
|---|---|
| 动词 | verify、prove、validate、confirm、ensure、check、gate |
| 名词 | verification gate、acceptance test、smoke test、end-to-end、E2E |
| 范围 | first on one、then all、one before the rest、before proceeding、don't continue until |
| 证明 | prove it works、make sure、demonstrate、show that |
触发规则——仅当符合以下条件时,任务才算用户设置的关卡:
- 命中名词项(这些短语是明确无歧义的关卡名词),或
- 命中范围项(顺序承诺本身就是关卡),或
- 动词项与范围项或证明项同时命中。 仅匹配 动词还不够。日常工作简报经常会说“验证输出”或“检查导入是否正常”,但并未要求设置关卡。如果用户想要设置关卡,就会明确要求按顺序执行(“先做 X,再做 Y”“先在一个对象上做”)、指出具体产物(“冒烟测试”“验收测试”),或要求提供证明(“证明它能用”“展示结果”)。除了动词之外,以上条件中还必须满足一项。
如果没有匹配任何类别,或者只匹配动词 → 普通任务,无需添加标签。
第 2 步 — 为任务添加标签。 在任务的 json:metadata 代码围栏中:
- 设置
"userGate": true。 - 将
"user-gate"添加到tags数组中(如果数组不存在,则创建它)。 - 如果用户的简报具体说明了如何执行(指出了命令、实体、子 Agent 或可观察对象),就将其直接填入
verifyCommand和acceptanceCriteria——完成。 - 如果如何执行的说明很模糊,只有在验证语句中既没有可测试的名词(函数、命令、实体、端点、文件、日志模式),也没有具体值(预期结果、阈值、示例输入/输出)时,才设置
"requiresUserSpecification": true。只要有一个可据以着手的线索——例如“使用真实输入验证每项操作”——Agent 就足以自行确定做法。此标记仅适用于纯粹的形容词(“扎实”“能用”“良好”“正确”),因为面对这些要求,任何猜测都只能碰运气。
第 3 步 — 添加说明横幅(userGate: true 时必须添加)。在任务描述靠前的位置、紧接 目标: 之后,原样添加:
用户指定的关卡 — 不可跳过。 此任务由用户在当前对话中提出。绝不能通过绕过任务、宣称“已在代码中验证”,或改用成本更低的检查来关闭此任务。只有在独立重新验证
acceptanceCriteria中的每一项并捕获输出后,才能关闭任务。
- 用户明确指定的验证方式已确定,不是可选项。 如果用户将具体的线上目标(真实 MR/分支/工单/端点)指定为验证方式,就必须将其编码为必需项:将线上调用写入
verifyCommand,并确保每个requireEvidenceTokens维度(例如绿色/红色状态)只能通过捕获的线上运行输出得到证明。不得将干运行/纸面演练列为验收条件或替代关闭路径——计划必须固定执行方式,避免执行时降级处理。
声明了证据维度的任务 — 设置 requireEvidenceTokens。 当协调者实际观察到两个(或更多)带标签的状态后,任务才有意义地满足关闭条件时,应在元数据中声明这些维度。post-task-complete-revalidate hook 会拒绝关闭,除非关闭窗口中每个维度至少出现一个标记。示例:
- 实证重构 / A/B 对比: 明确声明(
"requireEvidenceTokens": [["baseline","old","iter-0"], ["refactored","new","iter-1"]]),或使用快捷方式("requireABCompare": true)。 - v2→v3 迁移验证:
"requireEvidenceTokens": [["v2","legacy"], ["v3","migrated"]]。 - 性能前后对比:
[["slow","unoptimized","p50=X"], ["fast","optimized","p50=Y"]]— 包含你期望协调者发布的字面指标标签。 - 多组实验:
[["control"], ["variant-a"], ["variant-b"]]— 维度数量不限。 - 安全修复前后对比:
[["vulnerable","CVE-","before-patch"], ["patched","after-patch","hardened"]]。
如果不声明维度,“看起来不错,继续吧”这样的关闭方式是允许的;声明维度后,协调者必须提供每一方的证据。尽可能配合能实际运行两方的具体 verifyCommand(例如 diff <(old-cmd) <(new-cmd))。
横幅 ↔ 元数据不变量 — 两处必须一致。 横幅必须与 json:metadata 代码围栏位于同一个 TaskCreate description 字符串中,不能只出现在计划 .md 文件里。如果你既要编写计划文档,又要创建原生任务,同一任务的横幅必须同时出现在两处,或者两处都不出现。继续之前先自行检查:对于每项任务,计划文档部分和 TaskCreate 描述必须同时包含 userGate: true、横幅和代码围栏,或者都不包含这些内容。
Step 4 — 检查验收标准的可操作性。 每条标准都必须明确一个可观察的指标。含糊的表述(“集成可用”“通过了”)不可接受——改写为“传感器 X 报告空闲”“从 /health 收到 HTTP 200”“存在 setup.done 文件”等。如果无法让标准具备可操作性,则设置 requiresUserSpecification: true,让 /specify-gate 收集真实答案。
Step 5 — 逐任务隔离自检。 对每个设置了 userGate: true 且未设置 requiresUserSpecification: true 的任务,只重新阅读该任务的 Goal 句子,并将其单独看待——假设其他任务都不存在。仅凭这句话,是否明确指出了一个可观察指标、一种捕获方法,以及一个通过/失败值?只要有一项不明确,就设置 requiresUserSpecification: true,即使你已经根据上下文填写了 verifyCommand 也一样。从同级任务借用具体信息,正是这项检查要捕捉的问题。例如,一个计划中的逐操作任务写着“验证 add(3,2)==5”(具体明确),而最终任务写着“确保整体运行正常”(含糊)——逐操作任务起到了参照作用;最终任务未通过这项检查,必须设置 requiresUserSpecification: true。
只要存在真实的门控信号,就积极添加标签。 三种门控类型(严格用户门控/严格 Agent 门控/介于两者之间的灰色地带)都使用相同的标签——如果符合上述触发规则,就宁可添加标签。但不要把普通动词解读为门控:“validate”“check”“verify”单独出现时,描述的是常规工作,而不是用户设置的门控。对真实信号过度添加标签无害(只是多一些元数据)。仅因普通动词就过度添加标签,会导致提示横幅泛滥,让每个任务看起来都很繁琐,从而淹没真正的门控。
编写计划时不要向用户提问。 推荐的默认做法是“添加标签并继续”。想回答问题的用户会说“brainstorm”。如果用户的简述没有明确说明门控的操作方式,则 requiresUserSpecification: true 标志会将问题转到执行阶段,由 /specify-gate 通过 3-5 个简短的多选问题处理。
完整的元数据架构(包含全部六个与门控相关的键:userGate、tags、requiresUserSpecification、gateScope、failurePolicy、subagentBrief),请参阅 skills/shared/task-format-reference.md → “User-Thrown Gates”;端到端流程请参阅 docs/user-gate-flow.md。
TaskCreate 描述 — 完整的结构化正文,而非摘要
硬性规则。 每个 TaskCreate description MUST 原样包含你写入该任务计划 .md 的 Goal / Files / Acceptance Criteria / Verify 部分。不要压缩成一句话摘要。不要把 AC 改成“见计划文档”。不要省略 **Verify:**。描述 MUST 以 json:metadata 代码围栏结尾。
原因。 两条执行路径(executing-plans 和 subagent-driven-development)都会通过 TaskGet 读取任务描述,并将其传递给负责实现的子 Agent。一句话描述会让子 Agent 自行编造 AC。计划 .md 不是备用方案——TaskGet 不会读取它。
结束技能前的自检。 这是机械计数,不是阅读并确认——文字审阅可以敷衍了事,计数则不行。对于四个部分标题(**Goal:**、**Files:**、**Acceptance Criteria:**、**Verify:**),在 <plan>.tasks.json 上运行 grep -c:
grep -c '\*\*Goal:\*\*' <plan>.tasks.json
grep -c '\*\*Files:\*\*' <plan>.tasks.json
grep -c '\*\*Acceptance Criteria:\*\*' <plan>.tasks.json
grep -c '\*\*Verify:\*\*' <plan>.tasks.json
每个计数 MUST 等于任务数量。如果任何计数较低 → 有任务缺少该部分;在 Execution Handoff 之前,使用完整内容块对该任务执行 TaskUpdate。还要确认每个任务都包含 json:metadata 围栏。只有在任务文件缺失时,才逐个使用 TaskGet 检查。
精简主题行。 执行框架会在定期提醒时将每个任务的主题行重新注入上下文,因此主题行会反复占用上下文——尽量控制在 ≤ 60 个字符,详细信息放在描述中。
TaskCreate:
subject: "Task N: [Component Name]"
description: |
**Goal:** [From task's Goal line]
**Files:**
[From task's Files section]
**Acceptance Criteria:**
[From task's Acceptance Criteria]
**Verify:** [From task's Verify line]
```json:metadata
{"files": ["path/to/file1.py"], "verifyCommand": "pytest tests/path/ -v", "acceptanceCriteria": ["criterion 1", "criterion 2"], "modelTier": "mechanical"}
```
activeForm: "Implementing [Component Name]"
为什么要嵌入元数据
TaskCreate 上的 metadata 参数会被接受,但不会由 TaskGet 返回。将其作为 json:metadata 代码围栏嵌入描述中,可确保:
- TaskGet 返回完整的元数据(它是描述的一部分)
- 跨会话恢复时,可以从 .tasks.json 中解析元数据
- 分派子 Agent 时,可以提取元数据并用于实现者提示词
完整的元数据架构请参阅 skills/shared/task-format-reference.md。
设置依赖关系
创建所有任务后,设置 blockedBy 关系:
TaskUpdate:
taskId: [task-id]
addBlockedBy: [prerequisite-task-ids]
执行期间
随着工作进展更新任务状态:
TaskUpdate:
taskId: [task-id]
status: in_progress # when starting
TaskUpdate:
taskId: [task-id]
status: completed # when done
任务持久化
计划完成后,将任务持久化文件写入与计划文档相同的目录。
如果计划保存到 docs/superpowers/plans/2026-01-15-feature.md,则任务文件必须保存为 docs/superpowers/plans/2026-01-15-feature.md.tasks.json。
{
"planPath": "docs/superpowers/plans/2026-01-15-feature.md",
"tasks": [
{
"id": 0,
"subject": "Task 0: ...",
"status": "pending",
"description": "**Goal:** ...\n\n**Files:**\n...\n\n```json:metadata\n{\"files\": [\"path/to/file.py\"], \"verifyCommand\": \"pytest tests/ -v\", \"acceptanceCriteria\": [\"criterion 1\"], \"modelTier\": \"mechanical\"}\n```"
},
{
"id": 1,
"subject": "Task 1: ...",
"status": "pending",
"blockedBy": [0],
"description": "**Goal:** ...\n\n```json:metadata\n{\"files\": [], \"verifyCommand\": \"\", \"acceptanceCriteria\": [], \"modelTier\": \"standard\"}\n```"
}
],
"lastUpdated": "<timestamp>"
}
计划 .md 和 .tasks.json 都必须放在 docs/superpowers/plans/ 中。
恢复工作
任何新会话都可以通过运行以下命令恢复工作:
/superpowers-extended-cc:executing-plans <plan-path>
该技能会读取 .tasks.json 文件,并从上次中断处继续。