# Corpus syllabus assignments

**Why this file exists:** all 34 syllabus items must be covered by the 20 problems collectively, and
`tools/validate-corpus.mjs` fails the build naming any uncovered item. Leaving coverage to chance
would mean discovering a gap after 20 problems are written. So each problem is **assigned** the items
it must genuinely exercise, chosen to fit that problem's natural shape.

**Honesty rule:** an assignment is a design constraint on the contract and reference, not a licence to
tag an item the problem does not really exercise. An author who cannot exercise an assigned item must
say so plainly in their report so it can be reassigned — parking-lot did exactly this, dropping `A6`
and `B2` with reasons.

## Covered by `parking-lot` (done, validated)

`A1 A2 A4 A5 A7 · B1 · C1 C2 C3 · D1 D2 D3 · F1 F2 F3 F4 F5` — 17 items.

Dropped with justification: **A6** (the contract fixes the exception classes, so a domain hierarchy is
constrained out) and **B2** (no factory; a default constructor as composition root is not one).

## Remaining 17 items, assigned

| Problem | Tier | Sealed | Stress | Must exercise |
|---|---|---|---|---|
| `vending-machine` | 1 | | | **A6** exception hierarchy · **B6** state machine as data · **B2** factory |
| `elevator` | 2 | | **yes** | **C5** interface segregation · **E1** shared mutable state · **E3** lock ordering |
| `snake-and-ladder` | 1 | | | **A3** sealed hierarchy · **B4** observer/listener |
| `shopping-cart` | 1 | | | **B3** builder · **D4** bulk/pagination shape |
| `tic-tac-toe` | 2 | | | **C4** composition over inheritance |
| `library` | 2 | | | **B5** repository abstraction |
| `lru-cache` | 3 | | **yes** | **B7** decorator/chain · **E4** thread-safe collection choice |
| `movie-booking` | 2 | **yes** | **yes** | **E2** atomicity vs visibility |
| `food-ordering` | 2 | **yes** | | **B8** template method / lifecycle hook |
| `notification-service` | 3 | **yes** | **yes** | **E5** idempotency under retry |
| `rate-limiter` | 3 | | **yes** | reinforces E1, E2, C3 (injected clock) |
| `splitwise` | 2 | | | reinforces A2, D2 |
| `file-system` | 3 | | | reinforces B5, C1 |
| `cost-explorer` | 3 | | | reinforces D4 |
| `rating-system` | 2 | | | reinforces D4, B5 |
| `middleware-router` | 3 | | | reinforces B7, B8 |
| `logger` | 3 | **yes** | **yes** | reinforces B4, E4 |
| `customer-satisfaction` | 2 | **yes** | | reinforces D1, F1 |
| `trip-state-machine` | 3 | **yes** | | reinforces B6, A3 |

**Sealed (6):** `movie-booking`, `food-ordering`, `notification-service`, `logger`,
`customer-satisfaction`, `trip-state-machine`. Every artifact is still required — they are used in
full rounds, and `forDrill()` refuses them so they can never leak into practice.

**Stress suites (6):** `elevator`, `lru-cache`, `movie-booking`, `notification-service`,
`rate-limiter`, `logger`. Each must **provably fail a naive non-thread-safe implementation** before it
is accepted; a stress test that passes broken code manufactures false confidence.

## Conventions proven by `parking-lot`, to be copied

1. **`reference-patch/` per curveball** — the new file plus a `PATCH.md` diff, so a measured budget is
   reproducible rather than resting on a discarded working copy.
2. **`contract-delta/` overlays by filename** — the delta ships a full revised `*Api.java`, so a
   missing new method is a compile error rather than a runtime surprise.
3. **Curveball tests never assert a literal id the candidate invents** — compare ids the
   implementation itself returned, so his naming scheme stays irrelevant.
4. **`skeleton_spec.required_seams` names are matched literally** by the Phase 2 grader, which is only
   fair because the Seam Lantern renders them live in the editor rail. Keep the `note` field saying so.
5. **Every arbitrary rule lives in the contract javadoc** — rounding direction, prices, which exception
   each failure throws, thread-safety expectations. The user must never fail on a rule he could not
   have known.
