# Reference patch — 01-scheduled-orders

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/OrderRequest.java` onto `contract/OrderRequest.java`. Contract
   files are given, so nothing here is charged. The revision adds a fourth component,
   `notBefore`, and keeps the three-argument constructor as a convenience that supplies
   `Instant.MIN` — which is why every existing caller, including the whole base suite, still
   compiles and still passes.
2. **Add** `ScheduledPreparing.java` (in this directory) to `reference/src/`. New file, so
   `measureChange` charges nothing for it.
3. **Change one line** in `reference/src/Stages.java`, in `standard()`:

   ```diff
   -                        new PlainStage(OrderState.PREPARING, List.of(Audience.CUSTOMER)),
   +                        new ScheduledPreparing(),
   ```

Measured: `reference_diff = 2` (1 added, 1 removed, one file touched), so
`diff_budget = max(3, 2 + ceil(2/2)) = 3`.

Verified after the patch: the curveball suite is 7 tests green, and the base suite is 23 tests
green. **The base suite staying green matters here** — the requirement said an order with no
booked time must not notice this change, and that is a claim about the old tests, not the new ones.

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

`OrderStage` was not opened. Nor was `OrderBook`, `Order`, `Lifecycle`, `PlacedStage`,
`CancelledStage`, `DeliveredStage` or either tariff. The class that runs every transition on the
platform has no opinion about when a particular stage is allowed, so a rule about timing cannot
reach it.

**What the requirement itself cost: one overridden hook.** Read `ScheduledPreparing` and notice
how much of the requirement change is not written down anywhere:

| The requirement said | Where it is enforced |
|---|---|
| a refusal notifies nobody | nowhere — the guard is step 1 and notifying is step 5, so there is nothing to suppress |
| a refusal adds no history entry and does not move the order | nowhere — the guard runs before the order is applied, so there is nothing to undo |
| at the booked instant it may start | nowhere in particular — `isBefore` is the requirement's own word, and "not before" is what it means |
| an order with no booked time is unaffected | nowhere — `Instant.MIN` is before every clock reading, so the comparison never fires |
| a scheduled order can still be cancelled while it waits | nowhere — it is still `ACCEPTED`, and `CancelledStage` already allows that |
| the money and the forty-five minute promise are unchanged | nowhere — a tariff has never known what a stage is |

Six rules, one `if`. **That is the template method's payoff**: a stage only ever has to say the one
thing that is different about it, because everything a stage has in common with the others is
somewhere it cannot be reached from.

## What this costs without the seam

The plausible alternative is a guard inside `advance`:

```java
        Order order = find(orderId);
        OrderStage next = lifecycle.after(order.state());
        if (next.state() == OrderState.PREPARING
                && clock.instant().isBefore(order.request().notBefore())) {
            throw new IllegalStateException("order " + orderId + " is not to be prepared yet");
        }
        return next.enter(order, clock, notifier).state();
```

**Measured, not asserted: 7 lines** (6 added, 1 removed) in `OrderBook.java` — against this
patch's 2 in `Stages.java`. Both pass all seven curveball tests. The extra five lines are not the
whole cost, though: they are five lines in the class that coordinates every order on the platform,
plus a second reading of the clock that can disagree with the one the transition is eventually
recorded with. It works, and it is the version where the next timing rule is a second
clause in the same condition, and the one after that is a third. Within three requirements
`advance` knows the name of every stage that has ever had a rule attached to it, which is exactly
the shape the stage classes exist to avoid.

The reference reads the clock **once**, at the top of `enter`, and hands the same instant to the
guard and to the history. That is worth pointing at in a defence: with two reads it is possible for
an order to be refused for being 20 ms early and then, on the retry, be recorded as having started
before its booked time. One read makes that unrepresentable.
