Allow progressive insight, and apply two to the bus record

A record can assert a fact that goes stale while the decision it supports
stays right. Superseding for that buries a sound record under a second one
and makes every reader work out which is live. So a correction of fact is
now made in place, marked and dated, with the old wording quoted — bounded
by three conditions and checked by records.py, which fires on an unmarked,
undated or back-dated note. Judgements still supersede.

Applied to 0115: no conformance suite exists to recapture, and the full
genesis bed cannot run until the links exist. Designs 25 and 28 follow.
This commit is contained in:
2026-09-26 18:39:38 +02:00
parent 6ab113e6c6
commit 1c808898a5
7 changed files with 205 additions and 64 deletions
@@ -61,8 +61,9 @@ may not disagree about* still describes the bus being replaced.
waits for the one after it. The cutover remains a single rollout** — dividing the build does not
divide the bus.
**Step 1 — genesis raises the broker.** The `nats` module and a mesh raised on it from nothing.
This is built and proven even though the mesh it is for will never travel this path, because
**Step 1 — genesis raises the broker.** The `nats` module, and genesis placing it in the
foundation. This is built and proven even though the mesh it is for will never travel this path,
because
genesis is where the foundation is *defined*: the only place the mesh comes from nothing, and the
definition every other path is measured against. A genesis path that exists only on paper is one
nobody discovers is wrong until there is a second mesh.
@@ -78,8 +79,9 @@ renamed by every change the seat exists to survive.
protocol, an SDK is an implementation of it in one language and nothing more, the protocol is split
per capability, and conformance is executable fixtures per capability rather than prose. What
changes is what the specification specifies. Design 19's wire section is rewritten from exchanges
and queues to subjects and streams; the fixtures are recaptured on NATS; every SDK claims the
capabilities it passes, and a language may arrive with connection and events alone.
and queues to subjects and streams; the conformance suite is built — first against the bus the
mesh has, then restated on NATS; every SDK claims the capabilities it passes, and a language may
arrive with connection and events alone.
**The SDK gains no conveniences in the process.** [ADR 0039](0039-what-the-sdk-holds-and-refuses.md)
refuses frequent-and-cascading code in the shared library, and ADR 0074 restates it — an SDK is
@@ -119,17 +121,48 @@ is still on AMQP throughout. The bus moves on one day, at the end, once.
## How it is checked
- **Per step, a bed, and the bed named in design 25 §10 against the step it belongs to.** Step 1:
a mesh raised on NATS from genesis. Step 2: the broker adopted into a mesh already running, and
a second holder of `mesh-broker` refused at resolution. Step 3: the conformance suite passing per
capability, on NATS, for every SDK that claims it — and a module built before the binding serving
its tools unchanged. Step 4: each converted flow proved against the behaviour it replaced. Step 5:
the cutover bed, then the rollout with every node reporting.
a mesh raised from nothing has the server standing, its streams asserted and every account
composed from the manifests — no mesh traffic on it yet. Step 2: the broker adopted into a mesh
already running, a second holder of `mesh-broker` refused at resolution, and nothing routed to it.
Step 3: the conformance suite passing per capability, on NATS, for every implementation that
claims it — and a module built before the binding serving its tools unchanged. Step 4: each
converted flow proved against the behaviour it replaced, **and the full genesis bed** — a mesh
enrolling, holding a push, and rolling out an upgrade on NATS. Step 5: the cutover bed, then the
rollout with every node reporting.
- **Step 3 is not done when the code runs.** It is done when the fixtures match byte for byte
across implementations, which is ADR 0074's own test and the only one that catches two SDKs
quietly ignoring each other.
- **A step that cannot name what its bed proves is not a step**, and is divided further before it
is started.
## Progressive insights
Corrections of fact made in this record after it was accepted, under the rule in
[`README.md`](README.md). The decision — five steps, each proved, one rollout — is untouched by
both; each corrects something this record asserted about the *state of the code*, which nobody had
measured when it was written.
> **Progressive insight — 2026-09-26.** *There is no conformance suite to recapture.* This record
> said step 3's "fixtures are recaptured on NATS", and design 19's wire was described as specified
> and conformed. Measuring the four repositories found no conformance fixtures in any of them:
> [design 22](../03-DESIGN/01-to-be/22-the-work-ahead.md)'s Phase 1.2, which would have built the
> suite, is still open. Step 3 therefore **builds** it, and builds it first against the bus the
> mesh has — a suite born on the new bus certifies whatever the new bus happens to do. The step's
> place in the order, and ADR 0074's model it implements, are unchanged.
> **Progressive insight — 2026-09-26.** *The full genesis bed belongs to step 4, not step 1.* This
> record attributed "a mesh raised on NATS from genesis" to step 1, and described that step as "the
> `nats` module and a mesh raised on it from nothing". A bed that enrols a node, holds a push and
> rolls out an upgrade needs the controller and the host to speak NATS — which is step 3's
> implementations and step 4's flows. A step whose proof cannot run is exactly the failure this
> record was written to prevent, so step 1 now ends at the server standing from genesis, correctly
> configured and carrying nothing, and the full bed is named under step 4. The five steps, their
> names, their order and the single rollout are unchanged; only where two beds run has moved.
>
> Recorded here rather than superseded because the decision this record makes — that the work is
> divided and each division is proved — is what *produced* the correction: the dependency was
> invisible while the build was one item.
## References
- [ADR 0106](0106-the-bus-is-nats.md) — the decision this divides.
+39 -2
View File
@@ -8,8 +8,45 @@ the decision is recorded here, and only then is the design written. Following th
numbers walks the process in the order it happens.
One file per decision, numbered, never deleted. A superseded record has its `status:` changed
and gains a pointer to what replaced it — **its text is never edited**. The reasoning that was
rejected is the expensive half to rediscover.
and gains a pointer to what replaced it — **its reasoning is never rewritten**. The reasoning that
was rejected is the expensive half to rediscover.
## Progressive insight
A record is a decision, not a snapshot of everything that was true the day it was written, and
those two fail differently. **A fact a record asserted can turn out to be wrong while the decision
it supports stays right** — a count taken before anyone measured, a file named that does not
exist, a proof attributed to a step that cannot run it. Superseding a record for that buries a
correct decision under a second one, and teaches every reader to first work out which of two
records is live. Done a few times, the reading order stops being one.
So: **a correction of fact that leaves the decision standing is made in the record, in place,
marked and dated.**
> **Progressive insight — YYYY-MM-DD.** What was found, what the record said before, and what it
> says instead.
Three conditions, all of which hold:
- **It corrects a fact, not a judgement.** That a suite does not exist is a fact. That building it
is the wrong order is a judgement, and judgements supersede.
- **It adds; it never quietly replaces.** Where body text changes, the note says what stood there
before, so a reader who followed a citation to the old wording can find out what happened to it.
A correction nobody can see is indistinguishable from a record that was always right, which is
the failure the immutability rule exists to prevent.
- **The decision, the options weighed and the consequences stand untouched.** If the correction
changes what was decided, which alternatives were rejected, or a consequence another record
relies on, it is not an insight — write the superseding record.
**What still supersedes**, without exception: reversing a decision, changing its scope, rejecting
an option it accepted, or making a consequence false that a later record cites. The test is not
how large the edit looks in a diff; it is whether a reader who acted on the old text would now be
wrong about *what was decided* rather than about *a detail the decision did not rest on*.
**How this is checked.** `00-META/checks/records.py` requires every insight to be marked in the
form above and dated no earlier than the record's own `date:` — an unmarked edit is a rule
violation the reviewer looks for in the diff, and a marked one is legible in the record itself.
The git history is the backstop, not the record of intent; the note is the record of intent.
The records run in the order the decisions were taken, oldest first.