# Retiring `document.json`

Branch `retire-projection`, cut from `479b2c5`.

`revs/{head}` is the document. `document.json` beside it was a *view* of that
document, written after every edit on a debounce, and **nothing ever read its
body**: the one programmatic reader is `projection::found_in`, which takes the
stamp off the front to report `Freshness` — so the only thing the code did
with the projection was ask whether it had kept up with itself.

It was kept for one reason its own module states: revs are `*.json.gz`, so a
git diff of one is binary noise, while the projection is pretty-printed one
field per line so *"a diff of two folds reads as the edits between them"*.
That purpose is spent. The manifest is the changelog now — who, when, where,
what each rev named — and the History section reads it.

What that leaves is a second representation of the document, maintained
eagerly, that can silently disagree with the first. It already has: reading an
archive's projection gave a drawing two revs behind what opening the same
archive gave (#56, `what_an_archive_reads_as_is_what_it_opens_as`).

## What goes, and what stays

`projection.rs` holds two unrelated ideas under one name. Only the first goes.

| Stays | Because |
|---|---|
| `Stamp`, `Provenance`, `Source` | What a *stamped export* carries — the PDF's metadata, and what a `.json` opened from the command line remembers |
| `export_text`, `exported_stamp_in` | The export half, which has no container in it |
| `document_file::{parse, to_json}` | JSON is the document format; the CLI opens one |

| Goes | |
|---|---|
| `Freshness`, `Found`, `Refresh`, `refreshed`, `found_in`, `stamp_in`, `text`, `write_in` | |
| `container::PROJECTION`, its row in `LAID_DOWN`, its `.gitattributes` line | |
| `Store::{save_projection, projection}` and the `projected` field | |
| `Doc::{save_projection, projection}` | |
| `Effect::SaveProjection`, `REFRESH_PROJECTION` | |
| `Liveness::Writing` | see below |
| The debounce in both shells | |
| The `Unrecognized` notice in the kernel's chrome | |

## `Liveness::Writing` goes with it

`Liveness::Writing` is defined as *"the projection is behind the log; the
debounced write is due"* — it has never meant anything else. A rev is written
when it is committed.

The web is the one host where a rev's write is not immediate: it goes through
a journal that drains to the origin. That signal already exists and is already
what the status line reports — `status_line.rs`'s `(_, Owed(depth))` arm says
`Writing… (n)` off the journal depth whatever the liveness is. So the honest
durability signal survives untouched, and `Liveness` becomes:

```rust
pub enum Liveness { Recorded, ReadOnly(Locked), Scratch }
```

## Steps

- [x] **P0** Branch and this playbook.
- [x] **P1** `store`: `projection.rs` becomes `stamp.rs`, keeping only the
      export stamp. The container stops laying a projection down, `Store` and
      `Doc` stop offering to write one, `migrate` and `prefix` stop asking.
- [x] **P2** `kernel` and `tools`: `Liveness::Writing`, `Effect::SaveProjection`,
      the `Refresh document.json` command and the `Unrecognized` notice go.
- [x] **P3** Both shells: the debounce loops go — `keeps_the_projection_fresh`
      in the web shell, `save_projection` in `src/library.rs`.
- [x] **P4** `docs/json-format.md` loses the projection section; the walks and
      the suites follow.

## What `Liveness` cost

Nothing: `status_line.rs` already reported `Writing… (n)` off the journal
depth for any liveness, so the web's durability signal is untouched. The
desktop's amber dot is gone, its four states being three — a rev is written
as it is committed, so there was never anything for it to be catching up
with there.

## Containers already on disk

They keep a `document.json` that nothing writes and nothing reads — an inert
file in a directory. It is not swept: no reader will be confused by it, and
`blockworx migrate` is the zstd→gzip one-off rather than a migration
framework to hang this on. Delete it by hand, or leave it. An archive packed
from such a container carries the dead file along; also harmless.

This is a breaking format change, and the project is undeployed.
