mcpField
S
specification-writing

specification-writing

github.com/epicenterhq开发4.8k85 次安装2 周前更新
代码仓库

关于 specification-writing

用于编写实现规格的写作技能,为 Agent 和维护者提供自主启动工作的必要背景。它强调明确现状与目标、基于证据的调研、开放问题、决策记录,以及将长期决策保存在规格之外。

主要功能

  1. 01以背景为核心的规格编写指引
  2. 02一句话主题与维护者时间要求
  3. 03基于证据的调研和决策规范
  4. 04架构与 API 变更文档
  5. 05实现计划与规格生命周期

适用场景

  1. 01编写供自主实现的功能规格
  2. 02记录调研结果和未决设计问题
  3. 03规划架构或 API 变更
  4. 04工作完成后归档规格

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/epicenterhq/epicenter --skill specification-writing

安装后在 Claude Code 中输入/specification-writing确认已加载。

附带文件references/decision-hygiene.md

详细介绍

规范编写

文案部分请遵循 writing-voice。解释归属关系或流程时,先给出有用的模型,再结合相关边界说明,只保留实现所需的图示和文案。

规范为 Agent 或维护者提供自主实现功能所需的上下文。目标不是详尽描述一切,而是提供足够的依据,证明方向可信,并为实现者提供明确的起点。

规范是进行中的脚手架,不是持久记录。 它用于规划工作,并在工作进行期间记录研究内容。规范不具权威性,工作完成后也不应继续保留。持久决策记录在 docs/adr/,共享词汇记录在 docs/CONTEXT.md,当前状态记录在 docs/reference/ 和代码中。编写规范时,如果某项关键决策逐渐明确,应立即将其记录为 docs/adr/ 中的 Proposed ADR,并在规范中引用;不要把它埋在规范里,留待以后“整理”。工作完成后,请按照规范生命周期退役该规范。ADR 的接受流程请遵循 ADR 指南;实现完成并不意味着可以更改状态。历史记录由 Git 和 docs/spec-history.md 保留。

注意:本指南使用 [PLACEHOLDER] 标记需要填写的内容。代码块展示的是模板;请将所有方括号中的内容替换为功能的具体细节。

参考资料

根据规范涉及的决策范围,按需阅读以下资料:

核心理念

规范应当:

  • 提供上下文,而非指令:说明“为什么”和“是什么”,让实现者自行决定“如何做”
  • 记录研究过程,而非结论:展示探索过什么、现有内容是什么、还缺少什么
  • 保留开放问题:开放问题部分是规范的优点,不是缺陷
  • 支持自主实现:阅读规范的 Agent 应当派生子 Agent 来验证并扩展内容
  • 尊重维护者的时间:在要求读者了解历史、附录或实现日志之前,先明确展示当前要走的路径
  • 避免流程作秀:只有当某个章节会影响实现或评审时才加入,不要仅仅因为模板列出了它就添加

好的规范是起点,而不是照着执行的脚本。

在规划章节之前,先应用 one-sentence-test。 如果无法用一个具体句子说明规范的主题,说明设计尚不连贯。这就是需要得出的结论,规范也尚未准备就绪。


维护者时间约定

规范的首屏必须回答:

What is this?
Is it active, implemented, superseded, or historical?
What is the current shape?
What is the target shape?
What proves the change is done?

允许编写较长的规范。深入的工作值得详尽记录。原则不是“超过 N 行就拆分”,而是不要让同一位读者同时承担彼此冲突的任务。

如果一份文档混合了以下内容,请拆分文档,或添加一个简短的当前重点部分:

  • 北极星架构与具体执行步骤。
  • 历史争论与当前实现路径。
  • 规范内容与交接提示词。
  • 有用但并非启动工作所必需的附录或台账。

如果决定将所有内容保留在同一个文件中,请在靠近文档开头处添加“如何阅读本规范”部分:

Read first:
  One Sentence
  Current State
  Target Shape
  Implementation Plan
  Verification

Read if changing the architecture:
  Design Decisions
  Rejected Alternatives
  Edge Cases

Historical only:
  Implementation Notes
  Superseded Decisions
  Execution Prompts

读者应能在一分钟内了解当前事实,五分钟内掌握模型,十五分钟内了解执行路径。


规范放置位置

所有实现规范都放在根目录的 /specs/ 中。不要在 apps/ 或 packages/ 下创建嵌套规范。

新规范命名为 specs/YYYYMMDDThhmmss-feature-name.md:使用本地时间戳和 kebab-case 功能名称。

提示词和交接文档可以放在规范旁边,并使用 .prompt.md、.handoff.md 或 .execute.md 等明确后缀。它们应链接回规范的权威版本;除非后缀表明它们是当前实施计划,否则不应将其视为当前实施计划。


决策规范

对每项重要决策进行分类:

类别判定依据规则
1证据通过源码、测试或版本检查进行验证。
2设计一致性始终如一地遵循规范的核心主张。
3约束下的取舍有意做出选择并写明约束。

