# Reference patch — 02-storage-quotas

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/FileSystemApi.java` onto `contract/FileSystemApi.java`, and add
   `../contract-delta/QuotaExceededException.java` to `contract/`. Contract files are given, so
   nothing here is charged.
2. **Add** `Sizes.java` and `QuotaLedger.java` (in this directory) to `reference/src/`. New files,
   free.
3. **Overlay** `InMemoryFileSystem.java` (in this directory) onto `reference/src/InMemoryFileSystem.java`.

Measured: `reference_diff = 20`, all of it additions in one file — `diff_budget =
max(3, 20 + min(ceil(20/2), 6)) = 26`.

Both the curveball suite (9 tests) and the base suite (29 tests) are green after the patch.

## Where the 20 lines went, and why nothing else moved

| Addition | Lines | Why it is there |
|---|---|---|
| a `QuotaLedger` field, constructed in the constructor | 1 | one line, because quotas are tracked in a new collaborator rather than inline |
| `setQuota(path, maxBytes)` | 3 | the new contract method every design must declare somewhere — the same reasoning as vending-machine's `enterMaintenance` and library's `overdueLoans` |
| two `checkQuotas(...)` calls inserted into `write`'s existing two commit branches | 2 | this is the entire cost of *wiring the check in* — the original `if (existing instanceof DirectoryNode) ... else if (existing instanceof FileNode file) ... else ...` structure is untouched, so the diff here is two one-line insertions, not a rewrite |
| the `checkQuotas` method itself | 9 | the actual algorithm: walk every ancestor from the root to the immediate parent, and for each one that has a limit, check whether this write's size delta would put it over |

**Nothing else in `InMemoryFileSystem` changed, and nothing outside it changed at all.** `mkdir`,
`read`, `ls`, `mv`, `delete`, `exists` and `kindOf` are byte-for-byte what they were. `write`'s own
structural checks — the missing-parent lookup, the directory clash — were not touched or
reordered; the quota check was added *inside* the two branches that already decided the write is
otherwise legal, which is what makes the ordering rule in the contract ("structural refusal before
quota") true by construction rather than by a separate `if` guarding it.

## Why this is the cheap kind, on purpose

Two design choices from the base reference are what kept this to one file:

- **Quotas are tracked by directory identity in a new `QuotaLedger`, not as a field on
  `DirectoryNode`.** `DirectoryNode` did not need to know quotas exist. Had the limit lived on the
  node itself, this would still have been a small change, but it would have been a change to a
  class three other files depend on instead of to the one class that owns the operations.
- **`Sizes.bytesOf` reuses the same closed, two-variant `Node` switch as `Nodes.kindOf`.** A
  subtree's size was not a concept this problem needed before; computing it did not require
  touching `FileNode`, `DirectoryNode`, or the resolver at all, because both already exposed
  everything a new read-only query over the tree needs (`content()`, `childNames()`, `child(name)`).

What this curveball is really measuring is whether `write` still had exactly one place that decides
"is this write legal" before committing anything — it did, so the new dimension of legality slotted
into the two branches that already existed for the old ones.
