4.8 KiB
status: resolved
opened: 2026-10-01
located-in: [mesh-controller cmd/mesh-controller/seatverbs.go (argvFor, "build": --wait 0, no --self), mesh-controller cmd/mesh-controller/main.go (builds.Built records a build and registers nothing)]
fixed-by: mesh-controller PR 179 (one take-in for a build's outcome, called by the waiting command and by the daemon; --wait 0 asks and returns the id; the seat verb says --self for a forge path); ADR 0157 (mesh-controller PR 178) gave the tool something to hear
amended-design: 03-DESIGN/01-to-be/18-building-a-module.md
176 — The console's build tool neither waits nor registers, and does not take a forge path
What was observed
Eight media modules held by the mesh had not been rebuilt after their manifests changed, because a
merge rebuilds only the modules whose recorded source is the merged repository and theirs was another
one. Asked through the console — the controller's build tool, served on its seat
(ADR 0154) —
with the repository given as its path on the forge, the way the tool's own description invites:
- every call answered at once with no build machine answered within 0s … the work is queued;
- the builder, asked in the same breath, failed each one with cannot clone novox/mesh-catalog: the
path was handed to
git cloneas written, because the tool never says the repository is a path on the forge holding the git seat (--self), which the command line requires for that form; - given the repository's URL instead, the call still answered within zero seconds, the build ran on the builder, its result was heard and recorded — and the module was not registered: what hears a finished build records the build and stops; only the caller that waited would have parsed the manifest and registered it, and the caller had gone.
So the console can start a build and never learn its outcome, and a build it starts cannot change what the mesh holds. The tool's description — have the build machine build a repository and record what came out — is true of the build record and false of the module.
Why this is here
The seat verb was written as fire-and-forget, deliberately (--wait 0), so that a tool call over the
bus does not sit for the minutes a build takes. That reasoning moved the wait but not the work that
followed it: registration lives in the waiting caller, not in the path that hears the result. The two
halves of "build" — asking, and taking in what came back — are split across the command and the
event handler, and the tool reaches only the first.
The forge-path form is a second, smaller gap: the seat verb maps three arguments and forgets the flag the same command needs to read one of them.
What would be right
Registration belongs where the result is heard, once, so a build's outcome reaches the mesh whoever
asked and whether or not they waited — the same rule as an announcement's builds. The tool then
answers with what it can say at once (asked, queued, or refused) and builds says the rest. A
repository given without a scheme is a path on the git seat, and the verb says so.
Open questions
- Should a tool call be able to wait at all? A builder answers in minutes; the console's transport holds a call for a bounded time. If not, the tool needs a way to follow one build — which is the builder's missing progress (no tools, no events) named in the console's review of 2026-10-01.
Resolved, 2026-10-01
Registration moved to where the outcome is heard. One function takes a build's outcome in — records
the build, parses the manifest, refuses a definition that names an installation, registers the module
with its source as the seat and path the request carried and the outcome echoes — and both the
command that waited and the daemon that follows the role's built event call it. So a build asked
for by anything that could not wait reaches the catalogue the same as one asked for by hand, and the
same outcome heard twice writes one row twice with the same values.
The tool keeps not waiting, and says so: build --wait 0 publishes the work and answers with the
build's id, and builds --log <id> follows the build line by line (ADR 0157),
which is what a tool call over the bus can do in the seconds it has. A repository given without a
scheme is said to be a path on the git seat, so the forge-path form the tool's description invites
now works.
The open question is answered by the shape: a tool call does not wait; it asks, gets the id, and follows. How it is checked: the shared take-in against a raised store — registered with the seat source, a definition naming an installation recorded and refused, a failure said in the builder's words — and the tool's mapping of a forge path against a URL.