7.1 KiB
topic, status, date, deciders, reconstructed, extends
| topic | status | date | deciders | reconstructed | extends |
|---|---|---|---|---|---|
| the mesh | accepted | 2026-10-01 | jochen | false | 02-DECISIONS/0121-a-system-seat-is-named-for-its-scope-and-modules-define-their-own.md |
157. A build says what it does on the bus, as it happens
Context
ADR 0121 made a build work submitted to a role: the build-machine seat accepts a build and emits its outcome, one publish that reaches whoever asked, the controller that records it and the catalogue that places it. Everything between the request and the outcome — which command is running, how long it has taken, where it hung, the compiler's error, the clone's refusal — lived in one container's standard error on one machine.
The night of 2026-09-30 showed the cost three times over. A build that failed showed a person one
line, the first of its failure, in the controller's builds; the rest was read with docker logs over
ssh, which the mesh's own rule forbids. A build that ran for minutes could not be told from one that
had hung. And the builder has no tools and emits nothing but the outcome, so the console
(ADR 0152) had nothing to show while a
build ran, and no viewer could be built on top of it. The operator's ask was plain: the builder is to
be fully transparent, with its log on the bus, so that a log viewer can be built on the bus later.
Considered Options
- Keep the log in the outcome. The result carries the whole log when the build ends. Nothing new on the bus; nothing while the build runs; a viewer sees a build only once it is over, which is exactly when the log matters least.
- A log store. The builder writes its log to a file or a table and a tool reads it. A second place to keep something the bus already carries, with its own retention, access and failure modes, and no live reading without inventing a subscription over it.
- The log is the role's own events. Two more events on the build-machine seat beside
built:startedwhen work is taken, andlog.<build id>for every line, published as the build runs. The events stream already retains every role's events for a week, so a reader follows a build live by subscribing its subject, or reads it back afterwards from the stream, and a viewer is a subscriber and nothing more.
Decision
Option 3. A build machine says everything it does on the bus, as the role it holds, under the build's id, and the mesh keeps no other copy.
- The build-machine seat's protocol gains
startedandlog.*. A holder may therefore publishmesh.seat.mesh-build-machine.event.startedand…event.log.<id>, and no other subject, by the same derivation every seat's grants follow (ADR 0132). The event's tail token is the build's id, so one build is one subject: a reader filters by subject alone, on the server, and a week of other builds does not travel to show one. - Every line goes two ways: to the machine's own standard error as before, and onto the bus. That includes every command the builder runs, its duration and its failure, and on failure the command's own output line by line — the compiler's words, the clone's refusal. A build machine with nobody listening still prints; a listener reads the same lines.
- A line is a core publish, unawaited. The stream that holds the role's events captures it on its way
through, and a build does not slow to the pace of an acknowledgement per line. Each line carries a
sequence number from one, so a reader who joined late, or reads two copies, sees order and gaps.
startedandbuiltare published into the stream and awaited, because they are the two facts a later reader must never find missing. - The mesh reads it back from the stream, never from a record of its own:
builds --log <id>, and the same verb on the controller's seat (ADR 0154), reads one build's subject with a consumer that is gone when the reading is done.buildslists each build's id beside it, andbuildsays the id it asked with, so a person can follow. - Nothing is declared by the builder module for this. The protocol is the seat's, seeded additively into the store (ADR 0132), and the holder's grant follows on the next composition of the broker node.
Consequences
- A build is watchable while it runs, from anywhere on the mesh, with no access to the build machine. The console's gap of 2026-10-01 — no live progress, no per-merge view — closes on the progress half; the per-merge view is a reader over these subjects and the outcome, and is not built here.
- A log viewer on the bus is now a plain subscriber: live on
mesh.seat.mesh-build-machine.event.>, historical from the events stream filtered by a build's subject. NATS carries and retains; it does not view. Thenatscommand-line client can tail or replay a subject today; a viewer of our own is later work and needs nothing more from the builder. - The events stream grows by a build's log per build, for a week. A build is a few hundred lines; the stream's limits are the bound, as for every other event, and a stream that fills drops the oldest.
- A line the bus did not take is lost, deliberately, and visible as a gap in the sequence. The outcome is not affected: a build's result never depended on its narration.
How this is checked
| Rule | Checked by |
|---|---|
The seat's holder may publish started and log.<id> and nothing wider |
TestTheBuildMachineMaySayWhatItDoesUnderTheBuildsId (broker) |
| A build's lines reach a reader of its subject in order, and the stream holds them afterwards | TestNatsABuildIsTakenAndItsOutcomeReachesEverybody against a real server (link) |
The seat verb builds with a build's id reads that build's log |
TestBuildsWithAnIdReadsThatBuildsLog |
| Every command the builder runs is said, with its output on failure | Command speaks through the hook every build sets; the builder's tests still see the lines on standard error when nothing listens |
| Live: a build triggered after the roll-out is readable line by line through the console | done by hand after the merge of mesh-controller PR — see the design's note |
References
- ADR 0121 — extended: the role now narrates as well as answers
- ADR 0132, ADR 0154 — the protocol and the verb
- ADR 0152 — the console this feeds
- Design 25 — The bus on NATS §3, Design 18 — Building a module
- Issue 176 — the tool that starts a build and hears nothing; this gives it something to hear