inkeep/open-knowledge-pack-software-lifecycle-record-a-decision
Records an architecture decision as a Nygard/MADR-shaped ADR under decisions/ — capturing the context that forced the choice, the options weighed, the decision itself, and its consequences in both directions, plus the supersedes chain that keeps a decision log honest. Read when asked to record an architecture decision, write an ADR, log the decision we made, document why we chose X over Y, capture this decision for the record, or supersede an old decision with a new one. Do NOT read to frame a proposal or explore an idea not yet decided (frame-a-proposal), to write a spec or implementation plan (write-a-spec), to write an incident postmortem (write-a-postmortem), or to judge whether a design is sound (review-a-design). This skill records a decision already made; it does not make one.
npx skills add https://github.com/inkeep/open-knowledge --skill open-knowledge-pack-software-lifecycle-record-a-decision
decisions/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.
An ADR records a decision; it does not make one. Before anything else, establish that a choice has been settled.
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.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.
A new ADR that silently contradicts an accepted one is how a decision log rots. Before allocating a number, find what already exists.
search({ query: "<subsystem or topic of the decision>" }) — semantic sweep for related decisions, proposals, and specs.exec("ls -A decisions/") — see the existing sequence and titles.exec("grep -rln <subsystem-keyword> decisions/") — find records touching the same subsystem, interface, or constraint.exec("cat decisions/NNNN-x.md") — read its Decision and Status.Then classify and surface to the user before writing:
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.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.
Never guess the sequence number. List the folder and take the next integer.
exec("ls -A decisions/") — read the highest existing NNNN.0001.0012-adopt-event-sourcing-for-orders, not 0012-orders.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:
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.
## 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:
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.
## 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:
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.
## 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:
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.
Read the draft as a skeptic who disagrees with the decision. Answer each honestly and fix what fails:
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.
If this record replaces an earlier one, the chain must be wired in both directions or the log lies from one side.
supersedes: frontmatter.edit({ document: { path: "decisions/0012-adopt-event-sourcing-for-orders.md",
frontmatter: { supersedes: ["decisions/0007-use-rest-api.md"] } } })
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.
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.
links({ kind: "backlinks", docName: "decisions/0012-adopt-event-sourcing-for-orders" }) to see who points here; add the missing ones so the record is discoverable.links({ kind: "dead", sourceDocNames: ["decisions/0012-adopt-event-sourcing-for-orders"] }) returns clean — zero dead links. Fix or remove every one; a broken link to a superseded record defeats the whole chain.type, description, status, date, deciders, supersedes, tags all present and correct.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.## Context, ## Decision, ## Consequences, in order. No extra top-level sections — depth that doesn't fit these three belongs in a linked spec.Close in conversation, three things:
Then note whether status is accepted (deciders signed off) or proposed (awaiting sign-off), so the user knows what, if anything, is still open.
frame-a-proposal. This skill records; it does not choose.write-a-spec). The ADR captures what and why, not how.review-a-design.Take inkeep/open-knowledge-pack-software-lifecycle-record-a-decision from the repository into ~/.claude/skills for personal
use, or into .claude/skills inside a project.
The agent identifies a skill by the name field in its header. Two skills with the
same name cannot sit side by side — one of them will be ignored.