Communitygithub.com

morzecrew/agent-skills

技能集合

agent-skills 是什么?

此技能专门用于在代码仓库中编写和维护轻量级 RFC(请求评论)设计文档。RFC 是编号的 Markdown 设计提案,与代码共存,旨在记录设计决策及其背后的原因。主要目的是防止设计背景丢失,使设计工作流变得高效(仅需一个“小型 PR”),并避免对已否决的替代方案进行无意义的反复讨论。该技能提供了一套完整的工作流程,包括创建新 RFC、更新现有 RFC、维护索引(INDEX.md)、初始化 RFC 目录以及通过自动化脚本管理编号和状态。它支持 Draft、In progress、Complete 和 Rejected/withdrawn 等多种状态,并强调基于代码的严谨写作风格。该技能适用于支持 Skill Markdown 的 AI 代理平台(如 Claude Code、Cursor、Codex 等),帮助开发者结构化地记录技术设计。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add morzecrew/agent-skills

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

RFC 编写与维护

本技能负责编写和维护轻量级 RFC——编号的 Markdown 设计提案,与它们描述的代码一同存放在仓库中。RFC 在构建之前(或期间)捕获设计:包括问题、代码当前状态、已锁定的决策及其理由,以及明确不作为范围的内容。所有 RFC 通过单个 INDEX.md 文件进行跟踪,使整个设计历史可在一个表格中快速浏览。

此处的 RFC 是工作文档,而非官僚流程:它们确保决策不会因上下文丢失而消失,使重新拾起的设计仅需“一个小型 PR”即可完成,并防止被否决的替代方案被反复质疑。

何时使用此技能

  • 用户要求编写 RFC、设计文档、设计提案、技术规范或架构提案
  • 用户希望在实现之前记录或锁定设计决策——包括它击败的替代方案,或某个方法被否决的原因
  • 用户要求更新 RFC(状态变更、执行注释、标记为已发布或已否决)
  • 用户要求创建、索引或重新组织 rfcs/(或 rfc/)目录
  • 一个大型功能讨论需要被固化为一篇持久的文档

何时不要使用此技能

  • 用户想要产品文档、README 或面向用户的文档(非设计提案)
  • 用户希望在一个已有成熟 ADR 约定的仓库中创建 ADR——请遵循已有约定
  • 变更过于微不足道,通过提交消息或 PR 描述即可承载

目录和索引

存放位置。 RFC 存放在仓库根目录下的单一扁平目录中:rfcs/(首选默认)或 rfc/。创建任何内容之前,请先查找是否存在具有这两个名称之一的目录,并遵循其约定。如果两者都不存在,则创建 rfcs/。

Gitignore 由用户决定,而非你。 某些项目会提交 RFC;其他项目则将其作为本地工作笔记而添加到 gitignore 中。除非明确要求,否则切勿为 RFC 目录添加或删除 .gitignore 条目。如果该目录被 gitignore,则 INDEX.md 头部应说明此情况(参见模板),以便读者知晓其为何不在仓库历史中。

INDEX.md 是整个集合的事实来源。 它承载了三个内容:

  1. 下一个可用编号,需显式声明——编号在并行创建时会发生冲突,因此索引会指明下一个编号,每次创建 RFC 时都会在同一个变更中更新它。
  2. 索引表格:| # | 标题 | 状态 | 一句话描述 |,每行对应一个 RFC,编号链接到对应文件。
  3. 状态图例。

如果目录存在但有一个 README.md 充当索引角色,请将其视为索引。如果要求全新设置,则使用 INDEX.md——复制 references/index-template.md。

编号和文件名

  • 编号为 4 位数字,零填充,单调递增:0001、0002……
  • 分配方法:从 INDEX.md 中读取“下一个可用编号”,与目录的 ls 输出进行交叉检查(索引可能已过时),然后取下一个未使用的整数。
  • 文件名:NNNN-kebab-case-title.md。确保文件名中的编号与 H1 标题 # RFC NNNN — 标题 保持一致——否则两者会漂移,链接也会双向失效。
  • 切勿对已有 RFC 重新编号。编号是标识符,而非需要整理的排序。

