← 1.0.0 scope SAPE-2

Versioning and compatibility policy: what 1.0.0 freezes, and what it refuses to promise

Status
To do
Component
docs
Priority
Highest — every other ticket's "is this allowed to change" answer comes from here
Blocked by
SAPE-1
Blocks

Description

Write the compatibility policy into the repository as a document a stranger can read without asking anyone. It names four frozen surfaces — the on-disk format, the wire protocol, declaration semantics, and the public API — and for each one says what a 1.x release may do to it. It also names, out loud, the things 1.0.0 does not promise. Each component (server, the three clients, the app) gets its own version line; what binds them is the protocol version, not a shared number.

Why now

This is a promise on a public surface, and a promise made by silence is still a promise. After the tag, the answer to "may this change in 1.1" is whatever the first person to ask happens to assume, and by then their code depends on the assumption. A shared version number is the same trap in reverse: it forces a client release every time the server patches a bug, and undoing that later means renumbering something somebody already installed.

Measured 2026-09-20. Three of the four surfaces have a value that can be read today: internal/pager/pager.go:61 holds Magic = [8]byte{'S','A','P','E','D','B',0,1} and pager.go:63 holds const Format uint16 = 1; frame types 1…13 are declared in internal/protocol/frame.go:37-58, ending at Declare Type = 13. The fourth already has a guard: sapedb_test.go:44 is TestTheSurfaceIsExactlyTheseThirtyThreeNames, which compares the exported name set in both directions rather than counting it. What does not exist anywhere is a document saying which of these four a 1.x release may touch.

Acceptance criteria

  1. The policy document exists in the repository and names all four surfaces. For each one it cites the file and symbol that holds the current value, and each citation resolves — checked by a test that opens every cited path and fails on one that is not there.
  2. A test asserts the frame-type table: adding a type numbered 13 or below, or renumbering an existing one, turns it red. Adding type 14 leaves it green.
  3. A test asserts pager.Format and pager.Magic byte-for-byte. Changing either turns it red, so the change cannot be made without someone deleting an assertion on purpose.
  4. TestTheSurfaceIsExactlyTheseThirtyThreeNames still passes, and the policy document points at it by name as the enforcement for the API surface.
  5. The "not promised" list is in the same document and includes, at minimum: performance, the relative ordering of reads and writes, file layout inside a partition, and everything under internal/.

Out of scope