From 748f95d4175502a978bcee12c93820a1a4afbbb8 Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 27 Sep 2026 19:51:09 +0200 Subject: [PATCH 1/2] Issue 131: nothing tells the mesh a source moved MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Six merges landed today and the build machine built nothing — no build was requested, refused or failed, because none was asked for. Asked what was wrong, the mesh said every module was current with its source. All six had moved. The trigger is not broken; there is no trigger. One repository still carries a forge webhook aimed at a port belonging to a different service, and the rest carry none. The intended shape is decided and unbuilt: the forge emits that a pull request merged, the build machine reacts. The forge's module already declares the event; the build machine consumes nothing. Recorded with the question that outlasts the fix — "current with its source" compares what was built against what the mesh was last told, so it agrees with itself and can only ever agree. Whether the trunk moved is a question the forge answers, and an overview that cannot ask it should stop claiming to know. --- .../00-report.md | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 04-ISSUES/131-nothing-tells-the-mesh-a-source-moved/00-report.md diff --git a/04-ISSUES/131-nothing-tells-the-mesh-a-source-moved/00-report.md b/04-ISSUES/131-nothing-tells-the-mesh-a-source-moved/00-report.md new file mode 100644 index 0000000..abd4182 --- /dev/null +++ b/04-ISSUES/131-nothing-tells-the-mesh-a-source-moved/00-report.md @@ -0,0 +1,66 @@ +--- +status: open +opened: 2026-09-27 +located-in: [] +fixed-by: +amended-design: +--- + +# 131 — Nothing tells the mesh a source moved, and it reports itself current anyway + +## What was observed + +Six changes were merged to the trunk of six repositories in one sitting. The build machine built +nothing. Its last build, minutes before the first merge, was still the one it reported; no build was +requested, refused or failed, because none was ever asked for. + +Asked afterwards what was wrong, the mesh said: + +> 4 machine(s), all doing what they were told, all heard from, running what the mesh would send them, +> and every module current with its source + +Every one of the six had moved. The last clause was false for all of them, and it is the clause a +person reads to decide whether there is anything to do. + +## Why it matters beyond this instance + +**The mesh learns a source moved by being told, and there is no longer anything to tell it.** The +command exists — a person names the module and the commit — and so does the question the overview +answers. What is missing is whatever used to connect the two. One repository still carries a forge +webhook aimed at a port; the rest carry none, and the port belongs to a different service than the +one the arrangement implies. So the state is not "the trigger is broken" but "there is no trigger, +and nothing says so". + +**A wrong answer is worse here than no answer.** "Every module current with its source" is +indistinguishable, to a reader, from a mesh that has genuinely caught up. The overview is built to be +the thing you check instead of checking by hand, so a confident false negative removes the habit that +would otherwise have caught it. Nothing in the mesh is at fault for being out of date — it is at +fault for saying it is not. + +**It is also why "current with its source" cannot be a stored fact.** The mesh compares what it built +against what it was last told the source was, and calls that agreement. Two facts agreeing tells you +nothing when both come from the same place. + +## The intended shape, which is decided and not built + +The forge emits what happened to it — a pull request merged — and the build machine reacts by +building what that commit affects. That keeps the forge ignorant of the build system and the build +machine ignorant of the forge's internals, which is the same argument +[ADR 0126](../../02-DECISIONS/0126-a-module-declares-its-own-seats.md) makes for addressing an event +to its emitter: the merge is a fact about the forge, and what should be rebuilt because of it is not +the forge's business to know. + +The forge's module already declares the event. The build machine declares that it consumes nothing. + +## Open questions + +- Is "the source moved" still a thing a person can assert by hand once the event path exists, or does + the hand-operated form become the thing that made this failure possible? +- Which commit does the build machine act on — the merge, or each commit it brought — and what does + it do when several arrive for one module at once? +- How does the overview stop being able to lie? Comparing what was built against what was recorded + will always agree. Whether the trunk has moved is a question only the forge can answer, so either + the overview asks it, or it stops claiming to know. +- Does this want to be the same mechanism as the build request on the bus + ([ADR 0129](../../02-DECISIONS/0129-a-seat-carries-the-protocol-of-its-role.md)), or does it sit in + front of it? -- 2.54.0 From af6a3978408a577e4cb0fac04cbafeec9e67389f Mon Sep 17 00:00:00 2001 From: jochen Date: Sun, 27 Sep 2026 21:08:57 +0200 Subject: [PATCH 2/2] Issue 131: the trigger cannot be one build per changed module MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Correcting my own framing. The modules are a graph, not a flat set: several build from one repository, and some are the base another compiles on. Firing a build per changed module starts work that cannot succeed yet and reports one cause as a failure per dependent. Observed catching the mesh up by hand today — a compiler base had to move first, and when it failed the right behaviour was for its fifteen dependents to wait, not to fail identically. So what reacts to the forge's event has to resolve what changed into an order and hold a dependent while its base is unbuilt. That is a bigger thing than "rebuild what the commit touched", and cheaper to know now. --- .../00-report.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/04-ISSUES/131-nothing-tells-the-mesh-a-source-moved/00-report.md b/04-ISSUES/131-nothing-tells-the-mesh-a-source-moved/00-report.md index abd4182..f29ae06 100644 --- a/04-ISSUES/131-nothing-tells-the-mesh-a-source-moved/00-report.md +++ b/04-ISSUES/131-nothing-tells-the-mesh-a-source-moved/00-report.md @@ -52,6 +52,24 @@ the forge's business to know. The forge's module already declares the event. The build machine declares that it consumes nothing. +## What the trigger cannot be + +**Not one build per changed module.** The modules form a graph: several are built from one +repository, and some are the base another is compiled on — a runtime image, a compiler base, a +repository whose context a second module builds from. Firing a build for each changed module +independently would start work that cannot succeed yet and produce a failure per dependent, for one +cause. + +Observed while catching the mesh up by hand on 2026-09-27: a compiler base had to move before +anything compiled against it could build, and when it failed, the right behaviour was for its +dependents to wait rather than each fail the same way. Fifteen modules shared the cause. A trigger +that reports it fifteen times has buried it. + +So whatever reacts to the forge's event resolves what changed into an order, builds the bases first, +and holds a dependent while its base is unbuilt or failed. That is a larger thing than "rebuild what +the commit touched", and knowing it now is cheaper than discovering it from fifteen identical +failures. + ## Open questions - Is "the source moved" still a thing a person can assert by hand once the event path exists, or does -- 2.54.0