# Reference patch — 03-member-free-shipping

The answer key for how the reference absorbs this change, and the thing that makes `budget.json`
reproducible. **Never shipped to the candidate.**

1. **Overlay** `../contract-delta/MemberTier.java` and `../contract-delta/Entry.java` onto
   `contract/`. Contract files are given, so nothing there is charged — including the one line of
   `Entry.createFor` that names the new factory.
2. **Add** `MemberShipping.java` and `MemberCartFactory.java` (in this directory) to
   `reference/src/`. New files, so `measureChange` charges nothing for them.
3. **Change nothing else.** `edits.json` is deliberately empty.

Measured: `reference_diff = 0`, `touchedFiles = 0`, `newFiles = 2`, so
`diff_budget = max(3, 0 + ceil(0/2)) = 3` — the floor, and a Phase 4 level 3.

Both the curveball suite (7 tests) and the base suite (23 tests) are green after the patch. **No
base assertion is invalidated**, and one of the curveball's own tests exists to prove it:
`Entry.create()` still builds a standard cart that pays 499 on a pair of socks.

## Where the requirement landed, and where it did not

Nothing that already existed was opened. Not `Cart`, not `Totals`, not `ThresholdShipping`, not even
`CartFactory`. Three earlier decisions are what made a whole new class of customer free:

- **`CartFactory` exposes its parts, not just the whole.** `standardCatalog()`,
  `standardCoupons()` and `standardShipping()` are public so that a variation reuses what it is not
  changing. Without that, `MemberCartFactory` would either have copied the five-sku catalogue — the
  version that silently goes stale the first time a price changes — or forced a new method into
  `CartFactory` itself.
- **`Cart` has no convenience constructor**, so "what a cart is made of" was never knowledge that
  lived inside the class that runs the operations. A `Cart()` that supplied its own catalogue and
  delivery rule would have put this requirement inside the class that validates skus and merges
  lines.
- **`ShippingPolicy` takes the amount after discount.** The requirement's sharpest edge — a silver
  member losing their free delivery to their own voucher — needed no code at all, because the
  threshold was already measured on what is owed rather than on the subtotal. A policy handed the
  subtotal instead would need the discount passed to it now, which is a signature change and
  therefore an edit everywhere.

**`MemberShipping` decorates rather than restates.** The only new number in it is silver's 2500,
because that is the only genuinely new fact in the requirement; the charge, the standard threshold
and "an empty cart is not delivered" are all still `ThresholdShipping`'s, reached by delegation.
Copying `new ThresholdShipping(499, 2500)` would also have measured 0 lines and would have been
worse engineering — two copies of the delivery charge, disagreeing the first week it moved. Worth
saying out loud, because "the diff was zero" and "the design was right" are not the same claim.

**The one alternative worth naming:** `forTier` could have been a second method on `CartFactory`. It
would have cost about six charged lines, still inside a budget of… well, no: the budget is 3, so it
would have scored level 2 rather than level 3. That is a fair outcome rather than a trick — the
measurement is asking whether construction is a place you can add to, and a factory whose parts are
public is the design that says yes.

**What a candidate is most likely to get wrong here** is not the tier table. It is having a cart that
cannot be built two ways at all — a constructor that hard-codes the delivery rule, or a singleton
factory with one `standard()` and nothing reusable inside it. The tier table is five lines; being
unable to build a second kind of cart is a rewrite.
