Compare commits

...
Author SHA1 Message Date
jschoubben f67c788c82 Merge pull request 'Design 47 G: the lead's answers A-353 to A-362 (G's start)' (#608) from design/47-G-lead-answers-30 into main
Reviewed-on: #608
2026-11-13 19:08:20 +00:00
jschoubben 4fd3612c56 Answer A-361 and A-362: call words obey the cycle rule; the start seat list holds mesh-delivery
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 17:44:13 +01:00
jschoubben 8531306165 Answer A-360: the indexer says each change of modules on its views family
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 17:31:03 +01:00
jschoubben b0d52a1119 Answer A-359: the gate's start path passes the four seat verbs alone
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 17:27:52 +01:00
jschoubben 14acd2b593 Answer A-353 to A-358: G's start breaks the runner's own wait, grants keeps its modules read, the SDK declares the verbs it calls
Found after G's merge: a G tool runner waits on itself, grants freezes once
G's indexer runs, the watchman does not build, gitea needs G's build runtime,
and the graph ordered the tool runner first because the SDK's calls were undeclared.

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 17:25:39 +01:00
mesh-tools 2b39e39385 Merge pull request 'Playbook 07: hold a delivery-system release's push on a dry run with no item open' (#607) from playbook/07-dry-run-delivery into main 2026-11-13 13:49:14 +00:00
jschoubben 010a93d6bc Hold a delivery-system release's push on a dry run with no item open
mesh/delivery merged: source.main moved to novox/hq@2b39e39385b6
mesh/check checking 010a93d6bc69 on 2b39e39385b6
Milestone G was pushed with its dry run's take-in item still open; once
merged, the running indexer refused G's own indexer with the live seat
list, and its trunk builds waited on renamed packages only the take-in
publishes. Playbook 07 gains step 2b: the live take-in run whole, every
build against the published packages, the gate's merge path read for the
group, and a dry run with an open item is not a pass. The glossary gains
"dry run"; the playbooks page lists the step.

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 14:26:22 +01:00
mesh-tools 0bbcf98baa Merge pull request 'Design 47 G: A-352, a bus module's running build counts while its newer build waits for the operator's yes' (#606) from design/47-G-lead-answers-29 into main 2026-11-13 12:10:51 +00:00
jschoubben 328ca1b320 Answer A-352: a bus module's running build counts while its newer build waits for the operator's yes
mesh/delivery merged: source.main moved to novox/hq@0bbcf98baa96
mesh/check checking 328ca1b32047 on 0bbcf98baa96
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 13:09:39 +01:00
mesh-tools 67960e12ba Merge pull request 'Design 47 G: A-350, the catalog's fill starts above every number the builder gave' (#605) from design/47-G-lead-answers-29 into main 2026-11-13 12:09:15 +00:00
jschoubben 258de07806 Answer A-351: the filled edges count the builder's numbers too; no digest where the builder kept none
mesh/delivery merged: source.main moved to novox/hq@67960e12ba4f
mesh/check being carried to 258de078064c on 67960e12ba4f | from aed903059436
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 13:05:30 +01:00
jschoubben 5dee91703f Answer A-350: the catalog's fill starts above every number the builder gave, published or not
mesh/delivery closed: a newer head of the same pull request
mesh/check checking 5dee91703f2e on aed903059436
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 13:02:51 +01:00
mesh-tools aed9030594 Merge pull request 'Design 47 G: A-349, the pipeline runner's old forms accepted before G' (#604) from design/47-G-lead-answers-28 into main 2026-11-13 11:03:20 +00:00
jschoubben ca86c2d8e7 Answer A-349: the pipeline runner's old forms are accepted before G, as §529 names it
mesh/delivery merged: source.main moved to novox/hq@aed903059436
mesh/check being carried to ca86c2d8e7b7 on aed903059436 | from afdb26b05706
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 11:46:29 +01:00
mesh-tools afdb26b057 Merge pull request 'Design 47 G: A-343 to A-348, the third reader release before G' (#603) from design/47-G-lead-answers-28 into main 2026-11-13 10:45:27 +00:00
jschoubben 96307d5f56 Answer A-343 to A-348: the third reader release before G, its scope and its checks
mesh/delivery merged: source.main moved to novox/hq@afdb26b05706
mesh/check being carried to 96307d5f56fe on afdb26b05706 | from dc76022e04b8
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 11:34:39 +01:00
mesh-tools dc76022e04 Merge pull request 'Design 47 G: the lead's answers A-339 to A-342, met merging the zfs group into G' (#602) from design/47-G-lead-answers-27 into main 2026-11-13 08:54:30 +00:00
jschoubben 14b5b324a2 Answer A-342: the node-engine sets MESH_NODE for every process it runs
mesh/delivery merged: source.main moved to novox/hq@dc76022e04b8
mesh/check pass 14b5b324a258 on a7004d5e2ad8 | unit 43 run, 0 kept, 1 skipped | integration 43 run, 0 kept, 1 skipped | composition passed in 61s on 2…
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 09:17:36 +01:00
jschoubben 253c18c693 Answer A-341: a zfs device's finding in the writer's key form
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 09:16:08 +01:00
jschoubben 20a04f0226 Answer A-340: a process's bus may name what its module consumes; the writer's three events
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 09:10:36 +01:00
jschoubben 325bf80f19 Answer A-339: zfs's findings take G's writer over its keeper
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 09:08:48 +01:00
mesh-tools a7004d5e2a Merge pull request 'Design 47 G: the lead's answers A-323 to A-334, from the dry run of G on itself' (#601) from design/47-G-lead-answers-26 into main 2026-11-13 08:00:18 +00:00
jschoubben ed8b3bbd98 Answer A-338: f1-circuits' cache and Link2Pay's logs are class cache
mesh/delivery merged: source.main moved to novox/hq@a7004d5e2ad8
mesh/check pass ed8b3bbd98e7 on bba961f9fd86 | unit 43 run, 0 kept, 1 skipped | integration 43 run, 0 kept, 1 skipped | composition passed in 68s on 4…
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 08:52:09 +01:00
jschoubben 50c4980a49 A-337: the glossary's word, the manifest validator
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 02:47:38 +01:00
jschoubben b216d914f7 Answer A-337: the judge counts and finds declarers over the whole trunk case
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 02:47:09 +01:00
jschoubben e7e3691799 A-336 holds for every start of a pipeline, not only a take-in
mesh/delivery closed: a newer head of the same pull request
mesh/check pass e7e369179944 on bba961f9fd86 | unit 43 run, 0 kept, 1 skipped | integration 43 run, 0 kept, 1 skipped | composition passed in 66s on 4…
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 02:42:06 +01:00
jschoubben cbd32e3fa4 Answer A-336: a take-in heard before its branch's half starts with no steps
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 02:35:19 +01:00
jschoubben 712eca24ad Answer A-335: the ten repositories still on version 1 join G's form (the operator's yes)
mesh/delivery closed: a newer head of the same pull request
mesh/check pass 712eca24ad12 on bba961f9fd86 | unit 43 run, 0 kept, 1 skipped | integration 43 run, 0 kept, 1 skipped | composition passed in 69s on 4…
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 02:27:56 +01:00
mesh-tools bba961f9fd Merge pull request 'Design 42 zfs-owns-zfs: the lead's answers A-30 to A-45 met in develop and review (issue 1979)' (#600) from design/42-zfs-answers-2 into main 2026-11-13 01:27:30 +00:00
jschoubben 4a466efcac A-329, A-333: the glossary's word catalog
mesh/delivery closed: a newer head of the same pull request
mesh/check being carried to 4a466efcac84 on bba961f9fd86 | from a5eae7aa0a68
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 02:18:35 +01:00
jschoubben 5df4fb0ff6 Answer A-334: in a group take-in the changed runner is wanted on its own pass, first
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 02:12:58 +01:00
jschoubben e4145affa2 Answer A-333: package-only cycles and delivery edges into packages are not refused
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 02:06:52 +01:00
jschoubben 7c13ee5682 Answer A-332: a kind-4 edge keeps its first-process-resource source
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 02:02:20 +01:00
jschoubben f9f78f8f36 Answer A-331: a cycle across steps is a cycle; amends 272 as A-323 built it
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 01:58:42 +01:00
jschoubben 9fa132e393 Answer A-330: the acting-cycle finding; the node-engine's want is held by no acting edge, other rules stand
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 01:53:08 +01:00
jschoubben 04e259524f Answer A-329: the seed's left-out module raises seed-left-out until a seat builds it
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 01:49:50 +01:00
jschoubben a60e04ed47 Answer A-326 to A-328: the build-input cycle is allowed, a late registration places its pipelines, the runner's own pipeline is never held
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 01:49:27 +01:00
jschoubben 6f417f30e7 Correct A-324 as A-325: a bypassed step is still placed and said
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 01:49:07 +01:00
jschoubben 75149fb5f3 Answer A-324: an archive or upstream artifact has its steps bypassed; a module no seat builds is left out of the seed by name
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 01:48:25 +01:00
jschoubben 87fdd04e81 Answer A-323: the assigner and the node-engine are one step, the node-engine's want first
Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
2026-11-13 01:44:49 +01:00
4 changed files with 244 additions and 6 deletions
+6
View File
@@ -696,6 +696,12 @@ controller (the planner, the rollout) until release 6 of ADR 0429; from each rel
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). 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.
- **dry run** — a session's run, before a release is pushed, of the parts that will take it in, build it and merge it,
as they run live, on the revision as the merge will make it: in process on the session's machine, reading the mesh
and writing nothing there. It holds four items: the live take-in run whole with the seat list it will read, every
build against the packages as published, the gate's merge path read for the group, and no item left open (hq
playbook 07, step 2b). Not a **try** nor a **run on request**, which the mesh runs and which deliver a verdict; a dry
run owes the forge nothing and is not a check.
- **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). Goes at milestone G's delivery with the merge check: a pipeline
+74 -2
View File
@@ -62,13 +62,18 @@ A small fix (one repository, one issue, about an hour of work) follows
take, or assuming a part already built that was not. The prepare had read the design alone. It now reads the code
each design line lands in as well, and lists every place where the two disagree before any developer starts
(step 0, items 3 and 10; the operator, 2026-11-11).
- **A dry run with an open item, taken as a pass.** On 2026-11-13 milestone G of design 47 was pushed with its dry
run's item "the take-in's seat path is not run" still open; once merged, the running indexer refused the milestone's
own indexer and five more modules with the live seat list, and its trunk builds waited on renamed packages only the
take-in would publish. The dry run (step 2b) now runs the live take-in, the builds against what is published and the
gate's merge path, and holds the push while any item is open.
- **A module proven only after it reached the machines.** The mail modules were delivered with unit tests
only, then failed live three times (issues 859, 865, 868) and took five more hours of fixes.
## The shape
One feature is **one branch name**, **one worktree per repository**, **one pull request per repository**,
opened **once**, after the review, and **one check** (ADR 0548). It runs in five steps, with the design completed between the first two (step 0b), and its time is bounded. A milestone has no phases
opened **once**, after the review, and **one check** (ADR 0548). It runs in five steps, with the design completed between the first two (step 0b) and, for a change of what judges, builds or merges it, a dry run between the review and the check (step 2b), and its time is bounded. A milestone has no phases
(the operator, 2026-10-17): these are its steps, and a report names the step it is in:
| Step | What happens | Bound |
@@ -77,6 +82,7 @@ opened **once**, after the review, and **one check** (ADR 0548). It runs in five
| 0b. Design complete | every design question and every place where design and code disagree is answered: by the lead in one line against the principles, or, where no principle settles it, by the operator or `hq-design-writer` (step 0); each answer is written down (the lead's in the milestone's lead-answers file, the others into the milestone part, playbook 02) and its build map rows added | until the list is empty: develop never starts before |
| 1. Develop | one fixing agent per repository builds every design line of its build map locally, each commit citing the lines it builds, the whole unit suite before every commit, the integration tests compiled, and once per head it reports those of the packages it touched and their importers run against an embedded bus (below); nothing is pushed | the milestone's issues, 30 minutes each |
| 2. Review | one reviewer reads all of it, the local commits, judging the integration tests by reading them against the code; reports go both ways; at most 3 rounds | 15 minutes |
| 2b. Dry run | for a release that changes a part judging a change, or a module path, a package or a manifest form the take-in reads: the live take-in run whole with the seat list it will read, every build against the packages as published, the gate's merge path read for the group, and no item left open | until no item is open: nothing is pushed before |
| 3. Check | push the reviewed heads once and open the pull requests together; the checker's one check runs the integration tests; no further review unless the check fails | one check run |
| 4. Deliver | merge; the source revision moves, each module is built once and wanted on its nodes, its canary first | until the view says the source revision `delivered` |
@@ -505,10 +511,74 @@ an answer no hq commit holds, is a finding of the review (step 2, item 2a).
in the design. How it is checked: the review report has a line for each question with its answer, and the lead reads both before the
push; a report without them is not an approval.
## Step 2b — Dry run (a change of the delivery system, or of what the take-in reads)
**When it runs.** After the review approves the heads and before the push of step 3, for every release that changes a
part judging a change (step 3, item 3: the indexer and its manifest validator, the gate, the builder, a build module,
the checker or the pipeline runner, the node-engine, a seat definition), and for every release that adds or renames a
module path or a package other modules take, or changes the form of manifests the take-in reads. The prepare step's
milestone file says per release whether it runs and why (`Dry run: yes` or `no`, with the reason); the review refuses a
group that lists a judging part with no such line. The operator, 2026-11-13: "remember the mistake and make sure our
pipeline catches this".
**What it is.** A dry run runs the parts that will take the change in, build it and merge it, as they run live, on the
revision as the merge will make it: in process on the session's machine, reading the mesh and writing nothing there,
asking no try and no check. An agent of hq's definitions runs it, read-only on the mesh and on every working copy; the
lead writes only the handover. Everything live it uses (the builds the nodes run, the seat list, the published
versions, the trunks) is read in the same hour as the push, and read again, with the dry run run again, when a head,
a main or a live build moves before the push. Four items, each held before any push:
1. **The live take-in, run whole.** The indexer that will take the revision in (the running one, read from the view's
reach of its module; for a revision that names another build of the indexer, the running one, which keeps it
pending, and the named one, from its start) runs on the revision: every member's head merged onto its base's main as
it is now, the other trunks' manifests as the indexer's state holds them, and **the seat list as the take-in will
read it**, which is the seat list the seat `mesh-catalog`'s verb `seat-definitions` answers at that moment, not the
group's own definitions laid over it (step 1's brief lays them over for the developer's case; the take-in does not).
It runs through to the keys the take-in would write (each fingerprint, a pending revision, a group's members
gathered), never the manifest validator alone. A manifest refused, a module set aside, or a revision left pending
with no indexer that can take it in is a fault of the release: it is fixed in the release, or what the running parts
cannot take in is delivered first (step 3, item 3), before the push.
2. **Every build against the packages as published.** Every build the revision starts (each module whose fingerprint it
moves, as the indexer's run of item 1 lists them) is built with `GOWORK=off` and no `replace` toward a local tree,
each mesh package resolved from the registry seat of its language as that seat serves it at that moment (its verb
`versions`), never from the group's heads. A new or renamed module path, or a package that only the revision's own
take-in or build would publish, shows here as a package with no published version: a circle in which the build
waits on a take-in that waits on the build. It is a gap of the build and delivery system, built there before the
push (in the same milestone or before it) and said to the operator, never pushed into.
3. **The gate's merge path, read for the group.** Before the push, and again before the operator's Approve is asked:
each member's base, read with `mesh-delivery.show` (the gate never hands a member whose base is not the branch it
merges into, and every member after it in the gate's order waits behind it); the group itself, read with
`mesh-delivery.show` on the group's id, open and holding every member (a pull request reopened into a group the gate
holds closed joins it as a lone delivery); and every member present before the first ask. The gate merges a group's
members one at a time and undoes none, so one member it cannot merge leaves the group half merged. A member on
another base is moved to the gate's branch or left out of the group, a group the gate holds closed is pushed under a
new branch name, and an Approve ask that names fewer members than the group is ended and said to the operator,
never answered.
4. **No item open.** The dry run's report says of each item what ran, at which heads and on which live builds, and its
counts ("ran: 193 manifests, 0 refused, seat list read at 13:05"). An item said "not run", "not known" or "read, not
run" is closed, by running it or by showing why it does not apply, or the push is held: **a dry run with an open
item is not a pass**, and no rule is weighed against it. Before the push the lead says to the operator, in one line
per item, what each showed.
The faults it answers, 2026-11-13: milestone G of design 47 was pushed after two dry runs, the second of which said
"with the live seat list 26 refused; the take-in's seat path is not run", and the lead pushed with that item open.
Once merged, the running indexer took the revision in with the live seat list and refused the milestone's own indexer
and five more modules. The milestone renamed module paths, and the trunk builds waited for packages that only the
take-in publishes; no dry run had built a trunk module against the published packages alone. The same day the gate
merged a group one member at a time with no undo, stopped at a member whose base was not main, and asked an Approve
while a group was still forming and per member of a closed group.
**How it is checked.** The milestone file holds a section `Dry run` with each item's result, the reviewed heads it ran
on and its time (`grep -n -A6 '^## Dry run' .work/<slug>/milestone.md`), older than the push (the forge branch's
first push of the heads) and with no item open; the pull requests' description names it in one line. A push of a
release whose milestone file lists a judging part with no such section, or with an item open, is this step skipped;
a fault met after the merge that an item would have shown is named at the next report and written here as a lesson.
## Step 3 — Check (no review)
1. **Push the reviewed heads once, then open one pull request per repository, together** (ADR 0548; the operator,
2026-10-26: "every release should only run 1 check or 1 try"). **No pull request, draft or not, exists before the
2026-10-26: "every release should only run 1 check or 1 try"), after the dry run where step 2b asks one, with no
item open. **No pull request, draft or not, exists before the
review approves the heads**, and no fix round is pushed to an open pull request: every push to an open pull request
asks a new check, of every member for a group, and the mesh's build capacity is spent on it ("we don't have more
processing power"). The integration tests run once, in the checker's merge check on the merge with the trunk's head, at the unit
@@ -873,6 +943,8 @@ issues in `fixing` that nobody works on reads to the operator as stuck work.
item 6b). A fixing agent started on a file without the section, or an effect of a removed or moved part met only
after the delivery, is the prepare step skipped, named in the next detailed report and written into the playbook's
lessons here.
- A release whose milestone file lists a part judging a change holds a `Dry run` section with all four items closed,
older than its push (step 2b); one pushed without it, or with an item open, is that step skipped.
- No issue of a running milestone is sized over an hour in its prepare note; an issue whose fixing agent passes
twice its bound was not split.
- Every issue of a running milestone has a note from the prepare step naming its files and tests (file:line), how
+3 -3
View File
@@ -476,11 +476,11 @@ const P = [
{n:"07",name:"Features",kind:"build",c:"--build",
trig:"Work that changes code across issues or repositories, too large for a small fix.",
who:"A lead (larger model), one fixing agent per repository (smaller), one reviewer (larger).",
steps:["Prepare: name the branch, make the worktrees, read the milestone part and the design's main file whole, then the code each design line lands in. (new)","List every place where a design line and the code disagree, beside the design questions. (new)","Every agent is one of hq's definitions (mesh-preparer, mesh-developer, mesh-code-reviewer, mesh-watcher); the lead writes only the handover. (new)","The prepare's only output: a build map per repository, each row a design line and where it lands, and the design questions. No rulings. (new)","Design complete: the lead answers every question against the principles; one no principle settles goes to the operator or the design writer; then develop. (new)","Read what exists today from the code and the live mesh: every effect of what is removed or moved, every reader of each, what happens to each and its test. No code before it is complete; the review refuses work without it. (new)","The build map opens with what exists today; subtasks ordered contract first, one writer per file.","Write the findings and acceptance criteria into each issue.","Survey every other reader and writer of each changed value. (new)","Answer three questions in the milestone file: who deletes each new key and stream, how the switch-over is tried on one node first, what the one check does not cover. The review checks them. (new)","List every part the change reaches; copy fixtures from the real writer.","Develop: one agent per repository, one commit per subtask, each citing its design lines; a question stops only its subtask. (new)","A test fails first on behaviour, not on compiling. (new)","Bring each branch up to the trunk; nothing is pushed, no try runs. (new)","Review all of it against the design lines, code no line asks for a finding, reading the integration tests against the code; at most 3 rounds; the report answers the state-and-seams and mesh-agnostic questions. (new)","A group pins the group's own mesh-sdk head in every member. (new)","Push the reviewed heads once and read each forge head against the reviewed commit; no draft pull request, no fix round on an open one. (new)","Open one pull request per repository, together, with Reviewed-by and Pushed-by; the one check runs. A failed check is read, fixed, reviewed, pushed once more. (new)","The operator's Approve on Telegram; the group merges in one pass.","Follow the delivery in the status view (moving, settled, stuck, delivered) to done; resolve the issues; clean up. (new)","When the builder cannot deliver its own fix: revert, a build by a session's call, a registration at the terminal, copies kept outside the store; a broken controller is put back by a want the operator writes, a hand build by mesh-hand-compose and a want. (new)"],
steps:["Prepare: name the branch, make the worktrees, read the milestone part and the design's main file whole, then the code each design line lands in. (new)","List every place where a design line and the code disagree, beside the design questions. (new)","Every agent is one of hq's definitions (mesh-preparer, mesh-developer, mesh-code-reviewer, mesh-watcher); the lead writes only the handover. (new)","The prepare's only output: a build map per repository, each row a design line and where it lands, and the design questions. No rulings. (new)","Design complete: the lead answers every question against the principles; one no principle settles goes to the operator or the design writer; then develop. (new)","Read what exists today from the code and the live mesh: every effect of what is removed or moved, every reader of each, what happens to each and its test. No code before it is complete; the review refuses work without it. (new)","The build map opens with what exists today; subtasks ordered contract first, one writer per file.","Write the findings and acceptance criteria into each issue.","Survey every other reader and writer of each changed value. (new)","Answer three questions in the milestone file: who deletes each new key and stream, how the switch-over is tried on one node first, what the one check does not cover. The review checks them. (new)","List every part the change reaches; copy fixtures from the real writer.","Develop: one agent per repository, one commit per subtask, each citing its design lines; a question stops only its subtask. (new)","A test fails first on behaviour, not on compiling. (new)","Bring each branch up to the trunk; nothing is pushed, no try runs. (new)","Review all of it against the design lines, code no line asks for a finding, reading the integration tests against the code; at most 3 rounds; the report answers the state-and-seams and mesh-agnostic questions. (new)","Dry run, for a change of what judges, builds or merges it: the live take-in run whole with the seat list it will read, every build against the packages as published, the gate's merge path read for the group; an item left open holds the push. (new)","A group pins the group's own mesh-sdk head in every member. (new)","Push the reviewed heads once and read each forge head against the reviewed commit; no draft pull request, no fix round on an open one. (new)","Open one pull request per repository, together, with Reviewed-by and Pushed-by; the one check runs. A failed check is read, fixed, reviewed, pushed once more. (new)","The operator's Approve on Telegram; the group merges in one pass.","Follow the delivery in the status view (moving, settled, stuck, delivered) to done; resolve the issues; clean up. (new)","When the builder cannot deliver its own fix: revert, a build by a session's call, a registration at the terminal, copies kept outside the store; a broken controller is put back by a want the operator writes, a hand build by mesh-hand-compose and a want. (new)"],
prod:"One pull request per repository, one source revision delivered, resolved issues, no branch or worktree left.",
next:"02 (when it ships)",bounds:"Prepare 15 min · 30 min per issue · review 15 min, ≤ 3 rounds · one check, pushed once",
prev:["Pull requests as scratchpads","Context bought again and again","A change built on what was remembered, not on what runs","Review rounds spent on what a run would show","A node agent's bus reads, proven only by review"],
check:"The checker's one status, mesh/check; the review record; the tracker's move."},
prev:["Pull requests as scratchpads","Context bought again and again","A change built on what was remembered, not on what runs","Review rounds spent on what a run would show","A node agent's bus reads, proven only by review","A dry run with an open item, taken as a pass"],
check:"The checker's one status, mesh/check; the review record; the dry run's section in the milestone file; the tracker's move."},
{n:"08",name:"Small fixes",kind:"build",c:"--build",
trig:"One issue in one repository, about an hour of work.",
who:"The session, with one reviewer on the larger model.",
@@ -3,7 +3,7 @@ layer: to-be
status: in-progress
design: 47
milestone: G
updated: 2026-11-12
updated: 2026-11-13
decisions:
- "ADR 0667"
---
@@ -586,3 +586,163 @@ the principle that settles it, cited as "design 47 G A-n".
catch-all of seat events by one handler per seat it consumes; for the seat `mesh-catalog` it takes each event it
consumes except `registration-changed`, which the branches follower takes, and whatever the watchman needs of that event
it takes from the follower. The SDK's hub keeps one taker per message.
- **A-323** (§49, §268; principle 3) The assigner and the node-engine on one node are an acting cycle of delivery edges
only (compose and place), so they are delivered as one step (§49), never held by each other: the assigner writes that
node's node-engine want first, held by nothing but its build (§268), and holds the node's other wants, its own included,
until the node-engine seat says the new version runs there. The acting-wait check finds a cycle across steps as well as
within one, and a want held on a cycle it cannot break says so as a finding (found in the dry run of G on itself,
2026-11-13).
- **A-324** (§8, §535, §704, design 51; principles 3, 7) An artifact the builder packs or fetches itself, kind `archive` or
`upstream` with no language (design 51), has no lint, unit or integration step to ask: the seed and the runner call no
build seat's `steps` for it, its registration carries those steps as `bypass` (§8's reason), and the runner places no
bypassed step. An artifact that names a language or kind no build seat serves stays a failure as §535 says, naming the
artifact, in the seed as in the runner: the seed leaves that one module out with a finding naming it, never the whole
seed.
- **A-325** (corrects A-324's runner half; §23, §28; principle 3) The runner places a bypassed step as §23 and §28 say:
outcome `bypassed`, asked of no one, said. For an artifact of kind `archive` or `upstream` with no language, its lint,
unit and integration steps are `bypass` whatever its policy says, so no build seat is asked for them; every other step
keeps its policy.
- **A-326** (§47, §49, §51, §270, ADR 0614 §6; principles 3, 8) A cycle through a build module's own inputs is not
§49's: where the build edge (kind 3) goes out of an artifact of a module that holds a build seat into an artifact it
builds, the running version builds the new one (§270), so the cycle is broken at the running version and is allowed.
Every other cycle with a build edge is refused at take-in, naming every artifact on it (§49, §51); the indexer builds
that rule in G, over the catalog graph it keeps. An edge of kind 4 names the artifact that offers the provision (its
`answered-by`), not the module's first process resource.
- **A-327** (§21, §23, §54; principles 1, 3) A pipeline started before its module has a registration is placed when the
registration arrives: the runner, on `registration-changed`, places from the registration the steps of every pipeline of
that module that has none, once each (by compare-and-set), and says it. Until then the pipeline says it waits on the
module's registration.
- **A-328** (§29, §65, §270; principle 5) A take-in that changes the runner holds every other pipeline of the take-in
until the new runner runs (§65), but never the runner's own pipeline: that one runs on the running runner, as a build
module's running version builds its successor (§270), so its pass lets the new runner be wanted (§29) and its running
releases the held ones. The bound stays only as a failure bound, with its finding.
- **A-329** (A-324, §8; principles 3, 7) The module the seed leaves out raises the indexer's finding `seed-left-out`,
scope `module`, id the module's name, naming the artifact and its language or kind, and is named in the seed's ask
beside the unprotected branches (`Left`, §8). It clears only when a later seed finds a build seat for every artifact of
it, or the module leaves the catalog; the seed being applied without it does not clear it.
- **A-330** (sharpens A-323; §268; principles 3, 8) A want the assigner holds on a cycle it cannot break raises its finding
`acting-cycle`, scope `module`, id `<node>.<module>` of the held want, naming the cycle with each edge's step; the next
pass that finds the want held on no cycle clears it. "Held by nothing but its build" means held by no acting edge: the
node-engine's want on a node (the holder of the seat `node-engine` there, read from the acting edges' seat) keeps every
other rule of a want (grant, hold, canary, composition).
- **A-331** (amends §272 by A-323; §49; principle 3) §272's "a cycle across two steps is none" no longer holds: a cycle of
acting waits across steps is a cycle (A-323), delivered as one step where it has delivery edges only (§49), and a want
held on one no rule breaks raises `acting-cycle` (A-330).
- **A-332** (withdraws A-326's last sentence; §47; principle 7) A manifest names no artifact for a provision (`answered-by`
is `helper` or unsaid), and the delivery waits cut edges down to module names, so the artifact a kind-4 edge starts from
changes no order: it stays the module's first process resource, as built, and G changes nothing there.
- **A-333** (sharpens §49 and A-326; §47; principles 3, 7) Two more cycles are not §49's. (1) A cycle of package edges
(kind 1) alone: a real import cycle is refused by the language's own build, and one found only because imports are
given to every artifact of a module is not a cycle of what is built. (2) No delivery edge (kinds 2, 4, 5, 6) ends at a
package artifact: a package is delivered only inside what uses it, which a kind-1 edge carries, so such an edge is not
made and cannot close a cycle. How it is checked: the indexer's cycle rule accepts today's trunk catalog and G's own
(the dry run's entries, kept as test data), and refuses a cycle with a build edge among delivered artifacts, naming
them.
- **A-334** (sharpens A-328; §29, §65, §268; principle 5) In a group take-in that changes the runner, the runner is the
acting part the other members wait on, so it goes first as the node-engine does (§268): its member is wanted on its own
pipeline-ended once that passed, ahead of the group. The other members keep §29: their pipelines run on the new runner
once it runs, and they are wanted together on group-ended. The bound stays a failure bound only.
- **A-335** (§368, §583; principle 5; the operator, 2026-11-13 about 02:30 CET: yes) Every module on the trunk joins G's
form, not only G's own: the ten repositories whose 24 manifests still say `"version": "1"` (mesh-media-catalog,
Link2Pay, de-spiegel, photos, okioki, car-hunter, f1-circuits, snake, txt-game, amqp-email-forwarder) are members of
G's group, each manifest's `version` written as §583 says (the `MAJOR.MINOR` of its newest published version through
`builder_versions`, `0.1` for one with none). §368's rule keeps no old form. How it is checked: G's judge accepts every
trunk manifest at G's heads (the dry run's mesh-wide read, again before the push).
- **A-336** (A-327, §200; principles 3, 7) Any start of a pipeline (a take-in, a package published) heard before its branch's catalog half is held starts its pipelines
with no steps, never with steps placed from empty entries (§200: nothing new of a branch is acted on until its half is
held); the path of A-327 places them once the half is held.
- **A-337** (§712, ADR 0579 §2; principles 3, 7) "Refusing only what the revision causes" takes the trunk case as it
stands: the manifest validator counts old sections and finds the declaring modules over every trunk-case manifest that decodes,
accepted by its own rules or not, so a trunk manifest the new rules refuse still counts and still declares. A trunk-case
manifest that does not decode is named in the verdict's report. How it is checked: G's manifest validator on G's heads against
today's unmigrated trunk refuses none of G's 169 manifests for a count or a declarer (the dry run's re-creation).
- **A-338** (A-335, ADR 0233; principle 7; the operator, 2026-11-13 about 03:50 CET: "it's a poc") The two trunk manifests
the manifest validator refuses once they change, for a written directory with no data declared, declare it in G's
change: f1-circuits' `cache` and Link2Pay's `logs`, both class `cache`.
- **A-339** (G §383, §384, §387; design 42 zfs-owns-zfs A-32, A-37, A-39, A-41; principles 1, 7) The zfs module's
findings take G's form through the bus path it already has: its keeper's closed list gains exactly what G's generated
findings writer needs (the publish of `finding-written` on its stream `zfs-findings`, and a hear of
`mesh-conditions.findings-asked`), and the root follower runs G's writer over the keeper; its manifest gains the
`finding-events` stream and that `consumes`. The follower keeps writing its findings, since it is the part that sees
them; nothing else of the keeper's list widens.
- **A-340** (sharpens A-339; design 42's V5 and G1; principle 7) A process's `bus` may name, under `consumes`, an event its
module's `consumes` names, as V5 lets it name what its module's `requires` asks; the manifest validator judges it as V5
does, and the grants part gives that process's account the hear and the consumer of exactly those events, as G1 gives
the publish. The zfs keeper names `mesh-conditions.findings-asked` there. "Exactly what G's writer needs" is its three
events on the module's `finding-events` stream: `finding-written`, `finding-cleared`, `findings-stated`.
- **A-341** (A-339; design 42 §27; G's findings writer; principle 7) Under G's writer a zfs device's finding is scope
`module`, id `zfs.<pool>.<device>` (the pool's own state: `zfs.<pool>.pool`), kind `not-online`, its subject scope
`module`, id `zfs`, on the node; `<device>` is the device's own name, the last element of its path. §27's one finding
per device not online stands; only its key takes the writer's form.
- **A-342** (A-339, A-341; principles 2, 7) A process learns its node the way the SDK already reads it: the node-engine
sets `MESH_NODE` to its own node's name in the environment of every process it runs, beside the resource's own `env`
(a resource's own `MESH_NODE` is refused by the manifest validator, so the mesh's value is the only one). The zfs
follower's writer and its `node-service-manager` calls then name the node; no new reference form and nothing special to
the keeper.
- **A-343** (§50, §494, §697; principles 5, 7; the operator, 2026-11-13: G's order put right, readers first) A third reader
release goes before G: one delivery group of mesh-sdk and mesh-delivery that carries exactly the readers of the seven
forms today's manifest validator refuses in G's manifests (R1 invokes `seat:<seat>.accept.<queue>` and
`seat:<seat>.<stream>.<kind>`; R2 reads `seat:<seat>.<state>`; R3 `last-per-subject`; R4 `objects-max-mib`; R5
`mesh-host-findings`; R6 the old `objects` section of gitea and distribution; R7 a process's `bus.consumes`), built from
mesh-sdk main after the revert (27da9491). The node-engine is rebuilt with the release's mesh-sdk, so it states
`word:streams.last-per-subject`. Nothing accepted on main today is refused after it: f1-circuits and link2pay stay as
they are, named in the whole-run test. How it is checked: today's validator, rebuilt with the release, accepts all 193 of
G's manifests and every trunk manifest it accepts today; delivered and reached on every node before G is asked again.
- **A-344** (A-343; §601, A-128; principle 3) The release reads each form with G's check of it (a `seat:` name that names
no seat, queue, stream or state of that seat is refused, as G refuses it), never the form alone; no trunk manifest uses
these forms, so nothing on main is refused for them.
- **A-345** (A-343, §584, §627; principle 7) Before G's merge the foundation list stays as it is; the two old forms of
gitea, distribution and the node-engine (bus state in `requires`, the old `objects` section) are accepted for exactly
those modules until G puts them on the list.
- **A-346** (A-343, §600, §601; principle 7) The release changes no grants code: until G is delivered the grants part
keeps its reading; G's own grants part is delivered first within G (§90).
- **A-347** (A-343, §714, §715) G's take-in is one revision of its group, so the acceptance of the release is the
all-of-G run (G's 193 manifests with G's 65 seat definitions), not the live per-member verdicts of before.
- **A-348** (corrects §703's sentence; A-343) The second reader release did not carry `last-per-subject`; the third does.
- **A-349** (sharpens A-345; §529; principle 7) The modules whose old forms the release accepts before G puts them on the
foundation list are those §529 and §584 name: gitea, distribution, the node-engine and the pipeline runner
(mesh-delivery-pipeline). The runner is new in G, so no trunk verdict moves.
- **A-350** (sharpens §372; principles 2 and 3) The fill takes, for each module, the highest version the builder's state
`versions` gave a number, whether its state is `numbered` or `published`, not only `published`: today's builder numbers
fresh bundle versions without publishing them (the late publish finds no digest), so a fill from `published` alone
would number again below what the builder already said (mesh-config/tools: `published` 0.1.0, numbered up to 0.1.14),
and one version would name two contents in the builder's log, its conditions and the catalog.
- **A-351** (sharpens A-350; principles 2 and 7) The filled edges of kinds 1 and 3 take the same rule: the dependency's
version the builder gave a number, numbered or published, since that is the version the module was built against; a
filled version or edge whose number the builder kept no digest for carries none (the fill needs only the number to
count above it, and a filled edge is stale until the module's next build).
- **A-352** (ADR 0614 §5 and §2; principle 3) The assigner's bus-state rule counts a build that offers `bus-state` and
runs healthy from the holder's have, also while a newer build of the bus module waits for the operator's yes: the
running build serves the bus state, so a consumer that needs none of the new build's forms is not held; a consumer
whose new form only the new build reads still waits for it by its edge of kind 4 (§50).
- **A-353** (G's start, found 2026-11-13 after its merge; principles 3 and 7) While its catalog half is unread, a tool
runner's approval gate lets through the first-view calls the catalog half is read by (the seat mesh-catalog's
`registrations`, `revision` and `entry`, the seat mesh-delivery's `source`, and their owners' first-view tools) and
holds every other call as today, so the runner that serves the indexer's tools can answer the reads it waits on; the
rule lives once, in mesh-sdk's approval gate.
- **A-354** (G's start; deb88b17 "grants keeps its read of modules until W8"; principles 3 and 7) The indexer keeps
serving the first view `modules` in its current form until grants reads the catalog half, so grants issues new
rights once G's indexer runs; the two move together in the same release as W8.
- **A-355** (G's start; principle 5) Every G part builds from main before any is placed: the watchman's go.mod
requires and replaces the seats it imports (nodebuildimage, nodebuildnode), as every module's go.mod does.
- **A-356** (G's start, the forge; principle 7) G's gitea is built by G's mesh-build-node, which is therefore delivered
before gitea; no lock file is kept for a mesh package that the build runtime exempts.
- **A-357** (§47 kind 6; principles 3 and 7) A package's `calls` names every seat verb its code calls on a module's
behalf, in the `invokes` form (`seat:<seat>.<verb>`); mesh-sdk's Go package adds `seat:mesh-catalog.registrations`,
`seat:mesh-catalog.revision`, `seat:mesh-catalog.entry` and `seat:mesh-delivery.source`, and the indexer derives an
edge of kind 6 from such a call word against the verb's server exactly as from `invokes`, so every module built
against the SDK is delivered after the running versions that serve its start.
- **A-358** (§47; principle 7) The tool runner keeps `invokes: "*"`, its role of forwarding any call; what its own start
needs comes to it through the SDK's `calls` (A-357), as for every module.
- **A-359** (narrows A-353; principle 7) The catalog half is read by seat verbs alone, so the gate lets through, while
it is unread, exactly the calls whose seat and verb are `mesh-catalog` `registrations`, `revision` and `entry` and
`mesh-delivery` `source`, told from the call's seat and verb as today; no tool is marked as a first-view tool and no
owner is named.
- **A-360** (completes A-354; principles 1 and 3) "Its current form" is the first view and its changes: the indexer
also says each change of `modules` on its views family (`mesh-delivery-indexer.views.modules`, in its `emits`) when a
new trunk revision changes it, so grants hears a newly merged module without asking again.
- **A-361** (clarifies A-357, ADR 0614 §3; principle 7) "Exactly as from `invokes`" includes the cycle rule: a package's
seat call words count among the invokes of every module built against it when the graph leaves out the edges that lie
on a cycle, so a call word's edge on a cycle is left out like an invoked verb's.
- **A-362** (completes A-353; principles 3 and 7) The seat list a runner starts with (mesh-sdk's bootstrapped list)
holds `mesh-delivery` beside `mesh-catalog`, so `mesh-delivery.source` is admitted before the seat list is read.