# Architecture Decision Record (ADR) Guide

## CIDM 6330/6395 — Student Reference

---

## What Is an ADR?

An **Architecture Decision Record** captures a single design decision for your
project: what you decided, why you decided it, and what the consequences are.

Think of it as a **lab notebook entry for software design**. Scientists don't
just record results — they record what they tried, why they tried it, and what
happened. ADRs do the same for architectural choices.

### What Counts as an "Architecture Decision"?

Any choice that would be **hard to reverse later** or that **affects how the
whole system works**:

| Decision | Why It's Architectural |
|----------|----------------------|
| "We'll use SQLite instead of PostgreSQL" | Changes how every database interaction works |
| "Authentication will use JWT tokens" | Affects every endpoint, frontend, and test |
| "The API will be REST, not GraphQL" | Determines how clients consume data |
| "We'll separate billing into its own service" | Changes deployment, testing, and data flow |
| "Course search will use a local index, not live queries" | Affects performance, freshness, and complexity |

Things that are **not** ADRs: bug fixes, code formatting choices, which IDE
to use, variable naming conventions. These are important but reversible.

---

## Why Write ADRs?

### The Knowledge Loss Problem

You make a design decision today. Three months from now:

- You forget *why* you chose that approach
- A teammate joins and asks "why is it done this way?"
- You consider changing it but can't remember the tradeoffs

Without an ADR, you either:

1. Waste time re-discovering the reasoning, or
2. Make a change that re-introduces a problem you already solved

### The Communication Problem

On a team (or with an AI coding assistant), decisions need to be **shared and
explicit**. An ADR ensures everyone — including future-you — knows:

- What was decided
- What alternatives were considered
- What tradeoffs were accepted

### The Accountability Problem

When working with AI coding assistants (Claude, Copilot, etc.), the human
must remain the **architect**. ADRs are how you prove you made the design
decisions, not the AI.

> "The human is index zero — first in priority, final in authority."
> — gzkit Zero Doctrine

---

## How to Write an ADR

### Step 1: State the Intent (2-3 sentences)

What specific problem or capability does this decision address? Connect it
back to your PRD.

**Weak:** "We need a database."

**Strong:** "Course registration requires persistent storage of student
enrollments, schedule conflicts, and course metadata. The storage layer must
support concurrent reads during peak registration periods and survive server
restarts."

### Step 2: Record the Decision

State what you decided as a numbered list of concrete commitments:

```markdown
## Decision

1. Use SQLite as the persistence layer for v1
2. Store the database file at `data/courses.db`
3. Use the repository pattern to abstract database access
4. Support in-memory SQLite for testing
```

Each item should be **specific enough to implement**. If a teammate reads
this list, they should know exactly what to build.

### Step 3: Document Consequences

Every decision has tradeoffs. Be honest about both sides:

```markdown
### Positive
- No external database server to install or manage
- SQLite is included in Python's standard library
- File-based storage simplifies backup and portability

### Negative
- SQLite has limited concurrent write support
- No built-in replication or high-availability
- Will need migration if we outgrow SQLite
```

### Step 4: List Alternatives Considered

What else did you consider, and why didn't you choose it?

```markdown
## Alternatives Considered

- **PostgreSQL** — Better concurrency, but requires server
  setup that adds complexity for a class project
- **MongoDB** — Document model doesn't fit our relational
  course/student data well
- **Plain JSON files** — Too fragile for concurrent access;
  no query capability
```

This section is critical because it shows you **thought through options**
rather than grabbing the first thing that came to mind.

### Step 5: Create a Feature Checklist

Break the decision into **observable outcomes** — things you can demonstrate
or test when the work is done:

```markdown
## Feature Checklist

1. [ ] Database schema created with courses, students, enrollments tables
2. [ ] Repository class with find, save, delete operations
3. [ ] In-memory adapter for unit tests
4. [ ] Migration script for schema changes
5. [ ] CLI command to initialize the database
```

Each checklist item becomes a **task** (see [Task Guide](guide-tasks.md)).

---

## Anatomy of an ADR

```text
ADR-NNN: Title
   │
   ├── Metadata ...................... ID, status, date, author
   ├── Intent ........................ WHAT problem are we solving?
   ├── Decision ...................... WHAT did we decide?
   ├── Consequences .................. WHAT are the tradeoffs?
   │     ├── Positive
   │     └── Negative
   ├── Alternatives Considered ....... WHAT else did we consider?
   ├── Feature Checklist ............. WHAT are the observable outcomes?
   └── Approval ...................... WHO reviewed and agreed?
```

