# Reference patch — 02-annual-plan

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/CostExplorerApi.java` onto `contract/` — replaces the file of the
   same name, adding `subscribeAnnual(Plan)` and the "Annual billing" section. Contract files are
   given, so nothing here is charged.
2. **Add** `AnnualSubscription.java` (in this directory) to `reference/src/`. New file, so
   `measureChange` charges nothing for it.
3. **Add one method** to `reference/src/CostExplorer.java`, next to `subscribe`:

   ```java
   @Override
   public String subscribeAnnual(Plan plan) {
       String id = "SUB-" + nextId.getAndIncrement();
       subscriptions.save(id, new AnnualSubscription(plan, today(), pricing));
       return id;
   }
   ```

`edits.json` beside this file is the same edit in machine-readable form.

Measured: `reference_diff = 6` (all in `CostExplorer.java`, all additions), so
`diff_budget = max(3, 6 + ceil(6/2)) = 9`.

Both the curveball suite (6 tests) and the base suite (13 tests) are green after the patch.
`changePlan`, `cancel`, `costForMonth` and `projectYear` in `CostExplorer.java` are **not touched
at all** — the "refuses to change the plan or cancel" behaviour and the once-a-year billing shape
both live entirely inside `AnnualSubscription`, reached through the same four existing methods.

## Where the requirement landed, and why `BillingAccount` is the reason, again

Two curveballs in a row land the same way, and that repetition is itself the point being measured:
`BillingAccount` was not built for either of them specifically, and it absorbs a decorator
(`TrialAccount`) and an entirely different billing shape (`AnnualSubscription`) by the same
mechanism — `CostExplorer` and `SubscriptionRepository` ask an account four questions and never ask
what kind of account it is.

**Why this is a new implementation and not a mode inside `Subscription`.** The tempting shortcut is
a `boolean billedAnnually` flag on `Subscription`, with `costForMonth` branching on it. It is a
worse design for a reason sharper than "it is a bigger diff": `Subscription`'s whole design is a
timeline of day-dated segments, built to answer "how much of this month does each plan cover".
Annual billing does not have segments to prorate — it has a start month and a cycle length — so a
flag would not extend that machinery, it would grow a second, unrelated machinery inside the same
class and switch between them. `AnnualSubscription` is the size it is (about fifty lines) because
that is genuinely how much simpler "charge once, then nothing for eleven months" is than day-level
proration — and that simplicity would have been lost by forcing it through `Subscription`'s.

**Why `changePlan` and `cancel` throw rather than silently doing something.** The requirement scopes
both out explicitly. Throwing `IllegalStateException` — the same exception the base contract already
uses for "the subscription is not in a state that allows this" — means a caller who forgets this
restriction gets a loud, immediate failure rather than a plan change that quietly did nothing, or
worse, that was silently accepted and never billed correctly.

**The discount computation stays local to `AnnualSubscription` on purpose.** It could have been a
new method on `PricingPolicy`, but that would mean every implementation of a one-method interface
grows a second method the base problem's own tests never exercise, for a discount that has nothing
to do with what a plan costs *monthly*. `AnnualSubscription` already depends on `PricingPolicy` for
the one fact it actually needs — the monthly price — and works out its own arithmetic from there,
the same way a candidate's own code is expected to ask for a fact rather than a finished answer when
only one caller needs the finished answer.
