# Reference patch — 02-adjacent-seats

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

1. **Add** `AdjacencyFinder.java` (in this directory) to `reference/src/`. New file, so
   `measureChange` charges nothing for it. It takes a `MovieBookingApi` and calls nothing but
   `seatsOf`, `availableSeats` and `hold` on it — no access to `Show`, `HoldRecord` or anything
   internal.
2. **Add one method** to `reference/src/MovieBookingSystem.java`, right beside `hold`:

   ```diff
        @Override
   +    public HoldResult holdAdjacent(String showId, SeatType type, int count) {
   +        return AdjacencyFinder.holdAdjacent(this, showId, type, count);
   +    }
   +
   +    @Override
        public Booking confirm(String holdId) {
   ```

3. **Add** `contract-delta/MovieBookingApi.java` (the full revised interface) to the candidate's
   contract. It is not counted in the measured diff, the same convention shopping-cart's
   member-shipping curveball established: a contract extension is free, and only the reference's
   own absorption of it is charged.

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

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

Both the curveball suite (6 tests) and the base suite (20 tests) are green after the patch. **No
base assertion is invalidated** — `hold`, `confirm` and `releaseHold` are untouched, and the base
suite never calls the new method.

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

`Show` was not opened, and neither was any part of `MovieBookingSystem` that already existed. The
reason is the same reason `hold` needed no changes either: the requirement is exactly "find a run
of free seats and then do an ordinary hold", and "do an ordinary hold" was already a public method
on the contract. `AdjacencyFinder` is not privileged in any way a candidate's own code could not
be — it is a client of `MovieBookingApi`, same as a test is.

The test worth watching in a candidate's design is `skipsAGap`: the naive version of this feature
returns the *first* row of the right length without checking that every seat in it is actually
free, which passes every test where the lowest run happens to be open and fails the moment
something is already taken there. A correct implementation has to search past a taken seat for the
next candidate window, not just take the type's first `count` seats.
