The prerequisite for checkpointing. `recovery_generation` was two numbers
wearing one name: the logical generation of the segment recovery seals, and
the generation of the manifest recovery installs. Every index run publishes a
manifest, so every seal moved the number — and the segment recovery then
wrote took the moved value while the frames inside it were already named by
the old one. Persisted index locations dangled.
Split, each answers its own question. The logical generation is the tail's,
derived from the manifest's committed prefix, so sealing a journal into a
segment changes where the bytes are and not what they are called. The
manifest generation is the next free one, so an index run's manifest and a
recovery's cannot collide. Collision detection moved with them: the old check
compared against a maximum mixing all three namespaces, which an index run
could raise on its own, and only a segment can collide with a segment.
This closes the coverage restriction the previous commit had to impose. A run
may again cover locations naming the active tail, because the tail's identity
now survives being sealed away — so sealing covers the frames of the session
that wrote them instead of lagging one behind. Mutation-checked by putting the
segment's identity back on the manifest counter, which reproduces the original
defect exactly: a recovered run pointing at a logical generation nothing pins.
One case is not closed, and a test found it rather than review. An orphan
`.seg` from an interrupted seal occupies a logical generation whether or not
it is a readable segment, and it may hold exactly the identity the tail wants.
`an_orphan_segment_leaves_the_active_journal_the_authority` is also the test
documenting why recovery must not refuse there — the active journal is still
the authority and an outage would be the wrong answer — so the seal falls back
to a free generation and renames the frames, as it did before. An index run
against the old identity then dangles. Confined to roots carrying an orphan
segment, where it was previously universal; the closure is for recovery to
discard runs whose identity was not preserved, recorded in scope §6.5.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01XKzM69CHmBuDcA3qN1jFdh