---

## ADR Lifecycle

An ADR moves through these states:

```text
Draft ──→ Proposed ──→ Accepted ──→ Completed
                          │
                          └──→ Superseded (replaced by a newer ADR)
                          └──→ Abandoned (decision reversed)
```

| Status | Meaning |
|--------|---------|
| **Draft** | Still being written; not ready for review |
| **Proposed** | Ready for review by instructor/team |
| **Accepted** | Approved; implementation can begin |
| **Completed** | All checklist items done and verified |
| **Superseded** | Replaced by a newer ADR (link to it) |
| **Abandoned** | Decision was reversed; record why |

---

## Common Mistakes

| Mistake | Why It Hurts | Fix |
|---------|-------------|-----|
| Too many decisions in one ADR | Hard to track status; partial completion is ambiguous | One decision per ADR |
| No alternatives section | Looks like you didn't think it through | Always list at least 2 alternatives |
| Vague decision statements | "Use a good database" — which one? How? | Numbered, specific commitments |
| Skipping consequences | You'll forget the tradeoffs you accepted | Be honest about negatives |
| Never updating status | ADRs rot; nobody knows what's current | Update status as work progresses |
| Writing ADRs after implementation | It becomes documentation, not a decision record | Write the ADR *before* you code |

---

## ADRs in Practice: A Small Example

Suppose your PRD says: "Students need to search for courses by department,
time slot, and instructor."

**ADR-001: Course Search Implementation**

- **Intent:** Enable students to search courses using multiple criteria
  without requiring a full-text search engine.
- **Decision:**
  1. Implement search as filtered SQL queries against the courses table
  2. Support filtering by department, time slot, and instructor name
  3. Return results sorted by course number
  4. Limit results to 50 per page
- **Positive consequences:** Simple, no external dependencies, fast for
  our data size (~500 courses)
- **Negative consequences:** Won't scale to full-text search; no fuzzy
  matching
- **Alternatives:** Elasticsearch (overkill), whoosh (extra dependency),
  in-memory filtering (slow for large datasets)
- **Checklist:**
  1. Search repository method with filter parameters
  2. Unit tests for each filter type
  3. CLI or API endpoint for search
  4. Results pagination

---

## Creating an ADR in gzkit

gzkit provides both CLI commands and skills for ADR creation.

**CLI (terminal):**

```bash
gz plan 0.1.0 --title "Course Search Implementation"
```

**Skill (Claude Code session):**

```text
/gz-plan
```

The `/gz-plan` skill is strongly recommended — it runs 20+ design
forcing-function questions (pre-mortem analysis, constraint archaeology,
reversibility assessment) that the raw CLI skips entirely. These questions
surface risks and alternatives before you commit to a decision.

For design exploration before committing to an ADR:

```text
/gz-design
```

The `/gz-design` skill runs a collaborative design dialogue that produces
ADR artifacts after structured brainstorming.

---

## From ADR to Tasks

Once an ADR is accepted, each checklist item becomes a task (called an
**OBPI** — One Brief Per Item — in gzkit):

```text
ADR-001: Course Search Implementation
  ├── Task 1: Search repository method with filter parameters
  ├── Task 2: Unit tests for each filter type
  ├── Task 3: CLI or API endpoint for search
  └── Task 4: Results pagination
```

In gzkit, decompose checklist items into OBPI briefs:

| CLI | Skill | What it does |
|-----|-------|--------------|
| `gz specify slug --parent ADR-0.1.0 --item 1` | `/gz-obpi-specify` | Create and semantically author the OBPI brief |

The `/gz-obpi-specify` skill performs lane resolution from the ADR's WBS
table and validates decomposition scorecard alignment — raw CLI generates
thin placeholder briefs that require manual authoring.

See: [Task Guide](guide-tasks.md) for how to structure these.

---

## Template

A ready-to-use ADR template is available at:
[templates/adr-template.md](templates/adr-template.md)

---

## Video Companion

See [Part 3 of the video tutorial series](presentations/part3-script.md) for
a narrated walkthrough of the ADR template, the decomposition scorecard, and
the reading list example.

## Further Reading

- [Michael Nygard's original ADR proposal](https://cognitect.com/blog/2011/11/15/documenting-architecture-decisions)
  — The format that started it all
- [adr.github.io](https://adr.github.io/) — Community resources and tooling
- [gzkit ADR examples](https://github.com/tvproductions/gzkit/tree/main/docs/design/adr) — Real ADRs used to govern this tool
- [PRD Guide](guide-prd.md) — How PRDs feed into ADRs
