# Architecture Decision Review

> Run a rigorous, evidence-first review of an architecture or platform decision, land it as an ADR, and translate it into tracker stories. Use this whenever the user weighs two or more technical options and asks for advice, a recommendation, a comparison, or a justification — "should we use X or Y", "which project/platform should host this", "is it worth migrating", "help me justify this decision", "how much would we save" — even if they never say "ADR" or "architecture decision". Also use it when the user asks to draft or update an ADR, to create Jira/tracker stories from a design decision, or presents a decision already half-made and wants it validated. The heart of the skill is verifying the user's stated premises against primary sources before recommending, so trigger it even when the user sounds certain of the answer. Do NOT use it for generic technology overviews or casual comparisons with no project context to verify and no durable decision to record. Optionally takes any number of source arguments (GitH

- Skill: `qili09/architecture-decision-review` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds@latest add qili09/architecture-decision-review`
- Raw SKILL.md: https://api.skillmd.com/api/skills/qili09/architecture-decision-review/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Coding & Dev Tools
- Author: qili09 (https://skillmd.com/u/qili09)
- Updated: 2026-09-22
- Page: https://skillmd.com/skills/qili09/architecture-decision-review

---


# Architecture Decision Review

Turn "should we do A or B?" into a defensible, documented decision: verify the premises
against primary evidence, build a reviewable comparison, iterate on the stakeholder's
corrections, and land the result as an ADR the team can act on.

Why this shape: architecture decisions arrive wrapped in a framing ("A is more secure",
"B saves money") that is often stale or secondhand. The reviewer's value is not eloquent
prose about the framing — it is checking the framing against what the code, config, and
tickets actually say. Sometimes the evidence reverses the expected answer; that reversal
is the most valuable thing you can deliver, and it must be stated plainly, not softened.

## Arguments

Passed at invocation: $ARGUMENTS

The invocation string may carry two kinds of content, mixed freely; separate them by
shape:

- **Sources** (any number, optional): primary-source pointers for the review — a GitHub
  repo (`owner/name` or URL), a website or wiki URL, or a document (local file path,
  project-folder doc, tracker/Confluence link). Repo-looking values are read via
  `gh api`/clone, URLs are fetched, paths are read from disk.
- **The decision question** (optional): any remaining free text is the request itself —
  the decision to review ("should we split X into Y?"). Treat it exactly as if the user
  had asked it in chat; if free text appears both here and in the chat message, read
  them together as one request.

When sources are given, treat them as the pre-authorized starting set for Phase 1's
access preflight: read them *before* asking the user for links or access, and fold what
they show into the premise check. They seed the evidence base; they do not cap it — if
the claims in the request need sources beyond those passed, list the gap in the
preflight as usual. If a passed source is unreachable or ambiguous (a bare name that
could be several repos), say so explicitly rather than guessing.

When no sources are passed, nothing changes: derive the source list from the request
during the access preflight as Phase 1 already describes.

## Phase 1 — Verify the premise

Before comparing anything, identify the factual claims embedded in the request (costs,
security posture, platform maturity, who owns what, what already exists) and check each
against a primary source. Start with an access preflight: list the sources those claims
require (repos, trackers, billing, docs), confirm which you can actually reach, and ask
for missing links, credentials, or exports up front. If a source stays unreachable, do
not bluff evidence-gathering — run the review in explicit "claimed vs. verified" mode
and say which conclusions rest on unverified claims. Tool mechanics below use GitHub
and Jira as examples; adapt to whatever SCM and tracker the project actually uses.

- **Prior art before primary sources**: locate and read the project's own earlier
  analyses of the same decision — assessments, ADRs, design docs in the project folder,
  wiki pages, ticket attachments. The decision usually has a paper trail; it may already
  answer questions you would otherwise flag as unverified, and a current claim that
  contradicts the paper trail is itself a finding. Skipping this step produces redundant
  asks to stakeholders that later need retracting.
- **Repos and infrastructure-as-code**: read them directly. For GitHub repos, `gh api`
  lets you inventory without cloning — list branches by last-commit date as a signal
  for the live branch (the default branch is often stale, but recency alone misleads in
  repos using release branches or trunk-based deploys; corroborate with deploy/CI
  config and protected-branch settings), fetch the file tree
  (`git/trees/<branch>?recursive=1`), then pull the specific files that answer the
  question (env configs, module lists, sizing). Quote any `gh api` URL containing `?`
  (zsh treats it as a glob and fails with "no matches found"). What *exists* in the repo — and what is
  commented out, placeholder, or dormant — is evidence the user's summary may not reflect.
- **Tickets**: read the actual issue tree, not just the top-level item. Children of an
  epic/initiative live on the *children's* parent field — search for them; do not
  conclude "nothing exists" from an empty subtask list.
- **Behavioural claims get a literal observed-behaviour pass, not spot checks**: when a
  claim describes how a system behaves ("all paths redirect to one destination", "every
  record type goes through X"), enumerate and probe the input space exhaustively —
  all record types, path variants, methods, headers, from an external vantage point —
  *before* comparing against the document. The document's own claims must not define
  the probe set: a spec that says "all paths" checked with two paths is not verified,
  and the miss it hides (a case-sensitive prefix rule routing to a different
  destination) can be a blocking error in both the document and the recommended option.
  **On a second-round review, replay the same probe set against the new implementation**
  — the author's own verification table is bounded by the author's model of the
  behaviour, so "every behaviour is now measured, all checks pass" can be literally true
  and still miss the case the first round flagged. A parity claim is verified only when
  the reviewer's probe set passes against the new system, not when the author's does.
- **Record what you could not test as claimed, not as skipped**: when the review machine
  lacks the tooling to reproduce an author's forcing fact (no cloud CLI, no access to the
  failing account), check it against vendor docs, release notes and public issue trackers,
  say what those show, and carry it as "claimed — high/low plausibility — unverified here"
  with the confirmation path named. The recommendation may still rest on it, but the
  artifact must show that it does.
- **Activity signals**: last-commit dates, merged-PR recency, and which environments
  actually exist distinguish a live platform from a stalled one. "Reinstate project X"
  means something very different when X turns out to be dev-only with prod commented out.
- **Forecast inputs are not verifiable facts**: vendor roadmaps, procurement lead
  times, commercial quotes, staffing plans. Record each with source, date, confidence,
  and owner, and keep them visibly distinct from observed evidence in the comparison —
  a forecast presented as a verified fact is the premise-check failing at its own game.

Report what you verified, what contradicted the framing, and what you could not verify.
Unverifiable claims stay in the analysis but are explicitly marked ("unconfirmed — verify
with the owning team before citing this in a memo"). Never let an unverified claim be a
recommendation's load-bearing support.

## Phase 2 — Build the decision artifact

Produce a single reviewable surface the stakeholder can annotate, structured so the
conclusion is visible in ten seconds and every claim beneath it is traceable to evidence.
If the lavish skill is available, build it there (HTML in `.lavish/`, open a session,
poll for annotations). Always attempt the launch — past server or polling failures are
not a reason to pre-emptively skip it, and neither is a harness "non-interactive" flag:
what matters is whether the user can open a browser, and they usually can. If the server
or poll fails *during this run*, the downgrade is scoped to feedback collection: the
built artifact stays the deliverable, and stakeholder feedback moves to chat; do not
silently drop the visual report. Otherwise (lavish unavailable, or `lavish-axi` itself
fails) write a standalone document (markdown or HTML) with the same structure:

1. **The decision, named, at the top** — one line stating what is being decided and by
   when it matters.
2. **Recommendation banner** — the chosen option, the one-sentence reason, and the
   headline numbers. Never bury the verdict.
3. **One card per option** — for each: what the evidence actually shows (tables of
   facts with sources), genuine strengths stated fairly, and why it wins or loses.
   Every option gets its strengths acknowledged — a comparison where the losers have no
   redeeming qualities reads as (and usually is) motivated reasoning. Rank *all*
   options, not just first place; the runner-up matters when conditions fail.
4. **Sub-decision table** — when the decision decomposes into named sub-decisions (a
   reviewer's question list, design choices inside the winning option), give each its
   own row or control: the question, the recommendation pre-selected, and the one piece
   of evidence that decides it. Don't fold them into option-card prose — reviewers
   answer itemized questions; buried ones come back as another review round.
5. **Cost/effort comparison table** — one column per option, one row per cost driver,
   with totals for recurring cost AND one-time effort. Cost rules:
   - Ranges, not points ("≈ $710–745/mo"), with the basis stated (list price, region,
     ±% confidence, currency and conversion rate).
   - Include elapsed time and process friction as costs (a "free" option that requires
     a ticket per change is not free).
   - Say how to firm the numbers up (pricing calculator, billing export) — estimates
     justify a decision, they do not go in a budget.
6. **Concern → mitigation** — take the stakeholder's stated worries seriously, one row
   each: the concern, the standard mitigation, and what residual risk remains.
7. **Adoption conditions and revisit triggers** — a recommendation is rarely
   unconditional. Name the sign-offs it depends on (security review, owner agreement,
   privacy assessment) and the events that reopen the decision (a dependency getting a
   committed date, a scope change). For interim decisions, time-boxing with explicit
   revisit triggers is what makes "interim" honest. Some locks are phase-scoped rather
   than permanent: record what the lock holds *while* ("cached reference data while the
   batch channel exists") and the event that expires it.
8. **Q&A section** — grows during review (Phase 3); answers to stakeholder questions
   live in the artifact so the document stays self-contained for later readers.

Scale the artifact to the decision's stakes: a small or easily reversed decision may
compress sections 4–8 into a short paragraph each; sections 1–3 are never skipped.

Throughout: values not yet decided stay **TBD** with the deciding owner named. Do not
invent a concrete hostname, region, or sizing to make prose flow — a plausible-looking
invented value gets copied into tickets and becomes accidentally load-bearing.

## Phase 3 — Iterate on review feedback

Stakeholder annotations come in three kinds; handle each differently:

- **Corrections** ("that's not stored here", "those aren't the same users"): apply them
  in place, weaken or delete the disproven claim, and — critically — say out loud
  whether the correction changes the recommendation or only its supporting detail. If
  a correction strengthens the *other* option, acknowledge it; credibility of the final
  ADR depends on the review having been adversarial.
- **Questions** ("what does DPIA mean?", "will this need a public URL?"): answer both
  in chat and in the artifact's Q&A section. Questions reveal what the eventual ADR
  readers will also not know — a question asked once in review should be answered
  permanently in the document.
- **New options** ("we could also deploy on-prem"): late options get first-class
  treatment — a full card, a column in the cost table, an honest re-ranking. Never
  bolt a late option on as a footnote to protect the existing recommendation.
- **End-state visions** ("eventually we'll call the API directly and store nothing
  locally"): when the stakeholder is right about a future state but not about today,
  neither defend the recommendation unconditionally nor cave — scope it. Name the
  vision as an explicit later phase with its own gating dependency, record which of
  today's locks expire when that phase arrives, and re-grade your supporting reasons
  honestly: conceding that three of four are transitional costs nothing if the fourth
  still carries today's decision. This converts a stalemate about the future into
  agreement about sequencing.

Keep iterating until the stakeholder stops finding corrections. If the stakeholder
goes quiet or is unavailable, do not stall: deliver the artifact as a review-ready
draft pending their validation, with open questions and unverified assumptions called
out. The final chat message after each round must summarize what changed and re-state
the current recommendation.

## Phase 4 — Land the ADR

When the stakeholder asks to record the decision:

1. **Match the house style.** Read one or two existing ADRs or assessments wherever the
   project keeps them — `docs/adr/` in a repo, a project document folder, a wiki — and
   mirror their structure, numbering, tone, and length. If none exist, use: title,
   status, context, decision, consequences.
2. **Status reflects reality.** If sign-offs are pending, the ADR is `proposed` with the
   conditions listed as a numbered section — not `accepted` with hopes.
3. **Context section carries the comparison**, compressed: each rejected option gets a
   sentence of genuine strength and a sentence of why it lost, with the key numbers.
   The ADR is what future readers find; the artifact may be gone.
4. **Decision details are concrete**: the actual mechanism (which repo, which pattern,
   which shared resources, what stays isolated), plus a portability/exit note if the
   decision is interim.
5. **Consequences include the revisit triggers** and any constraint the decision
   places on future work.
6. **Ripple the decision through companion docs**: amend superseded ADRs (an
   `Amendments` section with date, not a rewrite), update the project's agent/context
   docs (e.g. CLAUDE.md) if the project uses them to record constraints, decisions, or
   open questions, and the solution-architecture doc if one exists. An ADR that contradicts the docs around it is worse than no ADR. Ask the
   user before adding change-log entries if the project has that convention.
7. **Respect the repo's contribution rules** (when the ADR lives in a repo): if main is
   protected, commit to a fresh branch and open a PR; follow the project's attribution
   and commit-message norms.
8. **Close the loop on the originating thread.** Reviews usually start somewhere — a
   ticket comment, a review request, a thread. The conclusions go back there as a reply
   that answers the questions actually asked and points to the ADR; an ADR alone is
   invisible to the people waiting in the thread. Tracker-comment mechanics are in
   Phase 5 step 5 — they bite here too.

## Phase 5 — Translate the decision into tracker stories

A landed ADR changes the work plan; if nobody turns it into tracked work, the decision
exists only on paper. When the user asks to create stories from the decision (or once
the ADR lands, offer to):

1. **Read the existing tree before adding to it.** Find the epic the work belongs
   under and enumerate its current children — in Jira, children hang off the
   *children's* `parent` field, so search (`parent = <epic>`), don't trust the epic's
   own subtask/link lists. You are looking for two things: where the new work belongs,
   and which existing stories the decision has superseded or re-scoped. Creating new
   stories while stale ones still say the opposite makes the plan incoherent.
2. **Derive stories from the ADR's own structure.** Adoption conditions become stories
   (each sign-off is work someone must drive); each concrete mechanism in the decision
   details becomes a story (the onboarding, the credential setup, the DNS/cert work,
   the pipeline change). Give every story: a Context section citing the ADR, verifiable
   acceptance criteria (not vague intents), and its dependencies on sibling stories.
3. **Draft first, create second.** Writing to a shared tracker is externally visible —
   save the full drafts to a local file and show the user a summary for approval before
   creating anything. The local file also means nothing is lost if tracker access turns
   out to be broken. Check write access early: read-only API tokens/scopes are common,
   and discovering that while drafting is fine; discovering it after promising created
   tickets is not.
4. **Comment on superseded stories; don't edit or close them.** A comment stating what
   changed, which new stories replace which parts, and a pointer to the ADR gives the
   story's owner everything needed to re-scope — the status change is their call.
5. Mechanics worth knowing (Jira example): when the MCP/tracker integration is wedged
   and you fall back to direct REST, note Jira Cloud removed the legacy search endpoint —
   `GET /rest/api/2/search` returns 410 Gone; use `GET /rest/api/3/search/jql?jql=...&fields=...`
   instead (single-issue `issue/<key>`, `user?accountId=`, and attachment `content` reads
   still work on v2 with the same bearer token). Many REST v2 setups accept wiki markup in
   descriptions (`h2.`, `*bold*`, `{{code}}`, `*` bullets), but some instances require
   ADF or plain text — confirm the format with one test ticket before batch-creating.
   Create with `project`, `issuetype`, `parent` (the epic), `summary`, `description`.
   Verify after creating by re-running the parent search. Comments have extra traps:
   markdown→wiki converters commonly strip code spans and turn multi-underscore
   identifiers into emphasis (`list_skip_codes` renders as list*skip*codes) — prefer
   hyphenated or descriptive phrasing for identifiers in comments, and check the
   returned body after the first write. Comments usually cannot be deleted through the
   API, only edited — a regretted comment can only be repurposed, so the draft-first
   gate matters double. Don't promise @-mentions until you've confirmed you can resolve
   account IDs; plain names are the safe fallback.

## Principles that run through every phase

- **Draft first, write second — for every externally visible write.** ADR commits,
  doc amendments, PRs, tracker tickets, and comments all get the same gate: show the
  user the proposed content or diff and get approval before writing. The phase-specific
  rules below are instances of this one rule, not exceptions to it.
- **The premise check is the product.** If the evidence supports the user's initial
  lean, say so and quantify it. If it reverses it, lead with the reversal and show the
  evidence. Either way the user should leave knowing *why*, not just *what*.
- **Distinguish structural findings from practical ones.** "This couples our exit to
  another team's migration" (structural, hard to mitigate) outranks "this costs $200/mo
  more" (practical, budgetable). Make the ranking's real driver explicit.
- **Flag reversible sub-decisions.** When part of the choice can be cheaply undone later
  (a dedicated load balancer for $18/mo, a separate database instance), say so — it
  lowers the stakes of the main decision and defuses stalemates.
- **UI adjacency is not network adjacency; identity is not co-location.** More
  generally: when a stakeholder argues from proximity ("it's embedded in X so it must
  live near X"), separate the planes — presentation, network, data, identity — and show
  which plane the requirement actually lives on.

## Learning loop

When a run hits friction this skill didn't anticipate — a wrong assumption, a missing
step, a tool mechanic learned the hard way — append a dated note to `FIELD-NOTES.md`
in this skill's directory *at the moment it happens*, not in an end-of-run recall pass.
A clean run records nothing; do not manufacture observations. If the run produced notes,
offer the user a skill retro at the end; codify into SKILL.md only patterns the user
approves (recurring themes earn instructions, one-offs stay as notes), and clear
codified entries from the notes file.

