Merge pull request 'Declare every partial supersession in both records, and check it' (#305) from fix/loose-links-between-decision-records into main
This commit was merged in pull request #305.
This commit is contained in:
@@ -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 |
|
||||
|
||||
@@ -264,6 +264,74 @@ 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
|
||||
)
|
||||
|
||||
|
||||
# The form these notes had before the check: it named the later record but nothing read it.
|
||||
NARROWED_MARK = re.compile(r"^> \*\*Narrowed, not replaced — [^\n]*\[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.
|
||||
The note is dated by the newer record's `date:`, and the older form of the note, which named a
|
||||
later record and was read by nothing, is refused so it cannot be a way round this check.
|
||||
"""
|
||||
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 line in NARROWED_MARK.findall(record["text"]):
|
||||
failures.add(
|
||||
"partial-supersession",
|
||||
rel(record["path"]),
|
||||
f"a note names a later record in the old form ({line.strip()[:60]}…); write it as "
|
||||
f"'> **Superseded in part — YYYY-MM-DD, by [ADR NNNN](…).**' and declare it in that "
|
||||
f"record's `supersedes-in-part:`",
|
||||
)
|
||||
for date, by in PARTIAL_MARK.findall(record["text"]):
|
||||
if by in records and date != str(records[by]["front"].get("date", "")):
|
||||
failures.add(
|
||||
"partial-supersession",
|
||||
rel(record["path"]),
|
||||
f"the note for ADR {by} is dated {date}; ADR {by} is dated "
|
||||
f"{records[by]['front'].get('date', 'nowhere')}",
|
||||
)
|
||||
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 +474,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)
|
||||
|
||||
@@ -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.*
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-08-26
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0009-modules-and-the-graph.md
|
||||
extends: 02-DECISIONS/0009-modules-and-the-graph.md
|
||||
---
|
||||
|
||||
# 8. A context owns its store, exclusively
|
||||
|
||||
@@ -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
|
||||
@@ -38,7 +43,7 @@ hand.
|
||||
|
||||
### What a domain module turns out to be, and why it is not the one refused above
|
||||
|
||||
> **Narrowed, not replaced — 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 catalogue no longer
|
||||
> **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 catalogue no longer
|
||||
> holds a domain module: `networking` was retired, and every machine is assigned the private network's
|
||||
> own module. A module with requirements and no files stays a thing a module may be; "why it is worth
|
||||
> having" below describes what this record decided for `networking`, not what runs.
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-08-24
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0017-a-test-defends-a-decision.md
|
||||
extends: 02-DECISIONS/0017-a-test-defends-a-decision.md
|
||||
---
|
||||
|
||||
# 18. A picture of a system is read from the system, never from what asked for it
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-03
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0009-modules-and-the-graph.md
|
||||
extends: 02-DECISIONS/0009-modules-and-the-graph.md
|
||||
---
|
||||
|
||||
# 40. What a module is
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-03
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0040-what-a-module-is.md
|
||||
extends: 02-DECISIONS/0040-what-a-module-is.md
|
||||
---
|
||||
|
||||
# 41. Events are a relationship, the lighter sibling of provisioning
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-03
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0041-events-are-a-relationship.md
|
||||
extends: 02-DECISIONS/0041-events-are-a-relationship.md
|
||||
---
|
||||
|
||||
# 42. The shape of an event on the wire
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-04
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0041-events-are-a-relationship.md
|
||||
extends: 02-DECISIONS/0041-events-are-a-relationship.md
|
||||
---
|
||||
|
||||
# 43. A module's broker account is scoped by what it emits and consumes
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-04
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0027-a-provision-names-what-the-consumer-is-coupled-to.md
|
||||
extends: 02-DECISIONS/0027-a-provision-names-what-the-consumer-is-coupled-to.md
|
||||
---
|
||||
|
||||
# 44. A public name is provisioned, not registered by hand
|
||||
|
||||
@@ -4,11 +4,16 @@ status: accepted
|
||||
date: 2026-09-04
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0005-the-node-host.md
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-04
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0027-a-provision-names-what-the-consumer-is-coupled-to.md
|
||||
extends: 02-DECISIONS/0027-a-provision-names-what-the-consumer-is-coupled-to.md
|
||||
---
|
||||
|
||||
# 46. A module's configuration is its assignment's, not its manifest's
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-04
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0043-a-module-broker-account-is-scoped-by-emits-and-consumes.md
|
||||
extends: 02-DECISIONS/0043-a-module-broker-account-is-scoped-by-emits-and-consumes.md
|
||||
---
|
||||
|
||||
# 47. A module runs its code as its own process, with its own account
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-05
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0030-data-outlives-the-mesh-that-declared-it.md
|
||||
extends: 02-DECISIONS/0030-data-outlives-the-mesh-that-declared-it.md
|
||||
---
|
||||
|
||||
# 51. Shared data is the operator's, and a module is granted access to it
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-05
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0005-the-node-host.md
|
||||
extends: 02-DECISIONS/0005-the-node-host.md
|
||||
---
|
||||
|
||||
# 52. An init step is a container run once to completion, gating what follows
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-06
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0052-a-step-that-runs-once-before-a-container.md
|
||||
extends: 02-DECISIONS/0052-a-step-that-runs-once-before-a-container.md
|
||||
---
|
||||
|
||||
# 53. A scheduled step is a container run on a recurring schedule
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-06
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0050-model-access-is-vendor-agnostic.md
|
||||
extends: 02-DECISIONS/0050-model-access-is-vendor-agnostic.md
|
||||
---
|
||||
|
||||
# 54. Model usage is a vendor-neutral record, produced by the adapter, at two grains
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-07
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0050-model-access-is-vendor-agnostic.md
|
||||
extends: 02-DECISIONS/0050-model-access-is-vendor-agnostic.md
|
||||
---
|
||||
|
||||
# 55. Model access is answered by a licence, or by a node that hosts the model
|
||||
|
||||
@@ -4,14 +4,14 @@ status: accepted
|
||||
date: 2026-09-09
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0007-connectivity.md
|
||||
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.
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-10
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0006-the-substrate-and-the-control-plane.md
|
||||
extends: 02-DECISIONS/0006-the-substrate-and-the-control-plane.md
|
||||
---
|
||||
|
||||
# 67. Genesis is a pivot: a temporary control plane installs the registry that makes it permanent
|
||||
|
||||
@@ -4,7 +4,7 @@ status: superseded
|
||||
date: 2026-09-12
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0016-the-lab.md
|
||||
extends: 02-DECISIONS/0016-the-lab.md
|
||||
superseded-by: 02-DECISIONS/0149-the-live-mesh-is-the-test-bed.md
|
||||
---
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-12
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0009-modules-and-the-graph.md
|
||||
extends: 02-DECISIONS/0009-modules-and-the-graph.md
|
||||
---
|
||||
|
||||
# 69. A module is a repository and a path within it
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-12
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0067-genesis-is-a-pivot.md
|
||||
extends: 02-DECISIONS/0067-genesis-is-a-pivot.md
|
||||
---
|
||||
|
||||
# 70. The catalogue owns the module graph, and genesis builds rather than carries
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-12
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0070-the-catalogue-owns-the-module-graph.md
|
||||
extends: 02-DECISIONS/0070-the-catalogue-owns-the-module-graph.md
|
||||
---
|
||||
|
||||
# 71. Genesis clones from a mesh, and checks what it got
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-12
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0070-the-catalogue-owns-the-module-graph.md
|
||||
extends: 02-DECISIONS/0070-the-catalogue-owns-the-module-graph.md
|
||||
---
|
||||
|
||||
# 72. Two graphs, and a build chain that orders itself
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-13
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0070-the-catalogue-owns-the-module-graph.md
|
||||
extends: 02-DECISIONS/0070-the-catalogue-owns-the-module-graph.md
|
||||
---
|
||||
|
||||
# 73. The installer carries a builder, and the registry stays where it is
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-15
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0039-what-the-sdk-holds-and-refuses.md
|
||||
extends: 02-DECISIONS/0039-what-the-sdk-holds-and-refuses.md
|
||||
---
|
||||
|
||||
# 74. The mesh defines a module protocol; an SDK is an implementation of it
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-15
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0014-no-npm-workspace.md
|
||||
extends: 02-DECISIONS/0014-no-npm-workspace.md
|
||||
---
|
||||
|
||||
# 75. An artifact store is a provision; a package registry is a different one
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-16
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0075-two-stores-and-which-provides-what.md
|
||||
extends: 02-DECISIONS/0075-two-stores-and-which-provides-what.md
|
||||
---
|
||||
|
||||
# 76. The SDK is a published package, and the toolchain resolves it by version
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-16
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0006-the-substrate-and-the-control-plane.md
|
||||
extends: 02-DECISIONS/0006-the-substrate-and-the-control-plane.md
|
||||
---
|
||||
|
||||
# 77. The parts are named controller, foundation, node — not control plane, substrate, master
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-16
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0033-the-substrate-is-a-store-and-a-broker.md
|
||||
extends: 02-DECISIONS/0033-the-substrate-is-a-store-and-a-broker.md
|
||||
---
|
||||
|
||||
# 78. The store and the broker are ordinary modules
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-17
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0078-the-store-and-broker-are-modules.md
|
||||
extends: 02-DECISIONS/0078-the-store-and-broker-are-modules.md
|
||||
---
|
||||
|
||||
# 79. The foundation seats are named after their servers
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-17
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0019-how-this-repository-works.md
|
||||
extends: 02-DECISIONS/0019-how-this-repository-works.md
|
||||
---
|
||||
|
||||
# 80. The development cycle is checked, not trusted
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-17
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0080-the-development-cycle-is-checked.md
|
||||
extends: 02-DECISIONS/0080-the-development-cycle-is-checked.md
|
||||
---
|
||||
|
||||
# 81. A decision nothing cites is not yet in the chain
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-17
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0072-two-graphs-and-the-build-chain.md
|
||||
extends: 02-DECISIONS/0072-two-graphs-and-the-build-chain.md
|
||||
---
|
||||
|
||||
# 82. The registry is reached by name, and the overlay is its security
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-18
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0010-delivery.md
|
||||
extends: 02-DECISIONS/0010-delivery.md
|
||||
---
|
||||
|
||||
# 83. One push leaves the mesh consistent
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-21
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0052-a-step-that-runs-once-before-a-container.md
|
||||
extends: 02-DECISIONS/0052-a-step-that-runs-once-before-a-container.md
|
||||
---
|
||||
|
||||
# 99. A step that runs once names what it reads, and runs again when it changed
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-25
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0075-two-stores-and-which-provides-what.md
|
||||
extends: 02-DECISIONS/0075-two-stores-and-which-provides-what.md
|
||||
---
|
||||
|
||||
# 109. A package registry seat is one per ecosystem, not one for all of them
|
||||
|
||||
@@ -4,11 +4,16 @@ status: accepted
|
||||
date: 2026-09-25
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0009-modules-and-the-graph.md
|
||||
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
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-25
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0069-a-module-is-a-repository-and-a-path.md
|
||||
extends: 02-DECISIONS/0069-a-module-is-a-repository-and-a-path.md
|
||||
---
|
||||
|
||||
# 111. A build source is on the mesh's git seat, or it is an external repository
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-25
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0046-a-module-configuration-is-its-assignments-not-its-manifest.md
|
||||
extends: 02-DECISIONS/0046-a-module-configuration-is-its-assignments-not-its-manifest.md
|
||||
---
|
||||
|
||||
# 112. A module definition names no node, no mesh and no path: everything it needs is a requirement the mesh resolves
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-26
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0113-the-vault-makes-every-secret.md
|
||||
extends: 02-DECISIONS/0113-the-vault-makes-every-secret.md
|
||||
---
|
||||
|
||||
# 114. A credential two parties hold rotates over two credentials; one a single party holds rotates in place, staged; and retiring a credential never removes what it reached
|
||||
|
||||
@@ -3,7 +3,7 @@ topic: what runs on it
|
||||
status: accepted
|
||||
date: 2026-09-26
|
||||
deciders: jochen
|
||||
extends: 0112-a-module-definition-names-no-node-mesh-or-path.md
|
||||
extends: 02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md
|
||||
---
|
||||
|
||||
# 115. One assignment of a module per node: the module's name is the assignment's identity
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-26
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0110-a-seat-is-a-module-assignment-from-a-closed-set.md
|
||||
extends: 02-DECISIONS/0110-a-seat-is-a-module-assignment-from-a-closed-set.md
|
||||
---
|
||||
|
||||
# 117. A machine's uplink is a seat: the mesh configures the manager, never the link
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-27
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0102-the-mesh-writes-into-a-shared-file-never-over-it.md
|
||||
extends: 02-DECISIONS/0102-the-mesh-writes-into-a-shared-file-never-over-it.md
|
||||
---
|
||||
|
||||
# 118. Undeclaring removes what the mesh made, and gives a unit back the state it was found in
|
||||
@@ -80,7 +80,7 @@ records the state it first found the unit in, and undeclaring returns the unit t
|
||||
manager: running before the mesh arrived, running after it leaves.
|
||||
- **A unit the mesh started is stopped again**, and one it enabled is disabled again — the packet
|
||||
filter a converge loaded, which returning to adopted unloads.
|
||||
> **Narrowed, not replaced — 2026-10-09, by [ADR 0269](0269-what-the-meshs-own-declaration-stopped-is-started-again-when-it-goes.md).**
|
||||
> **Superseded in part — 2026-10-09, by [ADR 0269](0269-what-the-meshs-own-declaration-stopped-is-started-again-when-it-goes.md).**
|
||||
> "Never started on the way out" has one exception. The host now records what the mesh declared beside
|
||||
> what it found. A unit found running or enabled that the mesh's own declaration held stopped or disabled
|
||||
> is started or enabled again when that declaration goes, but only while it is still exactly as the mesh
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-27
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0105-the-mesh-adopts-the-predecessors-tunnel-in-place.md
|
||||
extends: 02-DECISIONS/0105-the-mesh-adopts-the-predecessors-tunnel-in-place.md
|
||||
---
|
||||
|
||||
# 119. A taken tunnel's predecessor is retired once the take is proven
|
||||
|
||||
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-09-27
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0112-a-module-definition-names-no-node-mesh-or-path.md
|
||||
extends: 02-DECISIONS/0112-a-module-definition-names-no-node-mesh-or-path.md
|
||||
---
|
||||
|
||||
# 120. A roster fact carries its format as a template: the mesh owns the data, the module owns the format
|
||||
|
||||
+10
-6
@@ -4,19 +4,23 @@ status: accepted
|
||||
date: 2026-09-27
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0110-a-seat-is-a-module-assignment-from-a-closed-set.md
|
||||
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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+3
-3
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
+5
-6
@@ -5,8 +5,8 @@ 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
|
||||
extends: 0191-the-meshs-resolver-holds-only-the-meshs-own-names.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
|
||||
---
|
||||
|
||||
# 194. The mesh has one resolver, and every node asks it for the mesh's names
|
||||
@@ -16,10 +16,9 @@ extends: 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.
|
||||
|
||||
+2
-2
@@ -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
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ status: accepted
|
||||
date: 2026-10-03
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 0194-the-mesh-has-one-resolver-and-every-node-asks-it-for-the-meshs-names.md
|
||||
extends: 02-DECISIONS/0194-the-mesh-has-one-resolver-and-every-node-asks-it-for-the-meshs-names.md
|
||||
---
|
||||
|
||||
# 199. A module that answers names declares its zone, and a node's hosts file is one module's
|
||||
|
||||
@@ -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
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
---
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
+1
-1
@@ -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,
|
||||
|
||||
+1
-1
@@ -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
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
---
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
---
|
||||
|
||||
|
||||
+6
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
---
|
||||
|
||||
|
||||
+1
-1
@@ -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
|
||||
---
|
||||
|
||||
|
||||
+2
@@ -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
|
||||
|
||||
+1
-1
@@ -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
|
||||
---
|
||||
|
||||
|
||||
+2
-2
@@ -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
|
||||
---
|
||||
|
||||
|
||||
+2
@@ -5,6 +5,8 @@ date: 2026-10-09
|
||||
deciders: jochen
|
||||
reconstructed: false
|
||||
extends: 02-DECISIONS/0118-undeclaring-gives-a-unit-back-the-state-it-was-found-in.md
|
||||
supersedes-in-part:
|
||||
- 02-DECISIONS/0118-undeclaring-gives-a-unit-back-the-state-it-was-found-in.md
|
||||
---
|
||||
|
||||
# 269. What the mesh's own declaration stopped is started again when it goes
|
||||
|
||||
+7
@@ -14,6 +14,13 @@ 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 or arrives while a batch assembles
|
||||
> stand as decided here.
|
||||
|
||||
## Context
|
||||
|
||||
Shortly after midnight on 2026-10-10 two pull requests of the catalogue were merged 18 seconds apart, the
|
||||
|
||||
+2
@@ -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
|
||||
|
||||
@@ -73,6 +73,19 @@ 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, when the note's date is not the newer record's, and on a note in the older form
|
||||
*Narrowed, not replaced*. Where the note sits is the reviewer's to see in the diff. 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 +105,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
|
||||
---
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user