状态

  • 📝 草稿 (Draft) — 已提案,但尚未开始(“设计已锁定、需求待确认”的 RFC 仍为 Draft)
  • 🚧 进行中 (In progress) — 已部分发布
  • ✅ 完成 (Complete) — 已完全发布
  • ❌ 已否决 / 已撤回 (Rejected / withdrawn) — 保留文件;记录否决可防止反复质疑

状态存在于两个必须一致的位置:RFC 头部的 **状态:** 行以及索引表格的状态列。两者必须在同一个变更中更新。

RFC 结构

在编写新的 RFC 之前,请阅读 references/rfc-template.md 并以其为起点。其结构如下:

头部块(H1 标题下方的项目符号列表,位于任何节之前):

  • **状态:** — 表情符号 + 文字,可选附注(“可执行——一个 PR”、“设计已锁定,未安排”)
  • **范围:** — 一个紧凑的段落:描述此 RFC 涵盖的内容以及明确不涵盖的内容。这是读者决定是否继续阅读的段落。
  • **相关:** — 指向被涉及代码的链接(仓库内的相对路径)、其他 RFC、先例、外部参考
  • **讨论:**(可选)— 设计正在进行或已进行辩论的链接(PR、问题、讨论串);持不同意见的读者可前往此处,而非分支该文档
  • **来源:**(可选)— 设计从何处移植或概括而来(如有)

编号节。 对于一份完整的 RFC,包含以下部分:

  1. 摘要 — 几句话说明即将发布的内容
  2. 动机 — 问题及来自实际代码库的证据
  3. 当前状态 — 当前存在的状况,需与代码核实,而非凭记忆
  4. 目标 / 非目标 — 明确两方面
  5. 设计 — 核心;按工作流程或组件划分子节,包含实际的签名/模式/代码块(用于固定设计)。如果某个选择存在争议,保留被否决的替代方案及其原因——对于小问题,一句话即可;当该选择塑造了设计时,使用 ### 考虑的替代方案 子节
  6. 测试 — 设计如何被验证
  7. 文档 — 随设计一同交付的文档
  8. 不在范围内 — 明确列出每个排除项并给出理由:说明为何排除以及什么情况会改变这一决定
  9. 风险 — 诚实的失败模式,包括文档被误读的风险
  10. 未解决的问题 — 必须在设计被视为锁定前解决的内容,与实现可以自由决定的内容之间的区别;明确未知事项比在构建过程中静默解决更好
  11. 决策 — 一个编号的决策表格;这是使拾取设计变得便宜且无需重新争论的关键。如果某个决策以非显而易见的方式限制了未来,表格行中应说明——一个决策的后果是下一个决策的上下文
  12. 分阶段实施 — 哪些内容先落地,哪些内容依赖于其他内容

按 RFC 的重要性调整规模。 一个用于锁定简单设计的 RFC 只需头部块、设计、非目标和决策表格。不要将只有两页的 RFC 扩充到十二个节;也不要将一个系统范围的提案缩减到三个。无论使用哪个子集,请保持节编号的连续性。

写作风格

  • 每个主张都要基于代码。 “当前状态”和“动机”需要引用文件、行级事实和可测量的数字——使用相对路径链接它们。凭记忆论证的 RFC 是带有标题的虚构作品。
  • 记录决策及其原因和代价。 决策表格是契约;正文承载推理过程。被否决的替代方案应有一句话说明为何被否决(记录其权衡的替代方案不会被再次提出;仅记录为“被否决”的替代方案则会)。如果某个决策在将来封闭了可能性,应在表格行中说明。
  • 及时优于精炼。 一个存在但粗糙的 RFC 胜过不存在但完美的 RFC(Oxide 的 RFD 规则:“及时而非精炼”)。草案的语言可能粗糙,但范围段落和决策表格则不应如此。
  • 诚实面对限制。 如果一个机制被推迟、被门控或已知不完整,应在 RFC 中说明,而不是让读者自己发现。失败封闭的措辞(“拒绝”、“引发”、“故意不安排”)优于乐观的模糊表述。
  • 精炼优于冗长。 优先使用一个承载关键信息的段落,而不是三个单薄的段落。索引中的一句话描述尤其如此:它必须足够自包含,以便读者可以跳过整个 RFC。

