diff --git a/00-META/glossary.md b/00-META/glossary.md index e2a9b1c5..ff4548a7 100644 --- a/00-META/glossary.md +++ b/00-META/glossary.md @@ -95,7 +95,9 @@ are a published vocabulary, fixed by the manifest's schema. **Decided by** ADR 0 and repair). - **manifest** — the file a module is defined by (`module.json`): what it is, what it provides and - requires, the seats it claims, the resources it declares, its tools, its data and its health. Say + requires, the seats it claims, the resources it declares, its tools, its data and its health. From the delivery of + design 47's milestone G it also names its artifacts and, where nothing else says it, each one's dependencies (`needs`), + and never a pipeline step's status, which is the registration's policy (ADR 0666 §7, §14). Say manifest in prose, not the file's name. *Not:* ~~module definition~~ (hq) - **resource** — one thing a manifest declares a node must have: a file, a directory, a service, a @@ -306,7 +308,9 @@ controller and the store; for module assignment, by the seat `mesh-module-assign Config) are `mesh-config`'s, never part of what the controller records (ADR 0348 §9). - **placement** — which module runs on which node, with its pins, host ports and bindings, and what a person decided of the node, as one key per node in the state `placement` of the seat `mesh-module-assigner`. It changes only by - a placement proposal the operator approves, and no repository holds it or names a node (ADR 0567). Until ADR + a placement proposal the operator approves, and no repository holds it or names a node (ADR 0567). From the delivery + of design 47's milestone G it names, per module, the **watched branch** its node runs, by default the registration's + first, and may name an earlier build to return to, one value (ADR 0666 §6, §24). Until ADR 0547's third milestone the controller's assignments are kept equal to it by the holder. *Not:* ~~placement file~~ (hq) - **mesh-module-assigner** — the seat, held once for the mesh, that keeps placement: its states @@ -526,28 +530,65 @@ and the operator act. **Recorded by** the controller's `identity` and `licences` back when it fails. The domain is continuous integration and delivery, named **delivery**, and its parts live in the repository `mesh-delivery` (ADR 0429 §2). **Recorded by** the `mesh-delivery` module (deliveries) and the controller (the planner, the rollout) until release 6 of ADR 0429; from each release on, by the parts it builds. **Downstream of** Module, Core, Health and repair and Data. -**Decided by** ADR 0162, 0218, 0236, 0237, 0238, 0239, 0250, 0267, 0270, 0276, 0323, 0401–0408, 0428, 0429, 0444–0447, 0524–0530, 0539, 0548, 0551, 0571, 0578, 0579, 0593, 0601, 0641, 0644, 0656, 0659. +**Decided by** ADR 0162, 0218, 0236, 0237, 0238, 0239, 0250, 0267, 0270, 0276, 0323, 0401–0408, 0428, 0429, 0444–0447, 0524–0530, 0539, 0548, 0551, 0571, 0578, 0579, 0593, 0601, 0641, 0644, 0656, 0659, 0666, 0667. **Uses:** module, node, declaration and send (Core), health (Health and repair), person. +- **pipeline** — the pipeline steps run for one commit, or one group, of a module on one of its watched branches, by + the seat `mesh-pipeline-runner`, before the commit is delivered (ADR 0666 §1, §7): each step asked of the seat that + serves it, its end heard as an event, the pipeline's end said as `pipeline-ended` with every step's result, from + which alone the assigner writes a want. From the delivery of design 47's milestone G. Not a **delivery**, the commit + on its way; and *check* is no longer the word for a bundle of steps (research 086). +- **pipeline step** — one action run on a module's commit before it is delivered: lint, unit tests, integration tests, + composition, code review or approval (ADR 0666 §7). Its outcome is `passed`, `failed`, `nothing to run`, `bypassed`, + `carried`, `could not run`, `accepted`, `superseded` or `cancelled`, or it waits on a person (design 47). Always written + whole here, never *step* alone: see [Homonyms](#homonyms). +- **policy** — a module's statuses of its pipeline steps, per artifact: `required` (runs, holds the delivery until it + passes), `optional` (runs, a failure shown and holding nothing) or `bypass` (nothing runs), kept in its registration + and never in a manifest (ADR 0666 §7). Not the **upgrade policy** (Module), how a module's builds reach its nodes (see + [Homonyms](#homonyms)). +- **registration** — a module's entry in the catalog: its git origin, the path of its manifest, its watched branches and + its policy, kept by the seat `mesh-catalog`, every version with who changed it and on whose Approve; + registering and changing one are trusted acts (ADR 0666 §2). The mesh knows modules, and a repository only as a + module's git origin. +- **watched branch** — a branch a module's registration names, whose commits start that module's pipeline and which a + placement may choose for a node; registering one the forge does not protect is refused (ADR 0666 §3, §6). +- **run on request** — a pipeline run for a named commit or group that delivers nothing, asked by the runner's verb + `run`; the indexer builds its candidate from the runner's `run-started` (ADR 0666 §18). +- **artifact reference** — an artifact written `:`, such as `mesh-grants:program`: the end of a + dependency edge of the catalog graph (ADR 0666 §14). +- **mesh-pipeline-runner** — the seat, held once for the mesh, that runs each pipeline: it reads the policy from the + registrations, asks each pipeline step of the seat that serves it, says each step's start and end and each pipeline's + end as its events, keeps each pipeline's state and step log on the bus, and serves the run on request (ADR 0666 §7, + §11). An acting part of the step `pipeline` (design 47). Of this domain: its contract is in `mesh-delivery-contracts`. +- **mesh-builds** — the seat, held once for the mesh, whose holder numbers a package's version when it is published and + says the publication as its event `package-published`, on which every artifact built against the package is rebuilt + and its pipeline started (ADR 0666 §15; design 51). Of this domain: its contract is in `mesh-delivery-contracts`. +- **composition step** — the pipeline step that composes each machine's declaration with a change, by the composer built + from its heads in the sandbox, refusing a change in which two modules own one path; served by the seat `mesh-wants` + (ADR 0666 §17). From milestone G's delivery it replaces the **composition check**. - **merge check** — what a pull request carries before it may merge, judging the merge of its head into a named **trunk commit**, made in a clone of its own on a build node and never pushed (ADR 0323). One status, `mesh/check`, written by the checker: the change's tests, run by the language's build module, and the **composition check**; for a delivery group, one verdict on every member's head (ADR 0445, ADR 0447). Before release 4 of ADR 0429 a pull request carried two statuses, one for the modules the change touches and one - for the repository's own script (ADR 0238). + for the repository's own script (ADR 0238). Goes at the delivery of design 47's milestone G, the **pipeline** in its + place (ADR 0666 §17); the word goes to the *pipeline* entry's *Not:* line with the as-is update after that delivery. - **catalog graph** — the modules as their manifests declare them at one revision (bases, packages, provides and requires, invokes and serves), with the acting rules the seats declare; the indexer keeps it, one revision per source revision it takes in (ADR 0656). Its other name is **module graph**, the word for it before ADR 0656, from which each delivery part orders a source revision by its own rule: provisions, bus state, a served verb and a reader's capability are waited on; a package, and until research 085's milestone a build module's change, are triggers that rebuild, never waits; a verb edge on a cycle is left out (ADR 0603 §1, §2, ADR 0614); from research 085's milestone an acting part's edge is a wait within - its step (ADR 0656). Nothing stores the order. Not the **assignment graph**, computed from it. + its step (ADR 0656). From milestone G's delivery it is kept once per **watched branch**, and its edges run between + **artifact references**, of six kinds, the reverse order holding when something goes away (ADR 0666 §6, §14). + Nothing stores the order. Not the **assignment graph**, computed from it. *Not:* ~~build graph~~ - **assignment graph** — the module versions placed on nodes at one revision, with the edges between versions that its inputs give: provisioning, contribution, and the acting parts' versions that are to act on each entry. The assigner computes it from the catalog graph, the placements and the nodes' capabilities, and nothing else writes it; it keeps each revision naming the revisions of its inputs, served by the seat `mesh-wants`, and writes the wants - from a trunk revision's alone (ADR 0656). Not the **catalog graph**, whose entries are modules, not + from a trunk revision's alone (ADR 0656), from milestone G's delivery from a revision of the watched branch a + placement chose whose `required` pipeline steps passed (ADR 0666 §9). Not the **catalog graph**, whose entries are modules, not versions on nodes; not an **assignment**, one module put on one node. - **mesh-wants** — the seat, held once for the mesh, that keeps what each node should run, one want per node and module (`want..`), and a person's upgrade policy, served as its verb `upgrade` @@ -555,7 +596,8 @@ controller (the planner, the rollout) until release 6 of ADR 0429; from each rel `mesh-delivery-contracts` (ADR 0641 §2). - **acting part** — the holder of a seat whose definition carries a rule: the step its holder acts in and the modules it acts on (ADR 0656), in the field `acts` (design 47): the indexer, the checker, the build modules, the - node-engine, the grants part, the assigner. Within a revision its new version acts first in its step, a wait with a + node-engine, the grants part, the assigner; from milestone G's delivery the holder of `mesh-pipeline-runner` in the + checker's place (ADR 0666 §19). Within a revision its new version acts first in its step, a wait with a bound (ADR 0656); when it fails or is late, the modules it was to act on stay on their running builds and a condition names it (design 47). Not every **part**: an acting part may be any module that holds such a seat, a build module among them. @@ -570,40 +612,46 @@ controller (the planner, the rollout) until release 6 of ADR 0429; from each rel and says so (ADR 0656). The node-engine reads only the catalog half, beside its want (design 47). - **delivery record** — the gate's record of one milestone's delivery, a ledger instance it alone writes: the group's state (heads, verdicts, checks, asks), the trace (milestone, issues, pull requests, commits, the assignment graph - revisions it moved between) and what happened to each entry on each node (ADR 0656). It holds no tiers and nothing + revisions it moved between) and what happened to each entry on each node (ADR 0656); from milestone G's delivery the + pipelines' step and pipeline events in place of the verdicts, checks and asks (ADR 0666 §9). It holds no tiers and nothing else orders by it. Not a **delivery**, one commit on its way. - **checking program** — the rules every check applies, built from the change's heads (ADR 0656, ADR 0644) and run in a build seat's sandbox (ADR 0448 §2) with the revision view as its input and no bus account; the running checker only asks for it, reads its verdict, records and publishes it (design 47). Not the **checker**, the part that asks for it. + Goes with the checker at milestone G's delivery: its rules become the indexer's validation and cycle rule and the + **composition step** (ADR 0666 §17). - **composition check** — whether the machines a change touches still compose with it, run by the assigner from the modules the indexer and the builder hold, with the composition of `mesh-delivery-sdk`, the one the controller composes with (ADR 0446). It replaces the controller's check of that kind, which composed every machine from release 4 of - ADR 0429 back (issue 1303). + ADR 0429 back (issue 1303). Becomes the **composition step** at milestone G's delivery; the word then goes to that + entry's *Not:* line with the as-is update. *Not:* ~~merge gate~~ (hq) - **kept verdict** — a package's passing verdict at one test level, kept by the checker under the digest of everything its tests read, written once and read-only; a check takes it instead of running an unchanged - package (ADR 0444). + package (ADR 0444). From milestone G's delivery the pipeline runner keeps it, and a test step takes it (ADR 0666 §8). - **carried verdict** — a delivery's verdict moved to a newer trunk commit, or a newer sibling commit, by its package digests: the checker merges the head onto the new commit and runs only the packages whose digest the move changed, keeping the composition while no composed fingerprint changed; the verdict names the commits it was carried from (ADR 0548 §5, §6). A head git refuses onto the new commit is not carried: its next check is - whole (ADR 0548 §7). + whole (ADR 0548 §7). From milestone G's delivery the pipeline runner carries a step by its package digests (ADR 0666 §8). - **try** — the checker's run of a delivery group's check on one or more members, each a repository at an exact commit, before or without a pull request: the same examiner as the group's check, stricter in that a missing candidate or a node's missing composition answer ends it as error, and owing the forge no status and no Approve. It keeps the verdicts of the packages it passed for the check to take (ADR 0637). Asked only when the operator - asks for one (ADR 0637 §6). + asks for one (ADR 0637 §6). Goes at milestone G's delivery, the **run on request** in its place (ADR 0666 §18); the + word goes to that entry's *Not:* line with the as-is update after that delivery. - **trunk commit** — the commit of the trunk a merge check's verdict was judged against: the trunk's head when the build module cloned it. The verdict holds for that commit only, goes out of date when the trunk moves, and - is then carried to the new commit (ADR 0323, ADR 0548). + is then carried to the new commit (ADR 0323, ADR 0548). Goes at milestone G's delivery with the merge check: a pipeline + runs on a commit of a **watched branch**, and the word goes to that entry's *Not:* line with the as-is update after it. - **merge turn** — an approved merge's key on a repository in the gate's `turns` bucket: the deliveries waiting to merge there in the order of their Approve, and the check each waits for. It holds new checks off that repository until the merge is done (ADR 0548 §3). Written only while the check gates merges (the gate's setting `check-gates-merge`); while it does not, no turn is written and an approved merge goes in at once (ADR 0551 §1). Goes at research 085's milestone with the hold and the setting, once the record that ends them is - accepted (the operator, 2026-11-09; design 47); the word goes to a *Not:* line with the as-is update after that - delivery. + accepted (the operator, 2026-11-09; design 47; ADR 0661); the word goes to the *pipeline* entry's *Not:* line with the + as-is update after milestone G's delivery. - **build seat** — a language's node seat, held on a node by that language's build module: `node-build-go`, `node-build-node` and `node-build-image` (ADR 0525 §2). Its accepted kinds are the **build streams**, and its verbs `current`, `pause` and `resume` serve that node's pulls. It replaces the seat `node-build-agent`, retired @@ -682,8 +730,10 @@ controller (the planner, the rollout) until release 6 of ADR 0429; from each rel ADR 0250, ADR 0270). From release 6 of ADR 0429 the gate keeps the merge's states alone (`proposed`, `ready`, `rejected`, `held`, `merged` and `closed`), and a merged delivery is delivered when its source revision is, - derived from the wants and the haves (ADR 0539 §17). Not *change* (a diff). *Pipeline* is the predecessor's build-and-deploy - mechanism, which the as-is designs describe; it is never a word for a delivery. + derived from the wants and the haves (ADR 0539 §17). From milestone G's delivery a commit's states before it is + delivered are its **pipeline**'s steps, and the gate keeps no merge states (ADR 0666). Not *change* (a diff), and + not a *pipeline*, which is what runs on a commit before it is delivered (below); the as-is designs' word for the + predecessor's build-and-deploy mechanism is theirs. *Not:* ~~deployment~~ (hq) - **covered** — the end of a delivery that a later merge containing it delivered: every module it moves was sent to every machine running it by the rollout of a later merge into the same trunk, delivered on its own @@ -693,7 +743,10 @@ controller (the planner, the rollout) until release 6 of ADR 0429; from each rel covers the older merges of its repository (ADR 0539 §17). - **delivery group** — two or more deliveries sharing a pull request head branch name across the mesh's repositories, delivered as one unit in an order declared (`after:`) or inferred by the planner. One - level: a group holds deliveries, never groups. Its state is derived from its members, never set. + level: a group holds deliveries, never groups. Its state is derived from its members, never set. From milestone G's + delivery: a shared branch name carrying its issue number, complete when each member's commit has landed on its + modules' watched branch, taken in as one source revision of that branch and run as one pipeline per watched branch + (ADR 0666 §13). - **hotfix** — one pull request in one repository, delivered at its merge (ADR 0401). - **feature** — one branch name across its repositories: in two or more, its pull requests are one delivery group, merged together and delivered member by member in the group's order; in one, a single pull request delivered as a @@ -735,7 +788,8 @@ controller (the planner, the rollout) until release 6 of ADR 0429; from each rel agent** (the node-engine's own process, applying its wants), the **watchman** (presence and pulses; it also holds the Health seat `mesh-watchdogs`, whose watchdogs are pulses, and keeps the dead letters, ADR 0564 §4, §5) and the **status view** (`mesh-delivery-cli` and a web view, writing only its answers to asks and saying the events - `delivered`, `moving`, `settled` and `stuck`, derived from the keys). The reviewer is the review + `delivered`, `moving`, `settled` and `stuck`, derived from the keys), and from milestone G the **pipeline runner** + (the holder of `mesh-pipeline-runner`, ADR 0666 §7), in the checker's place at its delivery. The reviewer is the review agent's session, not a part. Built over releases 1 to 6 of ADR 0429. - **manifest validator** — the indexer's rules that judge each manifest before anything of it reaches a node: strict decoding, the seat and namespace rules, the bus and stream limits and the whole-catalog checks. It refuses a @@ -746,17 +800,23 @@ controller (the planner, the rollout) until release 6 of ADR 0429; from each rel module that only the indexer and the checker use, never mesh-sdk's (ADR 0578 §4, ADR 0593 §1): the merge check runs the trunk's in its sandbox over the manifests a change touches, failing only on a problem in a manifest the change alters or one between manifests that an altered manifest takes part in, and - a group that changes it runs the one built from its own head (ADR 0578 §2, ADR 0579 §2). + a group that changes it runs the one built from its own head (ADR 0578 §2, ADR 0579 §2). From milestone G's delivery + the indexer alone runs it: the validator built from a revision's heads judges that revision in the sandbox before any + take-in, on every watched branch, and refuses a manifest that names a pipeline step's status (ADR 0666 §6, §7). *Not:* ~~the judge / a judge / its judge / no judge / judge's / own judge / whose judge / same judge / indexer's judge / trunk's judge / running judge / older judge / newer judge / stricter judge~~ (hq) -- **fingerprint** — what identifies a module's build by its content: a hash over its source files, its +- **build-input fingerprint** — what identifies a module's build by its content: a hash over its source files, its manifest and the fingerprints of its build-time inputs, so equal content gives an equal fingerprint whatever the commit (ADR 0429 §5). It is today's source fingerprint with a base entering by its module's fingerprint, and a build resolving packages by its lock; from R4g the builder is no input of any fingerprint (ADR 0530). From - release 4 a build's key, so one source is never built twice. + release 4 a build's key, so one source is never built twice. Its meaning is kept from ADR 0429 §5, and the name says + what it hashes beside an artifact's digest (research 086); *fingerprint* alone stays its short form where no other + fingerprint is meant. - **source revision** — one revision of the key `source.main`, written only by the gate: every repository's merged head and the group that moved it. A group reaches the mesh as one source revision (ADR 0429 §11); a source revision is **delivered** when every want equals its module's fingerprint and every have equals its - want and is healthy, derived from the keys and recorded by no part (§1). + want and is healthy, derived from the keys and recorded by no part (§1). From milestone G's delivery there is one + per **watched branch**, the key `source.` in place of `source.main`, served by the seat `mesh-delivery`'s verb + `source`, and each want names a build-input fingerprint computed at one such revision (ADR 0666 §6). - **pending revision** — a source revision the running indexer has not taken in, because it names another build of the indexer or follows one that does: only the named indexer's own keys are written, the rest kept in the indexer's state `pending` until that indexer starts and takes it in (ADR 0633 §1 to §3). A group's members wait @@ -816,7 +876,10 @@ controller (the planner, the rollout) until release 6 of ADR 0429; from each rel delivery part and the gate reach the forge: reads (`pull`, `open-pulls`, `tags`, `trees`, `file`, `contains`, `statuses`) for the parts that declare them, acts (`status`, `comment`, `view`, `note`, `merge-pull`) for the forge bridge alone, as the holder's trusted value `callers` names, and the forge's events (`pull.*`, `forge.*`, - `repo.writable`) as the seat's (design 47, *The verbs*). Not the **forge** itself, the server, nor the forge module's own tools. + `repo.writable`) as the seat's (design 47, *The verbs*). From milestone G's delivery `merge-pull` is a session's + merge, refused only for a head at whose fingerprint a run failed a `required` step, a head that moved or an unprotected branch + (ADR 0666 §11), the read `branch` and the event `branch-moved` say a branch's head and protection, and the callers per + verb are the seat definition's (ADR 0666 §20). Not the **forge** itself, the server, nor the forge module's own tools. ## Health and repair — what is wrong, and putting it right @@ -851,7 +914,8 @@ becomes a message). **Decided by** ADR 0227, 0231, 0240, 0252, 0283, 0564. and the watcher that raises a condition when it stops (to-be 45 §3). - **condition** — one open fact about something the mesh owns that is wrong, with a key and a severity; raised and cleared only by observation - (ADR 0231). + (ADR 0231). A pipeline step or a watched branch's head standing still five minutes is one, from the watchman's + finding `pipeline-stands`; a step waiting on a person is not (ADR 0666 §24). What a wrapped dashboard raises is its own; the mesh's notion is a condition. *Not:* ~~alert~~ (hq) - **self-check** — the mesh's own examination of itself, run on demand and on a schedule (to-be 45 §4), held @@ -899,7 +963,10 @@ becomes a message). **Decided by** ADR 0227, 0231, 0240, 0252, 0283, 0564. person (ADR 0232). - **bus state** — what a module keeps on the bus, asked for in `requires` as a provision of the bus module, by a template and its options; created by the bus module and reached by the owner's account alone. Another module - asks the owner's tools for its data, or hears its declared events (ADR 0595, ADR 0596). + asks the owner's tools for its data, or hears its declared events (ADR 0595, ADR 0596). A value is never refused for + its size: one over the bus's per-value limit is kept in the object store beside its state, `-objects`, granted + to its owner alone, its name in the key, and a reply or an event over the per-message limit carries the object's + name (ADR 0666 §16). - **`bus-state`** — the provision of the bus module that every bus-state entry of a manifest requires, so the module graph orders the bus module's build before a module asking bus state (ADR 0614 §5). Provided by the holder of the seat `mesh-broker`. @@ -1007,7 +1074,10 @@ asking, never the act. **Decided by** ADR 0152, 0175, 0234, 0259, 0272, 0383, 03 - **ask** — a request for the operator's input, of a declared kind (yes-no, one-of, text, number, date, acknowledge). An **authorising ask** is one whose chosen option its asker performs. The router holds every ask, checks each answer's proofs and issues a **warrant**; the asker acts on it with its - own grants (ADR 0234, ADR 0259). + own grants (ADR 0234, ADR 0259). No ask is hidden: an asker has at most three offered at once, a newer ask with the + same `about` replaces its open one, and a fourth is offered while the oldest waits, never the newest (ADR 0666 §12; + design 46 §6). From the delivery of design 47's milestone G the operator's approval of a delivery is the pipeline + step `approval`, asked as an ask like any other, and no merge is asked (ADR 0666 §10). - **warrant** — the router's record that a person chose one option of one ask: the ask, the option, who chose (the operator, as a channel kind's identity), through which channel, the proofs and when, published for that asker alone. The only thing an asker acts on (ADR 0259). @@ -1268,6 +1338,7 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical. | composition | one module's resources for one node at one fingerprint, signed, from release 6 | **composition** | Core | | | the function in `mesh-delivery-sdk` that composes them, which the node agents, the assigner and the grants part run (ADR 0635 §4) | **the composition of `mesh-delivery-sdk`** | Core | | | whether the machines a change touches still compose | **composition check** | Delivery | +| | the pipeline step that composes each machine's declaration with a change, from milestone G's delivery | **composition step** | Delivery | | membership | the subjects a bus account is issued | **membership** | Provisioning | | binding | the names on the bus of a module's bus state, in its membership | **binding** of bus state | Data | | | a consumer's tie to the data a provider keeps for it | **sticky binding** | Data | @@ -1296,6 +1367,12 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical. | | the check of what a change makes of the machines it touches, a pull request status until release 4 of ADR 0429 | ~~merge gate~~ (hq); the **composition check** | Delivery | | | the part that merges a group and moves the source revision | **gate part** (`mesh-delivery-gate`) | Delivery | | | a failed step stopping its module's later steps (ADR 0136) | *a failed step holds its module* | Core | +| policy | how a module's new builds reach its nodes (`roll`, `together`, `record`) | **upgrade policy** | Module | +| | a module's statuses of its pipeline steps, kept in its registration | **policy** | Delivery | +| step | an action run on a module's commit before it is delivered | **pipeline step**, always whole | Delivery | +| | the step an acting part acts in (`take-in`, `build`, `compose`, …) | an acting rule's **step** | Delivery | +| | a step a person starts, like the bus's | **planned step** | Core | +| | a step of a rollout | **tier** | Delivery | | tier | a level of the mesh | **layer** | Core | | | a step of a rollout | **tier** | Delivery | | | how much proof an ask needs | **assurance level** | Identity and access | @@ -1327,7 +1404,7 @@ renaming one sense, the old sense moves to a *Not:* line and becomes mechanical. | draft | a record's version being written, held by one author | **draft** | The record | | | a clause the import's judgement wrote from prose | **drafted** clause | The record | | | the predecessor's operational memory, in older playbooks (issue 430) | none: it no longer exists | — | -| check | a pull request's two statuses, until release 4 of ADR 0429 | **merge check**, **repository check**; from release 4, `mesh/check` | Delivery | +| check | a pull request's two statuses, until release 4 of ADR 0429 | **merge check**, **repository check**; from release 4, `mesh/check`; from milestone G's delivery, the **pipeline** | Delivery | | | whether the machines a change touches still compose, the assigner's | **composition check** | Delivery | | | a delivery group's verdict | **composed check** | Delivery | | | the mesh's own examination | **self-check** | Health and repair | diff --git a/03-DESIGN/01-to-be/46-the-conversation-with-the-operator.md b/03-DESIGN/01-to-be/46-the-conversation-with-the-operator.md index 140fe027..4d1ce8e3 100644 --- a/03-DESIGN/01-to-be/46-the-conversation-with-the-operator.md +++ b/03-DESIGN/01-to-be/46-the-conversation-with-the-operator.md @@ -2,8 +2,10 @@ layer: to-be status: in-progress code: [mesh-controller, mesh-tools, mesh-sdk, mesh-catalog] -updated: 2026-11-06 +updated: 2026-11-10 decisions: + - "ADR 0667" + - "ADR 0666" - "ADR 0347" - "ADR 0345" - "ADR 0344" @@ -221,7 +223,20 @@ when the title and the note alone do not fit, and says that too. ### Limits, batching, history -- An asker holds **at most three open asks**; a fourth is refused in words. +- An asker holds **at most three open asks**; a fourth is refused in words. *Amended 2026-11-10, ADR 0666 §12, from the + delivery of design 47's milestone G:* **no ask is hidden, and the newest is never held back.** An asker still has at + most three asks offered at once, but a fourth is offered, not refused: the oldest of its offered asks is held back + instead, kept open with its answer tickets withdrawn, its message edited to say it waits behind newer asks of the + same asker, and offered again, with new tickets, as soon as one of the three ends. An ask with the same `about` as an + open one of the same asker replaces it (§10), so a held-back ask is never one a newer ask already stands for. `asks` + lists each asker's held-back asks with since when, and the router's tool `ask-again` offers one now, holding back the + oldest offered one in its place. A Decline ends an ask like any answer, and its asker may ask again at once: the + pipeline runner's verb `ask-again` asks a declined `approval` step so (design 47, *Approval is a step*). Why the + oldest: the newest is what the asker needs now, and the oldest has had the operator's eye longest; holding it back + edits its message rather than removing it, so the operator still sees it waits. *How it is checked:* the router's + whole-module test offers a fourth ask and holds back the oldest, offers the held-back one again when one ends, + replaces an open ask by a newer one with the same `about`, and offers an ask after a Decline; live, a fourth ask and + a declined approval each reach the operator (design 47, test 71). - Asks count against the router's hourly cap, as messages do; answers do not. - Asks to one channel within the burst window go out together under a heading ("3 questions waiting"), each as its own message, answerable and editable alone. @@ -424,7 +439,8 @@ what it does in plain words, its assurance level (`acknowledge`, `approve`, `des answer (`operator`); an expiry; what happens on expiry, in words; and optionally what it is about (a condition's key), so a newer ask about it replaces the older. It is refused at once, on its asker's `decided` subject, when its words break a rule, when no ready channel can carry one of its options' levels, -or when the asker already has three open. +or, until the delivery of design 47's milestone G, when the asker already has three open; from that delivery a fourth +is offered and the asker's oldest held back (§6, *Limits, batching, history*; ADR 0666 §12). **A warrant** carries the ask's id and asker, the option, `by` ("the operator, via telegram, user id verified"), the channel module, the proofs, the level met and when. No secret. An ask that ends without one @@ -577,7 +593,8 @@ runner's bus permissions. refused and said: waiting, declined (not asked again for 10 minutes), expired, already run, or the router's refusal. - **Fail closed:** a secret's shape in an argument or more than 16 KiB of arguments, no operator channel, a - fourth open ask, an unpublished ask, an unreadable router record, node file or mark: nothing runs. + fourth open ask (until design 47's milestone G is delivered, after which a fourth is offered and the oldest held + back, §6), an unpublished ask, an unreadable router record, node file or mark: nothing runs. - **The controller** enforces the same mark on its own verbs, asking as `mesh-controller`. - **Marked first:** `node-login-shell.execute` on every node once the reads it carried have tools (issue 418). `mesh-delivery.release` waits until a warrant the controller holds passes the mark of a verb it calls (issue @@ -702,6 +719,7 @@ Each phase ends at its own *done when*. Owning repositories from [`repos.md`](.. | **5 — Authorise, with TOTP** | `authorises` in the verb table; the router's checks for the code; direct calls refused, break-glass; `retire approve` takes `expect`; the hand-act fields; the TOTP seed as the router's state, enrolled at a terminal with ten recovery codes; `factor recover`, `factor status`, the local-only break-glass enrolment; no P2 tier before recovery codes exist; optional key enrolment; the self-check probe for the away channel; agents' grants lose the authorising verbs | mesh-controller; mesh-catalog (agents' grants, the desk's code prompt) | one controller test per refusal passes; at the desk, approve needs a code; a recovery drill re-enrols with a recovery code, and is announced | | **6 — Telegram live** | the `telegram` module (built in 5a) with replies and forced-reply codes, under its own account on the control node; the operator's two bots configured; the watcher assigned off the control node; the dead-man ping | mesh-catalog | the self-check says the away channel carries every tier; rehearsals: an approve and a destroy answered on the phone, with the hand-acts read | | **7 — A call that needs approval** (ADR 0286) | `needs-approval` in the manifest and the seat list, issued in the membership, withheld from a runner without `approval-mark/1` in its bus permissions (controller); the act's digest in TypeScript beside Go, with shared vectors (shared library); the check, the ask, the runner's `approvals`, the node's used file and `warranted` (tool runner); the controller's own verbs; `execute` marked (the controller's seat list) once issue 418's reads exist | mesh-controller, mesh-sdk, mesh-tools, mesh-catalog | a marked call on a node is asked on the phone, does nothing, runs once when made again after Approve, is refused the third time and asked again, and `hand-acts` shows the warrant | +| **8 — No ask hidden** (ADR 0666 §12), delivered with design 47's milestone G | a fourth ask offered and the asker's oldest held back, offered again when one ends; `asks` lists the held-back asks; the router's tool `ask-again`; the pipeline runner's `approval` asks and their `about` | mesh-catalog (the router) | a fourth ask and a declined approval each reach the operator; `asks` shows the held-back one | **Switching phase 5a on: the operator's steps, in order** (amended 2026-10-09, ADR 0259). Each line is typed with `nox` (`mesh-cli`) on the control-node, from the operator's own account, which is the controller's terminal diff --git a/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md b/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md index 2c371b94..fbd77f3b 100644 --- a/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md +++ b/03-DESIGN/01-to-be/47-delivery-from-commit-to-delivered.md @@ -2,8 +2,13 @@ layer: to-be status: in-progress code: [mesh-controller, mesh-catalog modules/mesh-delivery-gate, mesh-catalog modules/gitea, mesh-delivery, mesh-host, mesh-sdk, mesh-vault, mesh-contracts, hq 00-META/checks] -updated: 2026-11-09 +updated: 2026-11-10 decisions: + - "ADR 0667" + - "ADR 0666" + - "ADR 0664" + - "ADR 0573" + - "ADR 0283" - "ADR 0663" - "ADR 0661" - "ADR 0660" @@ -172,6 +177,15 @@ their reasons). A statement in the sections that follow with no record beside it design makes under ADR 0656*, under *Two graphs, one source of truth*, gives each one's reason. *Two graphs, one source of truth* and *The check on the change's own acting parts* hold the whole of it. +**From milestone G's delivery, a change goes from a commit to the machines through its module's pipeline** (ADR 0666, +ADR 0667, from research 086). Each module's registration in the catalog names its watched branches and its policy; a +commit on a watched branch runs the module's pipeline steps (lint, tests, composition, code review, approval) by the +seat `mesh-pipeline-runner`; only a `required` step that did not pass holds a delivery; the order comes from edges +between artifacts; and no Approve is asked per merge, a session merging a pull request through the seat `git`. +The checker and its try go. Milestone G builds this with research 085's two graphs as one milestone, and until its +delivery the sections it replaces hold and check and deliver it (ADR 0667 §1, §2). *Pipelines per module*, below, +holds the whole of it. + This is the delivery of [to-be 10](10-delivery.md) carried out. To-be 10 says what is built: the comparison of source and artifacts decides, and nothing here changes that. This design says who answers for one commit's journey, in what order the steps are allowed, and where each fact of it is kept. It was rewritten on @@ -211,14 +225,23 @@ source revision is derived from the keys: every **want** equals its module's **f digests instead of judging it again (ADR 0548 §1, §5; *A move of the trunk carries every verdict*, below). From research 085's milestone its judging rules are a **checking program** built from the change's heads (ADR 0656) and run in a build seat's sandbox (ADR 0448 §2); the running checker only asks, records and publishes (*The check - on the change's own acting parts*, below). + on the change's own acting parts*, below). It makes milestone G's own check, and is removed with its buckets and its + bus account once the first pipeline after G's delivery has delivered a change end to end, after a tested backup + (ADR 0667 §2, §6): from then the pipeline makes the check (ADR 0666 §17). +- **The pipeline runner** (module `mesh-delivery-pipeline`, holding the seat `mesh-pipeline-runner`), from milestone + G's delivery: runs each module's pipeline for each commit or group on its watched branches, asking each pipeline step + of the seat that serves it and saying each step's end and the pipeline's end as events, its state on the bus; it + serves the run on request in the try's place, and is an acting part in the checker's place (ADR 0666 §7, §18, §19; + *Pipelines per module*). - **The gate** merges a group's pull requests once the check and the operator's Approve agree on the same heads, reading no review line (ADR 0659 §1), and then moves the mesh's source revision in one write. While the check gates merges, it holds an approved merge for another delivery's running check of the repositories the merge goes into, and keeps the merge's **merge turn** there (ADR 0548 §2, §3, as ADR 0551 §1 bounds them); research 085's milestone removes the hold, the turns and the setting (*Nothing merges into a repository under check*, below). From that milestone it keeps one delivery record per milestone's delivery as a ledger instance (ADR 0656), its `merges` - carried into the records (*The delivery record*, below). + carried into the records (*The delivery record*, below). From G's delivery it merges nothing and asks no Approve: a + session merges a pull request through the seat `git`, and the gate keeps the delivery record, its groups and the + source revision per watched branch (ADR 0666 §10, §11, §13). - **The teller** carries conditions and asks to the operator's phone and is the only writer of an ask's answer. - **The assigner** writes which fingerprint each node should run, by six rules: the build is done, the fingerprint is not held, the node is the module's **canary** or the canary runs it healthy, at most `step` @@ -240,7 +263,9 @@ source revision is derived from the keys: every **want** equals its module's **f what the node would run is the same. From research 085's milestone it computes the assignment graph from the catalog graph, the placements and the nodes' capabilities, keeps each revision (ADR 0656) as objects in an `objects` section in the old form (ADR 0619 §2), serves it and a change's graph difference by verbs of - its seat `mesh-wants`, and writes the wants from a trunk revision's assignment graph alone (ADR 0656). + its seat `mesh-wants`, and writes the wants from a trunk revision's assignment graph alone (ADR 0656). From G's + delivery it runs the composition step, and writes a want only from a revision whose every `required` pipeline step + passed, on the watched branch a placement chose (ADR 0666 §9, §17). - **The node agent**, the node-engine's own process, follows its node's wants, **composes each wanted module for its own node** with the composition of `mesh-delivery-sdk` from the manifest by digest, the module's resolved values from mesh-config, its secrets and bus credential asked of the vault sealed to the node's key, its licences and what @@ -267,7 +292,9 @@ source revision is derived from the keys: every **want** equals its module's **f `moving`, `settled` and `stuck` once for a module on a node at one composition (ADR 0539 §17; *A delivery* below). -Ten of these are modules of the repository `mesh-delivery`, prefixed `mesh-delivery-` (ADR 0429 §2); the +Ten of these are modules of the repository `mesh-delivery`, prefixed `mesh-delivery-` (ADR 0429 §2), and from +milestone G the pipeline runner is one more, under its `modules/` folder with the `contracts` and `sdk` modules +(ADR 0667 §3); the repository is made by the forge module from its config (ADR 0428; issue 1128 makes the config value reach the node at once); the grants part is one of them. The reviewer stays the review agent's session. @@ -331,7 +358,9 @@ The target (ADR 0547): - **The gate** (module `mesh-delivery-gate`, holding the seat `mesh-delivery`) owns hotfixes, features and milestones up to the merge: it keeps one key per pull request, asks the operator's Approve, merges a group in one pass and moves the source revision in one write. It asks the controller nothing, consumes no event of a - plan, never sends to a machine and writes no composition (ADR 0539 §17). + plan, never sends to a machine and writes no composition (ADR 0539 §17). From milestone G's delivery it asks no + Approve and merges nothing; it forms the groups, keeps one source revision per watched branch and one delivery record + per delivery (ADR 0666 §10, §11, §13). - **The controller** is no part of build and delivery (ADR 0547 §1). The jobs it still keeps outside them (nodes and adoption, identities, secrets and given values, licences, config moves, conditions and facts, ADR 0429 §9) each move by a decision of their own under research 072 before it loses its lease. All are decided: @@ -385,7 +414,605 @@ The target (ADR 0547): once, when every member's checks and the group's composed check passed, and covers every member's head (ADR 0421 §2); it is the review ADR 0382 §6 asks (ADR 0421 §9). No ready mark, label, comment, forge review or recheck stands before it. The operator's Approve is asked for every merge into main, a hotfix's too - (ADR 0398 §3; the operator, 2026-10-16 23:40). + (ADR 0398 §3; the operator, 2026-10-16 23:40). Milestone G's own merges are the last asked so (ADR 0667 §2). +- **From milestone G's delivery a merge waits for nothing of the mesh.** A session merges a pull request through + the seat `git`'s `merge-pull`, judged on its head, the branch's protection and the runs at its build-input + fingerprint, which refuse it only where a `required` step failed and are never waited for; the pipeline then runs on the landed commit, and only its `required` steps, the `approval` step where a policy names it among them, hold the + delivery (ADR 0666 §9, §11; *Pipelines per module*). The trunk is still what runs, on each module's watched branches, + which a placement chooses. + +## Pipelines per module + +*ADR 0666, ADR 0667; ADR 0595, ADR 0596, ADR 0448 §2, §4, ADR 0548 §5, ADR 0564 §2, §4, ADR 0283, ADR 0656 §4, §6, ADR 0633 §5, +ADR 0664 §4, ADR 0398 §2, ADR 0593 §9; research 086, Direction.* + +From milestone G's delivery. A change of any module, the delivery system's own parts included, goes from a commit to +the machines through that module's **pipeline**: the pipeline steps its **policy** names, run for each commit or group +on each of the module's **watched branches** by the seat `mesh-pipeline-runner`, ordered by the catalog graph's edges +between artifacts, with no hand act (ADR 0666 §1). Milestone G is the one milestone that builds it, beside the two +graphs, the revision view and the delivery record (ADR 0667 §1). Until G's delivery the sections this one replaces +(*Checks*, *A try*, *The Approve and the merge*, the state table and the trunk-only want) hold as written, and they +check and deliver milestone G itself (ADR 0667 §2); each of them says so in a line of its own. + +``` + a session ──merge-pull (seat git)──► forge ──commit on a watched branch──► forge bridge ──► indexer (mesh-catalog) + │ registrations; a catalog graph + │ per watched branch; the revision + │ validated before take-in + ▼ take-in.taken + pipeline runner (mesh-pipeline-runner) ── asks each pipeline step on the serving seat's work queue, hears step-ended: + │ lint, unit tests, integration tests ──► the build seats (node-build-go, node-build-node, node-build-image) + │ composition ──────────────────────────► the assigner (mesh-wants) + │ code review ──────────────────────────► the runner's own verb `review`, from the reviewer's bus account + │ approval ─────────────────────────────► operator-channel: ask, then decided + ▼ pipeline-ended (every step's result), keyed by source revision + assigner ──► wants from a revision whose required steps passed, on the watched branch a placement chose + gate ──► the delivery record keeps the step and pipeline events +``` + +### A module's registration + +- **What it holds.** The seat `mesh-catalog` keeps each module's **registration**: its git origin, the path of its + manifest, its watched branches and its policy, on the bus, every version with who changed it and the warrant of the + operator's Approve (ADR 0666 §2). The indexer is a foundation part, so the registrations are kept in its old sections + (ADR 0619 §1 to §3, ADR 0666 §4): one key per module in its old `state` section `registrations`, and every version on + its old `streams` section's stream `registration-history`, kept with no age limit. + The catalog graph is derived from the registrations and the manifests they point to; the mesh knows modules, and a + repository only as a module's git origin. +- **Changing one is a trusted act.** The seat's verbs `register` (a module whole), `policy` (one module's step + statuses, per artifact), `watch` and `unwatch` (add or remove a watched branch) each raise an authorising ask of tier + approve through the seat `operator-channel` (design 46 §10), naming every value the change moves, one line each + ("`mesh-grants:program` unit tests: `required` → `bypass`"), and write the version only on its warrant; a Decline or + an expiry writes nothing (ADR 0666 §2). Until a record binds each forge account to its bus identity, `register` and + `policy` refuse code review as a `required` step, naming why, so no review gates while its author cannot be told + (ADR 0666 §22; issue 1966, note 157). A manifest moved to another path is the one manifest change that changes the + registration; any other manifest change is a commit, judged at its revision. +- **Said and read.** Each written change is said as the seat's event `registration-changed` (the module, the version, + what moved); the verb `registrations` answers every registration, or one with its history. The indexer derives the + modules it keeps from them, and the forge bridge its watched branches, each by a first view of `registrations` and + then that event, never by reading the ledger (ADR 0666 §3, ADR 0596). +- **An unprotected branch is refused.** `register` and `watch` read a branch's protection through the seat `git`'s read + verb `branch` (its head, and whether a rule refuses a direct push and admits only merges), and refuse a watched branch + the forge does not protect, naming it (ADR 0666 §3). +- **No part fixes a name.** Every branch, repository and module name a part needs is read from the registrations and the + catalog graph; the lint step refuses such a name in a string, a constant or a table of code logic, a Go import path + not being code logic (ADR 0666 §5). About 39 such names in 9 parts were found on 2026-11-09 (research 086, Findings); + milestone G removes them. +- **The first registrations are one ask.** At its first start on G's build the indexer, holding no registration, + proposes one registration for every module its trunk revision holds, from what it took in (the origin and path of + each), its watched branch the repository's default branch read through the seat `git`, and the statuses the check + judged until then: lint, unit tests, integration tests and composition `required`, code review `optional`, approval + `bypass`; it raises them as one ask naming every registration, as the seat `mesh-module-assigner`'s `adopt` proposes + placement whole (ADR 0567). Until that Approve the runner starts no delivering pipeline and says why, so the + operator is told of this one ask before G's delivery starts. A Decline or an expiry leaves the seed unwritten and + says so; the indexer's tool `indexer_seed_again` raises the ask again, recorded in the hand-act log. +- **Kept for the life of the mesh**, never derived again (research 086, choice 25): the history stream's cap is 64 MiB. + About 120 registrations of about 1 KiB, and an estimated change a week each (a guess, not a measure), grow about 6 MiB + a year, so the cap holds about ten years; past 80 % the indexer says `filling`, as every store of *Two graphs, one + source of truth* does. +- **How it is checked.** Whole (indexer): an unprotected watched branch is refused, naming it; a policy change without + the warrant writes nothing, and a declined one writes nothing; a change from `required` to `bypass` asks, showing + that line; `registration-changed` is said and `registrations` answers the history; the first start proposes the seed + as one ask, and `indexer_seed_again` asks it again after a Decline and after an expiry; a policy making code review + `required` is refused. Unit (the Go build module's lint step): a module name in a string, a constant and a table is refused, an + import path is not. Tests 75, 68 and 83. + +### Watched branches and the catalog graph per branch + +- **Only a watched branch starts a pipeline.** The forge bridge hears every commit of every watched branch the + registrations name, through the seat `git`'s event `branch-moved` (a branch's new head, from the forge's push + webhook, which a merge and an admitted push alike say), and takes the commit from the forge's own record by the seat's + verb `branch`, never from the event's body (ADR 0666 §6). One event for every way a branch moves, because a merge is + not the only one. `branch-moved` is kept on the seat's stream `SEAT_git_branch-moved`, which the bridge hears through + a durable consumer, so a move said while the bridge is down is heard when it starts; at its start it also reads each + watched branch's head the same way. +- **A head with no pipeline is a finding.** A watched branch's head that starts no pipeline within five minutes is the + watchman's finding `pipeline-stands`, naming the branch and its head, raised by the condition keeper (ADR 0564 §2), + unless it waits as progress not owed: a member of a gathered group is governed by ADR 0633 §5's 30-minute bound, and + a merge behind a pending revision of the same branch by its 60-minute bound (ADR 0666 §24). The finding clears on the + runner's `pipeline-started` for that head. +- **The catalog graph per watched branch.** The indexer keeps the catalog graph once per watched branch, from that + branch's manifests at each source revision (ADR 0666 §6): each revision names its branch, and the stores, caps and + pins of *Two graphs, one source of truth* hold per branch. +- **A placement names the branch.** Each module of a placement key names the watched branch its node runs, by default the + registration's first, set by a placement proposal like every other placement change (ADR 0567, ADR 0666 §6). The + assigner computes each node's entries from the catalog graph of the branch its placement names, so a module watched on + `main` and `beta` runs `beta` only where a placement chose it. +- **A source revision per watched branch.** The gate keeps one source revision per watched branch, `source.`, + in place of `source.main` (ADR 0429 §11 to §13 as ADR 0666 §6 changes them), in the old `state` section `source` + already holds, its key's layout being the only change. The gate is no foundation part: the bus module's delivery + waits on no act of the gate's, since the indexer takes a revision in from the forge bridge's stream and the assigner + writes wants from the runner's events, so the gate's other kept data stay in ADR 0595's templates (ADR 0666 §4), and serves it by the seat + `mesh-delivery`'s verb `source` with the branch, saying `source-moved` on each new revision; the indexer and the + node-engine's catch-up read it there, never the gate's state (ADR 0596). Each want names a build-input fingerprint + computed at one such revision. +- **Validated before any take-in, on every branch.** Before it takes a revision in, on every watched branch, the running + indexer asks the manifest validator built from the revision's heads to judge it in the build seat's sandbox (the + ask `run`, *What ADR 0656 leaves to this design*). A revision it refuses stays pending under ADR 0633 §5's + 60-minute bound, its hand acts and its condition `take-in-waits`; the way back is a revert, an ordinary merge + (ADR 0666 §6, §26). A revision on the branch the indexer's own placement chose is taken in only by the indexer it + names (ADR 0633 §1). This validation is no pipeline step and waits on no pipeline, so every delivering pipeline runs + on a revision already taken in. +- **A branch whose protection was removed starts nothing.** On every `branch-moved` the forge bridge reads the + branch's protection again; a move of a watched branch whose protection was removed starts no delivering pipeline, and + the forge bridge writes the finding `branch-unprotected`, naming the branch, which the condition keeper raises and + clears once the protection is back (ADR 0666 §6). +- **A pending revision holds its own branch only.** A merge waits behind a pending revision only on the same watched + branch; other branches move on (ADR 0666 §6, which changes ADR 0633 §3). +- **How it is checked.** Whole (forge bridge): a commit of a branch no registration names starts nothing; a commit on a + watched branch is taken from the seat's `branch` read, not the event; a head missed while the bridge was stopped is + read at its start. Whole (indexer, assigner): a commit on `beta` gives a revision of the `beta` graph only and moves + only the want of the node whose placement chose `beta`; a revision whose own validator refuses it stays pending and + holds `beta` while `main` moves on. Whole (watchman): a head with no pipeline for five minutes raises + `pipeline-stands`, cleared by `pipeline-started` for that head, and a gathered member does not; a move said while the + bridge was stopped is heard from the seat's stream. Tests 64, 68, 76, 78 and 82. + +### Pipeline steps and the policy + +- **The runner.** The seat `mesh-pipeline-runner`, held once for the mesh by the module `mesh-delivery-pipeline`, + runs each pipeline (ADR 0666 §7). It is a foundation part, since the bus module's own delivery waits on its pipeline + (ADR 0666 §4): its kept data are in old sections (ADR 0619 §2), it waits on no bus module process to start, and it + joins the manifest validator's list of foundation parts, which refuses its manifest asking a template. It reads the policy from the registrations, asks each step that is not `bypass` of + the seat that serves it, and says each step's start and end and the pipeline's end (*Health and going back*, below). +- **The steps and who serves them.** Lint, unit tests and integration tests are the build seats' (`node-build-go`, + `node-build-node`, `node-build-image`): each gains the verb `steps`, which answers which pipeline steps an artifact + can run by its language's convention (as *The check from release 4* says the tests are found), and the accepted kind + `step` on its stream `check`, which runs one. Composition is the assigner's, an accepted kind `step` of the seat + `mesh-wants`. Code review comes in through the runner's own verb `review`. Approval is asked through the seat + `operator-channel`'s ask and heard on its event `decided` (ADR 0666 §7, §10). A step with nothing to do ends at once as + `nothing to run`, never as passed. +- **The policy.** Each step's status, per module and per artifact, is `required` (runs; holds the delivery until it + passes), `optional` (runs; a failure is shown and may be accepted) or `bypass` (nothing runs; said as bypassed), + kept in the registration and never in a manifest: the manifest validator refuses a manifest that names a status + (ADR 0666 §7; research 086, R3). A `required` step that ends `nothing to run` holds the delivery and names the step. +- **Asked on a work queue, ended by an event.** The runner asks each step on the serving seat's work queue and hears + its end as that seat's event `step-ended` (the record's `step ended`), on + `mesh.seat..event.step-ended.`, the node that ran it in the subject and each holder's account granted only + its own node's subject, through a durable consumer of its own, so a step outlives a restart of either side (ADR 0666 + §7, ADR 0363 §2). A build seat's holder restarted mid-step gets the step again from its work queue and finishes it + (ADR 0664 §1). A unit or integration test step says its test counts in `step-ended`, and `pipeline-ended` names any + repository over 50 integration or 500 unit tests, and any catalog module over them (ADR 0666 §8; the test budget). A step's outcome is one of `passed`, `failed`, `nothing to run`, + `bypassed`, `carried` (with the pipeline it was carried from), `could not run` (naming the part not heard), + `waiting on `, `accepted` (a failed `optional` step a person accepted, with who and why), `superseded` and + `cancelled`. +- **Carried, not run.** A step whose build-input fingerprint and policy did not change is carried by its package + digests, as ADR 0548 §5 holds, the runner making the carry instead of the checker: a test step runs only the packages + with no kept result for their digest, and a run on request's results are reused when the merged commit's inputs match + (ADR 0666 §8; research 086, choice 24). An `approval` step is never carried. +- **Approval comes last.** The runner asks the `approval` step only once every other `required` step of the pipeline + passed, so the operator approves a commit the mesh already judged, the one place ADR 0661 §3 had the check gate the + ask. A failure after an approval is said, as a failed `optional` step is, and the approval stays. +- **Kept on the bus, in old sections.** The runner keeps each pipeline's state in its old `state` section `pipelines`, + one key per pipeline keyed by its watched branch, source revision and module, written by compare-and-set so a holder + replaced mid-pipeline and its successor never both write one; its step log on its old `streams` section's stream + `step-log`; each step's output in its old `objects` section `step-outputs`, named in the log; and each package's + passing result per level in its old `state` section `kept`, under the digest of what its tests read (ADR 0666 §4, §8; + *The runner's kept data*, below). At its first start it takes the checker's kept verdicts into `kept`, read by the + checker's tool `checker_kept`, so the first pipelines after G carry what the checker had judged. +- **How it is checked.** Whole (runner): a step with unchanged fingerprint and policy is carried and says from where, + and an `approval` step is not; a module with no integration tests shows `nothing to run`, and a `required` unit-test + step on a module with no tests holds its delivery; a bypassed step is said; a runner restarted mid-step hears the + step's end and finishes the pipeline; two runners writing one pipeline key, one loses by compare-and-set; a test step's + counts are in `step-ended` and a repository over budget is named in `pipeline-ended`. Whole (Go build module): `steps` + answers the steps of a fixture artifact, a `step` ask ends with `step-ended` on its own node's subject, one on another + node's subject is refused by the bus, and a build module restarted mid-step finishes it. Unit (manifest validator): a manifest naming a status is refused. Tests 65, 66, 73 + and 88. + +### What holds a delivery + +- **The assigner writes a want only from a passed pipeline.** The runner says each pipeline's end as `pipeline-ended` + (the record's `pipeline ended`), keyed by source revision, with every step's result. The assigner consumes it, and + writes a want only from a source revision whose every `required` step passed for the modules it moves, on the watched + branch a placement chose, by compare-and-set on a newer revision, so an older revision ending after a newer one + writes nothing (ADR 0666 §9). This is one more rule beside the assigner's others (ADR 0429 §6), checked per module. + From G's delivery it replaces the trunk-only want (ADR 0656 §2 as ADR 0666 §9 changes it). For a group's source + revision the runner says one `group-ended` once every member's modules have ended, and the assigner writes the + group's wants only on it: a member's own `pipeline-ended` writes nothing (ADR 0666 §9). +- **A failed `optional` step holds nothing.** It is shown in `pipeline-ended`, in the delivery record and in the runner's + `show`; a person may accept it by the runner's verb `accept`, recorded in the hand-act log with who and why. +- **A newer commit supersedes an older pipeline of a module whose fingerprint it changed.** On a newer commit of the + same watched branch the runner ends a module's older running pipeline as `superseded` only when the newer commit + changed that module's build-input fingerprint (ADR 0666 §9); a module the commit leaves as it was finishes its + pipeline. A newer publish of a package likewise supersedes the rebuild pipelines an older publish of it started. A + superseded pipeline's waiting asks are dropped by each build seat's `drop` (ADR 0664 §4), naming + the newer commit as the cause, so a cancelled pipeline leaves no ask on a stream (a gap G's prepare found: a cancelled + build withdrew only the builder's wait). +- **A step nothing starts ends its pipeline.** A step whose prerequisite nothing starts (a seat with no holder, a + prerequisite step `bypass`) ends the pipeline refused within five minutes, naming the step and what it waits for, + never as a silent wait (research 086, R5); a step whose seat has no holder ends its pipeline failed, naming the seat + (ADR 0666 §17). +- **A failed head is said to its author, then to the operator.** A `required` step that failed, or ended `could not + run`, on a watched branch's head is the runner's finding `pipeline-failed`, naming the module, the branch, the commit + and the step; the condition keeper raises it as the commit's author's for two hours and then the operator's, as ADR + 0505 §5 and §6 have a delivery whose cure is its author's new head, and clears it when a newer revision of that branch + passes that step (ADR 0666 §24). The author is the forge's record of the commit, read through the seat `git`. +- **The delivery record keeps every step.** The gate's delivery record consumes the step and pipeline events and keeps + them as long as the record (ADR 0666 §9; *The delivery record*). +- **How it is checked.** Whole (assigner): a failed `required` step writes no want; a failed `optional` step holds + nothing; an older revision's `pipeline-ended` after a newer one's writes nothing; a group with one member passed and + another still running writes no want until `group-ended`. Whole (runner): a newer commit that changed a module's + fingerprint supersedes its older pipeline and drops its asks, and one that left it unchanged lets it finish; a step + with no holder ends the pipeline naming the seat within five minutes; a failed `required` step on a head raises + `pipeline-failed`, the author's for two hours and then the operator's, cleared by a newer passing revision. Tests 66, + 67, 87, 89 and 98. + +### Approval is a step, and a session merges a pull request + +- **No Approve per merge.** The operator's approval is the pipeline step `approval`, its status in each module's policy; + no Approve is asked per merge, and the delivery gate's merge turns and its Approve per merge go (ADR 0666 §10, which + changes ADR 0661 §3 to §5). The operator is asked only where a module's policy says `approval`, and for registrations + and policy changes. +- **The approval is an ask of the runner's.** The runner raises an authorising ask of tier approve on the seat + `operator-channel` under its own name, its `about` the module and the watched branch only, so a newer commit's ask + replaces the older one's (design 46 §10). The warrant ends the step passed; an ask that is declined, expires or is + refused ends it `declined`, and one that is replaced ends it `superseded`. Only a declined `approval` step is asked + again, by the runner's verb `ask-again` (ADR 0666 §10). While it waits the runner + says `wait-held` waiting on the operator, never a stall (ADR 0283). +- **A session merges a pull request.** Any session the tool runner proves, and the operator, merges by calling the seat + `git`'s verb `merge-pull` over the mesh, which merges with the forge tools' account (ADR 0398 §2) at the head the + caller names. It judges that this is still the pull request's head and that the branch's protection refuses a direct + push, the protection read again on every `branch-moved` of the branch, and it judges the head's runs by its modules' + policies: it refuses a head when any run at its build-input fingerprint failed a step a policy marks `required`, and + merges a head whose `required` steps passed or that has no run yet, a failed `optional` or a `bypass` step refusing + nothing; it never waits for a run and never asks an Approve (ADR 0666 §11). The forge keeps only its branch protection. +- **Judged from its own state, never by a call.** The holder of the seat `git` consumes the runner's `step-ended` + through a durable consumer of its own and keeps, in its own state `failed-steps`, each failed `required` step by + module and build-input fingerprint, with the commits it was seen at and the run that failed it, for 30 days; so a head + merges while the runner is down, judged on what it already heard (ADR 0666 §11, ADR 0596). A head's fingerprints are + those its runs named for its commit; a step that failed at that fingerprint in any run, a group's or another commit's + of the same content included, refuses it, unless a later run of that same step at that fingerprint, asked again by + the operator or the healers (the runner's `rerun`), passed: that pass clears the failure from `failed-steps` (ADR 0666 + §11). The runner's `step-ended` says that the step was a rerun and the caller the runtime proved, and the forge module + clears a failure only for a rerun whose caller is the operator or a healer; a plain pass, or a rerun asked by anyone + else, clears nothing. A run still running is judged by the steps it has ended, since the merge never waits. A refusal names the run, the module and the step, so the session knows what to fix. The gate merges nothing, and its forge merge token is + removed by G's delivery (ADR 0667 §6); the forge bridge hears the landed commit as it hears every commit of a watched + branch. +- **The operator-channel hides no ask.** It keeps design 46's three open asks per asker, never holds the newest back, + and replaces an open ask by the same asker's ask with the same `about` (ADR 0666 §12; design 46 §6). +- **How it is checked.** Whole (forge module, forge bridge): a session's `merge-pull` at its head merges with no run yet, + and with a passed one, and asks no Approve; with the runner stopped a head merges; a head at whose fingerprint any + run failed a `required` step, a head that moved and a branch whose protection was removed since its last move are + refused, each naming why; a failed `optional` step refuses nothing. Whole (runner): an `approval` step is asked last, + a Decline and an expiry each end it `declined` and `ask-again` asks it once more, and a newer commit's ask replaces the + older and ends its step `superseded`. + Live: a declined approval and a fourth ask each reach the operator. Tests 71 and 91. + +### Groups + +- **Formed from the branch name.** The gate forms a group from a shared branch name carrying its issue number, as it + does today without the fixed list of trunk names (ADR 0666 §13). +- **A member reaches its group by landing.** A member has reached its group when its commit lands on its modules' + watched branch. The forge bridge sets the group on each landed member's commit, reading the members from the seat + `mesh-delivery`'s verb `groups`, and publishes `forge.group.merged` when that verb says every member has (ADR 0666 §13, + which changes ADR 0633 §4). +- **One source revision, one pipeline per branch.** The indexer keeps landed members pending until the group's end and + takes them in together as one source revision of that watched branch, saying `take-in.taken`; the runner starts the + group's one pipeline per watched branch on that event, and a member of a gathered group starts no pipeline of its own. + When one member's `required` step fails, none of the group's modules is delivered (research 086, R5). +- **A group that never completes is said.** By ADR 0633 §5's 30-minute bound and its condition; `bridge_group_end_again` + says a group's end again from the gate's group verb, never the gate's `merges` state (ADR 0666 §13, which changes ADR + 0633 §5). +- **How it is checked.** Whole (indexer, gate, forge bridge): a group of three repositories, its own packages included, + is one source revision and one pipeline; one member's failed `required` step delivers none; a group with a member that + never lands raises `take-in-waits` at 30 minutes. Tests 67 and 81. + +### Dependencies between artifacts + +- **Six kinds of edge between artifact references.** The catalog graph's edges run between **artifact references**, + `:`, such as `mesh-grants:program`, of six kinds (ADR 0666 §14): + + | Kind | B before A | Derived from | + |---|---|---| + | 1 | B published before A builds | a package A's build source imports (ADR 0573 §3) | + | 2 | B published before A delivers | an artifact A's manifest fetches by reference at its start | + | 3 | B delivered before A builds | a build module A is built by, and the toolchain its agreed version names (ADR 0584 §1) | + | 4 | B delivered before A delivers | a provision A requires and B provides, bus state among them (ADR 0614 §5), and a format's reader (below) | + | 5 | B has acted for A's new version | a seat's acting rule (*What ADR 0656 leaves to this design*): a grant, a credential, a verdict, bus state | + | 6 | B runs a version that serves A | a verb or a manifest word A uses and B serves or reads (ADR 0614 §2, §4), the build seats' `kept-artifact` among them | + + Each kind is derived from what manifests and seat definitions already say, and declared per artifact in the manifest's + artifact entry, its field `needs`, only where nothing else says it. Today's edges run between modules, and only a + package edge names an artifact; at module level the tool runner and the grants part looked like a cycle, per artifact + they are a chain (`mesh-grants:program`, then `node-tools:runtime`, then `mesh-grants:tools`). +- **Removal runs the other way.** When something goes away the order is reversed: a seat moved to a new holder has its + old holder released before the new one claims (ADR 0666 §14). +- **The edges alone order.** The build and the delivery order by these edges alone; a cycle of delivery edges (kinds 2, + 4, 5, 6) is delivered as one step, and a cycle of build edges (kinds 1 and 3) is refused, naming every artifact on it + (ADR 0666 §14; research 086, R17). The cycle rule is the indexer's, in the catalog graph it keeps, so the checking + program's cycle rule goes with the checker. +- **A format's reader first.** A format a running reader cannot read is preceded by its reader, an edge of kind 4 on + every watched branch (ADR 0666 §14): the indexer's manifest validator for a new field of a seat definition or a + manifest, and on each node the node-engine that reads a manifest's new fields before any manifest that writes them + (ADR 0667 §4). +- **How it is checked.** Unit (indexer's graph): a chain per artifact where modules would cycle; two programs needing + each other's new verb are one step; two artifacts each needing the other's new package to build are refused, naming + both; a seat moved to a new holder releases the old first. Live: the tool runner and the grants part delivered in + the order `mesh-grants:program`, `node-tools:runtime`, `mesh-grants:tools`. Test 79. + +### A publish rebuilds + +- **Numbered at publication.** The builder numbers a package's version when it is published, never only when a build + is claimed, and says the publication as the event `package-published` of its seat `mesh-builds` (ADR 0666 §15; design + 51, *The versions*). The seat is new, held once for the mesh, defined in `mesh-delivery-contracts`; the builder held + none until now, and its waits stay on its own stream in this milestone. +- **Every dependent is rebuilt against it.** On `package-published` every artifact with a kind-1 edge to the package is + rebuilt against the new version, and the runner, which consumes the event, starts its pipeline; nothing else is + rebuilt, and a change to tests alone publishes nothing (ADR 0666 §15; research 086, R18). +- **Unread packages refuse.** A build that cannot read the published packages refuses and names the unread state + (ADR 0666 §15). +- **How it is checked.** Whole (builder, indexer): a mesh-sdk merge changing one package publishes one version, and only + the artifacts importing that package rebuild; a merge changing only tests rebuilds nothing; a build whose packages + cannot be read refuses naming the state. Tests 70 and 80. + +### Any size + +- **A value over the limit is an object.** mesh-sdk's own small object store package (ADR 0595 §9) puts a value over + the bus's per-value limit in the object store beside its state and keeps the object's name in the key; a verb's reply or an event over the + per-message limit carries the object's name (ADR 0666 §16). A value moved there is deleted with its key, and a + replaced value leaves one object. +- **One object store per state, granted to its owner.** Each state asked by the template `state` gets its object store + beside it, `-objects`, a template form of ADR 0595 that the bus module provides and the grants part grants to + the state's owner alone (ADR 0666 §16); a foundation part's large values go in an old `objects` section of its own. + Its size is the template's (ADR 0595 §3). An object store holds no space until a value is written to it, so the many + it adds reserve nothing; the few values over the limit (a delivery record, a catalog graph revision list, a test's + output) are estimated, as a guess, at under 1 GiB across the mesh. +- **An object sent is readable by the modules it is for.** A reply's or an event's object is written to the sender's + object store of sent objects, and the grants part derives from the manifests a standing grant to read them: the + callers its seat definition names for the verbs it serves, and the consumers whose `consumes` declare its events; + no other module may read them (ADR 0666 §16). The grant follows the manifests, so it is written when they change, + never per object. A consumer's reader of + the form is delivered before its producer writes it, an edge of kind 4. +- **Its tools come with the package.** The package serves each module that imports it `_state_objects` (the + objects of each state, with their size, the key that names each and the fill against its cap) and + `_state_objects_drop` (drop the objects whose key is gone, on a person's word as ADR 0595 §4 removes kept + data, recorded in the hand-act log). +- **Its cost.** Only the modules that import the package are built with it, so no other module is rebuilt for it: a + package published before its users build (ADR 0573 §2, ADR 0667 §3). +- **How it is checked.** Whole (mesh-sdk, against the real bus): values of one, ten and a hundred times the per-value + limit stored, sent as a reply and as an event, and read back whole by a caller and a consumer the manifests declare, + and refused to a module that declares neither; a replaced large value leaves one object; a key deleted takes its object. + Tests 69 and 90. + +### The pipeline makes the check, and the checker goes + +- **Every step runs on parts built from the change.** Every pipeline step that runs a change's code runs on parts built + from the change's own heads, in the build seat's sandbox, with no network and no bus account (ADR 0666 §17, ADR 0448 + §2, §4): the composition step composes each machine's declaration with the composer built from the heads and refuses + a change in which two modules own one path; the build seats' steps run lint and tests. A step whose serving part the + change alters runs from the change's build of it, built within 20 minutes or ending `waiting for a build node` or + `did not build`, the first tier of *The check on the change's own acting parts* made the runner's. +- **The run on request.** The runner's verb `run` takes one or more members, each a module at a named commit, runs them + through their pipelines and delivers nothing, replacing the checker's try (ADR 0666 §18). Its callers are the + sessions, as the agents' bus identities the tool runner proves, and the operator, and nothing else, since a run of a + group builds and publishes its packages' tagged versions (design 51). The runner says `run-started`, the indexer builds + the run's candidate from it, and the candidate's composition step writes no want (ADR 0656 §9); the candidate is + dropped on that run's `pipeline-ended`. A step that could not run ends `could not run`, never as passed. A + composition step for a node that sleeps passes it with a warning (ADR 0593 §9). +- **The runner is an acting part in the checker's place.** The acting rule's step `check` becomes the runner's step + `pipeline` (*What ADR 0656 leaves to this design*): its own change runs on its own new version, a failing new runner + holds while the old one runs pipelines (ADR 0656 §4), and the pipelines in flight when its holder is replaced are + taken up again from its kept state (ADR 0666 §19). +- **What the checker did, and where it goes.** + + | The checker's | From G's delivery | + |---|---| + | the merge check, one status `mesh/check` | the pipeline, its result in `pipeline-ended`, the runner's `show` and the delivery record; no status on the forge | + | the try | the run on request | + | the composition check | the composition step, the assigner's | + | the kept verdicts and the carry | the runner's `kept`, taken from the checker's at the runner's first start, and its carry (ADR 0548 §5) | + | the checking program: the manifest validator at the heads, the cycle rule, the composer, the rule names | the indexer's validation before take-in; the indexer's cycle rule; the composition step; `widens` in the pipeline's end | + | the `run` ask, published by the checker's account | published by the runner's account and the indexer's (its validation), each with step keys under its own name | + | its buckets and bus account | removed after the first pipeline after G's delivery has delivered a change end to end, after a backup kept 90 days whose restore is tested, the operator told before (ADR 0667 §6) | + +- **How it is checked.** Whole (runner, assigner): a run on request of `feature/1966-x` delivers nothing, and a call of + `run` from another account is refused; a composition step refuses two modules owning one path; a step whose part + cannot be heard ends `could not run`; a node asleep passes with a warning; a runner stopped mid-step takes its + pipelines up again. Live: once the checker is removed no module claims the seat `mesh-delivery-checker`. Tests 64, + 84 and 88. + +### Who may say what + +- **Callers per verb, in the seat's definition.** Each seat definition names, per verb, the callers allowed to call it, + in its field `callers` (holder roles, modules, the operator, the healers), which the grants part reads as its one + source of caller limits; the runner's verbs are the first (ADR 0666 §20). A verb whose definition names no `callers` + admits only the seat's holder roles and the operator, so a field left out opens nothing. It replaces the holder's + trusted config value `callers` of the seat `git` and the package seats (design 51), which no holder set for most + verbs. A format its running reader cannot read, so its reader is delivered first (ADR 0667 §4). +- **A step's result from its holder only.** The runner takes a step's result only from the bus account of that step's + seat holder, naming the commit and the build-input fingerprint; a result from another account, or naming another + commit or fingerprint, is refused and said (ADR 0666 §21). +- **A review gates, once it can.** A code review's result is taken through the verb `review` from the reviewer's bus + account and refused from the commit's author, so a review gates where a policy says `required` (ADR 0666 §22, which + changes ADR 0659 §2). Until a record binds each forge account to its bus identity no policy may say it (*A module's + registration*; issue 1966, note 157). +- **A widening is said, never refused.** A change that alters any part serving a step (the runner, step detection, the + lint rule, a build seat's test runner, the composer), or widens an acting rule, a grant or a credential, says so in + its `pipeline-ended`, its field `widens` naming each. The running runner computes it, from the sources of the change + against those of the watched branch, never the runner built from the change, so a change cannot hide its own + widening; nothing refuses it for that (ADR 0666 §23, the operator, 2026-11-10). The teller passes `widens` on to every + channel, as it does `recovery-merged`. This is what replaces ADR 0656 §8's naming in the Approve ask. +- **How it is checked.** Whole (runner, grants part): a forged step result and an author's own review are refused; a + caller not in a verb's `callers`, and any caller but the holder roles and the operator of a verb with no `callers`, + are refused by the bus; a change widening a grant, and one altering the Go build module's test runner, each name it in + `widens`, computed by the running runner, and are delivered. Tests 85 and 86. + +### Health and going back + +- **The runner's events.** Each on `mesh.seat.mesh-pipeline-runner.event....`, + a branch or group name escaped as a key's name is, declared in the seat's definition and published by the runner's + account alone (ADR 0666 §24, ADR 0363 §2): + + | Event | Says | + |---|---| + | `pipeline-started`, `pipeline-ended` | a pipeline's start, and its end with every step's result, its test counts, the source revision and `widens` | + | `group-ended` | a group's one pipeline's end, on which alone its wants are written | + | `run-started` | a run on request's start, with its members at their commits | + | `step-started`, `step-ended` | each step's start and end: the step, its status in the policy, its outcome, its build-input fingerprint, its test counts, for a carried result what it was carried from, and for a rerun that it is one and the caller the runtime proved; a bypassed step too | + | `wait-held`, `wait-ended` | a step's wait: on a person (approval, code review), on a build node, on the revision view | + +- **What a session hears after its merge.** Between its `merge-pull` and the delivery, a session waits with `mesh_wait` + on the runner's `pipeline-started` and `pipeline-ended` of its module, branch and commit, and then on the status + view's `delivered` of the source revision; a failed head reaches it as `pipeline-failed` (*What holds a delivery*). +- **Nothing stands still unseen.** The watchman times each step's owed progress from `wait-held` and `step-started`, + never by run length; a step or a watched branch's head standing still five minutes is its finding `pipeline-stands`, + raised by the condition keeper and cleared on the step's end, or for a head on its `pipeline-started` (ADR 0564 §2, + §4). A step waiting on a person is said as waiting on that person (ADR 0283), never as a stall; a group waiting for + its members, and a merge behind a pending revision, are governed by their own bounds (ADR 0666 §24). At its start the + watchman seeds its open waits from the runner's `stands`, as it seeds `take-in-waits` from `indexer_pending`. +- **The runner's own health.** Its manifest declares its health check, run outside its process (ADR 0240): the runner + answers `show`, and its durable consumers of `step-ended`, `take-in.taken`, `package-published` and `decided` are + each less than five minutes behind; a failed check names which. +- **The runner waits for its view.** With no revision view it says so in `_first_views` and raises `view-waits` + after five minutes, as every part does (ADR 0656 §6). +- **Going back is one act.** A failing new version holds while the old keeps running (ADR 0656 §4); a return to an + earlier build is one value in the placement, the module's `build` in its placement key, set by a placement proposal + (ADR 0666 §24). +- **How it is checked.** Whole (runner, watchman): a step whose worker dies raises `pipeline-stands` within five minutes; + a head with no pipeline raises it and its `pipeline-started` clears it; a step waiting on the operator raises nothing; + a runner restarted mid-step takes its pipelines up again; its health check fails naming a consumer behind. Whole + (assigner): a placement's `build` delivers the earlier build. Tests 76, 77 and 88. + +### A recovery fix is an ordinary merge + +- **No recovery merge verb.** A fix that recovers the mesh is merged like any change on a watched branch, by a + session's `merge-pull`, and runs its pipeline; no trusted recovery merge verb is built (ADR 0666 §26). The shape this + design sketched for one (a verb `merge` of the seat `mesh-delivery` with `recovery-callers`) is dropped. +- **Named a recovery, said everywhere.** Its author names it a recovery by the seat `mesh-delivery`'s verb `recovery` + (the commit and why), never by a pull request's text: the gate marks the delivery record `recovery` with the caller + the runtime proves, and says `recovery-merged`, which the teller passes on to every channel (ADR 0666 §26). A widening + it carries is said in its `pipeline-ended` like any other (*Who may say what*). +- **How it is checked.** Whole (gate): a merge named a recovery is marked in its record and `recovery-merged` is said; + a recovery named by a description is not. Test 92. + +### The tools + +Every new state has a tool that reads it and every new act a tool that starts it by hand (ADR 0666 §25), against the +four lines a module's tools answer; every read tool of a store also answers its fill against its cap: + +| Part (seat) | Read everything it holds | Do by hand what it does itself | Recover without help | +|---|---|---|---| +| the runner (`mesh-pipeline-runner`) | `show` (one pipeline whole, its steps, step log and outputs), `list` (the pipelines of a module, a branch or a commit), `stands` (what stands still, since when), `why-carried` (where a step's result was carried from), `kept` (the kept results by digest) | `start` (a delivering pipeline for a watched branch's head), `run` (the run on request), `rerun` (one step again) | `accept` (a failed `optional` step, with why), `cancel` (a pipeline, dropping its asks), `ask-again` (a declined `approval`) | +| the indexer (`mesh-catalog`) | `registrations` (with each one's history); `indexer_edges` (an artifact's edges per watched branch), `indexer_order` (the order of a change, its cycles named), `indexer_catalog_difference` (two revisions); `indexer_pending` (a group with its missing members) | `register`, `policy`, `watch`, `unwatch` (each on the operator's Approve) | `indexer_seed_again` (the first registrations' ask raised again), `indexer_take_in_pending` (a group taken in as gathered), `indexer_drop_pending` (dropped) | +| the gate (`mesh-delivery`) | `source` with a branch (`gate_source`: every branch's source revision) | — | `gate_source_again` (say `source-moved` again for a branch) | +| the forge module (`git`) | `git_failed_steps` (the failed `required` steps it holds, by module and fingerprint, with the run that failed each) | — | `git_failed_steps_drop` (drop one, with why) | +| the grants part (`mesh-grants`) | `grants_callers` (the callers each verb admits, read from the seat definitions) | — | `grants_why_refused` (for an account and a verb, the grant it lacks and the definition's line that leaves it out) | +| the build seats | `steps` (the steps detected for an artifact) | `steps` with `again` (detect again) | `drop` (ADR 0664 §4) | +| the builder (`mesh-builds`) | `builder_versions` (a package's published versions) | `builder_publish_again` | — | +| the assigner (`mesh-wants`) | `assigner_why_not` (why a module is not on a machine yet: the pipeline it waits for, its hold, the placement, the node's last `running`) | — | `assigner_release` | +| the watchman | `watchman_views` (how far behind each part's view is, from each part's `view-waits` and first-view tools) | — | each part's `_first_view_again` | +| the operator-channel | `asks` (with each asker's asks held back) | — | `ask-again` (offer a held-back ask now) | +| every module (mesh-sdk's runtime) | `_state_objects` | — | `_state_objects_drop` | + +Every recover tool writes its act, who and why in the hand-act log of the seat `mesh-hand-acts`. How it is checked: +each tool answers its whole-module test's case, every store's read answers its fill, and `mesh_describe` reads each +(test 93). + +### The runner's kept data, and the build capacity + +Each kept form names its section or template, its retention and its cap; a state template fixes its own size (ADR 0595 +§3), up to 64 MiB. The numbers are estimates, to be read from the fill tools once G runs: an estimated 20 merges a day +(as *The delivery record*), each starting a pipeline for about 3 modules of its repository whose fingerprint it changes, +and an estimated 2 mesh-sdk publishes a day, each rebuilding about 120 artifacts and starting about 120 pipelines: about +300 pipelines a day, of about 6 steps each. + +| Part | Kept data | Section or template | Retention | Cap and growth | +|---|---|---|---|---| +| the runner | `pipelines`: one key per pipeline, keyed by watched branch, source revision and module, its steps, statuses, outcomes, fingerprints and test counts | old `state` section | 30 days, or while it is its branch's newest for its module; the delivery record keeps its own copy of the events for 90 | 128 MiB; about 300 pipelines a day of about 4 KiB is about 36 MiB at 30 days | +| the runner | `step-log`: one entry per step's start and end, its output by name | old `streams` section | 30 days | 64 MiB; about 3,600 entries a day of about 0.2 KiB is about 22 MiB at 30 days | +| the runner | `step-outputs`: a lint or test step's output | old `objects` section | 7 days | 1 GiB; about 1,200 steps run a day (the rest carried) of about 50 KiB is about 420 MiB at 7 days | +| the runner | `kept`: a package's passing result per level, by digest | old `state` section | 30 days unread | 128 MiB; a publish changes the digest of about 1,000 importing packages at two levels, so about 4,000 entries a day of about 0.3 KiB, about 36 MiB at 30 days | +| the indexer | `registrations` and its stream `registration-history` | old `state` and `streams` sections | the life of the mesh, never derived again | 64 MiB (*A module's registration*) | +| the indexer | catalog graph revisions, per watched branch | objects in the old form (ADR 0619 §2) | while a record pins it or it is its branch's current | 512 MiB, as *Two graphs, one source of truth*; a second watched branch on a few modules adds a few MiB | +| the gate | `source`: one key per watched branch | its old `state` section, as today | 64 revisions of each key | a few KiB | +| the forge module | `failed-steps`: failed `required` steps by module and fingerprint | state | 30 days | the template's 64 MiB; an estimated 50 failed steps a day of about 0.5 KiB is under 1 MiB at 30 days | +| every module | `-objects` beside each state | objects | with its key | the template's; nothing reserved until written | + +**The build capacity.** A pipeline runs a module's steps once per commit on a watched branch, carrying what did not +change, where the check ran before the merge and carried after each trunk move; a group runs one pipeline per watched +branch; a second watched branch runs the steps of the modules it carries once more. A mesh-sdk publish asks about 120 +lint steps and the test steps of the importing packages, about 240 more, the rest carried; a newer publish of the same +package supersedes the older one's rebuild pipelines, so two publishes close together run the rebuilds once. The first +pipelines after G's delivery run every module once, but carry every package whose digest the checker's kept verdicts, +taken into `kept`, already hold, so they run only what changed since. The steps go on the build seats' stream `check`, +after `delivery` and before `recheck`, within each node's build capacity (ADR 0525 §4, §5), and a run on request on the +same stream. How it is checked: live, the build nodes' time per day in the week after G, read from the build modules' +step keys and the builder's build log, against the checker's last week (test 99). + +### How milestone G itself is checked and delivered + +- **Under the clauses as they stand.** Milestone G is checked and delivered under ADR 0656 §5 and the clauses it changed + as they hold before its delivery: the acting parts (the indexer, the build modules, the assigner, the grants part, + the node-engine, and the checker, which makes G's own check) act from the milestone's heads, each first in its step, + in the order of their ordering edges; the trunk-only want, the checker and the Approve per merge as ADR 0661 leaves it + govern this delivery, no exemption is asked and no delivery goes ahead of it (ADR 0667 §2, ADR 0644 §1). +- **Its other parts as any module.** mesh-sdk's small object store package is a package published before the modules + that use it build; the manifest validator moves with the indexer; the runner is placed like any module and acts only + from the next change on; mesh-delivery's `contracts` and `sdk` move under its `modules/` folder (ADR 0667 §3). +- **Readers, the stream maker and the bus module first** (ADR 0667 §4): the edges the delivery plan derives, kind 4 each: + the indexer's manifest validator for the seat definitions' new fields (`callers`, `acts`, `subject`, `keep`) before + any definition using them; on each node the node-engine that reads `form` and `catch-up` before any manifest writing + them; the grants part, which makes each kept seat stream and its durable consumers, before the parts that hear a kept + stream; the bus module, with `-objects` and its grant to the owner alone, before the modules requiring it, the + grants part writing that grant from the milestone's heads. A restart of the bus its new version needs is said to the + operator before it starts. +- **The new assigner before the new merge.** The new assigner, which writes a want only from a passed pipeline, is + delivered before the forge module's new `merge-pull`, which asks no Approve, and before the runner: an edge of kind 4 + from `mesh-delivery-assigner` to each, declared in their manifests' `needs` since nothing else says it. Without it a + merge made with no Approve could reach the old assigner, which writes wants from the trunk with no pipeline. Both + switch on one fact, the first registrations written, said as `registration-changed`: until it the new assigner keeps + the trunk-only want and the new `merge-pull` refuses every merge, naming the missing registrations (ADR 0667 §5). + Meanwhile a fix, an indexer fix included, is merged by the operator on the forge, whose protection admits the operator + (ADR 0398 §2), and delivered under the trunk-only want still in force, and `indexer_seed_again` asks the first + registrations again. +- **A gap is built, not worked around.** An order the delivery plan cannot derive from the edges is built in the + delivery system within G; a node-engine of the version before applies every want whose manifests use no field it does + not read, and a want that uses one waits for the new node-engine on that node (ADR 0667 §5). +- **What is removed, and when.** The checker's buckets and bus account and the gate's forge merge token are removed only + after the first pipeline after G's delivery has delivered a change end to end (test 63), after a backup of the buckets + kept 90 days, as the delivery records are, whose restore is tested, and the operator is told before it (ADR 0667 §6). + The checker leaves the manifest validator's list of foundation parts (ADR 0619 §1) when it is removed; the runner is + on that list from G's delivery. +- **Told to the operator before it starts**: one more Approve per merge under ADR 0661 for G's own group, then none; the + one ask of the seed registrations; the bus's restart; and later the + checker's removal. +- **How it is checked.** Tests 94 to 97, and 100 for the assigner's edge. + +### Choices this design makes under ADR 0666 and ADR 0667 + +| Choice | Why | +|---|---| +| The registrations in the indexer's old `state` section with their history on an old stream, capped at 64 MiB, kept for the life of the mesh | the indexer is a foundation part (ADR 0619 §1 to §3, ADR 0666 §4); a registration keeps every version with who and on whose Approve, and nothing derives it again | +| The runner a foundation part, its kept data in old sections, on the manifest validator's list | the bus module's own delivery waits on its pipeline (ADR 0666 §4) | +| The gate no foundation part, its `source` in the old section it already has | the bus module's delivery waits on no act of the gate's; only the key's layout changes | +| The verbs `register`, `policy`, `watch`, `unwatch`, `registrations` and the event `registration-changed` on `mesh-catalog` | one verb per trusted act, each its own ask naming what moves; readers follow the event (ADR 0596) | +| The seed of the first registrations proposed as one ask, with the statuses the check judged until then and approval `bypass`, raised again by `indexer_seed_again` | registering is a trusted act (ADR 0666 §3), and one ask for the whole seed is how placement was adopted (ADR 0567); a declined or expired seed must not leave the pipelines stopped with no way on | +| Code review refused as `required` until forge accounts are bound to bus identities | a review is refused from its author (ADR 0666 §22), which cannot be told until then | +| The seat `git`'s read verb `branch` and event `branch-moved`, kept on its seat stream | registering reads a branch's protection through the seat `git` (ADR 0666 §3); a branch moves by a merge or an admitted push; a stream keeps a move said while the bridge is down | +| The watchman's finding `pipeline-stands` for a step or a head still five minutes, cleared by the step's end or the head's `pipeline-started` | the record's five minutes (ADR 0666 §24), one finding for both, timed from the runner's events | +| The runner's finding `pipeline-failed`, the author's for two hours, then the operator's | ADR 0666 §24 with ADR 0505 §5, §6 | +| A module's watched branch and its `build` in the placement key, set by a proposal | a placement names the branch and a return is one value in it (ADR 0666 §6, §24); every placement change goes by a proposal (ADR 0567) | +| The gate's `source.`, its verb `source` and event `source-moved` | one source revision per watched branch (ADR 0666 §6), read through the seat (G's prepare, the indexer's watch of the gate's `source`) | +| The build seats' verb `steps` and accepted kind `step` on `check`; the assigner's kind `step` on `mesh-wants`; `step-ended` with the node in its subject | steps are asked on the serving seat's work queue (ADR 0666 §7); the `check` stream already orders after `delivery`; a node's account says only its own node's ends (ADR 0363 §2) | +| The outcomes, with `accepted`, `superseded` and `cancelled`; an approval expired or refused ends `declined`, replaced `superseded` | every end a step can have is said as itself (ADR 0666 §10) | +| `approval` asked last, its `about` the module and the branch | the operator approves a commit the mesh already judged, the point ADR 0661 §3 kept in one place; one ask per module and branch, a newer commit's replacing it | +| A superseded pipeline's asks dropped by `drop`, and a pipeline superseded only when its module's fingerprint changed | a cancelled pipeline must leave no ask on a stream (ADR 0664 §4; G's prepare); a module the commit did not change has nothing newer to run (ADR 0666 §9) | +| A group's wants only on `group-ended` | a group is delivered whole or not at all (ADR 0666 §9; research 086, R5) | +| The six kinds derived from existing words, `needs` per artifact only where nothing says it | one form of each fact (ADR 0656 §6); the catalog entry's `needs` already exists from G | +| The cycle rule in the indexer's graph | the graph is the indexer's, and the checking program goes with the checker | +| The builder's seat `mesh-builds` and its event `package-published` | the record has the builder say the publication as an event of its seat (ADR 0666 §15); its waits move only when a later change gives the seat its verbs | +| Each state's object store `-objects` through mesh-sdk's small package, sent objects readable by a standing grant derived from the manifests, and the package's two tools | one object store per state, granted to its owner; the sender's declared callers and consumers read what it sends (ADR 0666 §16); only its users import it, so nothing else is rebuilt | +| The `run` ask published by the runner's account and the indexer's; the verb `run` called by the sessions and the operator only | the steps and the validation run code from the change, in the sandbox only, and each asker reads only its own step keys (ADR 0363 §2); a run publishes tagged packages, so nothing else may ask one | +| The checker's step `check` becomes `pipeline`; the checker's kept verdicts taken into `kept` | the runner is an acting part in the checker's place (ADR 0666 §19); the first pipelines then run only what changed | +| The field `callers` in a seat definition replaces the holders' trusted `callers`, a missing field admitting the holder roles and the operator only | the record makes the definition the grants part's one source (ADR 0666 §20); a field left out must open nothing | +| `widens` in `pipeline-ended`, computed by the running runner over every part serving a step, passed on by the teller | a widening is said and nothing refuses it (ADR 0666 §23, §26); a change must not compute its own | +| `merge-pull` judged from the forge module's own `failed-steps`, heard from `step-ended`, any run at the head's fingerprint counting unless a later rerun of that step passed, the protection read again on every `branch-moved` | the record has it judge from the events it consumes, never by a call, so a head merges while the runner is down (ADR 0666 §11, ADR 0596) | +| The new assigner before the new `merge-pull` and the runner, by `needs`, both switching on the first `registration-changed` | a merge with no Approve must never reach an assigner that writes wants without a pipeline (ADR 0667 §5) | +| The forge bridge's finding `branch-unprotected` | a move of a branch whose protection was removed starts no delivering pipeline and is said (ADR 0666 §6) | +| The verb `recovery` of `mesh-delivery` | a recovery is named by its author as a fact the bus keeps with who said it, never read from text (ADR 0666 §26, research 086 R10) | +| No forge status for a pipeline | the step results live on the bus (research 086 R10), shown by the runner and the delivery record; a status would be a second copy outside it | +| The runner's `pipelines` kept 30 days, its outputs 7, keyed by source revision | the delivery record keeps its own copy of the events for 90 days; about 300 pipelines a day must fit its caps | +| The checker's removal after the first end-to-end pipeline and a tested restore, its backup kept 90 days | ADR 0667 §6; 90 days is the delivery records' retention, the longest a trace reads back | +| The pipeline steps on the `check` stream after `delivery` | a delivery's build is never held by a pipeline, as a check never held one (ADR 0525 §4) | ## A delivery @@ -430,7 +1057,9 @@ From research 085's milestone the gate, holder of the seat `mesh-delivery`, keep milestone's delivery, a ledger instance (ADR 0595's template `ledger`, ADR 0597) it alone writes (ADR 0656). It holds: -- **the group's state**: the heads, the verdicts, the checks and the asks, which `merges` holds today; +- **the group's state**: the heads, the verdicts, the checks and the asks, which `merges` holds today; from milestone + G's delivery the pipelines' `step-started`, `step-ended` and `pipeline-ended` in place of the verdicts, the checks and + the asks, kept as long as the record (ADR 0666 §9); - **the trace**: the milestone, its issues, its pull requests, their commits, and the graph revisions the delivery moved between; - **what happened to each entry on each node**: for every entry of the graph difference, taken in, built, checked, @@ -458,10 +1087,16 @@ ADR 0656. - **A node away that wakes adds its outcomes.** When it wakes and catches up by its wants (*A change's graph difference is its delivery*, below), its outcomes reach the record through the same consumer as any other, and the record shows the node no longer away. -- **An Approve given holds at its heads.** An Approve the operator gave for a group's heads holds while those heads +- **An Approve given holds at its heads, until G's delivery.** An Approve the operator gave for a group's heads holds while those heads stand: a check of the same heads asked again, after a main move or for any other reason, records its verdict in the record and asks the operator nothing again (issue 1972). The Approve is withdrawn only as ADR 0441 §1 has it, - when a member stops being mergeable, and a carried verdict is read as current (ADR 0548 §8). + when a member stops being mergeable, and a carried verdict is read as current (ADR 0548 §8). From G's delivery no + Approve is asked per merge; an `approval` step's answer is the runner's, kept in the record as its step's end + (ADR 0666 §10). +- **From G's delivery, a record for every landed merge.** A session merges through the seat `git` and the gate merges + nothing, so every merge is one the gate did not make: the gate opens a record for each source revision of a watched + branch the indexer takes in, a group's members in one, and `forge-made` no longer marks a record apart. A merge its + author names a recovery is marked `recovery` (*A recovery fix is an ordinary merge*). - **A small fix has a record of its own.** A small fix is a milestone of one issue (ADR 0493 §3), so it has a delivery record like any milestone; nothing is merged outside a released milestone (ADR 0493 §11). - **It pins the graph revisions it points at.** The gate says, as the seat `mesh-delivery`'s events `pinned` and @@ -498,7 +1133,7 @@ ADR 0656. | Line | The gate | |---|---| | read everything it holds | `gate_record` (one record whole: the group's state, the trace, each entry's outcome per node, the nodes away), `gate_records` (every record with its fill against the value limit, and the ledger's fill against its cap), `gate_consumer` (its durable consumer: the last event applied per family, the events waiting, the age of the oldest) | - | do by hand what it does itself | `gate_record_repair` (for one record, asks each owner for the outcome of each entry missing one through that owner's read verb: the indexer's `take-in` read, the builder's build read, the checker seat's check read, the seat `mesh-wants`'s `entry`, and the node-engine seat's verb `composition` of that node; applies the answers as the consumer would) | + | do by hand what it does itself | `gate_record_repair` (for one record, asks each owner for the outcome of each entry missing one through that owner's read verb: the indexer's `take-in` read, the builder's build read, the checker seat's check read (from G's delivery the runner's `show`), the seat `mesh-wants`'s `entry`, and the node-engine seat's verb `composition` of that node; applies the answers as the consumer would) | | recover without help | `gate_record_end` (end a record left open, a node gone for good or an entry that never runs, with the reason, recorded in the hand-act log of the seat `mesh-hand-acts`) | | one seat, many tools | the seat `mesh-delivery`'s verbs, with `groups` answering a group's members and the acts said for it | @@ -539,7 +1174,8 @@ checker's `mesh/check` from a watch of the checker's state `owed`: reads of anot id, and the seat `git`'s verb skips an id the pull request or note already holds. This is chosen over recording the id before the act: an id recorded and then not performed (the bridge stopped between the two) would be lost, while an act repeated changes nothing. The bridge's own state `performed`, a key-value state in the new form (ADR 0595), - form 1, one key per id with the outcome and when, kept 7 days as the stream is and capped at 16 MiB, is therefore a + form 1, one key per id with the outcome and when, kept 7 days as the stream is, its size the one its template fixes + (ADR 0595 §3), is therefore a saving and a read, never what keeps an act from happening twice. - **Every outcome is said, and the gate records it.** The bridge says each act's outcome on its own stream `forge` as the event `owed.ended`, with the id and one of `performed`, `refused` (the forge's own words), `could not be @@ -553,8 +1189,12 @@ checker's `mesh/check` from a watch of the checker's state `owed`: reads of anot every act its records hold unanswered. An act unanswered 15 minutes after it was said is listed by `stalled`, which the condition keeper raises as the stalled line (ADR 0421 §7, ADR 0564 §2): fifteen minutes is many times a forge call's time, and short beside the check's hour. -- **A group's merges follow one another.** The gate says a group's next `merge-pull` only once the previous member's +- **A group's merges follow one another, until G's delivery.** The gate says a group's next `merge-pull` only once the previous member's merged message is heard (ADR 0441 §5), so a member the forge refuses holds the rest, and none is merged ahead. +- **From G's delivery the gate owes no merge, and the checker nothing.** A session calls `merge-pull` itself (ADR 0666 + §11), and a group's members land one by one, the group ending when every member has (*Groups*); the checker's `owed` + goes with the checker, and the runner owes the forge nothing, a pipeline's result living on the bus. The gate still + owes the delivery's view, a comment and the note's line, performed by the forge bridge as above. - **The bridge catches up from the seat.** At its start the bridge resumes its durable consumer and also reads `groups`, which answers, per group, the acts the gate said with their ids and their recorded outcomes; an id said and not answered is performed. Its tools: `bridge_owed` (the ids it performed with their outcomes, and its @@ -617,6 +1257,12 @@ verdict that names the trunk's head (*A move of the trunk carries every verdict* backup hold, superseded, covered, stopped, retired and failed) and the machine steps went at release 6: a module's progress on each node is its want against its have, shown by the view (ADR 0539 §17). +**From milestone G's delivery the gate keeps no merge states.** With no check before a merge and no Approve per merge +(ADR 0666 §10, §17), nothing is `proposed`, `ready`, `rejected` or `held` before a merge: a commit's states are its +pipeline's steps, kept by the runner (*Pipeline steps and the policy*). The table, the gate's `table`, `recheck` and +`close` and the one key per pull request go with the check; `stalled` lists the acts owed to the forge past their 15 +minutes and the records `record-open` names. + ## Two graphs, one source of truth *ADR 0656, which supersedes ADR 0645 to ADR 0648; ADR 0595, @@ -662,10 +1308,12 @@ Findings 11). How each is kept, read and retained is this design's choice under (*Reverted*, below). - **A revision is made by a merge, and also with no merge.** The indexer makes a catalog graph revision when it takes a source revision in. The assigner makes an assignment graph revision on each new catalog graph revision, on - the seat `mesh-module-assigner`'s event `placement-changed` (ADR 0567 §5), and on the node-engine seat's event + the seat `mesh-module-assigner`'s event `assignments-changed` (ADR 0567 §5, ADR 0641), and on the node-engine seat's event `capabilities-changed`, which a node-engine says when the capabilities it states in its node record change (ADR 0614 §4), so the assigner follows an event and never reads a node record across the seam (ADR 0596). A - placement change is traced like a merge. + placement change is traced like a merge. At its first start with no revision kept, the indexer takes in the head the + gate's source names for every repository by its catch-up path and keeps that as revision 1, and its verb `revision` + answers that it waits until then (lead-47's ruling in G's prepare: a first start has no merge to make a revision). - **A revision is kept while a record pins it or it is current.** A revision of either graph, and the input revisions it names, is removed when no delivery record pins it and it is not current: neither trunk's newest revision nor the newest of an open candidate. Pins are counted per revision, so a revision two records point at stays until both @@ -701,6 +1349,11 @@ Findings 11). How each is kept, read and retained is this design's choice under - **The want stays the one record a node reads.** The assigner writes `want..` from a trunk revision's assignment graph only; a node-engine reads its want, never the assignment graph, and the have stays what it runs (ADR 0656, which changes ADR 0571 §8). +- **From G's delivery, per watched branch and between artifacts.** The catalog graph is kept once per watched branch, + each revision naming its branch, and its edges run between artifact references, of the six kinds of *Dependencies + between artifacts* (ADR 0666 §6, §14). The assigner computes a node's entries from the catalog graph of the branch its + placement names, and writes a want from a revision of that branch whose `required` steps passed, in place of a trunk + revision's alone (ADR 0666 §9, which changes ADR 0656 §2). - **Reverted.** Only the new form is written: the indexer, the assigner and the gate keep nothing of ADR 0603 §2's keys or of `merges` and `turns` beside the new forms, since nothing reads them after milestone G. A revert of milestone G is a change like any other, checked and delivered, and the delivery system restores what it must @@ -745,7 +1398,10 @@ Findings 11). How each is kept, read and retained is this design's choice under check, kept apart from trunk's, and dropped on the gate's event `heads-replaced`, said when the candidate's heads were replaced or its pull request closed. A candidate costs a computed graph per check. - **Only a trunk revision writes wants**, whether a merge taken in or a placement or capability change made it; a - candidate's graph writes none (ADR 0656). + candidate's graph writes none (ADR 0656). From G's delivery a want comes from a revision of the watched branch a + placement chose whose `required` steps passed, and a candidate is a run on request's: the indexer builds it on the + runner's `run-started` and drops it on that run's `pipeline-ended`, the gate's `heads-replaced` no longer making + candidates (ADR 0666 §9, §18). - **Each part acts on its own entries.** The builder, the build modules and the grants part each act when their own entries in the new revision differ from what they run (ADR 0656), reading them through the seat `mesh-wants`'s verbs and events, never its bus state (ADR 0596), and naming no other module (ADR 0656). The node-engine acts on its want @@ -774,7 +1430,8 @@ Findings 11). How each is kept, read and retained is this design's choice under inputs stay the placements and the capabilities (ADR 0656). A running part acts only on a trunk revision's view; a 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). + them). From G's delivery a running part acts on a revision of a watched branch as on a trunk revision, and a + candidate's view is read only by a run on request's steps and the indexer's candidate pass (ADR 0666 §6, §18). - **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*, above), so every module that learns from it which modules exist moves in milestone G, not after: the watchman (its @@ -800,7 +1457,7 @@ Findings 11). How each is kept, read and retained is this design's choice under forge through the seat `git`. For both the order is carried by ADR 0615 §4 and §6: the owner answers at once from what it holds, and a reader started before it waits, saying so. The tool runner asks `revision` of the indexer's own runtime, never through itself, the tool's `callers` list naming it (ADR 0663, which changes ADR 0621 §1, §2 and - ADR 0615 §3; proposed, to be accepted before G's push); the forge + ADR 0615 §3; accepted); the forge module answers the indexer's reads through the seat `git` before it has a first view of its own, so neither waits on the other. - **With no view, a reader waits; it never reads "no modules".** All eight follow *A part with no view says it @@ -855,8 +1512,9 @@ Findings 11). How each is kept, read and retained is this design's choice under ADR 0656 leaves how each part is built to this design, under issue 1921; these four needed a shape of their own. - **An acting rule's fields.** The seat's definition is where ADR 0656 has an acting part declare what it acts on. A - seat's definition gains one optional field `acts`, with three fields of its own: `step`, one of `take-in`, - `validate`, `check`, `build`, `compose`, `grant` and `place`; `on`, either `every` (every module) or a `language` + seat's definition gains one optional field `acts`, a list of rules, each with three fields of its own: `step`, one of `take-in`, + `validate`, `check`, `build`, `compose`, `grant` and `place`, and from G's delivery `pipeline`, the runner's, in + `check`'s place (ADR 0666 §19); `on`, either `every` (every module) or a `language` naming the language of the modules it acts on, matched against what the manifest says its language is, as the indexer's language map matches today; and `bound`, how long an entry waits in that step for the acting part's new version (*An acting part's new version acts first*, below, gives each step's default). The definition format's own @@ -868,9 +1526,10 @@ ADR 0656 leaves how each part is built to this design, under issue 1921; these f (ADR 0656, Consequences); that is the same rebuild the fingerprint handover makes, so the milestone rebuilds every module once in all, and no other module's code changes. A definition carrying `acts` reaches only readers built with that runtime: the seat definitions that gain it are members of milestone G's group, and every reader is rebuilt in - the same delivery. The bootstrapped definitions every reader carries from its start (ADR 0636 §2), four of which - gain `acts` (`mesh-catalog`, `mesh-delivery-checker`, `node-engine`, `node-backup`), are made again from the new - definitions in the same change, and mesh-sdk's existing test that each bootstrapped copy equals its definition holds + the same delivery; the format's reader itself is delivered before them, as a release of mesh-sdk's seat-definition + reader merged ahead of G's check (the operator's choice of a reader first, 2026-11-09; ADR 0667 §4). The bootstrapped + definitions every reader carries from its start (ADR 0636 §2), of which `node-backup` carries no `acts`, are made + again from the new definitions in the same change, and mesh-sdk's existing test that each bootstrapped copy equals its definition holds them to it. - **One wiring of the seat list's reader.** The reader of the seat list and its two tools of ADR 0636 §7 are wired once, by mesh-sdk's runtime (`go/seatlist`), for every part that reads the list; no part wires its own. Four delivery @@ -893,7 +1552,8 @@ ADR 0656 leaves how each part is built to this design, under issue 1921; these f the asker's own state (the checker's `inputs`, a day), asked of the seat `mesh-delivery-checker`'s verb `input` and checked against that digest, laid as a file, and writes the program's exit and its answer, carried whole, on the build module's step key named by the ask's id (ADR 0525 §6). It is an accepted ask of the seat, not a request verb, because it is a - long job pulled where there is capacity, never a call to a named node. Only the checker's account may publish `run`. + long job pulled where there is capacity, never a call to a named node. Only the checker's account may publish `run`, + and from G's delivery the runner's and the indexer's (its validation before take-in), each under its own name. Every step key of a `run` ask starts with the asker's name (`checker.`), so the checker's read grant is fixed in advance to its own prefix and never follows ask ids one by one (ADR 0363 §2); no other part can have a program run or read its verdict. From milestone G the seat definition of `node-build-go` in `mesh-delivery-contracts` names it; B0 @@ -980,7 +1640,9 @@ and the assignment graph revisions; an entry taken in, built, checked, composed, entry's fingerprint and its node. The gate's delivery record is built from them. The seat's event comes first where the parts follow it through a seat (ADR 0656); a holder's own event stays under its own subject, declared in its own manifest's `streams` and published on `mesh.stream..event.` (ADR 0363 §1, §2). A seat's event is -declared in its definition and its holder's manifest claims the seat. **An event a node publishes carries the node in +declared in its definition and its holder's manifest claims the seat; a seat event's name has no dot, since it is read +as a subject's token, and it is kept on the stream `SEAT__`, which the grants part makes with its durable +consumers. **An event a node publishes carries the node in its subject**, and the grants part grants each node-engine's account only its own node's subjects, so one node cannot say another runs a build (ADR 0363 §2); the gate's events are granted to the gate's account alone. @@ -998,7 +1660,11 @@ say another runs a build (ADR 0363 §2); the gate's events are granted to the ga | a wait held, and ended | `wait-held` (step, acting part, its version, the entry, since when, its bound), `wait-ended` (the same, and how: ran, released) | each holder: `mesh-wants` for the assigner (placing, wanting and composing), `mesh-grants` for the grants part, the builder's own stream | `mesh.seat..event.wait-held`, `.wait-ended`; `mesh.stream.mesh-delivery-builder.event.wait-held`, `.wait-ended` | each seat's definition; the builder's manifest | | a store filling, full, and back below its cap | `filling`, `full`, `room` | `mesh-catalog`, `mesh-wants`, `mesh-delivery` | `mesh.seat..event.filling`, `.full`, `.room` | each seat's definition | | a record pins or frees a revision; a candidate's heads replaced; a record ended | `pinned`, `freed`, `heads-replaced`, `record-ended` | `mesh-delivery`, the gate | `mesh.seat.mesh-delivery.event.` | the seat's definition in `mesh-delivery-contracts` | -| a milestone's ask asked, withdrawn and answered | `milestone.asked`, `milestone.withdrawn`, `milestone.answered` | `mesh-delivery`, the gate | `mesh.seat.mesh-delivery.event.milestone..`, apart from each delivery's `transition` | the same | +| a milestone's ask asked, withdrawn and answered, until G's delivery | `milestone-asked`, `milestone-withdrawn`, `milestone-answered` | `mesh-delivery`, the gate | `mesh.seat.mesh-delivery.event.`, the milestone in the event, on the seat's family stream, apart from each delivery's `transition` | the same | +| a delivery record opened, and a merge named a recovery | `record-opened`, `recovery-merged` | `mesh-delivery`, the gate | `mesh.seat.mesh-delivery.event.` | the same | +| a pipeline, its steps, its waits and a run on request, from G's delivery | `pipeline-started`, `pipeline-ended`, `group-ended`, `run-started`, `step-started`, `step-ended`, `wait-held`, `wait-ended` | `mesh-pipeline-runner`, the runner | `mesh.seat.mesh-pipeline-runner.event....` | the seat's definition in `mesh-delivery-contracts` | +| a pipeline step ended, from G's delivery | `step-ended` | each build seat, `mesh-wants` | `mesh.seat..event.step-ended.`, the node that ran it | each seat's definition | +| a registration changed; a package published, from G's delivery | `registration-changed`; `package-published` | `mesh-catalog`, the indexer; `mesh-builds`, the builder | `mesh.seat.mesh-catalog.event.registration-changed`; `mesh.seat.mesh-builds.event.package-published` | the seats' definitions in `mesh-delivery-contracts` | The events, their fields, their subjects and which are a seat's are this design's choices: a seat's event where other parts follow the step through the seat, a holder's own event where only the delivery record hears it, so that @@ -1073,7 +1739,13 @@ per module and node from the keys: - **A build before its want.** No want names a fingerprint whose build is not done; a module whose build waits is named by nothing and fails nothing (rule 1; ADR 0539 §18). - **A provider before its consumers.** A module's new fingerprint is wanted on a node only while every provider - it requires runs healthy (rule 5). + it requires runs healthy (rule 5). From milestone G a provider runs healthy while the build it runs is healthy, as + the node-engine seat's `running` says it, whatever a newer want of it waits for: a bus module whose new build waits + for the operator's yes (its have's phase `waiting-yes`) still serves bus state from the build that runs, so the + provision `bus-state` holds no requirer for it (ADR 0614 §5, ADR 0429 §6). The rule reads what runs, never the phase of + a want not yet applied: on 2026-11-09 a yes not yet asked on the bus held the delivery of every module asking bus state + (issue 1966, note 150). How it is checked: whole (assigner), a provider whose new want waits for a yes, with its old + build running healthy, holds no consumer's want, and one whose running build is unhealthy holds it. - **The canary before the rest.** A new fingerprint goes to the module's canary first, and to its other nodes once it runs healthy there, at most `step` of them ahead when `step` is above zero (rules 3 and 4). - **A credential and a composition before the want.** The module's credential and grant are written when its @@ -1175,7 +1847,8 @@ names go, since every new acting part needed code changes elsewhere (research 08 - **An acting rule grants nothing.** A holder's bus grants come from the grants part as today (ADR 0539 §7). An acting rule changes what a part acts on across every module it matches, so the operator's Approve ask of a change names any acting rule it adds, and any it widens: a `step`, an `on` or a longer `bound` that now matches more - modules or holds them longer is named like an added rule. + modules or holds them longer is named like an added rule. From G's delivery there is no Approve ask per merge, and + the pipeline's end names it in `widens` instead, refusing nothing (ADR 0666 §23). - **Each step's wait is its own part's, read and released by its own tools.** The part that does a step holds its wait, so each wait has one owner that already holds that step's state, and says `wait-held` and `wait-ended` (*What each step says*) with the step, the acting part, its version, the entry and since when: @@ -1226,6 +1899,10 @@ commit on the SDK's trunk or the head of an SDK pull request the forge holds, op ## Checks +**Until milestone G's delivery.** The sections under *Checks* hold as written until then, and make milestone G's own +check (ADR 0667 §2). From its delivery the pipeline makes the check and the checker goes (ADR 0666 §17): what each +part of the checker did, and where it goes, is in *The pipeline makes the check, and the checker goes*. + ### One check per set of heads, kept by the bus *ADR 0323, ADR 0350, ADR 0395, ADR 0406, ADR 0548 §1.* @@ -1321,22 +1998,19 @@ the check gates merges.* ### Nothing merges into a repository under check -*ADR 0548 §2 to §4, §9, §10, as ADR 0551 bounds them; from research 085's milestone removed by ADR 0661 (proposed, -needs the operator's Approve; below).* +*ADR 0548 §2 to §4, §9, §10, as ADR 0551 bounds them; from research 085's milestone removed by ADR 0661 (accepted +on the operator's Approve; below).* **Removed at research 085's milestone.** The hold, the merge turns, their stalled line, the gate's tools for them and the setting `check-gates-merge` go in milestone G, the gate's and the forge module's alike (the operator, on Telegram, 2026-11-09 01:11 UTC, choosing "Remove them in G"; the forge's merge then judges no check, *The seat `git`*). The setting has been false since 2026-10-25, so the gate wrote no turn and held no merge in that time, and the -operator's word for G is that no check gates delivery (1921's note of 2026-11-07). From G's delivery an approved merge -is handed to the forge bridge at once; a check running on a repository the merge goes into ends on the commit it read, -and its verdict is carried (*A move of the trunk carries every verdict*); the checker reads nothing of the gate, and -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. ADR 0662 -is withdrawn; G builds ADR 0661. Beside it, ADR 0663 (proposed: the indexer answers `revision` in its own runtime to -exactly the parts that invoke it, the tool runner among them) is to be accepted before the push too, since the tool -runner's first view of the catalog half rests on it (*Every other reader of which modules exist*). How it is checked: in the gate's whole-module test an approved merge into a +operator's word for G is that no check gates delivery (1921's note of 2026-11-07). From G's delivery no merge waits on a check, and none on an Approve either (ADR 0666 §10): the checker is gone, and the +pipeline runs on the landed commit (*Pipelines per module*). **Its record is accepted:** ADR 0661 ends ADR 0548 §2 +to §4, §9 and §10 and ADR 0551 and changes ADR 0534 §4's judgement of `mesh/check` by the merge; until G's delivery the +rule below holds as those records have it. ADR 0662 is withdrawn; G builds ADR 0661 §1, §2 and §6, and ADR 0666 §10 +changes its §3 to §5 (the merge on the Approve alone), which G therefore builds for no merge. Beside it, ADR 0663 (accepted: the indexer answers `revision` in its own runtime to +exactly the parts that invoke it, the tool runner among them) holds the tool +runner's first view of the catalog half (*Every other reader of which modules exist*). 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. @@ -1516,7 +2190,8 @@ running versions never check in their place, and a check fails, naming the part, §6, §10.* A try says beforehand whether a check will pass. It is the check's own code run on commits nobody pushed to a -pull request, and it owes the forge nothing. +pull request, and it owes the forge nothing. It holds until milestone G's delivery, when the runner's run on request +takes its place and the checker's try, its events and the indexer's try candidates go (ADR 0666 §18). - **A try is a delivery group at exact commits.** The checker's try takes one or more members, each a repository and the exact commit asked, never a branch's head, with an optional trunk commit. One repository at one commit @@ -1611,7 +2286,12 @@ pull request, and it owes the forge nothing. ## The Approve and the merge -*ADR 0421, ADR 0398 §3, ADR 0406 §1, ADR 0659.* +*ADR 0421, ADR 0398 §3, ADR 0406 §1, ADR 0659; from milestone G's delivery ADR 0666 §10, §11.* + +**Until milestone G's delivery**, which is merged under it (ADR 0667 §2). From that delivery no Approve is asked per +merge and the gate merges nothing: a session merges a pull request through the seat `git`'s `merge-pull`, and +the operator's approval is the pipeline step `approval` where a module's policy names it (*Approval is a step, and a +session merges a pull request*). - **Asked as soon as the checks pass.** When a pull request's delivery reaches `ready` (both `mesh/merge-gate` and `mesh/repo-check` passed at its head against its trunk's head), mesh-delivery asks the operator's Approve of its @@ -1646,7 +2326,10 @@ pull request, and it owes the forge nothing. commit other than the trunk's head and asks nothing (ADR 0534 §4), the carry making the verdict current. From milestone G the merge waits on nothing but the Approve's heads and a trunk that takes no push: the forge bridge merges through the seat `git`'s verb `merge-pull`, which judges those two and no check, and a trunk move holds no - merge for its carry (ADR 0661, to be accepted before the push; *The seat `git`*, under *The verbs*). + merge for its carry (ADR 0661; *The seat `git`*, under *The verbs*). This shape is built for no merge: milestone G's + own merges are made by the running gate, and from G's delivery `merge-pull` is the session's own act, judged on the + pull request's head, the branch's protection and the runs at its fingerprint, never on an Approve (ADR 0666 §11, which + changes ADR 0661 §3 to §5). - **A push or a Decline ends the Approve.** A new head ends its ask or its Approve, for a group every member's, and is said once on the pull request; the new head is asked again once its checks pass. A Decline merges nothing and is said once (ADR 0421 §6). @@ -1665,6 +2348,9 @@ pull request, and it owes the forge nothing. assigner writes each want when its six rules hold. A merge is never refused, held or dropped once it is made. What of it is taken in waits only for the indexer its source revision names, or for the rest of its group (*Taken in by the indexer it names*, below; ADR 0633). +- **From milestone G's delivery, per watched branch.** The gate writes one source revision per watched branch, + `source.`, as a commit or a group lands there; the pipeline runs on each revision the indexer takes in, and + the wants follow a revision whose `required` steps passed, on the branch each placement chose (ADR 0666 §6, §9). - **From research 085's milestone, the wants follow the trunk's assignment graph.** A merge taken in makes a catalog graph revision and then an assignment graph revision; the assigner writes each want from that revision, its rules unchanged (ADR 0656), and each acting part's new version acts first in its own step (ADR 0656; *Two @@ -1772,7 +2458,13 @@ timer. A group's merges arrive together. `take-in.taken`: a hand take-in as any take-in does, and a hand drop naming the drop, for a merge whose wait was said pending, so the watchman's `take-in-waits` clears; a drop of a merge never said pending emits none (ADR 0633 §5, ADR 0639 §9). -- **The check refuses an indexer the running parts could not move.** For a change to the indexer's own module, the +- **From milestone G's delivery** (ADR 0666 §6, §13, which change ADR 0633 §1 and §3 to §6): before any take-in, on every + watched branch, the running indexer validates the revision with the manifest validator built from its heads, in the + sandbox, and a revision it refuses stays pending, as the bullets above have it, with the way back a revert; a pending + revision holds only its own watched branch; a group's member reaches it by landing, and the group ends when the gate's + group verb says every member has; `bridge_group_end_again` reads that verb; and the check's refusal below goes with the + check (*Watched branches and the catalog graph per branch*, *Groups*). +- **The check refuses an indexer the running parts could not move, until G's delivery.** For a change to the indexer's own module, the check validates the new indexer's manifest, found as the manifest that claims the seat `mesh-catalog`, with the trunk's manifest validator in its sandbox and the seat definitions of the members' heads, and refuses the change when that validator would refuse or hold it: such an indexer would never run, and every revision behind it would @@ -1921,7 +2613,7 @@ later change of a kept data's form, not as a case of this milestone. its own node, the assigner's composition check for every node, and the grants part. Each fills the composition's input from the bus with its own credential and nothing else (ADR 0547 §2, ADR 0549 §3): - **placement**, the state `placement` of the seat `mesh-module-assigner`, one key `placement.`, written by the - assigner's credential alone on an approved proposal and said by `placement-changed` (ADR 0567); + assigner's credential alone on an approved proposal and said by `assignments-changed` (ADR 0567, ADR 0641); - **the node records**, each in its node's own have key `.node`, written by that node alone and heard as the key's change (ADR 0555 §3); - **the manifests**, the indexer's `modules.` and its manifests by digest, or the digest the composing @@ -1994,7 +2686,7 @@ later change of a kept data's form, not as a case of this milestone. keeps a timer, and the node's later answer judges again. On a passing verdict the holder raises an authorising ask under its own name, offered on a channel that proves who answered, bound to the proposal and the digest of its changes. On the operator's Approve it writes each changed key by compare-and-set at the revision the proposal was - laid over, records the warrant, deletes the proposal's candidates and says `placement-changed` for each node. A + laid over, records the warrant, deletes the proposal's candidates and says `assignments-changed` for each node. A key that moved since is not overwritten: the keys already written stand, and the rest is proposed again over the new keys, judged and asked again. A declined or expired ask ends the proposal and says `placement-withdrawn`. - **The node record.** What the machine observes of itself: its tunnel's public key, its capabilities, the @@ -2287,10 +2979,37 @@ From research 085's milestone the seat gains: |---|---| | `groups` with a group | that group's members, which the forge bridge reads in place of the gate's `merges` state (ADR 0656), and the acts the gate said it owes the forge for it, each with its id and its recorded outcome (*What the gate owes the forge*) | | `owed` | an act the gate owes the forge (a merge, a status, the delivery's view, a comment, a line on the commit's note), with its pull request, head and id, on `mesh.seat.mesh-delivery.event.owed..`, said only from the gate's account and heard by the forge bridge through a durable consumer (*What the gate owes the forge*) | -| `milestone.asked`, `milestone.withdrawn`, `milestone.answered` | the one Approve ask per milestone (ADR 0493 §9 as ADR 0659 §1 changes it, issue 1783), held until it is answered, or withdrawn by a new head and asked again (ADR 0441 §1); said on `mesh.seat.mesh-delivery.event.milestone..`, apart from each delivery's `transition`, which stays as it is, so a waiter on one member's pull request wakes only on that member's `transition` | +| `milestone-asked`, `milestone-withdrawn`, `milestone-answered` | until G's delivery: the one Approve ask per milestone (ADR 0493 §9 as ADR 0659 §1 changes it, issue 1783), held until it is answered, or withdrawn by a new head and asked again (ADR 0441 §1); said on `mesh.seat.mesh-delivery.event.`, the milestone in the event, apart from each delivery's `transition`, which stays as it is, so a waiter on one member's pull request wakes only on that member's `transition`. G's delivery ends the ask and its three events with the Approve per merge (ADR 0666 §10) | +| `record-opened` | a delivery record opened, which the watchman times for `record-open` | | `pinned`, `freed`, `heads-replaced` | the events by which the indexer and the assigner keep or drop graph revisions, said only from the gate's account (*The delivery record*) | | `record-ended`, `filling`, `full`, `room` | a delivery record ended; the ledger past 80 % of its cap; the ledger full; the ledger back below its cap (*The delivery record*) | +From milestone G's delivery the seat's `table`, `recheck` and `close` go with the merge states (*The state table*), +the milestone ask and its three events with the Approve per merge, and it gains (ADR 0666 §6, §26): + +| Verb or event | Answers or does | +|---|---| +| `source` with a watched branch | that branch's source revision; the indexer and the node-engine's catch-up read it, never the gate's state | +| `source-moved` | a new source revision of a watched branch | +| `recovery` | marks a merge its author names a recovery (the commit and why), its record marked `recovery` with the caller the runtime proves | +| `record-opened`, `recovery-merged` | a delivery record opened; a merge named a recovery, which the teller passes on to every channel | + +**The seat `mesh-pipeline-runner`**, from milestone G's delivery, defined in `mesh-delivery-contracts` with the callers +of each verb (ADR 0666 §7, §20, §25): + +| Verb | Answers or does | Callers | +|---|---|---| +| `run` | the run on request of one or more members, each a module at a named commit; delivers nothing | the sessions (the agents' bus identities the tool runner proves) and the operator, nothing else | +| `start` | a delivering pipeline for a watched branch's head, by hand | the operator, the healers | +| `show`, `list`, `stands`, `why-carried`, `kept` | one pipeline whole with its step log; the pipelines and runs of a module, a branch or a commit; what stands still; where a result was carried from; the kept results | any person, an agent session, the healers | +| `review` | a code review's result for a commit and fingerprint | the reviewers the definition names; refused from the commit's author | +| `rerun`, `accept`, `cancel`, `ask-again` | one step again; a failed `optional` step accepted with why; a pipeline ended, its asks dropped; a declined `approval` asked again | the operator, the healers (`accept` and `ask-again` the operator) | + +**The seat `mesh-catalog`** gains, from milestone G's delivery, `register`, `policy`, `watch`, `unwatch` and +`registrations`, and the event `registration-changed` (*A module's registration*). **The build seats** gain the verb +`steps` and the accepted kind `step`, and **the seat `mesh-wants`** the kind `step`, each saying `step-ended`. **The +seat `mesh-builds`**, new and held once for the mesh, says `package-published` (*A publish rebuilds*). + **The seats `mesh-catalog` and `mesh-wants`** gain, from research 085's milestone, `revision` on each (the two halves of the revision view, ADR 0656), and `entry` and `difference` on `mesh-wants` (ADR 0656), with the events of *What each step says*. @@ -2313,7 +3032,8 @@ parts' manifests declare in `invokes` and `consumes` and what their code calls, | Verb | Answers or does | Called by (today's call) | |---|---|---| -| `pull` | one pull request, by its repository and number or by its merge commit: number, base, head branch, head, merge commit, author, state | the forge bridge (a merge the gate did not make; `gitea_api`), the gate (a stalled line's author) | +| `pull` | one pull request, by its repository and number or by its merge commit: number, base, head branch, head, merge commit, author, state, and `merging` while the forge merges it; an unknown one answers the error kind `not-found` | the forge bridge (a merge the gate did not make; `gitea_api`), the gate (a stalled line's author) | +| `branch` | from milestone G's delivery: a branch's head, and whether a protection rule refuses a direct push and admits only merges | the indexer (`register`, `watch`), the forge bridge (a watched branch's head) | | `open-pulls` | every open pull request of every repository, its head and base, the statuses its base requires and those its head has | the forge bridge at its start and each reconnect (ADR 0443 §5), the indexer, the gate (`gitea_open_pulls`) | | `tags` | a repository's tags, paged, the page's bound said when more exist | the forge bridge, for the builder's floor (`gitea_api`) | | `trees` | the trees of one commit | the forge bridge, the checker, the indexer (`gitea_commit_trees`) | @@ -2321,13 +3041,14 @@ parts' manifests declare in `invokes` and `consumes` and what their code calls, | `contains` | whether one commit contains another | the indexer, the gate (`gitea_contains`) | | `statuses` | the statuses a commit carries | the gate (`gitea_commit_statuses`) | | `status`, `comment`, `view`, `note` | a commit status, a comment, the delivery's one view comment, a line on the commit's note under `refs/notes/mesh-plan`; a comment and a note line carry the act's id and an id already held is skipped | the forge bridge alone, performing the gate's and the checker's `owed` (`gitea_commit_status`, `gitea_add_comment`, `gitea_delivery_view`, `gitea_note_append`) | -| `merge-pull` | merges a pull request at the head the operator's Approve names; refuses a head that moved, a branch no rule guards, a head the Approve does not name and a merge git refuses; judges no check (below); a pull request already merged at that head is answered performed | the forge bridge alone (`gitea_merge_pull_request`) | +| `merge-pull` | until G's delivery: merges a pull request at the head the operator's Approve names; refuses a head that moved, a branch no rule guards, a head the Approve does not name and a merge git refuses; judges no check (below). From G's delivery: merges with the forge tools' account (ADR 0398 §2) at the head the caller names, judging that it is still the pull request's head and that the branch's protection refuses a direct push, the protection read again on every `branch-moved`, and refusing a head when any run at its build-input fingerprint failed a `required` step, judged from its own state `failed-steps` heard from the runner's `step-ended`, never by a call; a head with no run yet or a passed one merges, it never waits for a run and never asks an Approve (ADR 0666 §11). A pull request already merged at that head is answered performed | until G's delivery the forge bridge alone (`gitea_merge_pull_request`); from it any session the tool runner proves, and the operator | | Event of the seat | Says | Heard by (today's event) | |---|---|---| | `pull.updated`, `pull.merged`, `pull.closed` | a pull request's new head, its merge with the merge commit, its close | the forge bridge, the gate (`gitea.pull.*`) | | `forge.pull`, `forge.status`, `forge.delete` | the forge's own webhook of a pull request, of a commit status, of a deleted branch | the gate (`forge.pull`, `forge.status`), the forge bridge (`forge.delete`) (`gitea.forge.*`) | | `repo.writable` | a repository the forge can write again | the gate (`gitea.repo.writable`) | +| `branch-moved` | from milestone G's delivery: a branch's new head, by a merge or an admitted push, from the forge's push webhook | the forge bridge | Each is said on `mesh.seat.git.event.`, declared in the seat's definition, and heard through the hearer's `consumes` of the seat. @@ -2340,15 +3061,22 @@ Each is said on `mesh.seat.git.event.`, declared in the seat's definition - **Who may call an act.** The holder's trusted config value `callers`, which today names per verb who may call the two package seats' verbs (design 51), gains a line per verb of the seat `git`: the act verbs name the forge bridge alone, the reads name each part that declares them in `invokes`; the grants part grants by it, and the holder - refuses a caller it does not name. The forge module's own acting tools (`gitea_merge_pull_request`, + refuses a caller it does not name. From G's delivery the callers per verb are the seat definition's field `callers`, + the grants part's one source (ADR 0666 §20): `status`, `comment`, `view` and `note` the forge bridge alone, + `merge-pull` the persons and agent sessions the tool runner proves, the reads the parts that declare them. The forge module's own acting tools (`gitea_merge_pull_request`, `gitea_commit_status`, `gitea_delivery_view`, `gitea_note_append`, `gitea_add_comment`) retire with the milestone, and so do its watch of the checker's state `owed` and its read of the gate's `source`, so the bridge stays the one part that acts on the forge. How it is checked: test 51 reads the grants, not the code. -- **`merge-pull` judges no check.** The operator's answer that no check gates delivery (Telegram, 2026-11-09 01:11 UTC, +- **`merge-pull` judges no check, and from G's delivery no Approve, only the runs at the head's fingerprint.** The operator's answer that no check gates delivery (Telegram, 2026-11-09 01:11 UTC, "Remove them in G") covers the forge module's own setting `check-gates-merge` as well as the gate's: both are removed, and `merge-pull` merges an approved head whatever its `mesh/check` says. The record that ends ADR 0551 and ADR 0548 §2 to §4, §9 and §10 also changes ADR 0534 §4's judgement of `mesh/check` by the merge; it is to be accepted - before the push (*Nothing merges into a repository under check*). + before the push (*Nothing merges into a repository under check*). From G's delivery it judges no Approve either, its caller + is any session the tool runner proves, and it refuses a head when any run at its fingerprint failed a `required` step, + never waiting for one (ADR 0666 §11; *Approval is a step, and a session merges a pull request*). The reads the + gate would have needed to merge (the forge's word for a conflict, the base's required statuses, the merging account's + write access) are not added: no part of the mesh but `merge-pull` merges, and it answers git's own refusal of a merge + as refused. - **The order is the module graph's, and each step has its way back.** The verbs are a served-verb edge (ADR 0614): the forge module's new build runs before the forge bridge's, and the forge bridge's before the gate's, since the bridge calls the verbs and performs the gate's `owed`, and the gate says `owed` only to a bridge that hears it; all @@ -2670,9 +3398,8 @@ What milestone G's prepare found, and its test: grants composed from the holder's `callers` give the act verbs to the forge bridge's account alone, a call of one from another account is refused, and the forge module serves none of its retired acting tools (whole, forge bridge, grants part; live, the grants read with `grants_bindings`). -52. **Nothing holds an approved merge for another check.** Once ADR 0661 (proposed, needs the operator's Approve; to - be accepted before the push), which ends ADR 0551 and ADR 0548 §2 to §4, §9, §10 and changes ADR 0534 §4, is - accepted: an approved merge into a repository under a running check is handed at once and merged whatever that +52. **Nothing holds an approved merge for another check.** By ADR 0661 (accepted), which ends ADR 0551 and ADR 0548 + §2 to §4, §9, §10 and changes ADR 0534 §4: an approved merge into a repository under a running check is handed at once and merged whatever that check says; a merge after a trunk move is not held for the carry; neither the gate nor the forge module declares `check-gates-merge`, the gate declares no `turns`, and the checker is granted no read of the gate's state (whole, gate, checker and forge module). @@ -2745,6 +3472,130 @@ What milestone G's prepare found, and its test: put without hold at the step `released`; a held put stays until released (whole, assigner and watchman; live, `assigner_puts` after milestone G's put of its own indexer). +From research 086 (ADR 0666 and ADR 0667), its acceptance tests by level and repository (research 086, choice 29): one +end-to-end test against the real bus per requirement, R1 to R18, each as the requirement's check states it, then the +failure paths and ADR 0667's checks. Each whole-module test below is a case of its module's one whole-module +integration test, which starts the module whole against the real bus and store; the runner, +`modules/mesh-delivery-pipeline` in mesh-delivery, has one of its own. The checker's tests go with it at G's delivery, +its whole-module test, its try test and the examiner's table among them, and so do the indexer's try-candidate rows and +mesh-delivery's `tryevent`; tests 21 to 24, 26, 31, 41, 46, 52 and 58, which the checker proves, hold until then, and +the runner's tests below restate what of them stays (22 in 73, 23 in 84, 46 in 84, 58 in 84). No repository ends the +milestone with more tests than it starts with (research 085, Direction, One milestone; the test budget). + +63. **R1, no hand act delivers a change.** A change to the indexer, the grants part and the tool runner is delivered end + to end, and the hand-act log of the seat `mesh-hand-acts` names no act for it (live; mesh-delivery, mesh-tools). +64. **R2, a watched branch triggers, any commit can be run.** A commit on a watched branch runs its module's pipeline, + and a move of a watched branch whose protection was removed starts none and raises `branch-unprotected`; a branch + `feature/1966-x` runs on request and delivers nothing (whole, runner and forge bridge, mesh-delivery; live). +65. **R3, steps detected, statuses in the catalog.** A module with no integration tests shows `nothing to run`; a + manifest naming a status is refused (whole, Go build module, mesh-catalog; unit, manifest validator, mesh-delivery). +66. **R4, only a `required` step holds, and every step is shown.** A failed `optional` step does not hold the delivery; + the runner's `show` lists each step's result; a `required` unit-test step on a module with no tests holds it (whole, + runner and assigner, mesh-delivery). +67. **R5, a change across repositories whole or not at all.** A change over three repositories, its own packages + included, is delivered whole from one source revision; when one member's `required` step fails none is delivered; a + step whose prerequisite nothing starts ends its pipeline refused within five minutes, naming the step and the + prerequisite; with one member passed and another still running no want is written until `group-ended` (whole, + indexer, gate, runner and assigner, mesh-delivery and mesh-catalog; live). +68. **R6, modules, never repositories.** A module whose watched branch is `beta` on one machine is delivered from it + there only; the lint step refuses a module, branch or repository name in a string, a constant or a table, and not + an import path (whole, assigner, mesh-delivery; unit, the Go build module's lint, mesh-catalog; live, a search of the + delivery parts' code). +69. **R7, any size.** Values of one, ten and a hundred times the bus's per-value limit are stored, sent as a verb's reply + and as an event, and read back whole by a caller the sender's seat definition names and a consumer declaring its + event, and refused to a module that declares neither (whole, mesh-sdk, against the real bus). +70. **R8, an unread input refuses.** A build whose published packages cannot be read is refused, naming the state + (whole, builder, mesh-delivery). +71. **R9, no ask hidden.** A fourth ask and an ask after a Decline reach the channel; an ask with the same `about` from + the same asker replaces the open one (whole, the router, mesh-catalog; live). +72. **R10, the bus alone.** The runner, the indexer, the gate and the assigner, each restarted with nothing on its disk, + resume from the bus alone; a test over each one's code finds no read of a pull request's title, description or + comment (whole, each, mesh-delivery and mesh-catalog). +73. **R11, nothing twice.** A commit changing one package of one module builds that module, runs that package's tests + and delivers it alone; a step whose inputs did not change is carried, not run (whole, runner and builder, + mesh-delivery). +74. **R12, every requirement tested.** This list maps each of R1 to R11 and R13 to R18 to a named test against the real + bus, and the milestone's check runs each of them: its record names every one as run against the real bus, and the + milestone is not delivered while one is missing from it (live, read from the check's record). +75. **R13, a registration change is trusted.** Moving a step from `required` to `bypass` asks, showing that line, and + writes nothing without the warrant (whole, indexer, mesh-delivery). +76. **R14, nothing stands still unseen.** A step whose worker dies raises `pipeline-stands` within five minutes; a + watched branch's head with no pipeline raises it, and that head's `pipeline-started` clears it (whole, runner and + watchman, mesh-delivery). +77. **R15, going back is one act.** A failing new version leaves the old one running, and a placement's `build` set + back delivers the old build (whole, assigner, mesh-delivery; live). +78. **R16, a manifest judged per watched branch.** A `beta` manifest needing a seat nobody holds fails its composition + step for the machine on `beta` only (whole, assigner, mesh-delivery). +79. **R17, edges between artifacts.** A change to the tool runner and the grants part is delivered in the order + `mesh-grants:program`, `node-tools:runtime`, `mesh-grants:tools` with no hand act; two programs needing each + other's new verb are delivered together as one step; two artifacts each needing the other's new package to build + are refused, naming both; a seat moved to a new holder has its old holder released before the new one claims (unit, + the indexer's graph; whole, assigner, mesh-delivery; live). +80. **R18, a publish rebuilds.** A mesh-sdk merge changing one package publishes one version, and only the artifacts + importing that package rebuild against it and are delivered, with no hand act; a merge changing only tests rebuilds + nothing (whole, builder and indexer, mesh-delivery; live). + +The failure paths: + +81. **A group that never completes** raises `take-in-waits` at 30 minutes, and none of its members is delivered (whole, + indexer and watchman). +82. **An indexer whose manifest its validator refuses** leaves its revision pending, holds only its own watched branch, + raises `take-in-waits` at 60 minutes, and a revert taken in moves the branch on (whole, indexer). +83. **A declined registration change, and an unprotected branch,** each write nothing: the first after its Decline, the + second refused naming the branch; a watched branch whose protection is removed later starts no delivering pipeline + on its next move and raises `branch-unprotected` naming it (whole, indexer and forge bridge). +84. **A composition step for a node that sleeps** passes it with a warning; a step whose part is not heard ends `could + not run`, never passed; two modules owning one path are refused (whole, runner and assigner). +85. **A forged step result**, from an account other than the step's seat holder's, or naming another commit or + fingerprint, is refused and said; a `step-ended` on another node's subject is refused by the bus; a verb whose + definition names no `callers` admits only the holder roles and the operator (whole, runner and grants part). +86. **An author's own review** is refused; a reviewer's passes the step (whole, runner). +87. **A step seat with no holder** ends its pipeline failed, naming the seat, within five minutes (whole, runner). +88. **A runner stopped mid-step** takes its pipelines up again from its kept state when it starts, a replaced holder + and its successor never both write one pipeline key (compare-and-set), and a new runner's failing build leaves the + old one running pipelines; a build module restarted mid-step finishes the step from its work queue (whole, runner + and Go build module). +89. **An older revision ending after a newer one** writes no want; a newer commit supersedes a module's pipeline only + when it changed that module's build-input fingerprint (whole, assigner and runner). +90. **A replaced oversized value** leaves one object, and a deleted key takes its object (whole, mesh-sdk). +91. **A session's merge** through `merge-pull` at its head merges with no run yet and with a passed run, and asks no + Approve; with the runner stopped it still merges, judged on the `step-ended` it kept; a head at whose fingerprint any + run failed a `required` step, a head that moved, and a branch whose protection was removed since its last + `branch-moved` are refused, each naming why; a passing `rerun` of the failed step at that fingerprint, asked by the + operator, clears it and the head then merges, while a forged plain pass of that step clears nothing; a failed + `optional` step refuses nothing; a call from an account that is + no proved session nor the operator is refused (whole, forge module and forge bridge, mesh-catalog and mesh-delivery). +92. **A recovery named** by `recovery` is marked in its record and `recovery-merged` reaches every channel (whole, gate + and teller). +93. **Every tool of *The tools*** answers its whole-module case, every store's read tool answers its fill against its + cap, `grants_why_refused` names the grant a refused caller lacks, `gate_source_again` says `source-moved` again, and + each is read by `mesh_describe` (whole, each module). + +ADR 0667's checks, of milestone G itself: + +94. **G checks itself.** Its check names the checker, the validator and the composer built from its heads, and no + member was delivered ahead of it (live). +95. **Readers and the bus module first.** The reader releases, the node-engines that read `form` and `catch-up`, the + grants part and the bus module are delivered before the modules that use them, by the delivery plan's derived edges + (live). The manifest validator accepts every manifest on the bus module's path, and refuses a runner manifest that + asks for a template (unit, manifest validator). +96. **No order by hand.** The delivery plan names every ordering edge it derived, and the hand-act log of the seat + `mesh-hand-acts` names none for the milestone (live). +97. **What G removes, and when.** The checker's buckets and bus account and the gate's forge merge token are removed + only after test 63 has passed on the mesh, after a backup of the buckets whose restore was tested, and after the + operator was told; then they are gone, and the backup is kept 90 days (live). +98. **A failed head is said.** A `required` step that failed, or could not run, on a watched branch's head raises + `pipeline-failed`, the commit's author's for two hours and then the operator's, cleared when a newer revision of + that branch passes it (whole, runner and condition keeper). +99. **The build capacity.** In the week after G, the build nodes' time per day, read from the build modules' step keys + and the builder's build log, is set beside the checker's in its last week; a newer publish supersedes an older one's + rebuild pipelines, and the first pipelines after G carry what the checker's kept verdicts held (live; whole, runner). +100. **The new assigner before the new merge.** In G's delivery the delivery plan delivers the new assigner before the + forge module's new `merge-pull` and before the runner, by their `needs`, and no merge made through the new + `merge-pull` reaches an old assigner; until the first registrations' `registration-changed` the new assigner writes + wants from the trunk alone and `merge-pull` refuses every merge, and after it both switch (live, read from the + delivery plan and the forge module's and the assigner's `running`; whole, assigner and forge module). + ## What retires - The "release branches" and the controller's check of them (ADR 0358, superseded by ADR 0401). @@ -2799,6 +3650,16 @@ What milestone G's prepare found, and its test: the merge turns, their stalled line and tools and the setting `check-gates-merge`, once their record is accepted; the last three reads of a pull request's description (ADR 0659 §4); every delivery part's call of the forge module's own tools, for the seat `git`'s verbs; and the four seat-list readers the delivery parts wire by hand. +- At milestone G's delivery, from research 086 (ADR 0666, ADR 0667): the checker (`mesh-delivery-checker`), its seat, + its try with `tryevent` and the indexer's try candidates, its kept verdicts and carries (the runner's from then), the + checking program and `mesh/check`, and its buckets and bus account, removed with the gate's forge merge token only + after the first pipeline after G's delivery has delivered a change end to end, after a backup kept 90 days whose + restore is tested, the operator told before (ADR 0667 §6); the bundle of steps run before a merge; the Approve per + merge, the milestone ask and its three events, and the gate's merges; the gate's merge states, one key per pull request and its verbs `table`, `recheck` and + `close`; the trunk-only want; `source.main`, for one source revision per watched branch; every fixed branch, + repository and module name in code logic; the recovery merge verb this design sketched, never built; and the holders' + trusted `callers` values, for the seat definitions' `callers`. The words **merge check**, **try**, **trunk commit** + and **merge turn** go to *Not:* lines with the as-is update after that delivery, as the glossary's entries say. ## Milestones @@ -2849,7 +3710,7 @@ release reports the controller's code lines against research 063's baseline (acc | L6 | Provisioning leaves the controller (ADR 0570): every provision is one key of the seat `mesh-provisioner`, held by mesh-provisioner, holding a reference and never a value, and each placed module's provisioning plan a key of its state `plans`, both composed from placement, the wants and the manifests on change events; each provider acts once all a provision depends on is provided; the assigner moves a want only once its build's provisions are provided; a provision no want needs is retiring, and its account or credential is removed only on the operator's Approve, its data never; the vault mints each provision's secret sealed to the consumer's and the provider's node, and the consumer's node-engine writes it; a wait for a person is a provision's state, which the watchman reads; bus permissions stay with the grants part (ADR 0349, ADR 0230, ADR 0547 §11) | — | mesh-sdk, the node-engine (`mesh-host`), mesh-tools (the tool runner's provisioner client), mesh-catalog (mesh-provisioner, the vault, the provisioner client, postgres, keycloak, gitea, route-adapter), mesh-delivery (assigner, watchman) | 1954 | | L7 | History and records leave the controller (ADR 0571): the builder keeps its build log, one entry at a build's start and one at its end, from which build history and durations are read and the module mesh-catalog asks the builds it missed; the artifact sweep is the seat `mesh-artifact-sweep`, held by artifact-store-tools beside the artifact store, its keep set from the store's own listing, the wants and the build log, sweeping at each build's end from the lease write and recording each deletion in the hand-act log; disk readings are disk-load's own state on every node; who holds which seat is the state `seat-holders` of the seat `mesh-placement` (now `mesh-module-assigner`), and tools are found by the tool runners' announcements; what a node runs is its want and its have; the grants part writes `grants..` and keeps memberships in its own state; root-free is a probe of the self-check; no manifest but the controller's reads, invokes or consumes `mesh-controller`, but a named list kept to the lease write, so the lease write's check passes (ADR 0189, ADR 0547 §11, ADR 0549 §6) | — | mesh-sdk, mesh-controller (its pin only), mesh-delivery (builder, indexer, assigner, grants part, view), mesh-catalog (artifact-store-tools, disk-load, the backup seat's holder, mounts, nfs-server, minio, mesh-watcher, the messenger, the self-check, the module mesh-catalog, docker), mesh-tools (the tool runner) | 1955 | | B0 | The bootstrap delivery: every check, a lone pull request's as a group of one and a verdict carried after a trunk move included, is judged by a checking program built from the change's own heads in the build seat's sandbox, which also makes the heads' one seat list that the check hands the manifest validator and the composer; it brings no seat definition and no manifest field, so the running checker checks it (ADR 0644; *The bootstrap delivery, and the one milestone after it*) | 26 needs it | mesh-sdk (`go/delivery`: the seat `node-build-go`'s ask `run` and the checker's record of which checking program judged; `go/composer`: the request's seat list), mesh-catalog (mesh-build-go: the run step, the refused answer, the kept programs' tools and sweep), mesh-delivery (checker: the checking program and its command), hq (this design, the glossary) | 1921 | -| G | Two graphs and one revision view: the catalog graph and the assignment graph kept per revision, a change delivered as its graph difference, the acting parts' rules on their seats as bounded waits that hold their modules when the new version fails, the check on the change's own acting parts, the revision view and each process's own build, the gate's delivery record, and the trace's links (ADR 0656); no part reads a pull request's description (ADR 0659); every delivery part reaches the forge through the seat `git` and names no other module; nothing holds an approved merge for another check | 26 to 60 | mesh-sdk (the runtime: the fingerprint, the view, the definition reader, the seat list's one wiring), mesh-contracts and the domains' contracts modules (`acts`, the new verbs and events, the seat `mesh-grants`, the seat `git`'s verbs), mesh-delivery (indexer, assigner, checker, builder, grants part, gate's view, forge bridge, watchman), mesh-catalog (the gate, the build modules, the forge module, mesh-issues, mesh-knowledge, the `node-backup` holder, nats: a module's kept data on the bus as a backed-up item), the node-engine (`mesh-host`), hq | 1966, 1961 (retargeted to this row's shape), 1660, 1972, 1721, 1783, 1785, 1794, 1791, 1373, 595; 1962 goes back with 1958, whose assignment entry it needs (ADR 0641 §3) | +| G | Two graphs and one revision view: the catalog graph and the assignment graph kept per revision, a change delivered as its graph difference, the acting parts' rules on their seats as bounded waits that hold their modules when the new version fails, the check on the change's own acting parts, the revision view and each process's own build, the gate's delivery record, and the trace's links (ADR 0656); no part reads a pull request's description (ADR 0659); every delivery part reaches the forge through the seat `git` and names no other module; nothing holds an approved merge for another check; and, one milestone with them, research 086's pipelines: a change of any module goes from a commit on a watched branch to the machines through its module's pipeline, its policy in its registration, ordered by edges between artifacts, with no Approve per merge and no hand act, the checker gone (ADR 0666, ADR 0667). Test counts at its start (G's prepare, 2026-11-09): mesh-delivery 665 unit and 68 integration, the node-engine (`mesh-host`) 1,742 unit; each other repository's and each catalog module's from the last check's verdict, read in the joint prepare | 26 to 62, 63 to 100 | mesh-sdk (the runtime: the fingerprint, the view, the definition reader, the seat list's one wiring), mesh-contracts and the domains' contracts modules (`acts`, the new verbs and events, the seat `mesh-grants`, the seat `git`'s verbs), mesh-delivery (indexer, assigner, checker until its removal, builder, grants part, gate's view, forge bridge, watchman, the new pipeline runner `mesh-delivery-pipeline`, `contracts` and `sdk` moved under `modules/`), mesh-catalog (the gate, the build modules, the forge module, mesh-issues, mesh-knowledge, the `node-backup` holder, the router, nats: a module's kept data on the bus as a backed-up item and the object store beside each state), mesh-sdk (also its small object store package, for values of any size), the node-engine (`mesh-host`), hq | 1966, 1961 (retargeted to this row's shape), 1660, 1972, 1721, 1783, 1785, 1794, 1791, 1373, 595; 1962 goes back with 1958, whose assignment entry it needs (ADR 0641 §3) | An issue is in one row only (ADR 0493 §2): where a row named an issue another row names too, the last row keeps it and the earlier row says so in words (the operator, 2026-10-26). Milestone M1 makes each row a record of the issue tracker @@ -2967,7 +3828,9 @@ B0's own choices, each checked by the rows of *How it is checked* below: - **Milestone G keeps the rest**: the first tier for every acting part, the verdict that fails by name, the revision view, the two graphs, the difference, the acting rules, the delivery record and the trace's links. It is one milestone, one group and one check, its fixtures folded into the existing whole-module tests of the checker, the gate, the indexer and the assigner, and it ends with - no higher test count in any repository than it starts with (research 085, Direction, One milestone). + no higher test count in any repository than it starts with (research 085, Direction, One milestone). Research 086's + pipelines are one milestone with it, one design amendment, one review, one check and one release, checked and + delivered as *How milestone G itself is checked and delivered* has it (ADR 0667). - **The order inside milestone G is the module graph's**, never a delivery ahead: each acting part's new version acts first in its own step (ADR 0656; *Order without a person*); the node-engine handing the fingerprint composes the modules whose runtime reads it; the indexer's own steps keep *Taken in by the indexer it names*. @@ -2993,28 +3856,23 @@ B0's own choices, each checked by the rows of *How it is checked* below: - Who may review a change, and the review verb's grant: issue 1782, outside milestone G; no part reads a review line meanwhile, and the verb, if built, gates nothing (ADR 0659 §2, §3). -- **A session's merge of a recovery fix.** The operator asked that a session merge a recovery fix through a verb of - the seat `mesh-delivery`, recorded in the gate like any merge and said as an event, with no Approve (1921's note of - 2026-11-07; the instruction the operator approved on 2026-11-09 says the session uses that verb once the seat serves - it). No record decides a merge without the operator's Approve: ADR 0421 §1 and ADR 0398 §3 ask it for every merge, - and the forge's merge tool merges only a head the operator approved (ADR 0534 §4). The shape this design would give - it, once a record decides it: the verb `merge` of the seat `mesh-delivery`, taking the pull requests at their heads - and the reason; callable only by the callers the gate's trusted config value `recovery-callers` names; refusing a - change that adds or widens an acting rule, a grant or a credential, which ADR 0656 §8 has named to the operator in - the Approve ask and which a recovery merge has none of; opening a delivery record marked `recovery` with the caller - as the runtime proves it; and saying the event `recovery-merged`, which the teller tells the operator on every - channel, so a recovery merge cannot go untold. It waits for its own record; until that record is accepted it is not - built, and a recovery fix is asked the operator's Approve like any change. +- **A session's merge of a recovery fix** is decided: an ordinary merge through its pipeline, named a recovery by its + author (ADR 0666 §26; *A recovery fix is an ordinary merge*). The verb this design sketched for it is not built. +- **How the runner knows a review's caller is the commit's author.** ADR 0666 §22 refuses a review from the commit's + author; the forge names the author by its forge account and the runtime proves the caller's bus account, and no + record binds the two. Until one does, code review is never a `required` step: `register` and `policy` refuse it + (*A module's registration*); issue 1966 tracks it (note 157). - What a process started by a node-engine that hands no fingerprint does beyond saying `own build unknown`, for a part other than the indexer. - The caps' and the growth's numbers are estimates (*Two graphs, one source of truth*); the fill tools read the real ones once milestone G runs, and a cap is changed in its manifest. -- Whether the builder should hold a seat of its own, so that its waits are a seat's events like the other holders': - a later proposal. +- Whether the builder's waits move onto its seat `mesh-builds`, which from milestone G says `package-published`, so + that they are a seat's events like the other holders': a later proposal. - Which manifest grants the node agent the call of a restored part's catch-up tool (noted on issue 1921). -- How long the checker's stream `checks` keeps its events (*A try*, above). -- Who is granted `checker_try` and the take-in hand tools: the operator's grants, outside this design. +- How long the checker's stream `checks` keeps its events (*A try*, above), until it goes with the checker at milestone + G's delivery. +- Who is granted the take-in hand tools: the operator's grants, outside this design. - A web view of deliveries beyond the pull request's comment. - Whether `mesh/delivery-group` is required on the trunks: the operator's setting, through the forge module's protection tool. @@ -3071,6 +3929,33 @@ indexer's `modules` reads the catalog half in milestone G (*The revision view*, 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. +The amendment for research 086's graduation (2026-11-10) writes ADR 0666 and ADR 0667 into this design: *Pipelines +per module* whole (registrations, watched branches and the catalog graph per branch, the pipeline steps and the policy, +what holds a delivery, approval as a step and a session's merge through `merge-pull` judged on the runs at the head's +fingerprint, groups, the six kinds of edge between artifacts, a publish that rebuilds, values of any size, the pipeline +making the check, callers per verb, health, the recovery fix, the tools, the runner's kept data and the build capacity, +and how milestone G itself is delivered), a line in every section the pipelines replace, and tests 63 to 100. It folds +in what milestone G's prepare left for the joint amendment: the events `milestone-asked`, `milestone-withdrawn`, +`milestone-answered` and `record-opened` as built, `assignments-changed` for the seat's event, the size of the bridge's +`performed` fixed by its template, the seat `git`'s `merging` and `not-found`, `acts` a list with none on `node-backup`, +the gate's `source` per watched branch with `source-moved`, a superseded pipeline's asks dropped by `drop`, +`kept-artifact` an edge of the sixth kind (the operator kept six), and a provider counted healthy by the build it runs, +whatever a newer want of it waits for (issue 1966, note 150). Its review by architectural domain ran in three rounds, +the four reviewers side by side, fix-1965 ruling on every finding and the records' wording staged to match: + +| Round | Domain | Found | Answered by | +|---|---|---|---| +| 1 | seams and tools | foundation parts' kept data in templates; `merge-pull` calling the runner; no way to ask the seed again; `step-ended` with no node; no store for step outputs; `branch-moved` lost while the bridge is down; tools missing for callers, refusals, the source and every store's fill | old sections, the runner a foundation part and the gate not; `failed-steps` heard from `step-ended`; `indexer_seed_again`; the node in the subject; `step-outputs`; the seat's stream; `grants_callers`, `grants_why_refused`, `gate_source`, `gate_source_again` and fill in every read | +| 1 | health and events | a group's wants on a member's end; approval end states; a failed head unsaid; `pipeline-stands` never cleared for a head; an ask's `about`; what a session hears; the runner's health; the backup's keep | `group-ended` alone; `declined` and `superseded`; `pipeline-failed`, the author's then the operator's; cleared by `pipeline-started`; the module and branch; the runner's events then `delivered`; its health check; 90 days | +| 1 | security and upgrade | sent objects readable by anyone; the new `merge-pull` before the new assigner; the checker removed at once; `widens` computed by the change; a review gating while its author cannot be told; a missing `callers`; "own" pull requests; only the latest run judged; `run` open to all | readable by their recipients; the assigner's edge by `needs`; removal after a first end-to-end pipeline and a tested backup; computed by the running runner over every part serving a step; code review never `required` until a record binds the accounts; holder roles and the operator only; any proved session; any run at the fingerprint; sessions and the operator | +| 1 | running and testing | stores sized without publish rebuilds; the build capacity unmeasured; no test counts; pipelines keyed by commit; supersede on any commit; a build seat restarted mid-step; test 74 a review | re-estimated at about 300 pipelines a day; the checker's kept verdicts carried in, supersede per publish, a live measure; counts in `step-ended` and the budget named; keyed by source revision; only on a changed fingerprint; finished from its work queue and compare-and-set; live, from the check's record | +| 2 | seams and tools | the bus module's path unchecked; the checker on the foundation list; a failed step that a rerun passed still refusing | the manifest validator's cases; it leaves the list, the runner joins; a passing rerun clears it | +| 2 | security and upgrade | the new assigner and `merge-pull` switching apart; a branch that lost its protection; sent objects granted per object; the object store rebuilding every module | one switch fact, the first `registration-changed`; `branch-unprotected`; a standing grant from the manifests; a small mesh-sdk package | +| 2 | health and events, running and testing | approved | — | +| 3 | seams and tools | who may clear a failed step | `step-ended` says a rerun and its proved caller, and only the operator's or a healer's clears | +| 3 | security and upgrade | (with the last fix) how a fix lands before the first registrations | the operator merges it on the forge under the trunk-only want, and `indexer_seed_again` asks again | +| 3 | all four | approved | — | + 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 the catch-up call; the hold's bound while a large backup is taken; the granting and placing bound read from the first diff --git a/03-DESIGN/01-to-be/51-the-registries-keep-what-is-named.md b/03-DESIGN/01-to-be/51-the-registries-keep-what-is-named.md index 4e239566..04d82315 100644 --- a/03-DESIGN/01-to-be/51-the-registries-keep-what-is-named.md +++ b/03-DESIGN/01-to-be/51-the-registries-keep-what-is-named.md @@ -6,13 +6,15 @@ code: - mesh-catalog modules/artifact-store-tools (the store's tools), modules/distribution (its program, holding the two image seats) - mesh-catalog modules/gitea (package retention; the two package seats' verbs in its Go bundle) - mesh-catalog modules/mesh-build-go, modules/mesh-build-node, modules/mesh-build-image (publishing through the seats) - - mesh-delivery modules/mesh-delivery-builder (versions, tag asks), the forge bridge, the indexer, the checker, the assigner + - mesh-delivery modules/mesh-delivery-builder (versions, tag asks; from milestone G a package numbered at its publication, the seat `mesh-builds`), the forge bridge, the indexer, the checker, the assigner, modules/mesh-delivery-pipeline (`tag-wanted` from milestone G) - mesh-sdk (the bus helper for sending in parts) - mesh-catalog modules/docker (image pruning) - mesh-host internal/apply (every new image of a module pulled before any of its containers is replaced; a failed pull applied again on the status view's `settled` for the store's holder, and at the node-engine's start), internal/compose (each routed image reference written with its seat and that seat's holder) - mesh-delivery modules/mesh-grants (what a node-engine hears: the status view's `settled`) -updated: 2026-11-04 +updated: 2026-11-10 decisions: + - "ADR 0667" + - "ADR 0666" - "ADR 0605" - "ADR 0612" - "ADR 0614" @@ -160,7 +162,8 @@ the verb. entry turns `published` and the builder writes the done key then, so a late store is never lost. - **What is published when**: a package or an image from a trunk build under its version, or as a tagged version; a bundle or an archive from every done key by its digest alone, a candidate's included, and at the trunk's claim the - build module calls `publish` with the version and the held digest, which stores nothing. An upstream image is copied + build module calls `publish` with the version and the held digest, which stores nothing. From the delivery of design + 47's milestone G a package's version is given at its publication instead (*The versions*). An upstream image is copied by `mirror` with its pinned digest. - **The done key names the reference the seat answered**, in ADR 0605 §9's form from this milestone on: `//@sha256:` for an image, bundle, archive or upstream copy and @@ -263,7 +266,26 @@ the verb. ### The versions -- **The builder numbers every trunk build** of a package, image, bundle or archive at its claim: the package series +- **From the delivery of design 47's milestone G, a package is numbered when it is published** (ADR 0666 §15). The + builder numbers a package's version at its publication, never only when its build is claimed: a package's trunk + build is claimed with no number and built by its digest, and once its build is done the builder gives it the next + count of its series, under compare-and-set, and says `numbered`, on which the build module calls `publish` with + the version and the held digest, as below for a floor not yet known. A build of an older source revision of the + same watched branch than one already numbered for that name is not numbered and publishes nothing, so a version never + names older content than the one below it. When the holder says `published`, the builder says the publication as the + event `package-published` of its seat `mesh-builds` (the name, the version, the fingerprint, the commit, the watched + branch). On it every artifact with a "published before it builds" edge to the package is rebuilt against the new + version, and the pipeline runner, which consumes the event, starts its pipeline (design 47, *A publish rebuilds*); + nothing else is rebuilt, and a change to a package's tests alone publishes nothing. This removes the claim's wait + for earlier merges' numbers below, which held a group on 2026-11-09 (research 086, Findings). Why at publication: a + number given at the claim must wait for every earlier merge's number, and a build that never publishes keeps a + number nothing holds. An image, bundle or archive keeps the rule below. How it is checked: in the builder's + whole-module test a package's trunk build is numbered only once built, an older revision's build after a newer one + publishes nothing, `package-published` is said once per publication, and only the importing artifacts rebuild + (design 47, test 80). +- **A build that cannot read the published packages refuses**, naming the unread state, never building against a guess + (ADR 0666 §15; design 47, test 70). +- **Until that delivery, the builder numbers every trunk build** of a package, image, bundle or archive at its claim: the package series its manifest declares (design 32; `0.1` when it declares none) and the next count for that name, under compare-and-set. Numbers follow the order of the forge bridge's merge events: a claim of a later merge waits until every earlier merge of the same name whose fingerprint the indexer still holds is numbered (a fingerprint replaced @@ -318,7 +340,11 @@ the verb. - **Asked by an event, never by a push** (ADR 0610 §1). The checker emits `tag-wanted` (repository, branch, head, tag), on a family of its own, `checker.asks`, kept seven days, apart from its verdicts, so a waiter on a verdict does - not wake on it, for each head of a delivery group member that declares a package; a person asks through `builder_tag`. The + not wake on it, for each head of a delivery group member that declares a package; a person asks through `builder_tag`. + From the delivery of design 47's milestone G the checker goes, and the pipeline runner says `tag-wanted` instead, on + its own seat `mesh-pipeline-runner`, for each member that declares a package of a run on request of a group not yet + merged (ADR 0666 §18): a group merged together is one source revision whose packages are published before its + dependents build, so only a run on request needs a tagged version. The builder consumes the event on a durable consumer and keeps the ask in its own state `tag-asks`, removed when its branch is merged or deleted, or its pull request closed. An ask the builder has not answered within five minutes is narrated in the build log with what it waits on. @@ -326,7 +352,9 @@ the verb. and Go's `@latest` skips it. A package new in a group is numbered from its floor (`0.1.0-feat-x.1`). - **A group's check builds after `published`**: Go members by the tagged version, TypeScript members with their lock naming it and the registry's integrity; nothing is packed for a check, and a lone pull request's check publishes - nothing. No `published` within the publish's bound (10 minutes) fails the check naming the package. + nothing. No `published` within the publish's bound (10 minutes) fails the check naming the package. From the + delivery of design 47's milestone G the same holds for a group's run on request, whose pipeline steps build after + `published`, and a step that gets no `published` within the bound ends failed, naming the package. - **Removed with its branch**: on the forge bridge's `merged` event, its pull `closed`, or its branch-deleted event, heard on a durable consumer, the builder calls each seat's `remove`. It acknowledges the event only once every seat emitted `removed`; until then it retries