The Decision Archive
how teams stop relitigating the same calls every quarter
Every team has the same conversation twice a year. "Should we use Postgres or Mongo?" "Why did we pick this vendor again?" "Wait — didn't we already decide that?" The decision was made; the reason evaporated; nobody on the team can find the receipt. So you re-do the discovery, re-have the meeting, re-decide.
The Decision Archive is a markdown discipline that fixes it: one record per decision, append-only, written in a shape your AI can read. When someone asks "have we considered X?" the AI answers from decisions.md — with status, alternatives, and why-this-one — in five seconds.
This module is T02 of the Team Brain track. T01 (the Shared Folder) is the prerequisite — that's where decisions.md lives.
An ADR — Architecture Decision Record, though the pattern works for any kind of decision — is the smallest unit your archive can hold. Five lines. No more. The whole point of the discipline is that nobody reads anything longer.
## 2026-05-19 · Postgres for analytics, not Mongo **what:** Use Postgres (with timescaledb) for the analytics store. **why:** SQL skills already on team; joins to billing data; smaller ops surface than running Mongo + Postgres. **alternatives:** Mongo (rejected: no SQL; ops overhead). Snowflake (rejected: $$$ at our scale). DuckDB local-only (rejected: no concurrent writes). **status:** decided **date:** 2026-05-19
Each line earns its place. Drop one and the record stops being useful.
// what
One sentence. The actual choice. Not the rationale, not the context — just the verdict. If you can't fit it in one sentence, the decision isn't crisp enough yet; go back to the meeting.
// why
Two or three clauses, separated by semicolons. The reasons that actually drove the call — not the post-hoc justification you'd put in a memo. Six months from now this line is the only thing that stops the team from reopening the question; if it's hand-wavy ("seemed right"), the AI can't defend the decision and someone will relitigate it.
// alternatives
The 2–4 options you didn't pick, with a one-line reason for each rejection. This is where teams cheat. The honest version names the real losers; the cheating version lists only the option you picked, or lists straw-man alternatives that nobody actually proposed.
// status
One of three values. Nothing else:
open— we've articulated the question but haven't picked yet. The record exists so the team can find it and pre-empt re-discovery; the verdict line is[TBD].decided— we picked, it's in flight or shipped, and nothing has overturned it. The default end-state for most ADRs.superseded— a later ADR overruled this one. The old record stays in place; only the status flips. (Full pattern: section 05.)
// date
ISO-8601 (YYYY-MM-DD). Use the date the decision was made, not the date the ADR was written. If the ritual is working, those are usually the same day; if they drift more than a week apart, your promotion ritual is broken.
Decisions don't crystallize in a vacuum. They emerge from a 45-minute meeting where six people argued, a slack thread that ran for three days, and a hallway conversation nobody wrote down. The job of the promotion ritual is to compress all of that into five lines at the moment the decision is real — before the context evaporates.
You run it once, at the end of any meeting where a real call got made. You give the AI three things: the relevant opens entry from state-shared.md (T01 of this track), the meeting transcript fragment, and the slack snippets that fed the discussion. You get a draft ADR back; the steward edits and appends.
Act as my decision archivist. I'm promoting a stuck-open question into a decided ADR. Inputs: 1. The original "opens" entry from state-shared.md (the line the team had been carrying as undecided): --- [paste opens entry] --- 2. The transcript fragment from the meeting where we picked (just the section where the decision crystallized): --- [paste transcript] --- 3. The slack thread(s) that fed the discussion: --- [paste slack snippets] --- Output a 5-line ADR in this exact shape: ## YYYY-MM-DD · [title] **what:** [one sentence] **why:** [2-3 clauses; the reasons that ACTUALLY drove it] **alternatives:** [2-4 options not picked, one-line reason each] **status:** decided **date:** YYYY-MM-DD Rules: - No more than 5 lines after the header. - "why" must be the real reasons, not post-hoc justification. - "alternatives" must name real options the team weighed. Don't invent straw-men. - If the inputs don't actually show a decision being made (just discussion), say so and DON'T draft — flag it as still-open.
A typical output, run against the analytics-store discussion above:
## 2026-05-19 · Postgres for analytics, not Mongo **what:** Use Postgres (with timescaledb) for the analytics store. **why:** Existing SQL skills on team; need joins to billing rows which already live in Postgres; smaller ops surface than running two databases. **alternatives:** Mongo (rejected: SQL gap, doubled ops); Snowflake (rejected: cost at current volume); DuckDB embedded (rejected: no concurrent-write path). **status:** decided **date:** 2026-05-19
The steward eyeballs the draft, fixes anything that drifted from the real conversation (the AI often softens the rejection reasons — harden them back up), and appends it to decisions.md. Total time: under 5 minutes per decision.
// the "is this actually decided?" check
The prompt's last rule is load-bearing. The most common failure mode of the promotion ritual isn't a bad ADR — it's an ADR that shouldn't have been written yet because the team didn't actually decide. They discussed. Someone said "we're leaning Postgres," nobody objected, and the meeting ended. That's not a decision; that's a soft consensus that won't survive the next sprint.
open, leave the question in state-shared.md, and run promotion again the next time the team genuinely picks. Premature ADRs are worse than no ADR; they tell the AI a question is settled when it isn't.// when to run it
Three triggers:
- End of any decision-bearing meeting. Steward (or anyone) blocks 10 minutes at the bottom of the agenda to promote.
- Slack thread reaches a verdict. Someone in the thread says "ok, let's go with X" and nobody pushes back for 24 hours — promote.
- Friday promotion (section 06). The weekly sweep catches anything the first two missed.
An ADR archive has to live somewhere — somewhere every teammate's AI can read it on demand, somewhere the steward can append to it without ceremony, and somewhere the team's permission model already works. There are three places that fit, in order of looseness. Pick one; running two paths in parallel is how you end up with two archives that drift.
AFilesystem
A decisions/ directory in the repo (or a synced shared drive). One markdown file per decision, filename = ISO date + slug. decisions.md at the root of the directory is an auto-generated index.
Single source of truth. Versioned. Greps cleanly. Works with any filesystem-aware AI (Claude Code, Cursor, Windsurf, Copilot Agent, Aider).
Pros: git history is the audit trail; PR review for changes; works offline. Cons: requires git literacy from non-engineers; mobile editing is rough.
BShared Project
One ChatGPT Team / Claude Team / NotebookLM / M365 Copilot Project, owned by the team, with the four T01 files (including decisions.md) attached. Every session in that Project auto-loads the archive.
Cloud-collaborative. Permissions ride on your provider's team plan. Teammates can fork the Project for personal experiments without touching the shared copy.
Pros: no install; non-technical teammates onboard in 60 seconds; provider handles backup. Cons: vendor lock-in; no diff history on the file itself; "who edited this?" sometimes opaque.
CLinked archive
Decisions live in Notion / Confluence / Airtable / a shared Google Doc. The AI reads via a web-fetch tool or by working off a periodic export.
Loosest binding. Works when the team already has a wiki culture and the steward refuses to move the archive into a new tool.
Pros: meets the team where it is; rich formatting; non-technical-friendly. Cons: AI access is fetch-shaped, not native; stale exports lie silently; the index has to be rebuilt by hand.
// setup · path A (filesystem)
- Create
decisions/at the repo root (or in the team's shared drive root). - For each decision, write a file named
YYYY-MM-DD-slug.md— e.g.2026-05-19-postgres-vs-mongo.md. The slug is short, kebab-case, and uses the two real contenders so the filename greps cleanly. - Keep a
decisions.mdat the directory root as a reverse-chronological index (date · title · status · file link). Auto-generate it from the per-file frontmatter with a 20-line script in CI; never hand-maintain. - Add
decisions/toCLAUDE.md/AGENTS.mdso filesystem agents auto-load it.
// setup · path B (shared Project)
- Spin up a new Project: name it
<team> · Team Brain. - Attach the four T01 files.
decisions.mdhere is one growing file (not a directory) — append, newest first. - Give the project a one-paragraph system prompt: "decisions.md is the team's append-only decision log. When asked about a past decision, cite the ADR by date + title. Never edit a past entry; instead draft a new superseding entry."
- Add 1–2 backup stewards as co-owners so the Project doesn't go dark when the primary steward is on PTO.
// setup · path C (linked archive)
- Pick one canonical surface: a Notion database, a Confluence page tree, an Airtable base. Don't span two.
- Schema mirrors the 5-line ADR:
what,why,alternatives,status(single-select: open / decided / superseded),date, plus asupersedeslink field. - Wire AI access: either a web-fetch tool that hits the page URL, or a nightly export (Notion → markdown, Confluence → XML) that lands in a folder the AI can read.
- Document the export staleness explicitly — "last sync: 2026-05-19 06:00 UTC" — so the AI flags itself when answering from a stale snapshot.
// the decision matrix
| If your team is… | … and tooling is… | … pick |
|---|---|---|
| 2–8 engineers, shipping code daily | already in git, using a filesystem AI | Path A — the archive lives where the code lives; PR review for free. |
| Cross-functional product team (PMs, designers, eng) | on Claude Team / ChatGPT Team / M365 | Path B — the Project is the lowest-friction shared surface; PMs can append without git. |
| Distributed org with a wiki habit | Notion / Confluence is "where things live" | Path C — don't fight the culture; wire the AI to the existing wiki. |
| Regulated / high-privacy | local-first AI required | Path A on a private git remote — archive never touches a vendor's cloud. |
| One-steward team, mostly non-technical | no git, no team plan budget | Path C in a free Notion workspace — cheapest path that still gives the AI something to read. |
An archive that can't be searched is a graveyard. The decisions browser is a single prompt the team uses dozens of times a month — pre-meeting, mid-meeting, in slack, in code review — to answer "have we already discussed this?" in five seconds instead of five minutes.
Act as my decisions browser. Search the team's decisions archive for entries where: - status = $status (open | decided | superseded | any) - topic ~ $topic (free-text match against what + why + title) - date_from = $from (YYYY-MM-DD, inclusive; or "all") - date_to = $to (YYYY-MM-DD, inclusive; or "today") Return as a markdown table sorted by date desc: | date | title | status | what (one line) | link | If zero matches, say so explicitly and suggest the 2-3 nearest-neighbour entries (different topic, similar shape). Don't fabricate ADRs that aren't in the archive.
You don't fill the variables before pasting — the AI prompts you for whichever ones matter. topic = "analytics store", status = any, date_from = all — and you get back every ADR that ever touched the analytics-store question, including the one you wrote in March and forgot about.
// variants worth memorizing
By owner. Add owner ~ $owner to the filter set when your ADR template includes a decided-by line. Useful for "what has Priya decided since she joined?" and for handovers when an owner leaves.
By tag. If you tag ADRs (tags: [database, performance] in the frontmatter), browse by intersection: tags includes database AND performance. Tags pay back fast once you have ~30 ADRs.
By date range. "What did we decide in Q1?" is a real question at planning time. Quarterly date-range browses also surface stale open entries that the Friday promotion (section 06) missed.
"Decisions like this one." Paste a freshly drafted ADR and ask: "Find the 3 closest prior decisions in the archive by shape and topic. For each, summarize whether it argues for or against the new one." This is the highest-leverage query the team runs — it catches "we already tried this two years ago" before you ship.
Before this meeting, scan decisions.md for any prior entries about "$topic" (use loose semantic matching, not just keyword). Return as: 1. Direct matches (entries about exactly this question) — table of date, title, status, one-line outcome. 2. Adjacent matches (different topic, similar tradeoff) — table same shape. 3. If we previously decided this and the status is still "decided," flag that the meeting may be unnecessary and ask if I want to reopen vs. revisit-context-only.
The third point is the relitigation-killer. The most common waste of a team's hour is "let's discuss the analytics store" when the analytics store was decided in March and nobody pulled the receipt. Run this prompt 60 seconds before the meeting and you either cancel the meeting or walk in already grounded in the prior verdict.
Decisions get overturned. The team picked Mongo in March, learned in May that the ops overhead was worse than expected, and the analytics-store question is back on the table. Don't edit the March ADR. Write a new one that supersedes it.
This is the single discipline most teams skip, and it's the one that determines whether the archive is worth anything in eighteen months.
// the rule
Past records are append-only. The only legal edit to an existing ADR is flipping its status from decided to superseded. Nothing else — not the what, not the why, not the alternatives, not the date.
// why this matters
The audit trail is the value. The reason you keep an archive isn't to know what the team picked — you can usually figure that out by looking at production. You keep it to know what the team tried, what they learned, and why they switched. That story only survives if the past records stay intact.
Edit a past ADR and three things break:
- The AI can no longer tell you what changed. "Why did we switch from Mongo?" — if the Mongo ADR has been silently edited to argue for Postgres, the AI tells you the team always wanted Postgres. Which is a lie. And the team can't remember enough to correct it.
- New hires lose the learning loop. The most valuable thing about
decisions.mdfor a new joiner is reading the sequence: "in March we picked X, in May we superseded it with Y, here's what we learned." Edited archives just say "we picked Y" with no story. - Auditors and reviewers can't trace the chain. For regulated teams, the supersedes chain is the audit artefact. Editing is, depending on jurisdiction, a compliance violation.
// the supersedes pattern
## 2026-03-14 · Postgres for analytics, not Mongo **what:** Use Postgres (with timescaledb) for the analytics store. **why:** Existing SQL skills; joins to billing; smaller ops surface. **alternatives:** Mongo (rejected: SQL gap); Snowflake ($$$); DuckDB (no concurrent writes). **status:** superseded · see 2026-05-19-snowflake-for-analytics.md **date:** 2026-03-14
Note: what, why, alternatives, and date are all unchanged. The reasoning that drove the March call was correct given what was known in March; the archive preserves it. Only status flips, with a pointer to the superseding entry.
## 2026-05-19 · Move analytics from Postgres to Snowflake **supersedes:** 2026-03-14 · Postgres for analytics, not Mongo **what:** Migrate the analytics store from Postgres+timescaledb to Snowflake; keep billing data in Postgres. **why:** Postgres analytics ops cost grew 3x as event volume passed 40M/day; team SQL skills transfer cleanly to Snowflake; separating analytics from billing reduces blast-radius on incidents. **alternatives:** Stay on Postgres + shard (rejected: 3-month project, doesn't fix ops fatigue); BigQuery (rejected: re-tooling overhead); ClickHouse self-hosted (rejected: same ops surface we're trying to escape). **status:** decided **date:** 2026-05-19
The new ADR is a full record. It reads cleanly on its own, AND the supersedes line gives the AI the breadcrumb to walk the chain backwards when someone asks for history.
what line, updates the date, calls it done. Now your AI confidently tells the team you've been on Snowflake since March. Nobody can find the Postgres period in the archive. The learning — "we underestimated event growth by 3x" — is gone. Don't do this. Ever. The five seconds you save by editing in place are paid back as fifty hours when someone tries to reconstruct what actually happened.The end-of-meeting promotion (section 02) catches most decisions. The slack-thread-verdict promotion catches a few more. But every team leaks open entries that nobody promotes — the question got asked, the room talked around it, no formal verdict, and three weeks later it's still sitting in state-shared.md as a stuck-open. The Friday promotion is the weekly sweep that drags those into the light.
// the ritual
Friday afternoon, 10 minutes, before the steward signs off. List every open decision older than 7 days. For each, force one of three outcomes:
- keep-open — legitimately not decidable yet (waiting on data, vendor, external party). Required: a one-line reason for why it's still open and a date the team will revisit.
- decided — the room has actually converged but nobody promoted. Run the section-02 promotion ritual now; append to
decisions.md. - killed — the question is no longer interesting. Maybe the project pivoted; maybe the constraint that drove the question evaporated. Write a one-line ADR with status
decidedandwhat: "Drop this question. [reason]."The record exists so the AI can answer "whatever happened to X?" cleanly.
The forcing function matters. Without it, open entries accumulate forever and the archive's signal-to-noise rots. Five stuck-opens in state-shared.md is healthy churn; fifteen is a sign the team has stopped deciding.
// the stuck-open symptoms
You can spot a real stuck-open without thinking too hard:
- The same
openentry has appeared instate-shared.mdfor 3 weeks running, with the same wording. - No comments, no slack chatter, no PR has touched the question since the first week.
- The original owner has moved teams, switched projects, or quietly stopped attending the standup where it's tracked.
- When you ask the team "what's the status on X?" you get a shrug and "I thought Priya was driving that."
Any one of these = a stuck-open. Two or more = the question needs to be killed, not decided. Forcing a fake "decided" on a stuck-open creates a phantom ADR that the team will revisit later anyway; the kill is more honest.
// the prompt
Act as my Friday decisions sweeper. Load decisions.md (or scan the archive at the path I gave you). List every entry where status = "open" AND date is more than 7 days ago (relative to today's date). For each, output: | age | date | title | original "what" line | owner if known | Sort by age descending (oldest first). Then, for each entry older than 21 days, flag it with one of: - LIKELY STUCK — matches 2+ stuck-open symptoms (no recent comments, owner change, repeated 3+ weeks) - WAITING ON EXTERNAL — reason references vendor, contract, data, external decision - AMBIGUOUS — not enough signal; ask the steward End with: a recommended action per entry (promote / kill / keep-open with new revisit date).
The steward runs this, walks the list with the team lead (or solo, if they have the authority), and forces a verdict on every line older than 21 days. 10 minutes, every Friday, without exception.
// why Friday
The day choice is not arbitrary. Monday is panic energy — the week ahead crowds out any willingness to close past loops. Midweek won't happen — the team is heads-down on the current sprint and any "sweep the archive" task slips. Friday afternoon is uniquely low-stakes: the current week's work is mostly resolved (or accepted to be Monday's problem), and the steward has the bandwidth to actually decide instead of deferring.
status: open drifts from "we're still deciding" to "we forgot about this," and the AI can't tell the difference. With it, every open entry in the archive carries an implicit guarantee: "we actively chose not to decide this yet." That guarantee is what lets the team trust the browser (section 04) when it answers "have we already settled this?"// the discipline that beats relitigation
- 5-line ADRs only.
what · why · alternatives · status · date. Anything longer doesn't get read; anything shorter doesn't have enough context to survive six months. - Supersede, don't edit. Past records are append-only. The only legal edit is flipping
statustosupersededwith a pointer to the new ADR. The supersedes chain is the institutional memory. - Friday promotion is non-negotiable. 10 minutes every Friday: list
openentries older than 7 days; force each to promote / kill / keep-open with a revisit date. Without the sweep,openrots into "forgotten." - Three deployment paths, pick one. Filesystem for engineering teams in git. Shared Project for cross-functional teams on Claude/ChatGPT/M365. Linked archive for wiki-cultured orgs in Notion/Confluence. Don't run two; they drift in three weeks.
- The browser turns 5 minutes into 5 seconds. The pre-meeting "have we discussed this?" query is the single highest-ROI prompt the team runs — it kills relitigation meetings before they start.