Issue 121 diagnosed: the seats work renamed the requirement, not the order
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.
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
---
|
---
|
||||||
status: located
|
status: located
|
||||||
opened: 2026-09-25
|
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:
|
fixed-by:
|
||||||
amended-design:
|
amended-design:
|
||||||
---
|
---
|
||||||
|
|||||||
@@ -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.
|
||||||
Reference in New Issue
Block a user