在做出任何“保留”决定之前,先问:“如果它本来不存在,我还会添加它吗?”

  • 如果会,记录使用场景。
  • 如果不会,但移除会造成不必要的改动,则在决策日志中将其记录为类别 3 的保留项。
  • 如果不会,而且移除成本很低,就立即删除。

不要用设计一致性掩盖证据问题。删除旧路径前先进行验证。有关示例和失败模式,请阅读 references/decision-hygiene.md。


文档结构

并非每份规范都需要包含所有章节。小型功能可以省略研究发现。迁移规范则可以重点关注边缘情况。请酌情判断。

标题(必需)
# [Feature Name]

**Date**: [YYYY-MM-DD]
**Status**: Draft | In Progress
**Owner**: [Name/team responsible for decisions]
**Branch**: [optional: branch name if work has started]
**Supersedes**: [optional: previous spec paths]
**Superseded by**: [optional: later spec path]
一句话描述

每份规范都需要在概述前写一句具体的话。这是维护者的核心依据。

## One Sentence

[One sentence naming the new shape and the boundary it changes.]
概述

最多一段。描述功能的作用,不要推销它。

## Overview

[One to two sentences describing what this feature adds or changes and what it enables. Be specific about the capability, not vague about benefits.]
动机

按 当前状态、问题、期望状态 的顺序组织内容。

## Motivation

### Current State

[Show actual code or configuration demonstrating how things work TODAY. Use real code blocks, not prose descriptions.]

This creates problems:

1. **[Problem Title]**: [Specific explanation of what breaks or is painful]
2. **[Problem Title]**: [Specific explanation of what breaks or is painful]

### Desired State

[Brief description of what the target looks like. Can include a code snippet showing the ideal API or structure.]
研究发现

规范的亮点所在。记录你实际发现的内容,而非假设。

## Research Findings

### [Topic Researched]

[Description of what you investigated and methodology]

| [Category]    | [Dimension 1]  | [Dimension 2]    |
| ------------- | -------------- | ---------------- |
| [Project/Lib] | [What they do] | [Their approach] |
| [Project/Lib] | [What they do] | [Their approach] |

**Key finding**: [Your main discovery, for example that no standard exists, or that everyone does X]

**Implication**: [What this means for your design decisions]

包括:

  • 类似项目的做法(对比表)
  • 搜索过但未找到的内容(“不存在既定模式”)
  • 查阅过的文档链接或参考资料
设计决策

使用表格以便追溯。每项重要决策都应注明类别和理由。

决定架构、所有权、API 形式,或是否采用值得避免反复讨论的替代方案等关键决策(类别 2 的一致性决策或类别 3 的取舍),应记录在 ADR 中,而不应只写在此表中。一旦决策成形,就在 docs/adr/ 中将其写为 Proposed ADR,并在表格的理由栏中注明 ADR 编号。这样,表格就能将规范中的决策追溯至其长期归档位置;即使规范被删除,ADR 也会保留。

## Design Decisions

| Decision            | Class       | Choice           | Rationale                       |
| ------------------- | ----------- | ---------------- | ------------------------------- |
| [Decision point]    | 1 evidence  | [What you chose] | [Source, test, or version checked] |
| [Decision point]    | 2 coherence | [What you chose] | [How this follows the thesis]   |
| [Decision point]    | 3 taste     | [What you chose] | [Constraint and trade-off]      |
| [Deferred decision] | Deferred    | Deferred         | [Why it is deferred and what would bring it back] |
架构

图示优于文字说明。优先使用围栏文本图、文件树、路由表以及前后对照块。默认使用简单的 ASCII 图,因为它们编写快速且易于编辑。只有当精致图示值得付出额外成本时,才使用制表符绘图字符。

## Architecture

[Describe what the diagram shows]
[caller]
  -> [boundary or route]
    -> [policy or validation]
      -> [storage or primitive]

对于多步骤流程:

Step 1: [Step name]
  [What happens in this step]

Step 2: [Step name]
  [What happens in this step]
目录(引入一组基元时)

如果规范引入一组相互关联的新基元(列类型、操作变体、错误类型、修饰符方法等),应以目录的形式呈现:使用紧凑的代码块列出所有基元,并为每项附上一行注释;之后仅针对需要详细说明的基元设置详细章节。

目录让读者在深入了解单个基元前,就能一眼浏览完整的功能面。

## The field.* catalog

```ts
field.string<TBrand?>(s?)               // TEXT (TBrand for branded strings)
field.number(s?)                        // REAL
field.integer(s?)                       // INTEGER
field.boolean()                         // INTEGER 0/1
field.select([value])                   // TEXT (single-element set)
field.select([...])                     // TEXT + CHECK constraint
field.json<S extends TSchema>(schema)   // TEXT JSON-encoded, schema required
nullable(inner)                         // Type.Union([inner, Type.Null()]) (standalone)
field.datetime(s?)                      // RFC 3339 string, branded DateTimeString
field.string<IanaTimeZone>()            // IANA zone string, branded IanaTimeZone
```

Every primitive justified by N+ existing call sites in the audit.

