# Schema Bump

When `SCHEMA_VERSION` changes, the change must be atomic across four surfaces.
Partial bumps are how silent drift gets shipped.

## Triggers

A bump is required when any breaking change from
[wire-contract-review.md](wire-contract-review.md) lands. It is **not**
required for additive changes (new variant on an open enum, new optional field
with `skip_serializing_if`) — those need a new wire-test assertion only.

## Procedure

```bash
make bump-schema VERSION=lifeloop.vN REASON="<one-line rationale>"
```

(Direct invocation:
`cargo run --bin lifeloop-bump-schema -- lifeloop.vN "<rationale>"`.)

The tool handles two of the four surfaces atomically (temp-file + rename
with explicit lib.rs rollback if the tombstone promotion fails):

1. Updates `SCHEMA_VERSION` in `src/lib.rs`.
2. Writes `docs/tombstones/<old-version>.md` with a removal-criteria stub.

Manually complete the remaining surfaces in the same commit:

3. Update `tests/wire_contract.rs` so every assertion that pins
   `schema_version` reflects the new value.
4. Update `README.md` and `docs/product-thesis.md` if they cite the version
   explicitly.

Then run `make verify` and commit all four surfaces in a single commit. The
commit message should reference the rationale and link to the tombstone.

## Tombstone hygiene

Each tombstone must specify removal criteria — a concrete condition under
which it can be deleted (e.g. *"after two quarters with zero observed
`lifeloop.v0` receipts in production"*). Tombstones without criteria are
forbidden by AGENTS.md and accumulate as silent technical debt.

Migration notes must tell consumers exactly what to change. "See the source"
is not a migration note.
