-- +goose Up -- The book's pipeline SHAPE — does its work go through an editor — becomes two facts instead of one, -- because the single fact was answering two different questions and could only be right for one. -- -- `books.edit_wave` (00024) stays exactly as it is, monotone, and keeps its pin (D39.153 §4б): it is -- the HISTORICAL fact, "has this book ever been through an editing pipeline", and monotonicity is what -- stops a half-edited chapter counting as finished. What it is NOT, and was being used as, is the -- authority on how the book's LIFETIME count is computed. Read that way it is wrong in both -- directions, and both were open register rows: -- -- PD-403, editor REMOVED — the flag cannot come back down, so the count stays pinned to an edit -- column no run will ever fill: the book freezes half-done, the run closes `ready` at 50%, and the -- purchase scale goes on offering chapters that are already translated. The user is sold work twice. -- -- PD-404, editor ADDED — the flag flips true on the first progress event of the run, the count moves -- to the edit column mid-transaction, and a book showing 7/10 shows 0/10, backwards, inside one -- `structure_version`, which the canon forbids in as many words. -- -- The owner ruled on 28.08 (D39.165 §2): a change of pipeline shape is an EVENT OF THE BOOK, like -- cutting it again, and the count is legitimately RECOMPUTED when the boundary is crossed. So the -- boundary needs a carrier, and this is it. -- -- `epoch_editor` — the shape of the CURRENT epoch, ASSIGNED rather than accumulated. NULL until the -- engine has announced a shape at all; from then on it is what the engine last said. This is what -- the lifetime count reads. -- `shape_epoch` — how many boundaries this book has crossed. It is a COORDINATE, like -- `structure_version`: a client tells "the count was legitimately recomputed" from "the count moved -- backwards illegally" by seeing it change. It is the only half of this pair that goes on the wire, -- and it goes as an OPAQUE counter (canon 0.9.0): the shape itself — whether this book gets an -- editing pass — is NOT published, because the canon's boundary forbids the wire everything about -- HOW a book is translated (§Boundaries: names of models, phases and stages, internal vocabularies, -- sums of money). D39.163 granted that boundary its SECOND exception, `Progress.stage`, under two -- stated conditions; an opaque generation counter needs no exception at all, which is why this -- column is one. -- -- Backfill: every existing book gets epoch 0 and its CURRENT flag as the epoch's shape, so nothing -- moves on deployment — the first announcement that DIFFERS is the first boundary. Books that never -- announced (edit_wave IS NULL) stay NULL and keep falling back to the flag's own default. alter table books add column shape_epoch integer not null default 0, add column epoch_editor boolean; update books set epoch_editor = edit_wave where edit_wave is not null; -- ⚠ 00024's header comment describes the frozen rule this migration supersedes, and it is IMMUTABLE -- (released migrations are append-only, TestReleasedMigrationsAreUnchanged). It is corrected here -- rather than there: the monotone flag it introduced is still correct for the question IT answers. -- +goose Down alter table books drop column epoch_editor, drop column shape_epoch;