inspire-adr
ADR lifecycle for architectural decisions at three scopes, set by placement (global, one module, one face): create / update / promote / supersede / migrate along a maturity ladder (design → prototyped → implemented). Use when proposing, recording, advancing, or retiring an architectural decision.
- License 许可
- MIT
- 最近更新
- 2026-11-13
- Stars
- ★ 0
- Forks
- 1
01 前言 Front Matter
- name
- inspire-adr
- description
- ADR lifecycle for architectural decisions at three scopes, set by placement (global, one module, one face): create / update / promote / supersede / migrate along a maturity ladder (design → prototyped → implemented). Use when proposing, recording, advancing, or retiring an architectural decision.
02 资源文件 2
- 参考文档templates/adr.rationale.template.md422 B
- 参考文档templates/adr.template.md1.2 KB
03 SKILL.md 正文
/inspire-adr — Architecture Decision Records
Scope
An ADR records an architectural decision. Where its files sit is its scope:
| Scope | Directory | Holds |
|---|---|---|
| Global | inspire_kb/01_spec/_adr/ |
a decision that spans ≥2 modules or ≥2 faces, or is system-wide |
| Module | inspire_kb/01_spec/_modules/{module}/_adr/ |
a decision that binds one module |
| Face | inspire_kb/01_spec/_faces/{face}/_adr/ |
a decision that binds one face, even when it spans two modules within that face |
Nothing else declares the scope. Tools find every ADR by its extension, *.adr.md,
wherever it sits under inspire_kb/01_spec/. This skill owns their full
lifecycle. It does not run the global review — /inspire-workspace review
checks that an ADR's consequences have actually propagated; this skill authors and
advances the decisions themselves.
An ADR is the decision rung of the authority ladder
(_references/authority.md). A rule binding one
module belongs in that module's hub, and one binding a single use case, descriptor or
screen belongs in that artifact — each of those outranks an ADR on the question it
actually decides. The reverse is the usual reason to open an ADR: the same departure
declared in a third artifact is a decision sitting at the wrong rung, and it belongs
here.
The maturity ladder
ADR Status is a maturity ladder, not a binary — it declares how far the
decision has been realized, and therefore how far its consequences should have
propagated (the propagation contract):
design— design reasoning. Reach: the whole design workspace — features (*.feature.md) + screens (*.screen.md) + the horizontal prototype (/prototypeby default, a non-functional interactive mock — resolveprototype_rootper_references/product-roots.md, wherenonemeans this project has no horizontal prototype for a decision to reach) + specs (*.entity.md,*.action.md). Refined in place on new evidence.prototyped— additionally validated in an external functional prototype: real running code in a vertical spike repo has proven the architecture works (record it with a**Prototype:**pointer to that repo). The horizontal prototype does not count. Still refined in place.implemented— additionally realized in the product codebase. Immutable — both files of the pair;supersedeto change.superseded(by[adr-{new-slug}]({new-slug}.adr.md)) /rejected— terminal.
There is no proposed/accepted state: an ADR present and not
superseded/rejected is the current decision at its maturity; the debate
happens in chat before authoring.
Invocation
/inspire-adr create {slug}— new ADR (defaults toStatus: design)/inspire-adr update {id}— modify an ADR (supersede required only atimplemented)/inspire-adr promote {id} {maturity}— advance maturity and propagate consequences/inspire-adr supersede {id} {new-id}— mark old ADR superseded and wire the link/inspire-adr migrate [{id}…]— split single-file ADRs into a decision and a rationale
The decision and its rationale
Every ADR is a pair of files that share one slug, side by side in the same _adr/:
{slug}.adr.md— the decision. The H1 title,**Status:**,**Modules affected:**,**Rationale:** [adr-{slug}.rationale]({slug}.adr.rationale.md), anySupersedes:or**Prototype:**line, on a global ADR thefaces:/bundles:frontmatter, and## Decision: one or a few imperative statements ("Authentication uses the Better Auth library."). It binds, so it stays short: the session-start hook injects every live decision into every session, through.inspire/bin/decisions.sh.{slug}.adr.rationale.md— the rationale.**Decision:** [adr-{slug}]({slug}.adr.md), then## Context,## Consequences(with### Breaking changes),## Alternatives consideredand## Related ADRs. It explains the decision and constrains nothing, so it is read only when someone questions or supersedes it.
The test for a sentence in ## Decision: would a reader who follows it build
something different without it? If not, it is a reason, and it belongs in the rationale.
A link to {slug}.adr.md always means the decision; link the rationale file
only when the reasons are the point. Links follow
kb-links.md.
Subcommand: create {slug}
Conventions
- Filename:
{slug}.adr.mdfor the decision and{slug}.adr.rationale.mdbeside it for the rationale. Slug-only — no numeric prefix, and noadr-prefix: the extension already says the file is an ADR. - Location is the scope: the global
_adr/, the module's_adr/or the face's_adr/(see Scope). A module ADR's slug does not repeat the module's name or prefix: its placement says the module. Which scope a write takes resolves per_references/face-scope.md§ Scope resolution: an explicit argument wins, and the skill asks when nothing pins it. - Slug uniqueness: unique across the project, whatever the scope.
spec-identity.shreports a duplicate. - Canonical ID:
adr-{slug}, the prefix added back to the slug when the id is read. The rationale's id isadr-{slug}.rationale. The H1 is the human title, and the rationale's H1 is the same title followed by— rationale. - Blast radius: a global ADR carries the
faces:/bundles:frontmatter the template below holds; absent means the whole project. A module or face ADR carries neither: its placement gives the scope.**Modules affected:**lists the modules either way. Semantics — what an absent field means and how an id resolves — live in_references/face-scope.mdand are not restated here.
Rationale. Numeric prefixes collide under parallel work (two branches grab the
same next number). Slug-only filenames are collision-free by construction
(mirroring the TASK-{id} convention).
Exposure lives in bundles
Which service exposes which modules is not an ADR. It is expressed by
bundles: each {bundle}.bundle.md lists, under ## Actions, the whole modules
([tenancy](../_modules/tenancy/tenancy.module.md) (whole module)) and the single actions it exposes, with its package
and profiles. /inspire-face owns the bundle files. The
domain stays a single untagged truth: no entity or action names a bundle. Overlap is
allowed — an action may sit in two bundles. A project with one bundle exposing
everything still has that one bundle file.
When the reasons for a split are worth recording ("the admin API is its own bundle
because it runs inside the operator network"), write a global ADR with
bundles: naming the bundles it concerns. The ADR states the reasons and links the
bundles; it never restates their ## Actions lists.
Action-granular pressure — most of one module's actions splitting across bundles —
is a modularity smell: split the module (inspire-module) rather than list its
actions one by one. A backend for a frontend is a bundle with an artifact of its own.
The action-verbs ADR
A named pattern for the project's action verbs: the last segment of every
action id. The verbs come from the application's own domain (a library reserves,
cancels and picks up a book), and they are one system-wide decision, recorded in one
ADR with the fixed id adr-action-verbs. /inspire-domain reads it whenever it
lands an action's verb, and falls back to its default set (list · get ·
create · edit · delete) while the ADR does not exist.
The ADR lists each verb with the kind of change it names, and any rule attached to a
kind of verb (an event every mutation emits, timestamps every mutable entity
carries). It does not restate the generic rules in
inspire-domain/references/interview-prompts-action.md:
one target object per action, plural verbs for reads that return many, singular
verbs for reads that return one. A new verb is added here before the descriptor
that uses it lands.
Template
Templates: templates/adr.template.md for the decision
and templates/adr.rationale.template.md for the
rationale — the decision's Supersedes: header line is optional (add only when superseding, per the
supersede subcommand below); the faces: / bundles: frontmatter is for a global
ADR only and defaults to the whole project by omission, per
_references/face-scope.md.
Steps
- Ask the user: short title, scope (global, a module or a face — see
Conventions), modules affected, for a global ADR the blast radius (the
faces:/bundles:fields; with exactly one face and one bundle there is nothing to ask), context, the decision, key consequences, alternatives considered. - Write both files in the scope's
_adr/:{slug}.adr.md, then{slug}.adr.rationale.md. Keep every reason out of## Decision(see the decision and its rationale). - Create every missing link target. A link to something that does not exist yet
requires its file. For each link the two files write (
**Modules affected:**,## Related ADRs, a face or bundle in the frontmatter) whose target is missing, create it from its template in draft: a module hub frominspire-module's template, an ADR fromtemplates/adr.template.mdat**Status:** design, a face or bundle frominspire-face's templates atlifecycle: draft. Name each one in the output. - Propose ADR references in the feature files that should link to it: list files to edit, wait for approval.
- Set
**Status:** designby default. Usepromotelater to advance.
Subcommand: update {id}
Modify an ADR in place. At design / prototyped maturity this is the normal
path — freely edit either file, including Decision; record new evidence (e.g. a
**Prototype:** pointer) when it drove the change.
At Status: implemented both files are frozen: a change to either one requires
supersede (product code depends on the decision, and the reasons it was taken are
part of the audit trail): present a warning and offer to switch approach. migrate
is the one exception, because it moves text without changing it. supersede also
stays available at any maturity for a genuine reversal you want recorded as a
distinct decision.
When the ADR is still in the single-file shape, offer migrate for it first.
Subcommand: promote {id} {maturity}
Advance an ADR along design → prototyped → implemented and propagate its
consequences to the layers the new maturity reaches.
- Verify the ADR exists and the transition is a forward step. Reject skips and
downgrades — refine the
Decisionin place withupdateinstead. - Update
**Status:** {maturity}in the decision file. Forprototyped, require a**Prototype:**pointer (which external repo validated it, and the evidence); forimplemented, note where in the codebase it lives. - Propagate / record evidence: confirm the design workspace reflects the
decision, then for each affected module invoke
/inspire-module review {module}to detect where the ADR's consequences are not yet reflected. Surface the gaps as follow-up actions. - Propose endorsement. Ask the operator whether to endorse the promoted
decision, then separately whether to endorse its rationale; on each explicit yes,
run
.inspire/bin/trust.sh endorse <file>on that file (trust-stamps).
Subcommand: supersede {id} {new-id}
Replace an ADR with a new one that changes its decision (create the new ADR first
via create).
- Verify both ADRs exist (the old one at any non-terminal maturity).
- Update the old decision file:
**Status:** superseded by [{new-id}]({new-slug}.adr.md). Its rationale stays as it is. - Update the new decision file's header:
Supersedes: [{old-id}]({old-slug}.adr.md). - Search
inspire_kb/for links to the old ADR's file name; propose updating each path.
Subcommand: migrate [{id}…]
Split ADRs written before the pair existed: one file holding all five sections. With
no ids it takes every single-file ADR: every *.adr.md under inspire_kb/01_spec/
with no rationale beside it. A project's KB is the
operator's, so an upgrade never runs this on its own: /inspire:update offers it, and
the operator runs it.
- List. Run
.inspire/bin/adr-split.sh --list(or with the ids' paths). Nothing listed means nothing to do. - Disclose. For each listed file carrying
endorsed:, say that the split rewrites content that person endorsed, and on which date (trust-stamps). - Split. Run
.inspire/bin/adr-split.shon the listed paths. It moves every line verbatim: the frontmatter, the header and## Decisionstay in{slug}.adr.md, a**Rationale:**link joins the header, and every other section moves, in order, to{slug}.adr.rationale.mdbeside it. It reports one line per file:split, orskippedfor a file with no## Decisionsection. Write that section with the operator for each skipped file, then run the script on it again. - Trim each decision. The old template asked
## Decisionfor "what we decided and why", so many of them carry reasons. For each split ADR, read## Decisionand show the operator the sentences that fail the test in the decision and its rationale, with the proposal to move them, word for word, to the end of the rationale's## Context. Move them on a yes. This step changes no word either, so it is allowed atimplementedtoo. A decision whose every sentence binds needs no question. - Stamp both files of every pair (rule 6 below). Propose no endorsement: nothing was decided.
Rules
Output language. Write every ADR in the project's declared
output_language(default English), per_references/output-language.md. Applies whatever language the conversation is in; machine-read tokens (frontmatter keys/values, link paths, filenames) stay verbatim.
Writing contract. ADR prose follows
_references/writing-style.md.## Decisionin the decision file and## Context,## Consequencesand## Alternatives consideredin the rationale are normative prose (R1–R6);**Modules affected:**and any tabular section are structured (R3, R4, R6). R6 carries section-scoped exemptions this skill relies on — see the no historical language rule below.
Lesson capture. At a natural pause, when the operator's feedback should change how this skill behaves, offer
/inspire-lesson note— never auto-write a lesson. Protocol and ticket-vs-lesson routing:_references/lesson-capture.md.
- Maturity is explicit, and only
implementedis immutable.createdefaults todesignandpromoteis the only way forward; adesign/prototypedADR is refined in place withupdate, while changing either file of animplementedADR requiressupersede. - Propagate to the maturity's reach. Design-workspace coherence (features +
screen spec + horizontal prototype + specs) is required at every maturity;
prototypedadds a pointer to an external functional prototype,implementeda codebase reference. Surface gaps within that reach. - Grep references on rename/supersede. Always scan the vault when renaming an ADR or changing its ID.
- No historical language, per the writing contract. R6 of
_references/writing-style.md: an ADR describes the decision context, never a migration narrative. This rule is deliberately narrower than unconditional — the contract exempts### Breaking changescontent,## Related ADRs, the**Status:**line and aSupersedes:header, because this skill mandates those sections and a ban on their content would ban a required section. - Consult the task tracker (
/inspire-task list) for tracked items; don't re-open what's already ticketed. - Check and stamp every write. After an ADR file is written — the
decision, the rationale, or both — run
.inspire/bin/review.sh <file>on each one and fix what it reports on that file: every error, and every warning the operator does not choose to keep (write-checks). Then run, for each one,.inspire/bin/trust.sh stamp <file> --skill adr(trust-stamps); rewriting an ADR that carriesendorsed:is disclosed to the operator first (trust-stamps).
Related skills
/inspire-workspace— the global review checks ADR-propagation alignment (that consequences cohere across the design workspace within each ADR's maturity reach)./inspire-module—promotepropagates by invoking module review to surface where an ADR's consequences aren't yet reflected.
04 同仓库更多 Skills
update
Update this project's INSPIRE runtime to the installed plugin's version: report drift, re-materialize unchanged files, and refuse to clobber local edits. Use after /plugin update inspire reports a newer base.
migrate
Move this project's knowledge base from the layered layout (01_adr, 02_modules, 03_features, 04_domain, 05_screens and the surface roster) to the concept layout under inspire_kb/01_spec/, where every artifact has a typed extension, and convert its [[wikilinks]] to relative Markdown links. Run once, on purpose, after /inspire:update reports the layered layout or counts wikilinks. Rebuilds nothing that is already built.
init
Install the INSPIRE runtime into this repository: materialize the skills, validators, hooks and knowledge-base skeleton, register the hooks, and freeze the runtime version. Run once per project. Use when setting up INSPIRE in a new or existing repo.
inspire-workspace
Workspace-level validation: the global pre-PR review (orchestrating module + cross-module checks) and vault-structure validation. Use for the required pre-merge gate and top-level structure checks. ADR lifecycle lives in /inspire-adr; the task tracker in /inspire-task.
inspire-task
Task tracker: create / update / close / list / show tickets in inspire_kb/99_tracker/. A plain-file kanban (one Markdown file per ticket, no external tool) for tracking work, drift, and skill-feedback. Use to open, advance, close, or query tickets.
inspire-spike
Vertical spikes: register and harvest external functional-prototype repos. A spike is a narrow, deep, throwaway build in its OWN repo that answers 'can we build it as we think?'. Use to register such a repo (name/reference it, set up its learnings hygiene) and to capture its learnings into the vault as a gap analysis against the current project.