Take in round 3 of design 47's G review: no module reads the indexer's modules, a put ends itself, ADR 0662 withdrawn

G stops declaring the indexer's modules, so the eight other modules that read it would break unless they
move to the catalog half in the same milestone. A put without hold never ended and pinned its want; ADR
0546 §5 already says it ends once the node runs it, now heard on the node-engine seat's running event.
ADR 0662 decided ADR 0661's switch another way and is withdrawn, so G builds ADR 0661 alone.

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
This commit is contained in:
2026-11-09 19:56:42 +01:00
parent 4f388e8452
commit e73a1a7bcf
@@ -47,6 +47,7 @@ decisions:
- "ADR 0549"
- "ADR 0548"
- "ADR 0547"
- "ADR 0546"
- "ADR 0539"
- "ADR 0536"
- "ADR 0534"
@@ -617,7 +618,7 @@ module's progress on each node is its want against its have, shown by the view (
## Two graphs, one source of truth
*ADR 0656, which supersedes ADR 0645 to ADR 0648; ADR 0595,
ADR 0596, ADR 0603 §2, §6, §7, ADR 0567 §5, ADR 0571 §8, ADR 0614 §4, ADR 0618 §2, ADR 0619 §1 to §3, ADR 0636 §1,
ADR 0596, ADR 0603 §2, §6, §7, ADR 0615 §1, §2, ADR 0567 §5, ADR 0571 §8, ADR 0614 §4, ADR 0618 §2, ADR 0619 §1 to §3, ADR 0636 §1,
§3, §4, §7, ADR 0639 §7, §8, ADR 0564 §2, ADR 0363 §2.*
From research 085's milestone. One graph answered two questions, which modules exist and which version runs where,
@@ -707,7 +708,7 @@ Findings 11). How each is kept, read and retained is this design's choice under
| Part | Kept data before G (form 0) | After G | Restored at a revert |
|---|---|---|---|
| the indexer | the state `modules` (ADR 0603 §2's one key per module) and its durable consumer's position on the forge bridge's stream `forge` | catalog graph revisions as objects, form 1; `modules` no longer declared | yes: `modules` as it stood at G's delivery, and the consumer's position |
| the indexer | the state `modules` (ADR 0603 §2's one key per module) and its durable consumer's position on the forge bridge's stream `forge` | catalog graph revisions as objects, form 1; `modules` no longer declared, nor its tool `indexer_read_modules` or its view, every reader of it reading the catalog half (*Every other reader of which modules exist*, above) | yes: `modules` as it stood at G's delivery, and the consumer's position |
| the gate | the states `merges` and `turns` | the delivery record's ledger, form 1; `merges` and `turns` no longer declared | yes: `merges` and `turns` as they stood at G's delivery |
| the assigner | the wants, written from the indexer's `modules` | the same wants, form 0, written from the assignment graph; the assignment graph revisions as objects, form 1 | no |
@@ -768,6 +769,19 @@ Findings 11). How each is kept, read and retained is this design's choice under
candidate's view is read only by the parts that judge a candidate, inside the check its manifest validator and
composer, and the indexer's candidate pass (ADR 0656, which changes ADR 0636 §4 in that the candidate pass joins
them).
- **Every other reader of which modules exist reads the catalog half, in the same milestone.** From milestone G the
indexer declares no state `modules` and serves neither its tool `indexer_read_modules` nor a view of it (*Reverted*,
below), so every module that learns from it which modules exist moves in milestone G, not after: the watchman (its
manifest findings), the status view (`view_reach`), the forge module (which repositories its account writes), the
holders of the seats `mesh-config`, `mesh-provisioner` and `mesh-self-check`, the claude-code module and the tool
runner. Each takes a first view of the catalog half by the seat `mesh-catalog`'s verb `revision` and follows its
event `catalog-revision`, through `meshcatalogclient` in Go or the seat's generated TypeScript contract in the forge
module, names the seat and never the indexer, and keeps no list of its own (ADR 0656 §6, ADR 0596 §2; ADR 0615 §1,
under which every reader of the indexer's state moves in one milestone). The order is the module graph's: each
declares the verb in its `invokes`, so the served-verb edge delivers none of them to a node before an indexer serving
`revision` runs there (ADR 0615 §2, ADR 0614). The design's choice under ADR 0656 §6: one form of the fact, never
`modules` kept beside the catalog graph for these readers, which would be a second source of the same fact. How it is
checked: test 61.
- **The trunk's heads come from the catalog half.** The checker takes the trunk heads a check merges onto from the
catalog half, which carries the heads, and never reads the gate's state `source` (ADR 0596 §2); with the hold and
the turns removed it reads nothing of the gate at all (*Nothing merges into a repository under check*).
@@ -1012,7 +1026,8 @@ code finds none of the reads the revision view replaces, each by name: the index
the checker's watch of the indexer's `candidates.<try id>`, the forge bridge's read of the gate's `merges` and `owed`,
the checker's read of the gate's `source` and `turns`, the forge module's watch of the checker's `owed` (its `mesh/check`
status, now the checker's `owed` event performed by the forge bridge) and its read of the gate's `source`, the grants
part's read of the assigner's state `wants`, the
part's read of the assigner's state `wants`, any module's read of the indexer's `modules` (its tool
`indexer_read_modules` in an `invokes`, its view in a `consumes`), the
checker's validator request with no seat definitions, a seat list compiled into the node-engine, the checker, the
builder or the grants part, a seat list's reader wired by a part itself, and a call of the forge module's own tools by
a delivery part or the gate; an old node-engine that wakes takes its new build in a form it reads.
@@ -1289,7 +1304,8 @@ and its verdict is carried (*A move of the trunk carries every verdict*); the ch
the gate no longer watches the checker's verdicts for a hold. **Its record is to be accepted before the push:** ADR
0548 §2 to §4, §9 and §10, ADR 0551 and ADR 0534 §4's judgement of `mesh/check` by the merge are in force, and ADR
0661, which ends the first two and changes the third (proposed, needs the operator's Approve), is to be accepted before
milestone G's pull requests are pushed; until it is accepted, the rule below holds as those records have it. How it is checked: in the gate's whole-module test an approved merge into a
milestone G's pull requests are pushed; until it is accepted, the rule below holds as those records have it. ADR 0662
is withdrawn; G builds ADR 0661. How it is checked: in the gate's whole-module test an approved merge into a
repository under a running check is handed at once, and the gate's manifest declares no `turns` and no setting
`check-gates-merge`; in the checker's, a check claims at once with no gate state granted to read.
@@ -1860,7 +1876,7 @@ later change of a kept data's form, not as a case of this milestone.
## Compositions, wants and the apply
*ADR 0360 §8, §9, ADR 0377, ADR 0429 §4, §6, ADR 0539 §9, §14 to §16, ADR 0547 §2 to §9, ADR 0549, ADR 0555.*
*ADR 0360 §8, §9, ADR 0377, ADR 0429 §4, §6, ADR 0539 §9, §14 to §16, ADR 0546 §5, §6, ADR 0547 §2 to §9, ADR 0549, ADR 0555.*
- **Each node composes its own.** For each want `want.<node>.<module>` the node agent composes that module for
its own node with the composition of `mesh-delivery-sdk` from the manifest by digest the indexer wrote, the module's resolved
@@ -2036,6 +2052,18 @@ later change of a kept data's form, not as a case of this milestone.
fingerprint, the digest, the phase and the health after the module's start window. A failed apply is loud,
retried by the next change of the want or the composition, never by a clock, and fixed forward (ADR 0360 §8,
ADR 0539 §9).
- **A put without hold ends itself once the node runs it.** A put the assigner's tool `assigner_put` writes with
`hold` false ends when the node's have runs its fingerprint healthy, and the assigner's rules write the want again
from their next pass (ADR 0546 §5); a held put stays until `assigner_release` (ADR 0546 §6). The assigner hears that
the node runs it as the node-engine seat's `running.<node>.<module>` naming the put's fingerprint, through a durable
consumer of its own declared in its `consumes`, the one its composing waits hear too (*Composing waits per node*),
so a put asked while the node was away ends once the node says it runs it; it never reads the node's have across
the seam (ADR 0596 §2). On that event it marks the put ended, says the step as its event `put`, and from then on its
rules own the want; a `running` naming another fingerprint ends nothing. The design's choice under ADR 0546 §5: the
event the node already says is the one fact that ends the put, so a put never pins a want by being forgotten, as
lead-47's puts of a node-engine build did for seven hours on 2026-11-09 (issue 1966), and milestone G's one logged
put of its own indexer ends by itself. Built first in the issue 1966 recovery, kept whole in milestone G. How it is
checked: test 62.
- **The bus module is wanted like any module; only a warranted want replaces its server** (ADR 0594, changing
ADR 0539 §14 and §15, ADR 0546 §8 and ADR 0565 §7 for the bus module). The assigner writes the bus module's want by
the same rules as every module's, and the node agent applies what that want brings (its files, its processes' bus
@@ -2640,6 +2668,17 @@ What milestone G's prepare found, and its test:
does not claim `oci-artifact-registry`; fetched bytes that differ from the done key's digest are not applied; an
artifact over the bus's value limit is fetched whole as an object; with the keeping node away, or the build swept,
the want waits and the have says why (whole, builder, build module and node-engine).
61. **No module reads the indexer's `modules`.** The watchman's manifest findings, the status view's `view_reach`, the
forge module's writable repositories and the reads of the holders of `mesh-config`, `mesh-provisioner` and
`mesh-self-check`, of the claude-code module and of the tool runner each answer from the catalog half: after a
merge that adds a module, each names it once `catalog-revision` is said, with no call of the indexer by name; the
indexer's manifest declares no `modules` (each module's existing tests, a row each; live, a search of the catalog's
and mesh-tools' code and manifests finds no `indexer_read_modules` and no view `modules`).
62. **A put without hold ends itself.** A put with `hold` false of a fingerprint the node does not run yet ends on that
node's `running` naming its fingerprint, says the step `put`, and the next pass of the rules writes the want, so a
later build is wanted with no `assigner_release`; a `running` of another fingerprint ends nothing; a held put stays
until released; a put whose `running` was said while the assigner was stopped ends after its restart (whole,
assigner; live, `assigner_puts` after milestone G's put of its own indexer).
## What retires
@@ -2961,7 +3000,11 @@ another, and the switch carrying what is owed; the seat `git` covers every forge
and the gate, its act verbs granted by the holder's trusted `callers`, the forge's acting tools and its watch of the
checker retired, and `merge-pull` judging no check, its record to be accepted before the push; the order forge, bridge,
gate with its way back, and the indexer's start without the forge; `module-held`, an error for a failed forge read and
the re-ask of a check that could not run; numbered tests 56 to 60; and the store seat's holder's own build.
the re-ask of a check that could not run; numbered tests 56 to 60; and the store seat's holder's own build. Round 3
takes in three findings of G's second prepare refresh, as lead-47 ruled (2026-11-09): every other module that read the
indexer's `modules` reads the catalog half in milestone G (*The revision view*, *Reverted*; test 61); a put without
hold ends itself on the node's `running`, built first in the issue 1966 recovery (*Compositions, wants and the apply*;
test 62); and ADR 0662, which decided the same switch as ADR 0661 another way, is withdrawn, so G builds ADR 0661.
Left as notes on issue 1921, not in this amendment: a conformance check that a changed layout raises its `form`; the
size and retention of restore points and set-aside data; who may call `restore` for bus data and which manifest grants