# ADR - Architecture Decision Record (lightweight)

> **What this is:** a short, durable note that captures *why* you chose what you chose - so the next person (and future you) isn't reverse-engineering the reasoning from the code. This is [Way #5: Keep it simple, write down the why](../../ways-of-working.md), anchored in `ENG-PRIN-DOC-STMT` (document decisions, not code - a decision must outlive the conversation it was made in).
>
> One decision per ADR. Half a page. AI may draft it; a human signs it ([Way #2](../../ways-of-working.md), `ENG-PRIN-REVIEW-STMT`). Delete the quote-blocks before you commit it.

---

## ADR-NNN: &lt;short imperative title - the decision, not the topic&gt;

> Title the *decision*, e.g. **"Compute team averages on the fly vs materialise them"** - not "Team averages". A good title reads like a verdict.

- **Status:** Proposed | Accepted | Superseded by ADR-NNN
- **Date:** YYYY-MM-DD
- **Deciders:** &lt;who was in the room&gt;

### Context
*What's the situation and the forces at play? What makes this a decision rather than an obvious call? Keep it factual.*

> e.g. "The `/compare` endpoint needs per-dimension team averages. The dataset is tiny (one team = 3 members, 6 dimensions). We could compute averages per request, or precompute and store ('materialise') them and refresh on write."

### Decision
*State the choice in one sentence, active voice. Then the one or two reasons that actually drove it.*

> e.g. "We compute averages on the fly per request. The data is small enough that the query is trivially cheap, and on-the-fly removes a whole class of staleness bugs - there's nothing to invalidate." (`ENG-PRIN-SIMPLE-STMT` - the simplest thing that works; don't add a cache you don't need yet.)

### Alternatives considered
*What else was on the table, and why it lost. One line each. This is the part future-you will thank you for.*

| Option | Pro | Con | Verdict |
|---|---|---|---|
| Materialise + cache averages | Fast at scale | Cache invalidation on every score write; staleness risk | Rejected - premature for this dataset (YAGNI) |
| Compute on the fly | No staleness, no cache | Recomputes each request | **Chosen** - cheap at this size |

### Consequences
*What becomes easier, what becomes harder, and what you're now on the hook to maintain. Be honest about the trade-off.*

> e.g. "Easier: no invalidation logic, simpler tests. Harder: if the org grows to thousands of members per scope, revisit and supersede this ADR. We accept that re-evaluation trigger explicitly."

### API & idempotency note (record this here, not in the code comments)
*If the decision touches the API surface, note the contract implications - this is where `REQ-API-6` reasoning lives.*

> e.g. "`/compare` and `/recommend` are **GET** - safe and idempotent by definition (`REQ-API-6`), so no `Idempotency-Key` header is required; a client can retry freely. **If** either ever becomes a write (e.g. a future `POST /compare/snapshot`), `REQ-API-6` requires an `Idempotency-Key` so retries after a dropped response don't double-apply. We are recording that boundary now so the next person doesn't have to rediscover it." This mirrors the inline note already in [`../../../../stacks/nextjs/openapi.yaml`](../../../../stacks/nextjs/openapi.yaml) - the ADR is where the *reasoning* lives; the OpenAPI file is where the *contract* lives. Keep them in sync (`REQ-API-2`).

---

*One ADR earns you points in the Feature Sprint. The five ways: [ways-of-working.md](../../ways-of-working.md).*