工作流程

簿记工作——编号分配、从模板创建文件、更新索引行和下一个可用编号、漂移检测——是机械性的,scripts/rfc_index.py 脚本可以无冲突地完成这些工作,避免了手动分配的问题:

python3 scripts/rfc_index.py check          # 索引与文件对比、H1与文件名对比、状态一致性、下一个可用编号
python3 scripts/rfc_index.py next           # 下一个可用编号
python3 scripts/rfc_index.py new "标题"    # 分配编号 + 初始化模板 + 索引行 + 编号递增
python3 scripts/rfc_index.py new "标题" --number 42   # 分配保留编号,或重建已删除的 RFC

(路径相对于此技能的目录;从仓库根目录执行时,脚本位于 skills/rfc-writer/scripts/rfc_index.py。除 new 外均为只读操作;如果仓库不是当前工作目录,请添加 --root 目录 参数——位于子命令之前或之后均可。) 思考部分——设计内容、一句话描述的主张、状态变更时机——则由你负责。

A — 创建新的 RFC

  1. 找到 RFC 目录(rfcs/ 或 rfc/);如果不存在,请先执行工作流程 D。
  2. 分配下一个编号并初始化文件:rfc_index.py new "标题"——它会生成编号、写入模板、添加索引行并更新下一个可用编号声明。步骤 3 和 4 仍由你负责:它留下的模板是未填充的,并在索引中写入字面上的 TODO: 一句话摘要。手动操作:从索引读取下一个可用编号,并与 ls 交叉检查——编号在并行创建时会发生冲突。
  3. 按照 references/rfc-template.md 的结构填充文件,并根据设计的重要性调整规模。在编写“当前状态”之前,请调查实际代码——这是大部分工作量所在。
  4. 将索引中的占位符一句话描述替换为紧凑、自包含的摘要。

B — 更新已有的 RFC

  1. 当工作部分或全部完成时,更新 **状态:** 行——并附注说明已发布的内容和日期(例如,“Shipped 2026-06-29:…;仅剩 P5”)。
  2. 如果执行过程偏离了设计,请在 RFC 中记录偏差(状态注释或相关节中的修正)——不要静默地重写历史;决策日志应保持仅追加。
  3. 在索引表格中镜像状态(如果结构发生变化,则镜像一句话描述)。
  4. 被否决的设计保留 ❌ 并留在目录中。

C — 维护索引

运行 rfc_index.py check——它会报告每一条缺失索引行的文件(反之亦然)、H1 与文件名不匹配、头部与表格状态不一致、重复编号以及非空闲的下一个可用编号。修复其指出的问题(修复需要判断:哪个状态是正确的,一句话描述应该如何书写),然后重新运行直到全部通过。报告不同步的内容。

D — 初始化 RFC 目录

  1. 创建 rfcs/(除非用户想要 rfc/ 或其中一个已存在)。
  2. 从 references/index-template.md 创建 INDEX.md,填写项目名称并将下一个可用编号设置为 0001。
  3. 不要修改 .gitignore——说明提交还是忽略该目录由用户决定。

参考资料

  • references/rfc-template.md — RFC 骨架及每节指导;在编写任何新 RFC 之前阅读
  • references/index-template.md — INDEX.md 骨架;初始化目录时使用

相关技能

  • altitude-docs — 设计发布后需要编写的面向用户的文档;RFC 的“文档”节指向它
  • self-audit — 在合并前对执行了 RFC 的分支进行对抗性审查
  • keep-a-changelog — 记录已发布的内容;RFC 记录为何以此方式构建

相关技能