关于 plan
plan 将已批准的规格转成详细、可执行的计划,供不熟悉代码库的工程师或 Agent 使用。它把需求映射到任务、准确文件、接口、代码步骤和验证命令,并记录计划、分派任务。
主要功能
- 01将规格需求映射到任务
- 02列出准确的文件和接口
- 03包含代码与测试步骤
- 04检查遗漏或相互冲突的需求
- 05在 wiki 中记录计划
- 06携带原始上下文分派任务
适用场景
- 01依据已批准规格规划多文件实现
- 02将工作拆分给多个 Agent
- 03规划大范围机械式重构
- 04在实现前发现规格矛盾
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ rheinmir/ setup --skill plan安装后在 Claude Code 中输入/plan确认已加载。
详细介绍
技能:plan
内容
目的与上下文
- 目的: 将已批准的 SPEC 转化为一份文档,让一位能力出色、但对这个代码库一无所知,而且品味还很可疑的工程师也能正确执行。在 overstack 中,这位“工程师”通常是一个廉价的无头 CLI(
opencode/agy/kiro):它不会继承主会话的任何上下文,无法追问,遇到模糊之处时会自行猜测,然后保持沉默。250626 的实测教训:简略的 brief → 交付量约为 1/5。 - 触发条件(何时使用):
- SPEC(
/propose)已在关卡中获得用户批准,即将向 Agent 分派任务。 - 工作涉及多个步骤、多个文件,或分配给 ≥2 个 Agent 并行执行。
- SPEC(
- 非目标: 尚未获得批准的 SPEC 时,不要使用(先使用
/propose);修改一行代码时也不要使用。不要用它来设计或询问需求(那是/propose的职责)。
心智模型
PLAN 中没有的内容,Agent 就无从得知。这就是此技能的全部原则。
已批准的 SPEC(FR-xxx、Global constraints)→ 范围检查 → 文件结构 → 任务 tracer bullet(或 expand → migrate → contract)→ 每项任务:目标 + 文件 + 接口 + 依赖 + 验证 + TDD 步骤 → 自我审查 → DDMMYY-<名称>-PLAN.md → orca 编排 task-create/dispatch --inject 原文内容
输入与输出约定
| 字段 | 必填? | 含义 | |
|---|---|---|---|
| 输入 | 已批准的 SPEC llmwiki/wiki/sources/draft/DDMMYY-<名称>.md | 是 | 原样取用 ## Context、## Global constraints、## Plan、## Agent Task Assignment |
| 输出 | llmwiki/wiki/sources/draft/DDMMYY-<名称>-PLAN.md | 是 | 严格遵循 PLAN 格式:frontmatter + ## Origin + 原文 Global constraints + 文件结构 + 若干 ### Task N |
| 输出 | wiki/index.md 中的一行 + 追加到 wiki/log.md | 是 | 按步骤 7 执行 |
| 输出 | SPEC 存在的问题报告 | 触发反向关卡时 | 一次性汇总,每个问题都附上导致该问题的 SPEC 原句 |
规则与能力
- RULE-01(必须):PLAN 不需要
.html文件——它是供机器读取的内容。HTML 与 SPEC 绑定(供审批时查看),由/propose生成。R7 对-PLAN.md分支免除图示检查。 - RULE-02(必须):文件路径必须始终准确;修改现有文件时,附上行号范围。
- RULE-03(必须):代码变更步骤必须提供完整代码——不能只做描述。
- RULE-04(必须):命令必须准确无误,并附上预期输出(Agent 需要知道什么算正确失败、什么算通过)。
- RULE-05(必须):遵循 DRY、YAGNI、TDD,并经常提交。
- RULE-06(必须):对于已有代码库,遵循现有模式。不要顺带重构任务之外的内容。
- 能力:读取 SPEC 和代码库,以确定真实的文件路径和签名;在 wiki 中写入 PLAN、index 和 log;完成自我审查前不得分派任务。
失败边界
- 尚无已批准的 SPEC → 已取消,转到
/propose。 - 反向关卡(需求无法归入任务、存在矛盾、方案不可行、需要虚构函数/类型/文件)→ 已阻塞:停止,不要编写半成品 PLAN;一次性汇总所有问题并报告,返回
/propose重新审批。 - 仍有占位符,或没有任务承接
FR-xxx→ 失败(R7/R18 阻止),就地修正。 - 修改一行代码 → 不使用此技能。
操作
Main workflow
| Step | Type | Inputs | Action | Outputs/exit | Failure/next |
|---|---|---|---|---|---|
| W01 | deterministic | SPEC | 阅读已批准的 SPEC,原样提取各部分 | SPEC 内容 | 没有已批准的 SPEC → 停止,/propose |
| W02 | judgment | SPEC | 范围检查 | 一个或多个 PLAN | 存在多个独立子系统 → 拆分 |
| W03 | judgment | SPEC + codebase | 在拆分任务前绘制 ## File structure | 文件列表 + 职责 | 文件/API 不存在 → B01 |
| W04 | judgment | File structure | 将任务拆分为 tracer bullet(或 wide refactor) | 任务列表 | WIDE REFACTOR → B02 |
| W05 | judgment | task | 按模板编写每个任务(完整包含 Files + Interfaces + Steps) | 各个 ### Task N | 必须虚构函数/类型 → B01 |
| W06 | judgment | PLAN 草稿 | 用 3 道关卡进行自我审查,并就地修改 | 完善的 PLAN | — |
| W07 | effect | PLAN | 写入文件 + 索引 + 日志 | DDMMYY-<tên>-PLAN.md | R7/R18 阻止 → 修改后重新写入 |
| W08 | effect | PLAN | 交接:task-create + dispatch --inject 原样注入,并附上 Global constraints | 已派发的 task | — |
各步骤的详细说明(W01–W08 的事实来源):
-
阅读已批准的 SPEC —
llmwiki/wiki/sources/draft/DDMMYY-<tên>.md。原样提取:## Context、## Global constraints、## Plan(- [ ]行)和## Agent Task Assignment。 -
范围检查 — 如果 SPEC 涵盖多个独立子系统,则拆分为多个 PLAN;每个 PLAN 都应能独立产出可运行、可测试的软件。不要塞得过多。
-
在拆分任务前绘制
## File structure— 列出所有将要创建/修改的文件及各自职责(一个文件承担一项职责;一起变更的文件放在同一处)。在这里确定分解方式,而不是等到编码时再决定。 -
将任务拆分为 TRACER BULLET — 每个任务都是一个纵向切片:贯穿所有层(数据 → 逻辑 → 界面/CLI)的薄片,本身可以运行并验证自身,并留下可独立测试的交付成果。不要采用“先完成整个数据层”再由下一项任务“完成整个逻辑层”这种“横向切片”——横向切片没有哪一项能单独运行。Setup、配置、脚手架和文档应合并到需要它们的任务中;只有当一个审查者可以驳回这项任务,同时仍批准另一项任务时,才将其拆分。
具名例外 — WIDE REFACTOR(expand → migrate → contract)。 当一项机械性变更的影响范围遍及整个代码库——例如重命名一列,或更改一个共享 symbol 的类型——就无法让任何纵向切片通过:一处修改会同时导致数千个调用点出错。不要强行套用 tracer bullet 模板。执行顺序:
- expand — 在旧形式旁边添加新形式,不删除任何内容。一个 task。旧形式仍然存在,因此不会破坏现有内容。
- migrate 分批迁移 — 将调用点迁移到新形式,并按影响范围分批(每个 package、每个 directory)。每批一个 task,依赖于 expand task。旧形式仍然可用,因此 CI 可以逐批通过。
- contract — 不再有任何调用方使用旧形式时,将其删除。一个 task,依赖于所有迁移批次。
- 如果连单个批次也无法独立通过,则将它们放在同一个集成分支上,并让所有批次都依赖于最后的“integrate-and-verify” task——只有到这一步才能承诺通过。
-
按下方模板编写每个 task(Files + Interfaces + Steps 缺一不可)。
-
自我审查(使用下方“Self-review”部分中的 3 道关卡),并就地修改。
-
将文件写入
llmwiki/wiki/sources/draft/DDMMYY-<tên>-PLAN.md,在llmwiki/wiki/index.md中添加一行,并向llmwiki/wiki/log.md追加内容。 -
交接:每个
### Task N对应一个orca orchestration task-create;dispatch --inject将该 task 的 brief 连同## Global constraints一起原样注入。不要重新概括——概括会导致上下文丢失。
分支
| ID | 类型 | 守卫条件 | 行为 | 跳过 / 失败 | 重汇合 |
|---|---|---|---|---|---|
| B01 | recovery | 逆向关卡:发生逆向关卡部分中的某个停止条件 | 停止,将所有问题汇总为一次报告,返回 /propose 修改 SPEC + 重新审核 | — | W01(SPEC 重新审核通过后) |
| B02 | conditional_required | 机械性变更影响整个代码库 | 大规模重构:task expand → migrate 批次(受 expand 阻塞)→ contract(受所有批次阻塞);批次无法自行通过 → 集成分支 + integrate-and-verify task | — | W05 |
| B03 | conditional_required | SPEC 涉及多个相互独立的子系统 | 拆分为多个 PLAN,每个 PLAN 都可独立运行 + 测试 | — | 每个 PLAN 对应 W03 |
验证与停止
确定性检查:R7 阻止占位符(写入时 + 提交时),R18 阻止没有 task 认领的 FR-xxx,R9/R2 阻止缺少 frontmatter/## Origin;每个 task 的 **Verify:** 行都是返回码为 0 的命令。需要审核:Self-review 三项检查(SPEC 覆盖、占位符、类型/名称一致性)。在 W08 后停止,或在 B01 处立即停止。
示例
- 正例: 已审核的 SPEC
DDMMYY-export-csv.md包含 FR-001..FR-003 → PLAN 包含 3 个 tracer bullet task,每个 task 都有**Thoả:**、**Files:**精确路径、**Interfaces:**Consumes/Produces、Verify 行为pytest tests/test_export.py -q、Step 1–5 TDD → 写入DDMMYY-export-csv-PLAN.md+ 索引 + 日志 → 连同 Global constraints 原样分发每个 task。 - 边界/失败: 在声明 File structure 时发现
## Approaches选择的 API 不存在,且 FR-002 与 Global constraints 冲突 → 停止,不写半成品 PLAN,一次性报告这两处问题及导致问题的 SPEC 原句,返回/propose重新审核。
参考 — PLAN 模板
必需的标头(不得省略 frontmatter 和 ## Origin — 文件位于 wiki/sources/draft/,因此缺少 frontmatter 会被 R9 阻止,缺少 ## Origin 会被 R2 阻止):
---
type: draft
title: <tên>-PLAN
status: proposed
timestamp: YYYY-MM-DD
task: T-YYMMDD-NN # cùng task-id với SPEC
---
# <Tên> — PLAN thi hành
**Goal:** <một câu: cái này xây ra cái gì>
**Architecture:** <2-3 câu: cách tiếp cận>
**Tech stack:** <ngôn ngữ, lib, test runner, version>
**SPEC nguồn:** `wiki/sources/draft/DDMMYY-<tên>.md` (đã duyệt <ngày>)
## Origin
- **SPEC:** `wiki/sources/draft/DDMMYY-<tên>.md`
- **Commit:** _(verify-before-commit điền)_
## Global constraints
<chép NGUYÊN VĂN từ SPEC — sàn version, giới hạn dependency, luật đặt tên, gate trước push.
Mỗi task ngầm mang theo section này.>
## File structure
- Tạo `path/chính/xác.py` — <trách nhiệm duy nhất của file>
- Sửa `path/có/sẵn.py` — <đổi gì>
每个 task:
### Task N: <tên>
**Thoả:** FR-001, FR-003
**Files:**
- Tạo: `đường/dẫn/chính/xác.py`
- Sửa: `đường/dẫn/có/sẵn.py:123-145`
- Test: `tests/đường/dẫn/test_x.py`
**Interfaces:**
- Consumes: <dùng gì từ task trước — chữ ký chính xác>
- Produces: <task sau dựa vào cái gì — tên hàm, kiểu tham số, kiểu trả về>
**Depends:** Task 1, Task 3
**Verify:** `pytest tests/x.py -q`
- [ ] **Step 1: viết test fail**
```python
def test_hanh_vi_cu_the():
assert ham(dau_vao) == ket_qua_mong_doi
```
- [ ] **Step 2: chạy cho THẤY nó fail**
Chạy: `pytest tests/đường/dẫn/test_x.py::test_hanh_vi_cu_the -v`
Mong đợi: FAIL — `NameError: name 'ham' is not defined`
- [ ] **Step 3: code tối thiểu cho pass**
```python
def ham(dau_vao):
return ket_qua_mong_doi
```
- [ ] **Step 4: chạy lại — PASS**
Chạy: `pytest tests/đường/dẫn/test_x.py::test_hanh_vi_cu_the -v`
Mong đợi: PASS
- [ ] **Step 5: commit**
```bash
git add tests/đường/dẫn/test_x.py src/đường/dẫn/x.py
git commit -m "feat: <việc cụ thể>"
```
为什么 **Thoả:** 是必需的: SPEC 会为每项需求分配稳定 ID,如 FR-001、FR-002……每个 task 都声明自己负责哪些 ID → Self-review 中“覆盖整个 SPEC”不再只是凭肉眼检查,而是变成了可通过 grep 检索的数据,并且 R18 会阻止任何没有 task 认领的 FR-xxx(准确列出被遗漏的 ID)。一项需求在两个 task 之间悄然丢失,是所有计划中最隐蔽的错误 — 只有在 Agent 交付不完整时才会暴露,或者更糟,在用户使用时才会暴露。
为什么有 ≥2 个 Agent 时 Interfaces 是必需的: 执行 Agent 只能看到自己的 task。如果不声明签名,两个并行 Agent 就会给函数起不同的名称,导致集成失败 — 这是一个必然会发生的错误,而不是风险。
参考 — 禁止使用占位符 — 这是有缺陷的计划,不是尚未完成的计划
R7 会在写入时和提交时阻止。绝不要写:
TBD、TODO、“稍后填写”、“细节之后补充”- “妥善处理错误”/“添加验证”/“处理边界情况” — 说明要做什么,不要说“妥善处理”
- “为上述内容编写测试”,但没有实际测试代码
- “与 Task N 类似” — 直接复制代码。Agent 可能会按任意顺序读取 task,而且每个 Agent 只能获取自己的 task。
- 描述必须做什么却没有说明如何做的步骤(修改代码的步骤必须包含代码)
- 提及任何未在某个 task 中定义的函数/类型/方法
参考 — Self-review
完成后,用全新的视角检查 — 直接修正,不需要第二轮:
- 覆盖 SPEC — 逐项浏览 SPEC 中的需求,指出由哪个 task 实现。若有遗漏 → 添加 task。
- 扫描占位符 — 搜索上文所列的确切模式。
- 类型/名称一致性 — 后续 task 使用的函数名、签名、字段名是否与前序 task 中定义的一致?Task 3 中的
clearLayers()和 Task 7 中的clearFullLayers()就是一个 bug。
参考 — 反向关卡 — /plan 有权驳回 SPEC
编写 PLAN 正是发现 SPEC 有误的方式:到了必须交代真实文件路径和真实函数签名时,不可行的设计才会暴露。如果审核关卡已经放行,现在才发现问题,就意味着用户批准了一个无法构建的方案——关卡已经失效。
停止,不要继续编写不完整的 PLAN,遇到以下任何情况时:
- SPEC 中的某项要求无法对应到任何可执行的任务。
- SPEC 中的两个条目相互矛盾,或与
## Global constraints相矛盾。 ## Approaches中已选的方案原来不可行(文件不存在、API 不存在、约束阻止实现)。- 必须捏造 SPEC 从未提及的函数/类型/文件,才能让计划“纸面上可行”。
处理方式:将所有问题汇总成一次报告(不要每发现一处就打断用户一次),每处都附上导致问题的 SPEC 原句,然后返回 /propose 修改 SPEC 并重新审核。基于有问题的 SPEC 编写 PLAN,比没有 PLAN 更糟:它会把错误注入 Agent,还摆出一副自信的样子,而廉价 Agent 会原样照办。