### What was considered and rejected

| Candidate | Why rejected |
|---|---|
| `field.id()` | Subsumed by `field.string<IdBrand>()` + a co-located `generate*` factory |
| `field.array(of)` | Subsumed by `field.json(Type.Array(of))` |
| Declaring `_v` as a column | Library-managed; positional in `defineTable(v1, v2, ...)` |

“已排除候选项”表格通常与目录本身一样有用:它能说明实施者不应添加什么以及原因,让读者确信功能面经过了精简。

调用点(真实代码的变更前/后对比)

当规范变更面向使用者的 API 时,请展示至少 2-3 个真实调用点的翻译,不要编造示例。真实代码中的调用能体现抽象方案容易遗漏的语义变化。

先在代码库中找到实际用法。先按原样展示“变更前”代码,并标注文件:行号,然后展示“变更后”的翻译。对不明显的映射,请附上简短注释。

## Call sites: before and after

### honeycrisp notes table

**Before** (`apps/honeycrisp/src/lib/workspace.ts:78`):

```ts
const notesTable = defineTable(
  type({ id: NoteId, title: 'string', _v: '1' }),
  type({ id: NoteId, title: 'string', wordCount: 'number | undefined', _v: '2' }),
).migrate(...)
```

**After**:

```ts
const notesTable = defineTable(
  { id: field.string<NoteId>(), title: field.string() },
  {
    id: field.string<NoteId>(),
    title: field.string(),
    wordCount: nullable(field.number()),
  },
).migrate(({ value, version }) => {
  switch (version) {
    case 1: return { ...value, wordCount: null };
    case 2: return value;
  }
});
```

**Semantic shift to flag**: rows previously stored with `wordCount` key absent will now read as `null` instead of `undefined`. Affects app code doing `if (row.wordCount === undefined)`. Also: `_v` no longer appears in the column record; it is library-managed and stripped from returned rows.

“需要标记的语义变化”说明至关重要:实现者需要根据这些说明在整个代码库中搜索并批量修改代码。

实施计划

分阶段制定计划。使用复选框跟踪进度。第 1 阶段应详细说明;后续阶段可以写得粗略一些(实现者会进一步完善)。

## Implementation Plan

### Phase 1: [Phase Name]

- [ ] **1.1** [Specific, atomic task]
- [ ] **1.2** [Specific, atomic task]
- [ ] **1.3** [Specific, atomic task]

### Phase 2: [Phase Name]

- [ ] **2.1** [Higher-level task the implementer will break down]
- [ ] **2.2** [Higher-level task]
平稳过渡的阶段顺序:构建、验证、移除

如果规范要替换旧代码路径,请规划使用者如何切换到新路径、如何验证替换有效,以及如何在弃用旧路径前确保能够恢复。对于可分离和不可分离的替换,请参考 rethink 的平稳过渡指南。应由依赖关系决定阶段,而不是强行规定固定的阶段数。

边缘情况

列出可能打破假设或需要特殊处理的场景。

## Edge Cases

### [Scenario Name]

1. [Initial condition]
2. [What happens]
3. [Expected outcome or "See Open Questions"]

### [Scenario Name]

1. [Initial condition]
2. [What happens]
3. [Expected outcome]
待解决问题

本节表示“由你决定”。请给出建议,但不要直接定论。

## Open Questions

1. **[Question about an unresolved design decision]**
   - Options: (a) [Option A], (b) [Option B], (c) [Option C]
   - **Recommendation**: [Your suggestion and why, but explicitly leave it open]

2. **[Another unresolved question]**
   - [Context about why this is uncertain]
   - **Recommendation**: [Suggestion or "Defer until X"]
相邻工作

大多数规范不需要本节;规范是执行主线,而非文件白名单。当相邻工作很重要时,只写实现者需要的信息:延后事项(当前不要求,但以后允许做)和顺带处理的事项(如果发现且有依据,允许一并修复)。

## Adjacent Work

- [Decision or feature]: [Why it is not required now, and what would bring it back.]
- [Issue or cleanup]: [Why it is not required, but may be fixed if discovered and grounded.]
决策日志

本节仅用于第 3 类保留项。每条记录都必须说明约束条件和重新审视的触发条件。

## Decisions Log

- Keep `[name]`: [constraint or trade-off].
  Revisit when: [specific signal that would make the keep decision worth re-opening].
成功标准

如何判断工作已完成?使用复选框进行验证。

## Success Criteria

- [ ] [Specific, verifiable outcome]
- [ ] [Specific, verifiable outcome]
- [ ] [Tests pass / build succeeds / docs updated]
参考资料

将修改或查阅的文件。

## References

- `[path/to/file.ts]` - [Why this file is relevant]
- `[path/to/pattern.ts]` - [Pattern to follow or reference]

如果规范规定得过于细致,Agent 就会盲目照做。如果规范过于含糊,Agent 就会无所适从。理想的平衡是:提供足够的背景以便着手,同时留有足够的空间让实现者自主完成实现。

评论

支持 Markdown