From 9766a3afcec8aac6343ec2473f657685fde3cc50 Mon Sep 17 00:00:00 2001 From: jochen Date: Sat, 26 Sep 2026 14:47:45 +0200 Subject: [PATCH] Issue 121 diagnosed: the seats work renamed the requirement, not the order MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Asked first whether the seats change fixed this in passing, since it landed the same day and touches both manifests the report names. It did not: the seat's holder is consulted only where several nodes provide the thing, and with none providing it resolution refuses outright. Genesis has no exemption — the unchecked first pass exists to learn what each node offers, and a declaration is never built from it. Records the part that did change: the three tests left failing on purpose were deleted by the controller's seats PR and replaced with passing seat-based ones, so the gap is invisible again. Adds the resolver to located-in, since that is where the refusal is. --- .../00-report.md | 2 +- .../01-diagnosis.md | 64 +++++++++++++++++++ 2 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 04-ISSUES/121-builders-real-package-registry-grant-deadlocks-genesis/01-diagnosis.md diff --git a/04-ISSUES/121-builders-real-package-registry-grant-deadlocks-genesis/00-report.md b/04-ISSUES/121-builders-real-package-registry-grant-deadlocks-genesis/00-report.md index 9fae9ff..a232e83 100644 --- a/04-ISSUES/121-builders-real-package-registry-grant-deadlocks-genesis/00-report.md +++ b/04-ISSUES/121-builders-real-package-registry-grant-deadlocks-genesis/00-report.md @@ -1,7 +1,7 @@ --- status: located opened: 2026-09-25 -located-in: [mesh-catalog modules/builder, mesh-catalog modules/gitea] +located-in: [mesh-catalog modules/builder, mesh-catalog modules/gitea, mesh-controller internal/catalogue/resolve.go] fixed-by: amended-design: --- diff --git a/04-ISSUES/121-builders-real-package-registry-grant-deadlocks-genesis/01-diagnosis.md b/04-ISSUES/121-builders-real-package-registry-grant-deadlocks-genesis/01-diagnosis.md new file mode 100644 index 0000000..769a18e --- /dev/null +++ b/04-ISSUES/121-builders-real-package-registry-grant-deadlocks-genesis/01-diagnosis.md @@ -0,0 +1,64 @@ +# 121 — Diagnosis + +## 2026-09-26 — the seats work renamed the requirement; it did not reorder the bootstrap + +The seats change landed the same day this was filed (ADRs 0109–0111 accepted, and the code on both +main branches), and it touches exactly the two manifests this report names. That made it worth +asking first whether the deadlock had been fixed in passing. It has not. + +### Step 1 — what the seats work changed + +`builder`'s requirement was renamed from `package-registry` to `npm-package-registry`, which is now +a **seat** the forge holds; the forge claims `npm-package-registry` and `git` at mesh scope and +serves both. The provision is the same relationship under a name the mesh defines rather than one a +manifest invented. + +### Step 2 — the seat's holder cannot answer when there is no holder yet + +The seat is consulted in exactly one branch of resolution: where **several** nodes provide the +wanted provision and no pin says which. That is the ambiguity case, and it is not the bootstrap +case. With nothing providing it at all, resolution takes the branch for no providers and **refuses**, +naming the remedy: + +> nothing in this mesh provides "npm-package-registry", wanted by builder — assign gitea to a node + +A refusal, not a deferral. So a seat delivering a provision does not make a requirement optional +before the seat is filled, and nothing about the seats work moves the order. + +### Step 3 — ruled out: genesis has no escape hatch + +Resolution has an `Unchecked` mode that "takes brokered requirements on trust instead of refusing +when nothing answers them", which would be exactly the exemption a bootstrap needs. It is not one: +it exists for the first of two passes — working out what each node offers — and its own comment +states that **a declaration is never built from an unchecked resolution**. The second pass, the one +that produces the declaration, refuses. + +### Step 4 — the other arm of the cycle is intact + +The forge's manifest still carries a `build` section, its runtime image compiled from the +toolchain's build and runtime bases like every other built module. `builder` is what runs that +build. So both arms stand: the builder cannot be assigned before the forge provides the registry, +and the forge cannot exist as a container before the builder has built its image. + +## What did change, and why it is the part worth recording + +The three tests that pinned the carried-fallback design — the builder's own `package-binding` +resource, its port taken from the node, its identity kept — were **deleted** by the controller's +seats PR and replaced by seat-based tests that pass. + +The report deliberately left those three failing so the gap would stay visible. It is no longer +visible: the suite is green, and the only remaining trace is this issue. That is the same way the +deadlock was invisible in the first place — a running mesh resolves the grant instantly, because the +forge is already built and assigned. Twice now, the evidence has been removed by something correct. + +## What would actually answer it + +- **A provision that resolves to a carried fallback when nothing provides it yet.** Nothing in the + model expresses "this, or a carried default until something can answer", for any provision. This + would be the first, which is why it belongs in a record rather than in a manifest. +- **Genesis sequencing instead** — build the forge before granting anything, with the builder never + resolving the registry during that window. +- **The forge's runtime image not being the mesh's to build** — an external image breaks the cycle + by removing the dependency rather than by expressing it. + +None is chosen here. The report's open questions stand as written.