Two backlogs: the release scope, and what the work turned up.
Planned work. An item is only here if it loses data, breaks a promise on a public surface, or stops a stranger installing and running the thing. A ticket that reaches Done carries the version it shipped in.
| Key | Summary | Component | Status | Version | Blocked by |
|---|---|---|---|---|---|
| SAPE-1 | Build identity: version embedded, version command, product version in handshake | server | Done | 1.0.0 | — |
| SAPE-2 | Versioning and compatibility policy | docs | To do | — | — |
| SAPE-3 | Prebuilt binaries and a published container image | release | In progress | — | a tag |
| SAPE-4 | Tag-driven release workflow for the server | release | In progress | — | a tag |
| SAPE-5 | Install path and quickstart | docs | To do | — | SAPE-3 |
| SAPE-6 | Upgrade rehearsal: one build writes, the next reads it all back | server | To do | — | ISS-4 |
| SAPE-7 | Config reload, led by partial reload | server | To do | — | — |
| SAPE-8 | Read an operation's cost envelope before trusting it | server | To do | — | — |
| SAPE-9 | Name collision: decide whether namespaces exist | server | To do | — | — |
| SAPE-10 | Sign and verify an operation bundle | server | To do | — | — |
| SAPE-11 | List the external operations installed on a server | server | To do | — | SAPE-8 |
| SAPE-12 | One worked external operation, published as a challenge | docs | To do | — | SAPE-7, SAPE-10 |
| SAPE-13 | An artifact describing the shape of a request body | protocol | To do | — | — |
| SAPE-14 | Declare for collections | server | Done | 1.0.0 | — |
| SAPE-15 | learn.sapedb.com | docs | In progress | — | hosting and DNS |
| SAPE-16 | sapedb.com | docs | In progress | — | SAPE-15, SAPE-5 |
| SAPE-17 | The on-disk format tag and the key labels say sapedb | server | Done | 1.0.0 | — |
| SAPE-18 | Reads share a database instead of queueing behind each other | server | Done | 1.0.0 | — |
| SAPE-19 | Declare an operation against a running daemon — frame 13 | protocol | Done | 1.0.0 | — |
| SAPE-20 | Composed operations, with a ceiling readable at any depth | server | Done | 1.0.0 | — |
| SAPE-21 | Scopes travel the wire as a signed grant | server | Done | 1.0.0 | — |
| SAPE-22 | A count must declare how far it walks | server | Done | 1.0.0 | — |
| SAPE-23 | InvokeVersion, so an older declaration is reachable | protocol | Done | 1.0.0 | — |
| SAPE-24 | Three clients, each run against a real daemon | clients | Done | 1.0.0 | — |
| SAPE-25 | Desktop workbench: connections, catalogue, run, shell, compose, declare | desktop | Done | 1.0.0 | — |
| SAPE-26 | Apply a change: replay a log entry into a database | server | Done | 1.0.0 | — |
| SAPE-27 | Follower mode: a daemon that subscribes, applies, and refuses writes | server | Done | 1.0.0 | — |
13 done, 4 in progress, 10 to do. Replication is complete: a sapedbd can
follow another one, survive being killed mid-stream, and refuse writes with a reason. SAPE-14 has
landed, so a collection can be declared against a running daemon — from the CLI, all three clients and
the desktop workbench — and it no longer blocks SAPE-11 or SAPE-12.
This table said Done for four tickets that are not, and all four were caught the same way: by
reading what the ticket asks for.
SAPE-15 and SAPE-16 — the learn site and the front page — have said
In progress on their own pages the whole time, while this table said
otherwise. Their criteria are plainly unmet: SAPE-16's first one is a person opens the page in a
browser and reads it, and its own text answers "nobody has done this". Measured tonight
and worse than that: dig A sapedb.com and dig A learn.sapedb.com both return
nothing, from two resolvers. The domain is registered; neither name points anywhere.
The pages are written, and no stranger can reach either of them.
SAPE-3 and SAPE-4 are waiting on one command nobody here may run. The whole release
pipeline has now executed on a real runner, end to end: binaries for four platforms, checksums, every
artefact proved to carry its version stamp rather than dev (the linux one by running it),
the container image built, started and connected to —
welcome's productVersion matches the stamp — and then all three publishing steps skipped,
because a manual run resolves publish: false. Each of those checks has also been watched
fail on purpose. SAPE-4 was briefly marked Done here; four of its five criteria need a tag
that has actually been pushed, including the one it calls the bar — an artefact downloaded onto a
clean machine and executed there.
Opened by the work in Backlog 1, not planned before it. Each one is triaged once: Fix in 1.0.0 only if it loses data, breaks a public promise, or blocks installing and running; otherwise Defer, and it goes to planning for the next version. The triage column is the decision, not a guess at how bad it feels.
| Key | Summary | Found while | Triage | Status | Version |
|---|---|---|---|---|---|
| ISS-1 | The covering index is built, decoded per entry, then discarded | SAPE-20 | Defer | Open | — |
| ISS-2 | Fixture copies kept identical by hand; nothing compares them | SAPE-19 | Defer | Open | — |
| ISS-3 | The fixture covers 9 of 14 frame types | SAPE-13 | Defer | Open | — |
| ISS-4 | The ErrFormat refusal path has no test at all | SAPE-6 | Fix in 1.0.0 | In progress | — |
| ISS-5 | A composed operation's rows come back flat and unlabelled | SAPE-20 | Defer | Open | — |
| ISS-6 | An encryption test is flaky: it searches ciphertext for a 3-character string | SAPE-17 | Defer | Open | — |
| ISS-7 | internal/cli's open() leaks partition files, as Server.Close did | SAPE-19 | Defer | Open | — |
| ISS-8 | Two write handlers in one file roll back differently | SAPE-19 | Defer | Open | — |
| ISS-9 | A read-only composed operation takes the write lock | SAPE-20 | Defer | Open | — |
| ISS-10 | A composed operation must name a collection it may never touch | SAPE-20 | Defer | Open | — |
| ISS-11 | A grant has no expiry and cannot be revoked short of rotating the server secret | SAPE-21 | Fix in 1.0.0 | Open | — |
| ISS-12 | The TypeScript client cannot present a grant, so it cannot reach a scoped operation | SAPE-21 | Fix in 1.0.0 | Done | 1.0.0 |
| ISS-13 | Declaring a collection is not recorded against anybody | SAPE-19 | Defer | Open | — |
| ISS-14 | The old product name survives in three production constants, assembled byte by byte | SAPE-17 | Defer | Open | — |
| ISS-15 | The release plan went stale the same day it was written | SAPE-2 | — | Done | 1.0.0 |
| ISS-16 | The TypeScript client ignores the product version the daemon now sends | SAPE-1 | Defer | Open | — |
| ISS-17 | sapedbd has no version command; it only says so in a log line | SAPE-1 | Defer | Open | — |
| ISS-18 | A linker stamp aimed at a symbol that does not exist is accepted in silence | SAPE-1 | Defer | Open | — |
| ISS-19 | The worked example declares no projection, so it teaches the untyped path | SAPE-13 | Defer | Open | — |
| ISS-20 | A client derives shapes from a schema file on disk, not from the server's catalogue | SAPE-13 | Defer | Done | 1.0.0 |
| ISS-21 | The most declaration-shaped refusal of all reads as "failed" | SAPE-14 | Fix in 1.0.0 | In progress | — |
| ISS-22 | Anyone holding a connection string can read the entire change log | SAPE-26 | Needs a decision | Open | — |
| ISS-23 | No operator can cap log retention; the disk fills while everything looks healthy | SAPE-26 | Defer | Open | — |
| ISS-24 | The PHP client's pinned fixture predated the wire it speaks, and its refresh command 404s | SAPE-24 | Fix in 1.0.0 | Done | 1.0.0 |
| ISS-25 | The PHP client had no CI, so a skipped test and a passing test read the same | SAPE-24 | Fix in 1.0.0 | Done | 1.0.0 |
| ISS-26 | Reading the catalogue is a write, so the operator shell cannot be pointed at a follower | SAPE-27 | Defer | Open | — |
| ISS-27 | A valid signature for a database that never existed brings it into existence | SAPE-14 | Defer | Open | — |
| ISS-28 | Both clients have CI; the database at the centre of them does not | SAPE-3 | Fix in 1.0.0 | Done | 1.0.0 |
| ISS-29 | SAPE-18's gate measures how many cores the machine has, not whether reads share | ISS-28 | Fix in 1.0.0 | Done | 1.0.0 |
| ISS-30 | The workbench cannot run the reads a follower would allow | SAPE-27 | Defer | Open | — |
One question, asked once, and written down: does it lose data, break a promise on a public surface, or stop somebody installing and running the thing? Nine of thirty answer yes, and one — ISS-22 — is not mine to answer at all, because it is a security posture that freezes at the tag. The rest are real, some are embarrassing, and they wait: a backlog that grows as fast as it shrinks has no answer to is it done yet.
The rule also has to stop things that sound like defects. One report this week said the
operator shell silently swallows the catalogue error at startup, which is literally true. Reading the
surrounding code showed the discard is deliberate and explained — it feeds tab completion, and
guessing names would be worse than silence — while ls, in the same file, reports the
refusal properly. No ticket was opened. A rule that only ever adds is not a rule.
ISS-12 is the cautionary one. It sat here marked open after the work had been done, and was then used as evidence — twice in one sitting — to write a public claim that was false, the second time while correcting the first. A ticket is a record of what somebody found on a day. It is not a measurement of what is true now.
ISS-29 is the best thing on this page. It was found by ISS-28 within an hour of CI existing: a gate guarding a Done ticket had been measuring the number of cores in the machine and reporting the answer as a verdict about locks. The replacement counts how many reads are inside the database at once — an exclusive lock cannot reach two on any number of cores — and on the very runner that had been failing, it found four reads inside the database together, in three milliseconds. The code had been sharing all along. Only the gate could not see it.
A version number here is a promise that cannot be withdrawn. From the tag onwards these four surfaces
are fixed: the on-disk format, the wire protocol (frames 1…13
never change role; fields may be added, never renamed or removed), the
meaning of a declaration, and the public API. It does not promise
performance, the ordering of reads against writes, the file layout inside a partition, or anything
under internal/.
Frame 14 is now spent: SAPE-14 took it for establish. The next
frame anyone adds starts at 15. The public Go surface is 39 names and follower mode
added none of them — everything it needed lives under internal/.