record-a-decision

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

Record a decision — write an ADR under
decisions/

记录决策——在
decisions/
下编写 ADR

The platform
/open-knowledge
skill still governs every markdown operation here (grounding, linking, the rule that OK's MCP tools own in-scope markdown); this skill layers ADR craft on top.
An Architecture Decision Record is a small, dated, frozen document that captures one decision, the forces that made it necessary, and what the team now has to live with. The value compounds over years: a reader who joins in three years should understand not just what was decided but why it was even a question. ADRs are frozen once accepted — you never rewrite one to change your mind, you supersede it with a new record and leave the old one standing as history. That supersedes chain is what separates an honest decision log from a pile of stale opinions.
Filenames are
NNNN-title.md
(zero-padded 4-digit sequence + kebab title). Status vocabulary:
proposed
/
accepted
/
deprecated
/
superseded
. Template id
decision
, body sections exactly
## Context
,
## Decision
,
## Consequences
in that order.

平台
/open-knowledge
skill 仍管理这里的所有 markdown 操作(事实依据、链接管理,以及范围内 markdown 由 OK 的 MCP tools 负责的规则);本 skill 在此基础上叠加 ADR 编写规范。
架构决策记录(Architecture Decision Record)是一份简短、带日期且冻结的文档,记录一项决策、促成该决策成为必要事项的各种力量,以及团队此后必须承担的结果。它的价值会随岁月不断累积:三年后加入的读者不仅应了解决定了什么,还应明白这为什么当初会成为一个问题。ADR 一经接受便已冻结——你绝不会通过重写旧记录来改变主意,而应创建一份新记录来 supersede 它,同时将旧记录保留为历史。正是这条 supersedes 链,将一份真实可信的决策日志与一堆陈旧意见区分开来。
文件名格式为
NNNN-title.md
(4 位零填充序号 + kebab-case 标题)。状态词汇为:
proposed
/
accepted
/
deprecated
/
superseded
。模板 id 为
decision
,正文各节必须严格按以下顺序排列:
## Context
、
## Decision
、
## Consequences
。

Step 0 — Confirm a decision was actually MADE (HARD GATE)

步骤 0——确认决策确实已经做出(硬性门槛)

An ADR records a decision; it does not make one. Before anything else, establish that a choice has been settled.
  • If the user is still weighing options, comparing approaches, or asking "should we do X or Y?" — they do not have a decision yet. Stop and route them to the
    /frame-a-proposal
    skill.
    A proposal is where options get explored and argued; an ADR is where the settled outcome gets recorded. Recording a decision the user has not made produces a fake record that misleads every future reader.
  • If the user says "we decided X" but you cannot tell what lost or why, ask one question: "What were the alternatives, and what made you pick this one?" An ADR with no rejected options is a press release, not a record.
  • If the thing in question is whether the design itself is sound — not the record of it — hand off to
    /review-a-design
    . This skill assumes the decision is sound; it captures it.
Do not proceed past this gate until the user has confirmed a specific decision. State it back to them in one sentence and get a nod.

ADR 用于记录决策,而不是做出决策。 在做任何其他操作前,先确定某个选择已经确定下来。
  • 如果用户仍在权衡选项、比较方案,或询问“应该采用 X 还是 Y?”——说明尚未形成决策。停止操作,并将其转交至
    /frame-a-proposal
    skill。
    提案用于探索和论证各种选项;ADR 用于记录已经确定的结果。记录用户尚未做出的决策会生成一份虚假的记录,误导未来的每一位读者。
  • 如果用户说“我们决定采用 X”,但你无法确定是什么方案被淘汰或为什么被淘汰,则只问一个问题:“有哪些备选方案,最终是什么让你们选择了这一项?” 一份没有记录被否决方案的 ADR 只是一篇新闻稿,不是决策记录。
  • 如果问题在于设计本身是否合理——而不是是否要记录该设计——则转交至
    /review-a-design
    。本 skill 假定该决策是合理的;负责记录它。
在用户确认具体决策前,不要越过此门槛。用一句话向用户复述该决策,并获得确认。

Step 1 — Scan for prior art (surface supersedes candidates BEFORE writing)

步骤 1——扫描既有内容(写入前提出 supersedes 候选项)

A new ADR that silently contradicts an accepted one is how a decision log rots. Before allocating a number, find what already exists.
  1. search({ query: "<subsystem or topic of the decision>" })
    — semantic sweep for related decisions, proposals, and specs.
  2. exec("ls -A decisions/")
    — see the existing sequence and titles.
  3. exec("grep -rln <subsystem-keyword> decisions/")
    — find records touching the same subsystem, interface, or constraint.
  4. For each promising hit,
    exec("cat decisions/NNNN-x.md")
    — read its Decision and Status.
Then classify and surface to the user before writing:
  • Contradicts an accepted record → this new decision reverses or replaces it. Flag the path as a
    supersedes:
    candidate: "This looks like it supersedes 0007-use-rest-api, which is currently
    accepted
    . Confirm and I'll wire the chain in Step 7." Do not silently write a contradicting record.
  • Extends without contradicting → note the related record; you'll link it, not supersede it.
  • Genuinely new → proceed.
If the decision graduated from an accepted proposal in
proposals/
, locate that proposal now (
exec("grep -rln <topic> proposals/")
) — you'll link it as the parent in Step 4.

新 ADR 若默默与已接受的记录相矛盾,决策日志就会腐坏。分配编号前,先查找已有内容。
  1. search({ query: "<subsystem or topic of the decision>" })
    ——对相关决策、提案和 spec 进行语义检索。
  2. exec("ls -A decisions/")
    ——查看已有序号和标题。
  3. exec("grep -rln <subsystem-keyword> decisions/")
    ——查找涉及相同子系统、接口或约束的记录。
  4. 对每个可能相关的结果,执行
    exec("cat decisions/NNNN-x.md")
    ——读取其 Decision 和 Status。
然后,在写入前对结果进行分类并告知用户:
  • 与已接受记录相矛盾→此新决策推翻了或取代了原记录。将对应路径标记为
    supersedes:
    候选项:“这看起来会 supersede 0007-use-rest-api,其当前状态为
    accepted
    。请确认,确认后我会在步骤 7 中接好这条链。”不要默默写入一份与原记录相矛盾的记录。
  • 扩展但不矛盾→说明相关记录;你只会链接它,而不会 supersede 它。
  • 确属新决策→继续执行。
如果该决策源自
proposals/
中一份已接受的提案,现在就找到它(
exec("grep -rln <topic> proposals/")
)——你会在步骤 4 中将其链接为父级提案。

Step 2 — Allocate the next number and create from the template

步骤 2——分配下一个编号并从模板创建

Never guess the sequence number. List the folder and take the next integer.
  1. exec("ls -A decisions/")
    — read the highest existing
    NNNN
    .
  2. Next number = highest + 1, zero-padded to 4 digits. First-ever decision is
    0001
    .
  3. Pick a short kebab title naming the decision, not the topic:
    0012-adopt-event-sourcing-for-orders
    , not
    0012-orders
    .
  4. Create it from the template:
write({ document: { path: "decisions/0012-adopt-event-sourcing-for-orders.md", template: "decision" } })
The template lays down the frontmatter scaffold and the three H2 sections. Fill the frontmatter now:
yaml
type: decision
description: "One line: the decision, active voice."
status: proposed        # proposed until the deciders accept; then accepted
date: YYYY-MM-DD        # today
deciders: [<user>]      # who owns this decision
supersedes: []          # fill in Step 7 if this replaces an earlier record
tags: [decision]
Leave
status: proposed
while drafting. It becomes
accepted
only when the deciders sign off (Step 8) — an ADR that ships
accepted
before anyone agreed is backdating.

绝不猜测序号。 列出文件夹并取下一个整数。
  1. exec("ls -A decisions/")
    ——读取现有最大的
    NNNN
    。
  2. 下一个编号 = 最大值 + 1,并补零为 4 位。首个决策为
    0001
    。
  3. 选择一个简短的 kebab-case 标题来命名决策,而不是笼统描述主题:使用
    0012-adopt-event-sourcing-for-orders
    ,不要使用
    0012-orders
    。
  4. 从模板创建:
write({ document: { path: "decisions/0012-adopt-event-sourcing-for-orders.md", template: "decision" } })
模板会创建 frontmatter 骨架和三个 H2 章节。现在填写 frontmatter:
yaml
type: decision
description: "One line: the decision, active voice."
status: proposed        # proposed until the deciders accept; then accepted
date: YYYY-MM-DD        # today
deciders: [<user>]      # who owns this decision
supersedes: []          # fill in Step 7 if this replaces an earlier record
tags: [decision]
起草期间保留
status: proposed
。只有决策者签字接受后(步骤 8),它才会变成
accepted
——在任何人同意前就以
accepted
状态发布 ADR,等同于事后伪造批准记录。

Step 3 — Context: the forces at play (invest here)

步骤 3——Context:起作用的各种力量(重点投入)

## Context
is the section that ages best. Write it so a reader three years from now understands why this was even a question — no access to the meeting, the thread, or your memory. Cover:
  • The state of the system when the decision was forced — what exists, what's under strain.
  • What changed to make a choice necessary now rather than never. A new requirement, a scaling limit hit, a deprecated dependency, a deadline.
  • The constraints that bounded the options — team size, existing tech, latency budgets, compliance, a hard date.
  • The forces in tension — the reason this is a decision and not an obvious call. If there were no competing pressures, there'd be nothing to record.
Write it neutrally and factually. Do not argue for the decision here — that's Step 4's job. Context describes the problem so completely that the Decision reads as one reasonable response to it. If a reader finishes Context and still can't see why a choice was needed, the section has failed; rewrite it.
Ground every factual claim about the system in something checkable — link the proposal, a spec, or a prior decision rather than asserting from memory.

## Context
是最经得起时间考验的一节。应确保三年后的读者即使无法访问会议、讨论串或记忆,也能理解这为什么当初会成为一个问题。需要涵盖:
  • 促成该决策时的系统状态——当时存在什么,以及哪些部分正承受压力。
  • 是什么变化使现在必须做出选择,而过去无需选择——新需求、触及扩展性上限、依赖项被弃用,或截止日期。
  • 限制可选方案的约束条件——团队规模、现有技术、延迟预算、合规要求或硬性日期。
  • 相互冲突的作用力——这正是它为何需要成为一项正式决策,而非显而易见选择的原因。如果不存在相互竞争的压力,就没有值得记录的内容。
要以中立、客观的方式撰写。不要在这里为决策辩护——那是步骤 4 的职责。Context 应如此完整地描述问题,以至于 Decision 读起来只是该问题的一种合理回应。如果读者读完 Context 后仍看不出为什么需要做出选择,说明这一节没有达到目的,应重新撰写。
系统中每项事实性陈述都应建立在可核查材料之上——应链接提案、spec 或既往决策,而不是凭记忆断言。

Step 4 — Decision: active voice, one paragraph, unambiguous

步骤 4——Decision:主动语态,一个段落,毫不含糊

## Decision
states what will be done, in the active voice, present or future tense: "We will ..." One clear paragraph. A reader must finish it knowing exactly what was chosen with zero ambiguity.
Then, briefly:
  • Name the options that were weighed and why the others lost. Two or three sentences per rejected option is enough — "We considered X but it couldn't meet the latency budget; Y was simpler but locked us to a single vendor." This is the heart of the record; a decision with no visible alternatives is unverifiable.
  • Link the parent proposal if the decision graduated from one: "This decision accepts 0004-orders-rearchitecture-proposal." Plain markdown relative link, never backticked, never an HTML anchor.
Do not fold implementation detail into the Decision — how it gets built belongs in a spec, not the ADR. The Decision says what and why, not the migration steps.

## Decision
使用主动语态,以现在时或将来时说明将采取什么行动:“我们将……” 只需一个清晰的段落。读者读完后必须确切知道选择了什么,不存在任何歧义。
随后简要说明:
  • 列出权衡过的选项,以及其余方案为何落选。 每个被否决的方案写两三句即可——“我们考虑过 X,但它无法满足延迟预算;Y 虽然更简单,却会把我们锁定在单一供应商上。”这是记录的核心;一份看不到备选方案的决策无法验证。
  • 如果该决策源自一份提案,请链接父级提案:“此决策接受 0004-orders-rearchitecture-proposal。”使用纯 markdown 相对链接,不要使用反引号,也不要使用 HTML 锚点。
不要把实现细节放进 Decision——如何构建属于 spec,而不属于 ADR。Decision 说明做什么以及为什么,不说明迁移步骤。

Step 5 — Consequences: both directions, honestly

步骤 5——Consequences:如实记录正反两方面

## Consequences
records what the team now lives with — good AND bad. A Consequences section with only upside is a marketing document, not an ADR. Cover, in whatever grouping fits:
  • What gets easier — the wins that motivated the choice.
  • What gets harder — the costs, the new complexity, the thing that's now more awkward.
  • What new obligation the team carries — ongoing maintenance, a new skill to hire for, a dependency to track, an invariant someone must now uphold.
  • What this forecloses — options you can no longer take cheaply, doors this closes.
  • Neutral consequences — facts that are neither win nor loss but that a future reader needs.
Force yourself to write at least one genuine negative and one new obligation. If you can't find any, you haven't thought hard enough — every real decision costs something. The negatives are the most valuable part of the record; they're what a future team checks when the decision starts to hurt.

## Consequences
记录团队此后必须承担的结果——好处和坏处都要写。只写好处的 Consequences 一节是营销文档,而不是 ADR。可以按适合的方式分组,涵盖:
  • 哪些事情会变得更容易——促使做出该选择的收益。
  • 哪些事情会变得更困难——成本、新增复杂性,以及现在变得更棘手的问题。
  • 团队新增了哪些义务——持续维护、需要具备的新技能、需要跟踪的依赖项,或必须由他人维护的不变量。
  • 该决策排除了什么——无法再轻易采用的方案,以及由此关闭的选项。
  • 中性后果——既非利也非弊,但未来读者需要了解的事实。
务必至少写出一个真正的负面后果和一项新增义务。如果找不到,说明你还没有充分思考——任何真实的决策都有代价。负面后果是记录中最有价值的部分;未来团队会在决策开始造成痛苦时查阅这些内容。

Step 6 — Soundness self-check (adversarial pass before committing)

步骤 6——合理性自检(提交前的对抗性检查)

Read the draft as a skeptic who disagrees with the decision. Answer each honestly and fix what fails:
  • One-way door or reversible? Is the reversibility of this decision stated? A one-way door (hard or expensive to undo) must say so explicitly in Consequences — that's the single most important thing a future reader needs to know before they inherit it.
  • Does Context actually motivate the Decision? Or does the Decision arrive from nowhere, with forces in Context that don't point at it? If the two sections don't connect, one of them is wrong.
  • Would a reader who disagrees find their objection addressed? The strongest counter-argument should appear somewhere — in a rejected option or a named consequence. If the obvious objection is missing, add it.
  • Is any consequence being hidden because it's inconvenient? The cost you'd rather not write down is exactly the one that belongs in the record.
If this pass reveals that the design itself is in question — not the quality of the record but whether the decision is right — stop and hand off to
/review-a-design
. This skill records sound decisions; it is not the place to relitigate one.

以一位不同意该决策的怀疑者视角阅读草稿。逐项如实回答,并修复未通过的内容:
  • 这是单向门还是可逆决定? 是否说明了该决定的可逆性?单向门(难以撤销或撤销代价高昂)必须在 Consequences 中明确指出——这是未来读者继承该决定前最需要了解的信息。
  • Context 是否真正促成了 Decision? 还是说 Decision 凭空出现,Context 中的力量也无法导向它?如果两节无法衔接,其中一节就是错误的。
  • 持反对意见的读者能否找到回应? 最有力的反驳应出现在某个位置——被否决的选项或明确列出的后果中。如果显而易见的反对意见有所缺失,就补充它。
  • 是否有后果因不便而被隐藏? 你最不愿写下的成本,恰恰就是应该记录的成本。
如果此次检查发现受到质疑的是设计本身——而不是记录质量,也不是决策是否正确——停止操作并转交至
/review-a-design
。本 skill 用于记录合理的决策,不是重新讨论决策。

Step 7 — Supersedes chain (both directions or it's broken)

步骤 7——supersedes 链(必须双向连接,否则链就断了)

If this record replaces an earlier one, the chain must be wired in both directions or the log lies from one side.
  1. Forward, on the new record: add the old path to
    supersedes:
    frontmatter.
edit({ document: { path: "decisions/0012-adopt-event-sourcing-for-orders.md",
  frontmatter: { supersedes: ["decisions/0007-use-rest-api.md"] } } })
  1. Backward, on the old record: flip its status and add a forward link so a reader landing on the old decision is sent to the new one.
edit({ document: { path: "decisions/0007-use-rest-api.md",
  frontmatter: { status: "superseded" } } })
Then add a line near the top of the old record's Context (or a short
> Superseded by ...
note):
Superseded by [0012-adopt-event-sourcing-for-orders](./decisions/0012-adopt-event-sourcing-for-orders.md).
Never edit the old record's Context, Decision, or Consequences prose. ADRs are frozen — the old decision was true when it was made and stays on the record as history. You add the status flip and the forward pointer; you do not rewrite what it said. Both edits land, or the chain is broken in one direction and the log becomes untrustworthy.

如果此记录取代了较早的记录,则必须双向连接这条链,否则日志会从一侧开始失真。
  1. **正向连接,在新记录中:**将旧记录路径加入
    supersedes:
    frontmatter。
edit({ document: { path: "decisions/0012-adopt-event-sourcing-for-orders.md",
  frontmatter: { supersedes: ["decisions/0007-use-rest-api.md"] } })
  1. **反向连接,在旧记录中:**将其状态改为
    superseded
    ,并添加一个正向链接,把从旧记录进入的读者引向新记录。
edit({ document: { path: "decisions/0007-use-rest-api.md",
  frontmatter: { status: "superseded" } })
然后,在旧记录 Context 靠前的位置添加一行(或添加一条简短的
> Superseded by ...
提示):
由 [0012-adopt-event-sourcing-for-orders](./decisions/0012-adopt-event-sourcing-for-orders.md) 取代。
绝不编辑旧记录中 Context、Decision 或 Consequences 的正文。 ADR 是冻结的——旧决策在做出时是真实的,并会作为历史一直保留。你只需添加状态变更和正向指针;不要重写它原来的内容。两次编辑必须同时落地,否则这条链只会连接一个方向,决策日志也将失去可信度。

Step 8 — Link and validate

步骤 8——链接并验证

  • Backlinks in: ensure the parent proposal links forward to this decision, and any spec that implements this decision links back to it.
    links({ kind: "backlinks", document: "decisions/0012-adopt-event-sourcing-for-orders" })
    to see who points here; add the missing ones so the record is discoverable.
  • Validate:
    audit({ path: "decisions/0012-adopt-event-sourcing-for-orders.md" })
    returns clean (every lint violation + broken internal link) — fix every finding; a broken link to a superseded record defeats the whole chain.
  • Frontmatter complete:
    type
    ,
    description
    ,
    status
    ,
    date
    ,
    deciders
    ,
    supersedes
    ,
    tags
    all present and correct.
  • Status reflects reality: if the deciders have accepted, flip
    status: proposed
    →
    accepted
    . If they haven't, leave it
    proposed
    and tell the user it's awaiting sign-off. Do not mark a decision
    accepted
    on the user's behalf.
  • Body shape: exactly
    ## Context
    ,
    ## Decision
    ,
    ## Consequences
    , in order. No extra top-level sections — depth that doesn't fit these three belongs in a linked spec.

  • **补齐入站反向链接:**确保父级提案正向链接到此决策,并且任何实现此决策的 spec 都反向链接到它。使用
    links({ kind: "backlinks", document: "decisions/0012-adopt-event-sourcing-for-orders" })
    查看有哪些文档指向这里;补上缺失的链接,使记录可以被发现。
  • 验证:
    audit({ path: "decisions/0012-adopt-event-sourcing-for-orders.md" })
    应返回 clean(即不存在任何 lint 违规或损坏的内部链接)——修复每项发现;指向已 superseded 记录的损坏链接会破坏整条链的可信度。
  • frontmatter 完整:
    type
    、
    description
    、
    status
    、
    date
    、
    deciders
    、
    supersedes
    、
    tags
    均须存在且正确。
  • **状态反映实际情况:**如果决策者已经接受,将
    status: proposed
    改为
    accepted
    。如果尚未接受,则保留
    proposed
    ,并告知用户正在等待签字。不要代替用户将决策标记为
    accepted
    。
  • **正文结构:**必须严格按顺序包含
    ## Context
    、
    ## Decision
    、
    ## Consequences
    。不得添加额外的顶层章节——超出这三节范围的深入内容应放入链接的 spec。

Step 9 — Recap to the user

步骤 9——向用户总结

Close in conversation, three things:
  1. The decision in one sentence — the "We will ..." line.
  2. Its biggest consequence — the one cost or obligation the team most needs to remember, especially if it's a one-way door.
  3. Any record it superseded — name the old ADR and confirm the chain is wired both ways.
Then note whether
status
is
accepted
(deciders signed off) or
proposed
(awaiting sign-off), so the user knows what, if anything, is still open.

在对话中以三件事收尾:
  1. 用一句话概括决策——即“我们将……”这一句。
  2. 说明最大的后果——团队最需要记住的那项成本或义务,尤其是在这是单向门时。
  3. 列出此决策取代的任何记录——指明旧 ADR,并确认 supersedes 链已双向连接。
然后说明
status
是
accepted
(决策者已签字)还是
proposed
(等待签字),让用户了解目前还有什么事项尚未完成。

Non-goals

非目标

  • Don't decide on the user's behalf. If no decision has been made, route to
    /frame-a-proposal
    . This skill records; it does not choose.
  • Don't rewrite an accepted record. ADRs are frozen. To change a past decision, supersede it (Step 7) and leave the old one standing — never edit its Context/Decision/Consequences prose.
  • Don't fold implementation detail into an ADR. The migration plan, the API shape, the rollout steps belong in a spec (
    /write-a-spec
    ). The ADR captures what and why, not how.
  • Don't record a decision that has no consequences section. A record with only upside, or with no costs and no new obligations, isn't an ADR — it's marketing. Every real decision costs something; find it and write it down.
  • Don't judge the soundness of the design here. If the question is whether the decision is right rather than whether it's well-recorded, that's
    /review-a-design
    .
  • 不要代替用户做决定。 如果尚未做出决策,应转交至
    /frame-a-proposal
    。本 skill 负责记录,而不是选择。
  • 不要重写已接受的记录。 ADR 是冻结的。要改变既往决策,应使用新记录将其 supersede(步骤 7),并保留旧记录——绝不编辑其 Context、Decision 或 Consequences 正文。
  • 不要把实现细节放进 ADR。 迁移计划、API 形态和发布步骤应写入 spec(
    /write-a-spec
    )。ADR 记录做什么和为什么,而不是如何做。
  • 不要记录缺少 Consequences 节的决策。 只有好处,或既无成本也无新增义务的记录并不是 ADR,而是营销材料。任何真实的决策都有代价;找出这些代价并写下来。
  • 不要在这里评判设计是否合理。 如果问题在于决策是否正确,而不是记录是否完善,应转交至
    /review-a-design
    。