diff --git a/00-META/checks/README.md b/00-META/checks/README.md index e2f8d23d..fbfc2666 100644 --- a/00-META/checks/README.md +++ b/00-META/checks/README.md @@ -26,6 +26,7 @@ indistinguishable from one that cannot. | `rests-on` | `decisions:` and `extends:` name records that exist and are **accepted** | the class behind both incidents | | `live-citation` | a governing document citing a **superseded** record names its replacement in the same paragraph | `01-to-be/README.md` citing ADR 0022 as live guidance | | `supersession` | if A says it was superseded by B, B says it supersedes A | ADR 0012 never declared that it superseded 0011 | +| `partial-supersession` | a record's `supersedes-in-part:` names records that exist, each carrying a dated *Superseded in part* note naming it under its heading; and every such note is named back by its superseder's field | 11 of 21 partial supersessions had no note on the record they change, and 6 more were said only in prose ([research 045](../../01-RESEARCH/045-a-knowledge-base-the-mesh-writes/00-overview.md)) | | `numbering` | the number in the filename is the number in the heading | — | | `topics` | every record names a topic of the reading order in `02-DECISIONS/README.md` | — | | *(index.py)* | the reading order is written, every record's topic is one of it, and the README stores no list of records ([ADR 0248](../../02-DECISIONS/0248-the-decision-index-is-generated-when-it-is-read-and-never-stored.md)) | a stored list made every two open decisions conflict ([issue 297](../../04-ISSUES/297-two-open-decisions-always-conflict/00-report.md)); it failed on the README of `main` before the list was removed | diff --git a/00-META/checks/records.py b/00-META/checks/records.py index 0c1ea1d2..aaa1d0f0 100644 --- a/00-META/checks/records.py +++ b/00-META/checks/records.py @@ -264,6 +264,53 @@ def check_supersession_symmetry(failures, records): ) +PARTIAL_MARK = re.compile( + r"^> \*\*Superseded in part — (\d{4}-\d{2}-\d{2}), by \[ADR (\d{4})\]\(", re.M +) + + +def check_partial_supersession(failures, records): + """A record superseded in part says so under its heading, and its superseder names it. + + A partial supersession was written only in the newer record's prose six times, and 11 of the + 21 `supersedes-in-part:` links had no note on the record they change, so a reader who arrived + at the older record by a citation read a rule that no longer held. Both directions are + checked: the field on the newer record and the dated note on the older one, naming each other. + """ + for number, record in records.items(): + claimed = record["front"].get("supersedes-in-part", []) + if isinstance(claimed, str): + claimed = [claimed] if claimed else [] + for entry in claimed: + match = ADR_FILE.match(os.path.basename(entry)) + if not match or match.group(1) not in records: + failures.add("partial-supersession", rel(record["path"]), f"no such record: {entry}") + continue + older = records[match.group(1)] + marks = [by for _, by in PARTIAL_MARK.findall(older["text"])] + if number not in marks: + failures.add( + "partial-supersession", + rel(older["path"]), + f"ADR {number} supersedes this in part; this record carries no " + f"'> **Superseded in part — YYYY-MM-DD, by [ADR {number}](…).**' note", + ) + for _, by in PARTIAL_MARK.findall(record["text"]): + if by not in records: + failures.add("partial-supersession", rel(record["path"]), f"note names no such record: ADR {by}") + continue + names = records[by]["front"].get("supersedes-in-part", []) + if isinstance(names, str): + names = [names] if names else [] + if record["name"] not in [os.path.basename(str(n)) for n in names]: + failures.add( + "partial-supersession", + rel(records[by]["path"]), + f"ADR {number} says this supersedes it in part; this record's " + f"`supersedes-in-part:` does not name it", + ) + + def check_topics(failures, records): """Every record names a topic of the reading order. @@ -406,6 +453,7 @@ def main(): check_rests_on(failures, records) check_live_citations(failures, records) check_supersession_symmetry(failures, records) + check_partial_supersession(failures, records) check_numbering(failures, records) check_topics(failures, records) check_status_against_code(failures) diff --git a/02-DECISIONS/0006-the-substrate-and-the-control-plane.md b/02-DECISIONS/0006-the-substrate-and-the-control-plane.md index 37f408cf..eacc6791 100644 --- a/02-DECISIONS/0006-the-substrate-and-the-control-plane.md +++ b/02-DECISIONS/0006-the-substrate-and-the-control-plane.md @@ -8,6 +8,11 @@ reconstructed: false # 6. The substrate and the control plane +> **Superseded in part — 2026-10-07, by [ADR 0244](0244-the-mesh-is-described-in-domains-and-one-word-names-one-thing.md).** +> The seven contexts below no longer describe the mesh: it is described in ten domains, and "domain" replaces +> "context" in this sense; *observability* becomes Health and repair. This record keeps its word, and the +> glossary says how to read it. Everything else decided here stands. + *Consolidated 2026-08-28 from six records. Extended 2026-08-29, by building it: the language, and what must be running before the control plane starts — which this record had left not established and could not have settled the way it was asking.* diff --git a/02-DECISIONS/0009-modules-and-the-graph.md b/02-DECISIONS/0009-modules-and-the-graph.md index 390c36a2..a12796d2 100644 --- a/02-DECISIONS/0009-modules-and-the-graph.md +++ b/02-DECISIONS/0009-modules-and-the-graph.md @@ -8,6 +8,11 @@ reconstructed: false # 9. Modules and the graph +> **Superseded in part — 2026-10-06, by [ADR 0226](0226-the-private-network-is-assigned-by-its-own-name-and-the-proxy-names-its-public-issuer.md).** +> The section *what a domain module turns out to be* no longer describes what runs: `networking` is retired, +> every machine is assigned the private network's own module, and the catalogue holds no domain module. The +> mechanism, a module with requirements and no files, and the rest of this record stand as decided here. + *Consolidated 2026-08-28 from six records.* ## Everything is a module diff --git a/02-DECISIONS/0045-a-machine-firewall-is-the-sum-of-what-it-listens-on.md b/02-DECISIONS/0045-a-machine-firewall-is-the-sum-of-what-it-listens-on.md index 440d333a..cd85065f 100644 --- a/02-DECISIONS/0045-a-machine-firewall-is-the-sum-of-what-it-listens-on.md +++ b/02-DECISIONS/0045-a-machine-firewall-is-the-sum-of-what-it-listens-on.md @@ -9,6 +9,11 @@ extends: 02-DECISIONS/0005-the-node-host.md # 45. A machine's firewall is the sum of what its modules listen on +> **Superseded in part — 2026-09-28, by [ADR 0138](0138-an-assignment-binds-an-endpoint-and-says-how-far-it-reaches.md).** +> That a listen's `from` "is the whole of public-versus-internal" no longer holds: an assignment states each +> endpoint's reach, a statement that also governs names and certificates, and `from` is the packet filter's +> share of it. The firewall derived and applied on the node, not a provider, stands as decided here. + ## Context The reverse proxy is a *provider*: a module `requires` the `route` capability and a running proxy diff --git a/02-DECISIONS/0066-public-routing-is-name-agnostic.md b/02-DECISIONS/0066-public-routing-is-name-agnostic.md index 9bfdb5ee..8c4f88e3 100644 --- a/02-DECISIONS/0066-public-routing-is-name-agnostic.md +++ b/02-DECISIONS/0066-public-routing-is-name-agnostic.md @@ -9,9 +9,9 @@ extends: 02-DECISIONS/0007-connectivity.md # 66. Public routing is name-agnostic, its names are resolved inside the mesh, and an internal authority can certify them -> **Narrowed, not replaced — 2026-10-03.** One clause of the decision below no longer holds: *publishing -> a granted name into internal resolution, mesh-wide*. A public name now resolves publicly, and only -> names under the mesh's own suffix get a private answer — [ADR 0191](0191-the-meshs-resolver-holds-only-the-meshs-own-names.md). +> **Superseded in part — 2026-10-03, by [ADR 0191](0191-the-meshs-resolver-holds-only-the-meshs-own-names.md).** +> One clause of the decision below no longer holds: *publishing a granted name into internal resolution, +> mesh-wide*. A public name now resolves publicly, and only names under the mesh's own suffix get a private answer. > Inside the mesh a route is reached and certified by its internal name > ([ADR 0151](0151-a-routes-internal-name-is-composed-under-the-node-that-serves-it.md)). The label, the > node's public domain and their composition stand as decided here. diff --git a/02-DECISIONS/0088-the-foundation-filters-before-anything-listens.md b/02-DECISIONS/0088-the-foundation-filters-before-anything-listens.md index d46e5c71..311663cd 100644 --- a/02-DECISIONS/0088-the-foundation-filters-before-anything-listens.md +++ b/02-DECISIONS/0088-the-foundation-filters-before-anything-listens.md @@ -9,6 +9,11 @@ extends: 02-DECISIONS/0078-the-store-and-broker-are-modules.md # 88. The foundation filters before anything listens +> **Superseded in part — 2026-09-22, by [ADR 0100](0100-a-node-in-use-is-adopted-before-it-is-converged.md).** +> On a node raised adopted, the base ruleset is not loaded: its duty, the store never reachable from outside, +> passes to a table of the mesh's that only refuses. On every other node the base ruleset, loaded before the +> store and broker are raised, stands as decided here. + ## Context Adopting the store and broker as ordinary modules diff --git a/02-DECISIONS/0097-a-vendor-image-is-a-declared-build-input.md b/02-DECISIONS/0097-a-vendor-image-is-a-declared-build-input.md index 066a53fc..f77de354 100644 --- a/02-DECISIONS/0097-a-vendor-image-is-a-declared-build-input.md +++ b/02-DECISIONS/0097-a-vendor-image-is-a-declared-build-input.md @@ -9,6 +9,10 @@ extends: 02-DECISIONS/0096-an-upstream-image-is-copied-between-registries.md # 97. A vendor image is a declared build input, and a recipe fetches nothing undeclared +> **Superseded in part — 2026-10-08, by [ADR 0257](0257-a-copied-base-is-recorded-where-it-is-copied-kept-by-the-builds-that-stood-on-it-and-held-once-per-image.md).** +> A declared image is no longer copied "under the module's repository": it is copied into one repository per +> upstream image, whichever modules stand on it. Everything else decided here stands. + ## Context Three modules could not be built by the mesh's builder because their recipes reached for what diff --git a/02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md b/02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md index 7dad5130..e0cbd990 100644 --- a/02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md +++ b/02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md @@ -5,10 +5,17 @@ date: 2026-09-22 deciders: jochen reconstructed: false extends: 02-DECISIONS/0078-the-store-and-broker-are-modules.md +supersedes-in-part: + - 02-DECISIONS/0088-the-foundation-filters-before-anything-listens.md --- # 100. A node in use is adopted before it is converged +> **Superseded in part — 2026-09-23, by [ADR 0105](0105-the-mesh-adopts-the-predecessors-tunnel-in-place.md).** +> The rule that the private network's range must not overlap a tunnel the predecessor still runs now applies +> only where the found tunnel is left running beside the mesh's. On the hub, where the mesh adopts the found +> tunnel in place, there is one tunnel and one range. Everything else decided here stands. + ## Context The mesh replaces a predecessor mesh that is running, on the same machines, with the services diff --git a/02-DECISIONS/0105-the-mesh-adopts-the-predecessors-tunnel-in-place.md b/02-DECISIONS/0105-the-mesh-adopts-the-predecessors-tunnel-in-place.md index 5767c367..0fb7080c 100644 --- a/02-DECISIONS/0105-the-mesh-adopts-the-predecessors-tunnel-in-place.md +++ b/02-DECISIONS/0105-the-mesh-adopts-the-predecessors-tunnel-in-place.md @@ -5,6 +5,8 @@ date: 2026-09-23 deciders: jochen reconstructed: false extends: 02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md +supersedes-in-part: + - 02-DECISIONS/0100-a-node-in-use-is-adopted-before-it-is-converged.md --- # 105. The mesh adopts the predecessor's tunnel in place diff --git a/02-DECISIONS/0110-a-seat-is-a-module-assignment-from-a-closed-set.md b/02-DECISIONS/0110-a-seat-is-a-module-assignment-from-a-closed-set.md index 99e4c966..42036ea2 100644 --- a/02-DECISIONS/0110-a-seat-is-a-module-assignment-from-a-closed-set.md +++ b/02-DECISIONS/0110-a-seat-is-a-module-assignment-from-a-closed-set.md @@ -9,6 +9,11 @@ extends: 02-DECISIONS/0009-modules-and-the-graph.md # 110. A seat is held by one assignment, from a closed set, and it may deliver a provision +> **Superseded in part — 2026-09-27, by [ADR 0122](0122-a-seat-is-data-a-rename-is-a-database-update.md).** +> "The controller carries the set in code" no longer holds: the seats are rows of a table in the controller's +> store, seeded by a migration, and a seat is referenced by a stable id, its name only a label. The closed set, +> one holder per scope and a delivering seat as the single answer for its provision stand as decided here. + > **Narrowed, not replaced — 2026-09-27, on merging two lines of work.** This was marked superseded by > [ADR 0126](0126-a-module-declares-its-own-seats.md), and that overstated it: 0126 says in as many > words that *"everything 0110 decided about what a seat is stands untouched"*. What moved is where the diff --git a/02-DECISIONS/0121-a-system-seat-is-named-for-its-scope-and-modules-define-their-own.md b/02-DECISIONS/0121-a-system-seat-is-named-for-its-scope-and-modules-define-their-own.md index a4120553..2c684b24 100644 --- a/02-DECISIONS/0121-a-system-seat-is-named-for-its-scope-and-modules-define-their-own.md +++ b/02-DECISIONS/0121-a-system-seat-is-named-for-its-scope-and-modules-define-their-own.md @@ -9,14 +9,18 @@ extends: 02-DECISIONS/0110-a-seat-is-a-module-assignment-from-a-closed-set.md # 121. A system seat is named for its scope, and a module may define its own -> **Narrowed, not replaced — 2026-10-03.** *"`the-dns-port` → `node-dns-resolver`"* no longer holds: -> the serving role moves to mesh scope as `mesh-resolver`, one per mesh, and `node-dns-resolver` is -> retired ([ADR 0194](0194-the-mesh-has-one-resolver-and-every-node-asks-it-for-the-meshs-names.md)). The -> distinction this record kept — serving and asking are two roles, two seats — stands, and -> `node-resolver-config` is unchanged. +> **Superseded in part — 2026-10-03, by [ADR 0194](0194-the-mesh-has-one-resolver-and-every-node-asks-it-for-the-meshs-names.md).** +> *"`the-dns-port` → `node-dns-resolver`"* no longer holds: the serving role moves to mesh scope as +> `mesh-resolver`, one per mesh, and `node-dns-resolver` is retired. The distinction this record kept — +> serving and asking are two roles, two seats — stands, and `node-resolver-config` is unchanged. > **The mechanism changed — 2026-10-02, by [ADR 0190](0190-a-seats-work-is-shared-by-its-holders-and-building-is-the-first-such-role.md).** The naming rule stands. The build role this record made mesh-scoped — *the mesh's single build machine* — is node-scoped now: `node-build-agent`, one holder per machine, every holder taking from one work queue. +> **Superseded in part — 2026-09-27, by [ADR 0122](0122-a-seat-is-data-a-rename-is-a-database-update.md).** +> "The renames are a coordinated migration, not a rename" no longer holds: a seat is a row in the controller's +> store, referenced by a stable id, so a rename is one update of its name, and only the claiming manifests are +> edited in the catalogue. The naming rule, the module-defined seats and the seats settled here stand. + ## Context [ADR 0110](0110-a-seat-is-a-module-assignment-from-a-closed-set.md) made seats a closed set the diff --git a/02-DECISIONS/0122-a-seat-is-data-a-rename-is-a-database-update.md b/02-DECISIONS/0122-a-seat-is-data-a-rename-is-a-database-update.md index 4d3eeb79..3676bdf0 100644 --- a/02-DECISIONS/0122-a-seat-is-data-a-rename-is-a-database-update.md +++ b/02-DECISIONS/0122-a-seat-is-data-a-rename-is-a-database-update.md @@ -5,8 +5,8 @@ date: 2026-09-27 deciders: jochen reconstructed: false supersedes-in-part: - - 0110-a-seat-is-a-module-assignment-from-a-closed-set.md - - 0121-a-system-seat-is-named-for-its-scope-and-modules-define-their-own.md + - 02-DECISIONS/0110-a-seat-is-a-module-assignment-from-a-closed-set.md + - 02-DECISIONS/0121-a-system-seat-is-named-for-its-scope-and-modules-define-their-own.md --- # 122. A seat is data the controller owns, and a rename is a database update diff --git a/02-DECISIONS/0138-an-assignment-binds-an-endpoint-and-says-how-far-it-reaches.md b/02-DECISIONS/0138-an-assignment-binds-an-endpoint-and-says-how-far-it-reaches.md index 0f795815..4996cc6f 100644 --- a/02-DECISIONS/0138-an-assignment-binds-an-endpoint-and-says-how-far-it-reaches.md +++ b/02-DECISIONS/0138-an-assignment-binds-an-endpoint-and-says-how-far-it-reaches.md @@ -5,6 +5,8 @@ date: 2026-09-28 deciders: jochen reconstructed: false extends: 02-DECISIONS/0045-a-machine-firewall-is-the-sum-of-what-it-listens-on.md +supersedes-in-part: + - 02-DECISIONS/0045-a-machine-firewall-is-the-sum-of-what-it-listens-on.md --- # 138. An assignment binds an endpoint and says how far it reaches diff --git a/02-DECISIONS/0151-a-routes-internal-name-is-composed-under-the-node-that-serves-it.md b/02-DECISIONS/0151-a-routes-internal-name-is-composed-under-the-node-that-serves-it.md index c4d7cd3a..7339440a 100644 --- a/02-DECISIONS/0151-a-routes-internal-name-is-composed-under-the-node-that-serves-it.md +++ b/02-DECISIONS/0151-a-routes-internal-name-is-composed-under-the-node-that-serves-it.md @@ -9,9 +9,9 @@ extends: 02-DECISIONS/0066-public-routing-is-name-agnostic.md # 151. A route's internal name is composed under the node that serves it -> **Narrowed, not replaced — 2026-10-03.** *"The roster publishes it as itself, once, at the serving -> node's address"* no longer holds: a public name is never given a private answer, and resolves publicly -> ([ADR 0191](0191-the-meshs-resolver-holds-only-the-meshs-own-names.md)). The internal name this record +> **Superseded in part — 2026-10-03, by [ADR 0191](0191-the-meshs-resolver-holds-only-the-meshs-own-names.md).** +> *"The roster publishes it as itself, once, at the serving node's address"* no longer holds: a public name +> is never given a private answer, and resolves publicly. The internal name this record > composes is what that rests on, and stands. ## Context diff --git a/02-DECISIONS/0191-the-meshs-resolver-holds-only-the-meshs-own-names.md b/02-DECISIONS/0191-the-meshs-resolver-holds-only-the-meshs-own-names.md index be16cb4f..735a1198 100644 --- a/02-DECISIONS/0191-the-meshs-resolver-holds-only-the-meshs-own-names.md +++ b/02-DECISIONS/0191-the-meshs-resolver-holds-only-the-meshs-own-names.md @@ -5,8 +5,8 @@ date: 2026-10-03 deciders: jochen reconstructed: false supersedes-in-part: - - 0066-public-routing-is-name-agnostic.md - - 0151-a-routes-internal-name-is-composed-under-the-node-that-serves-it.md + - 02-DECISIONS/0066-public-routing-is-name-agnostic.md + - 02-DECISIONS/0151-a-routes-internal-name-is-composed-under-the-node-that-serves-it.md --- # 191. The mesh's resolver holds only the mesh's own names; a public name resolves publicly diff --git a/02-DECISIONS/0194-the-mesh-has-one-resolver-and-every-node-asks-it-for-the-meshs-names.md b/02-DECISIONS/0194-the-mesh-has-one-resolver-and-every-node-asks-it-for-the-meshs-names.md index 5a9c10fc..8c2135e6 100644 --- a/02-DECISIONS/0194-the-mesh-has-one-resolver-and-every-node-asks-it-for-the-meshs-names.md +++ b/02-DECISIONS/0194-the-mesh-has-one-resolver-and-every-node-asks-it-for-the-meshs-names.md @@ -5,7 +5,7 @@ date: 2026-10-03 deciders: jochen reconstructed: false supersedes-in-part: - - 0121-a-system-seat-is-named-for-its-scope-and-modules-define-their-own.md + - 02-DECISIONS/0121-a-system-seat-is-named-for-its-scope-and-modules-define-their-own.md extends: 02-DECISIONS/0191-the-meshs-resolver-holds-only-the-meshs-own-names.md --- @@ -16,10 +16,9 @@ extends: 02-DECISIONS/0191-the-meshs-resolver-holds-only-the-meshs-own-names.md > server, each holding every node's internal domain from the same roster. One resolving module, the > mesh's names held only by its holders, and the retirement of every per-node copy stand. -> **Narrowed, not replaced — 2026-10-03.** How a node asks is decided again by -> [ADR 0196](0196-a-node-asks-the-meshs-resolver-first-and-a-public-one-only-when-it-is-silent.md): every -> node and container asks `mesh-resolver` first and a public resolver only when it is silent. There is -> no `systemd-resolved` module and no runtime `dns` naming `mesh-resolver`, and step 2 of the migration +> **Superseded in part — 2026-10-03, by [ADR 0196](0196-a-node-asks-the-meshs-resolver-first-and-a-public-one-only-when-it-is-silent.md).** +> How a node asks is decided again there: every node and container asks `mesh-resolver` first and a public +> resolver only when it is silent. There is no `systemd-resolved` module and no runtime `dns` naming `mesh-resolver`, and step 2 of the migration > reads as 0196 states it. Option 2 below was rejected for a laptop with its tunnel down resolving > nothing; a public resolver listed second answers exactly then. The one resolver, its placement and > the retirement of every per-node copy stand. diff --git a/02-DECISIONS/0196-a-node-asks-the-meshs-resolver-first-and-a-public-one-only-when-it-is-silent.md b/02-DECISIONS/0196-a-node-asks-the-meshs-resolver-first-and-a-public-one-only-when-it-is-silent.md index 0d192619..e77b8c8b 100644 --- a/02-DECISIONS/0196-a-node-asks-the-meshs-resolver-first-and-a-public-one-only-when-it-is-silent.md +++ b/02-DECISIONS/0196-a-node-asks-the-meshs-resolver-first-and-a-public-one-only-when-it-is-silent.md @@ -5,12 +5,12 @@ date: 2026-10-03 deciders: jochen reconstructed: false supersedes-in-part: - - 0194-the-mesh-has-one-resolver-and-every-node-asks-it-for-the-meshs-names.md + - 02-DECISIONS/0194-the-mesh-has-one-resolver-and-every-node-asks-it-for-the-meshs-names.md --- # 196. A node asks the mesh's resolver first, and a public one only when it is silent -> **Narrowed, not replaced — 2026-10-05, by [ADR 0223](0223-the-mesh-has-two-resolvers-and-a-machine-lists-only-them.md).** The public resolver listed second goes: musl asks +> **Superseded in part — 2026-10-05, by [ADR 0223](0223-the-mesh-has-two-resolvers-and-a-machine-lists-only-them.md).** The public resolver listed second goes: musl asks > every listed server at once and takes the first reply, so a public "no such name" for a mesh name > won it, and every Alpine build on the home server failed. Every machine now lists the mesh's > resolvers — two holders of `mesh-dns-resolver`, its own first on a holder — and nothing else. Every diff --git a/02-DECISIONS/0223-the-mesh-has-two-resolvers-and-a-machine-lists-only-them.md b/02-DECISIONS/0223-the-mesh-has-two-resolvers-and-a-machine-lists-only-them.md index a227d9ea..064127f6 100644 --- a/02-DECISIONS/0223-the-mesh-has-two-resolvers-and-a-machine-lists-only-them.md +++ b/02-DECISIONS/0223-the-mesh-has-two-resolvers-and-a-machine-lists-only-them.md @@ -5,7 +5,7 @@ date: 2026-10-05 deciders: jochen reconstructed: false supersedes-in-part: - - 0196-a-node-asks-the-meshs-resolver-first-and-a-public-one-only-when-it-is-silent.md + - 02-DECISIONS/0196-a-node-asks-the-meshs-resolver-first-and-a-public-one-only-when-it-is-silent.md extends: 02-DECISIONS/0194-the-mesh-has-one-resolver-and-every-node-asks-it-for-the-meshs-names.md --- diff --git a/02-DECISIONS/0226-the-private-network-is-assigned-by-its-own-name-and-the-proxy-names-its-public-issuer.md b/02-DECISIONS/0226-the-private-network-is-assigned-by-its-own-name-and-the-proxy-names-its-public-issuer.md index aa342c14..dbc5714c 100644 --- a/02-DECISIONS/0226-the-private-network-is-assigned-by-its-own-name-and-the-proxy-names-its-public-issuer.md +++ b/02-DECISIONS/0226-the-private-network-is-assigned-by-its-own-name-and-the-proxy-names-its-public-issuer.md @@ -5,7 +5,7 @@ date: 2026-10-06 deciders: jochen reconstructed: false supersedes-in-part: - - 0009-modules-and-the-graph.md + - 02-DECISIONS/0009-modules-and-the-graph.md extends: 02-DECISIONS/0007-connectivity.md --- diff --git a/02-DECISIONS/0234-the-mesh-holds-a-conversation-with-its-operator.md b/02-DECISIONS/0234-the-mesh-holds-a-conversation-with-its-operator.md index 8321d058..12fd639a 100644 --- a/02-DECISIONS/0234-the-mesh-holds-a-conversation-with-its-operator.md +++ b/02-DECISIONS/0234-the-mesh-holds-a-conversation-with-its-operator.md @@ -9,6 +9,13 @@ extends: 02-DECISIONS/0227-the-core-holds-nine-rules-each-checked-and-is-built-t # 234. The mesh holds a conversation with its operator, over channels that are seats, and an answer that performs an action is authorised by the controller +> **Superseded in part — 2026-10-09, by [ADR 0259](0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md).** +> §8's controller holding an ask whose answer performs an action, its verbs `authorise request`, +> `authorise answer` and `authorisations`, and the controller performing no longer hold: the router holds the +> ask and issues a warrant, and the asker performs. The operator's identities (§3) and the factors' secrets +> (§8) are the router's own state, not the controller's. The tiers and proofs, the kinded benches, the content +> rule, the desk never authorising, long polling and every tier completable on the away channel stand. + ## Context **The output channel was built in its smallest form** ([ADR 0227](0227-the-core-holds-nine-rules-each-checked-and-is-built-to-them-in-six-phases.md), diff --git a/02-DECISIONS/0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md b/02-DECISIONS/0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md index 47b2a3fe..51d5076c 100644 --- a/02-DECISIONS/0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md +++ b/02-DECISIONS/0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md @@ -9,7 +9,7 @@ extends: 02-DECISIONS/0227-the-core-holds-nine-rules-each-checked-and-is-built-t # 237. A change is judged against the mesh that runs, before it merges, on the build seat -> **Narrowed, not replaced — 2026-10-06, by [ADR 0238](0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md).** +> **Superseded in part — 2026-10-06, by [ADR 0238](0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md).** > Decision 4's *which* and *what* moved: a pull request is checked when the mesh's module graph says it > reaches a module — the planner's own answer, not *a repository it builds a module from into that > branch* — and every repository of the mesh runs its own `merge-check.sh` as a second status, diff --git a/02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md b/02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md index 40fe4c7e..1040b7ca 100644 --- a/02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md +++ b/02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md @@ -5,7 +5,7 @@ date: 2026-10-06 deciders: jochen reconstructed: false supersedes-in-part: - - 0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md + - 02-DECISIONS/0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md extends: 02-DECISIONS/0237-a-change-is-judged-against-the-mesh-that-runs-before-it-merges-on-the-build-seat.md --- diff --git a/02-DECISIONS/0239-a-delivery-is-owned-by-the-mesh-delivery-module-and-runs-from-commit-to-delivered.md b/02-DECISIONS/0239-a-delivery-is-owned-by-the-mesh-delivery-module-and-runs-from-commit-to-delivered.md index a8d9084e..8f4d6f45 100644 --- a/02-DECISIONS/0239-a-delivery-is-owned-by-the-mesh-delivery-module-and-runs-from-commit-to-delivered.md +++ b/02-DECISIONS/0239-a-delivery-is-owned-by-the-mesh-delivery-module-and-runs-from-commit-to-delivered.md @@ -5,7 +5,7 @@ date: 2026-10-06 deciders: jochen reconstructed: false supersedes-in-part: - - 0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md + - 02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md extends: 02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md --- diff --git a/02-DECISIONS/0244-the-mesh-is-described-in-domains-and-one-word-names-one-thing.md b/02-DECISIONS/0244-the-mesh-is-described-in-domains-and-one-word-names-one-thing.md index 8ec4d1f8..17322f64 100644 --- a/02-DECISIONS/0244-the-mesh-is-described-in-domains-and-one-word-names-one-thing.md +++ b/02-DECISIONS/0244-the-mesh-is-described-in-domains-and-one-word-names-one-thing.md @@ -5,6 +5,8 @@ date: 2026-10-07 deciders: jochen reconstructed: false extends: 02-DECISIONS/0006-the-substrate-and-the-control-plane.md +supersedes-in-part: + - 02-DECISIONS/0006-the-substrate-and-the-control-plane.md --- # 244. The mesh is described in domains, and one word names one thing diff --git a/02-DECISIONS/0248-the-decision-index-is-generated-when-it-is-read-and-never-stored.md b/02-DECISIONS/0248-the-decision-index-is-generated-when-it-is-read-and-never-stored.md index 47d70b56..82988c42 100644 --- a/02-DECISIONS/0248-the-decision-index-is-generated-when-it-is-read-and-never-stored.md +++ b/02-DECISIONS/0248-the-decision-index-is-generated-when-it-is-read-and-never-stored.md @@ -5,7 +5,7 @@ date: 2026-10-07 deciders: jochen reconstructed: false supersedes-in-part: - - 0019-how-this-repository-works.md + - 02-DECISIONS/0019-how-this-repository-works.md --- # 248. The decision index is generated when it is read, and never stored diff --git a/02-DECISIONS/0249-a-delivery-groups-order-rules-have-a-precedence-and-a-declared-order-outranks-them-all.md b/02-DECISIONS/0249-a-delivery-groups-order-rules-have-a-precedence-and-a-declared-order-outranks-them-all.md index ea3bde6b..acd7c2b9 100644 --- a/02-DECISIONS/0249-a-delivery-groups-order-rules-have-a-precedence-and-a-declared-order-outranks-them-all.md +++ b/02-DECISIONS/0249-a-delivery-groups-order-rules-have-a-precedence-and-a-declared-order-outranks-them-all.md @@ -5,7 +5,7 @@ date: 2026-10-08 deciders: jochen reconstructed: false supersedes-in-part: - - 0239-a-delivery-is-owned-by-the-mesh-delivery-module-and-runs-from-commit-to-delivered.md + - 02-DECISIONS/0239-a-delivery-is-owned-by-the-mesh-delivery-module-and-runs-from-commit-to-delivered.md extends: 02-DECISIONS/0239-a-delivery-is-owned-by-the-mesh-delivery-module-and-runs-from-commit-to-delivered.md --- diff --git a/02-DECISIONS/0253-a-condition-says-itself-to-the-operator-in-plain-words-beside-its-summary.md b/02-DECISIONS/0253-a-condition-says-itself-to-the-operator-in-plain-words-beside-its-summary.md index 4e88c3bb..f0621acb 100644 --- a/02-DECISIONS/0253-a-condition-says-itself-to-the-operator-in-plain-words-beside-its-summary.md +++ b/02-DECISIONS/0253-a-condition-says-itself-to-the-operator-in-plain-words-beside-its-summary.md @@ -9,6 +9,12 @@ extends: 02-DECISIONS/0234-the-mesh-holds-a-conversation-with-its-operator.md # 253. A condition says itself to the operator in plain words beside its summary, says whether the operator is needed, and is answered from the notification +> **Superseded in part — 2026-10-08, by [ADR 0258](0258-a-desk-click-performs-only-an-acknowledgement-and-an-answer-is-a-one-time-ticket.md).** +> §6's reading of *acknowledge*, its promise to honour a tier "when one exists", and the consequence that the +> verb's own record says who chose it no longer hold: a desk click performs only an acknowledgement (Details, +> Silence for a week) until answers are authorised, and release, stop, start and restart are said in words. +> The plain words, the verdict, the quiet rule, the time zone and the one-line clearance stand as decided here. + ## Context The operator could not read the mesh's notifications diff --git a/02-DECISIONS/0254-a-wait-for-a-persons-new-login-is-not-a-gates-failure-and-each-module-of-a-send-keeps-its-own-pass.md b/02-DECISIONS/0254-a-wait-for-a-persons-new-login-is-not-a-gates-failure-and-each-module-of-a-send-keeps-its-own-pass.md index bd6e2502..d77598d7 100644 --- a/02-DECISIONS/0254-a-wait-for-a-persons-new-login-is-not-a-gates-failure-and-each-module-of-a-send-keeps-its-own-pass.md +++ b/02-DECISIONS/0254-a-wait-for-a-persons-new-login-is-not-a-gates-failure-and-each-module-of-a-send-keeps-its-own-pass.md @@ -5,7 +5,7 @@ date: 2026-10-08 deciders: jochen reconstructed: false supersedes-in-part: - - 0252-a-module-puts-an-account-in-a-group-and-the-mesh-says-when-a-new-login-is-needed.md + - 02-DECISIONS/0252-a-module-puts-an-account-in-a-group-and-the-mesh-says-when-a-new-login-is-needed.md extends: 02-DECISIONS/0236-a-build-is-judged-on-its-first-machine-and-put-back-by-something-other-than-itself-and-so-it-rolls-out-unattended.md --- diff --git a/02-DECISIONS/0257-a-copied-base-is-recorded-where-it-is-copied-kept-by-the-builds-that-stood-on-it-and-held-once-per-image.md b/02-DECISIONS/0257-a-copied-base-is-recorded-where-it-is-copied-kept-by-the-builds-that-stood-on-it-and-held-once-per-image.md index 7a082ab2..c938a9dc 100644 --- a/02-DECISIONS/0257-a-copied-base-is-recorded-where-it-is-copied-kept-by-the-builds-that-stood-on-it-and-held-once-per-image.md +++ b/02-DECISIONS/0257-a-copied-base-is-recorded-where-it-is-copied-kept-by-the-builds-that-stood-on-it-and-held-once-per-image.md @@ -5,7 +5,7 @@ date: 2026-10-08 deciders: jochen reconstructed: false supersedes-in-part: - - 0097-a-vendor-image-is-a-declared-build-input.md + - 02-DECISIONS/0097-a-vendor-image-is-a-declared-build-input.md extends: 02-DECISIONS/0251-the-registries-say-what-they-hold-and-keep-what-is-named-and-a-machine-keeps-the-image-it-runs-and-the-one-before.md --- diff --git a/02-DECISIONS/0258-a-desk-click-performs-only-an-acknowledgement-and-an-answer-is-a-one-time-ticket.md b/02-DECISIONS/0258-a-desk-click-performs-only-an-acknowledgement-and-an-answer-is-a-one-time-ticket.md index 1bb6bda8..25600c57 100644 --- a/02-DECISIONS/0258-a-desk-click-performs-only-an-acknowledgement-and-an-answer-is-a-one-time-ticket.md +++ b/02-DECISIONS/0258-a-desk-click-performs-only-an-acknowledgement-and-an-answer-is-a-one-time-ticket.md @@ -5,6 +5,8 @@ date: 2026-10-08 deciders: jochen reconstructed: false extends: 02-DECISIONS/0253-a-condition-says-itself-to-the-operator-in-plain-words-beside-its-summary.md +supersedes-in-part: + - 02-DECISIONS/0253-a-condition-says-itself-to-the-operator-in-plain-words-beside-its-summary.md --- # 258. A desk click performs only an acknowledgement, an answer is a one-time ticket, and a verdict is never weakened diff --git a/02-DECISIONS/0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md b/02-DECISIONS/0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md index 63a6bcbf..1ae9b0fa 100644 --- a/02-DECISIONS/0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md +++ b/02-DECISIONS/0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md @@ -5,7 +5,7 @@ date: 2026-10-09 deciders: jochen reconstructed: false supersedes-in-part: - - 0234-the-mesh-holds-a-conversation-with-its-operator.md + - 02-DECISIONS/0234-the-mesh-holds-a-conversation-with-its-operator.md extends: 02-DECISIONS/0234-the-mesh-holds-a-conversation-with-its-operator.md --- diff --git a/02-DECISIONS/0267-an-artifact-is-rebuilt-only-when-its-build-source-changes-and-a-module-moves-only-along-build-dependencies-on-artifacts.md b/02-DECISIONS/0267-an-artifact-is-rebuilt-only-when-its-build-source-changes-and-a-module-moves-only-along-build-dependencies-on-artifacts.md index 0cc89164..b4799976 100644 --- a/02-DECISIONS/0267-an-artifact-is-rebuilt-only-when-its-build-source-changes-and-a-module-moves-only-along-build-dependencies-on-artifacts.md +++ b/02-DECISIONS/0267-an-artifact-is-rebuilt-only-when-its-build-source-changes-and-a-module-moves-only-along-build-dependencies-on-artifacts.md @@ -5,8 +5,8 @@ date: 2026-10-08 deciders: jochen reconstructed: false supersedes-in-part: - - 0162-a-merge-produces-a-tiered-plan-the-mesh-keeps.md - - 0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md + - 02-DECISIONS/0162-a-merge-produces-a-tiered-plan-the-mesh-keeps.md + - 02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md extends: 02-DECISIONS/0238-a-commit-is-the-build-at-hand-one-commit-one-change-plan-checked-off-the-trunk-and-published-only-on-it.md --- diff --git a/02-DECISIONS/0276-merges-are-assembled-in-a-rolling-window-and-each-batch-is-delivered-by-one-walk-with-one-commit-per-repository.md b/02-DECISIONS/0276-merges-are-assembled-in-a-rolling-window-and-each-batch-is-delivered-by-one-walk-with-one-commit-per-repository.md index 24053636..58333346 100644 --- a/02-DECISIONS/0276-merges-are-assembled-in-a-rolling-window-and-each-batch-is-delivered-by-one-walk-with-one-commit-per-repository.md +++ b/02-DECISIONS/0276-merges-are-assembled-in-a-rolling-window-and-each-batch-is-delivered-by-one-walk-with-one-commit-per-repository.md @@ -14,6 +14,12 @@ extends: 02-DECISIONS/0249-a-delivery-groups-order-rules-have-a-precedence-and-a # 276. Merges are assembled in a rolling window, and each batch is delivered by one walk with one commit per repository +> **Superseded in part — 2026-10-10, by [ADR 0282](0282-a-fix-to-a-leaf-module-runs-healthy-on-every-node-within-five-minutes-of-its-merge-and-a-core-module-within-ten.md).** +> Decision 4's "one walk at a time", and decision 1's window for every merge, no longer hold: a lone merge is +> cut at once, and walks that share no repository, module or edge of the module graph run at once, one +> first-node judgement per node at a time. Two walks of one repository never at once, no walk superseded once +> it started, and the window for a merge that waits for its delivery group stand as decided here. + ## Context Shortly after midnight on 2026-10-10 two pull requests of the catalogue were merged 18 seconds apart, the diff --git a/02-DECISIONS/0282-a-fix-to-a-leaf-module-runs-healthy-on-every-node-within-five-minutes-of-its-merge-and-a-core-module-within-ten.md b/02-DECISIONS/0282-a-fix-to-a-leaf-module-runs-healthy-on-every-node-within-five-minutes-of-its-merge-and-a-core-module-within-ten.md index 74a8fe31..29ad016f 100644 --- a/02-DECISIONS/0282-a-fix-to-a-leaf-module-runs-healthy-on-every-node-within-five-minutes-of-its-merge-and-a-core-module-within-ten.md +++ b/02-DECISIONS/0282-a-fix-to-a-leaf-module-runs-healthy-on-every-node-within-five-minutes-of-its-merge-and-a-core-module-within-ten.md @@ -5,6 +5,8 @@ date: 2026-10-10 deciders: jochen reconstructed: false extends: 02-DECISIONS/0276-merges-are-assembled-in-a-rolling-window-and-each-batch-is-delivered-by-one-walk-with-one-commit-per-repository.md +supersedes-in-part: + - 02-DECISIONS/0276-merges-are-assembled-in-a-rolling-window-and-each-batch-is-delivered-by-one-walk-with-one-commit-per-repository.md --- # 282. A fix to a leaf module runs healthy on every node within five minutes of its merge, and a core module within ten diff --git a/02-DECISIONS/README.md b/02-DECISIONS/README.md index 9535486c..ffda2c5a 100644 --- a/02-DECISIONS/README.md +++ b/02-DECISIONS/README.md @@ -73,6 +73,18 @@ rule for the author and the reviewer, and the diff is where it is caught. Making mean a record declaring the relationship in its frontmatter, which is a change to the record schema and has not been decided. +**A supersession in part is the declared case, and it is machine-checked.** A record that replaces part of +an older one names it under `supersedes-in-part:`, and the older record carries, directly under its +heading and newest first, a note in the form + +> **Superseded in part — YYYY-MM-DD, by ADR NNNN** (a link to it). What no longer holds, and what stands +> as decided here. + +dated by the newer record's `date:`. `00-META/checks/records.py` (`partial-supersession`) fails when +either half is missing. Saying "this narrows" or "this replaces" an older record in prose alone is not +enough: on 2026-10-11, 6 records did only that, and 11 of 21 declared links had no note on the record +they changed. + The records run in the order the decisions were taken, oldest first. **Every decision is a record.** There is no ledger and no index file — if a decision is worth @@ -92,6 +104,8 @@ deciders: name reconstructed: true|false # true when the record was written after the fact from evidence superseded-by: # 02-DECISIONS/NNNN-....md, when status is superseded extends: # 02-DECISIONS/NNNN-....md, when this record widens an earlier one +supersedes: # a list of 02-DECISIONS/NNNN-....md this record replaces whole +supersedes-in-part: # a list of 02-DECISIONS/NNNN-....md of which this record replaces a part --- ```