# Definition of Done - Spec-First Build

> **What this is:** the bar your work has to clear to count as *done* - not "it runs on my machine", but *specified, contracted, tested, reviewed, and signed.* Every item cites the real corporate-standards ID it comes from, so this sheet is three things at once: a **gate** during the session, a **grading sheet** for facilitators, and a **takeaway** you keep for Monday.
>
> It is the practical form of [The 5 Ways We Work With AI](../ways-of-working.md). Print one per person.

**How to read it:**
- **MUST** items gate the **merge**. Miss one and the work is *not done* - it cannot pass [Gate 2](facilitator-guide.md) and cannot be scored as shipped.
- **SHOULD** items are quality points: they raise your score and they're what "good" looks like.
- The arc this enforces: **spec → contract → code → six-layer tests → human review.** Tick top to bottom.

| | | |
|---|---|---|
| **MUST** | gates merge | non-negotiable |
| **SHOULD** | earns points | what "good" looks like |

---

## Contract - *the machine-readable agreement*

| ✓ | Item | Level | Cite |
|---|------|-------|------|
| ☐ | The endpoint has a **machine-readable OpenAPI definition** (the contract is a file, not a conversation). | MUST | REQ-API-2 |
| ☐ | The contract is **kept in sync** with the implementation - the response the code returns matches the schema exactly. | MUST | REQ-API-2 |
| ☐ | The `/recommend` 200 response is a real `$ref` to a defined schema (`RecommendResponse`), **not a TODO**, and was frozen at Gate 1. | MUST | REQ-API-2, REQ-API-5 |
| ☐ | Errors use the **shared error envelope** (RFC 7807 `Problem` / problem+json), not ad-hoc shapes. | MUST | REQ-API-5 |
| ☐ | **Explicit versioning** is present and governed (`info.version`; version belongs in the path for a real service). | MUST | REQ-API-4 |
| ☐ | Schemas are **reused, not copied** - `Lesson` / `DimensionScore` are `$ref`-ed, consistent conventions throughout. | SHOULD | REQ-API-5 |
| ☐ | The API is treated **as a product** - named, summarised, with examples a consumer could build against. | SHOULD | REQ-API-1, REQ-API-3 |

## Spec - *describe before you generate*

| ✓ | Item | Level | Cite |
|---|------|-------|------|
| ☐ | **Acceptance criteria written before any feature code** (defects prevented at inception, not caught after). | MUST | QUAL-PRINC-SHIFT-LEFT |
| ☐ | An **ADR** captures the decision and, crucially, the **why** - the trade-off, not just the choice. | MUST | ENG-PRIN-DOC-STMT |
| ☐ | The ADR includes **idempotency reasoning**: why GET is safe/idempotent here, and what would change (an `Idempotency-Key`) if it became a write. | MUST | REQ-API-6 |
| ☐ | The solution is the **simplest thing that meets the contract** - no speculative abstractions (KISS / YAGNI). | SHOULD | ENG-PRIN-SIMPLE-STMT |
| ☐ | The decision is **durable** - the ADR will outlive the chat it was made in, and lives where the team can find it. | SHOULD | ENG-PRIN-DOC-STMT |

## Implementation - *small steps, on trunk*

| ✓ | Item | Level | Cite |
|---|------|-------|------|
| ☐ | The endpoint **fulfils the frozen contract** - it actually returns the agreed shape for the happy path. | MUST | REQ-API-2 |
| ☐ | Work landed as **small, reviewable commits**, not one mega-change. | MUST | ENG-PRIN-INCR-STMT |
| ☐ | The **first commit was stub + a failing contract test** (red), then the implementation drove it green. | MUST | ENG-PRIN-INCR-STMT, QTEST-CONTRACT |
| ☐ | Code is **clean and self-explanatory** - readable names, no dead code, no commented-out experiments. | SHOULD | ENG-PRIN-CLEAN-STMT |
| ☐ | Branch was **short-lived** and integrated to trunk frequently (no long-running fork). | SHOULD | ENG-PRIN-TRUNK-STMT |
| ☐ | It **builds and the suite passes locally before push** - green on your machine first. | SHOULD | ENG-PRIN-LOCAL-STMT, ENG-PRIN-CI-STMT |

## Tests - *test at the lowest viable layer, no duplication*

| ✓ | Item | Level | Cite |
|---|------|-------|------|
| ☐ | A **contract test** asserts the response matches the OpenAPI schema. | MUST | REQ-API-7, QTEST-CONTRACT |
| ☐ | Each behaviour is tested at the **lowest viable layer** - pure logic as a unit test, not pushed up to E2E. | MUST | QTEST-EARLY, QUAL-PRINC-AUTOMATION |
| ☐ | **No duplicated coverage** - the same rule isn't asserted at three layers; each layer earns its place. | MUST | QTEST-NO-DUP, QUAL-PRINC-WASTE |
| ☐ | The **pyramid is right-shaped**: many unit, some component/contract, few system/E2E. | SHOULD | QTEST-UNIT, QTEST-COMPONENT, QTEST-SYSTEM, QTEST-E2E |
| ☐ | Quality was **shifted left** (fast tests catch it early) and **shifted right** is considered (what you'd monitor in prod). | SHOULD | QUAL-PRINC-SHIFT-LEFT, QUAL-PRINC-SHIFT-RIGHT |
| ☐ | Any remaining **manual checks are deliberate**, named, and minimal - not the default. | SHOULD | QTEST-MANUAL |

## UX - *every state has a design*

| ✓ | Item | Level | Cite |
|---|------|-------|------|
| ☐ | The UI handles the **core states**: loading, empty, error, and populated. | MUST | QUAL-PRINC-SDLC |
| ☐ | The **error state consumes the contract's error envelope** - the UI reads `Problem`, it doesn't invent its own. | SHOULD | REQ-API-5 |
| ☐ | Edge / boundary states are designed (e.g. user with N/A dimensions, fewer than 5 recommendations). | SHOULD | QUAL-PRINC-SDLC |

## Review - *a human always signs the work*

| ✓ | Item | Level | Cite |
|---|------|-------|------|
| ☐ | **Approved by a named non-author human**, reviewed against this DoD. **AI may assist the review; AI may not approve.** No self-merge. | MUST | ENG-PRIN-REVIEW-STMT |
| ☐ | An owner is named - **You Build It, You Own It** - accountable for what shipped. | MUST | ENG-PRIN-OWN-STMT |
| ☐ | The merge respects the team's **Definition of Done** as the shared SDLC bar (this sheet). | MUST | QUAL-PRINC-SDLC |
| ☐ | Cross-role handoff is **real and visible**: the build used Product's criteria, Architecture's ADR, QA's tests - quality is a team property, not one person's. | SHOULD | QUAL-PRINC-TEAM |
| ☐ | If a criterion changed mid-build, the **contract and its test were updated before merge** (no stale spec). | MUST *(if triggered)* | REQ-API-2, REQ-API-7 |

---

## The merge bar, in one sentence

> A change is **done** when its contract is machine-readable and in sync (REQ-API-2), its behaviour is proven by a contract test at the lowest viable layer (REQ-API-7, QTEST-EARLY), its decision and the *why* are in an ADR (ENG-PRIN-DOC-STMT), and a **named non-author human has signed it off against this list** (ENG-PRIN-REVIEW-STMT). Anything less runs, but it isn't done.

*Part of Innovation Day. The five ways: [ways-of-working.md](../ways-of-working.md). How the gates run: [facilitator-guide.md](facilitator-guide.md). How it's scored: [scoring-rubric.md](scoring-rubric.md).*
