Files
hq/02-DECISIONS/0068-the-lab-takes-requests.md
T
jschoubben bf4d4e2e7b The three parked questions are answered: 0114 accepted, 0068 superseded, 117 settled
**0114 accepted.** The separation it draws — a consumer's resource and a
credential that reaches it are different things — is a data-loss rule,
and a record naming one should not sit unresolved while the code that
could hit it is written. Not built, and accepting it schedules nothing;
accepted-and-not-built is where 0141 and 0142 already are.

**0068 superseded by 0149, the live mesh is the test bed.** Never built,
and contradicted by practice that was written down nowhere but a handoff
note. The faults that cost the most are faults of a mesh that already
exists — bound consumers, containers made against an older roster, an
adopted machine — and a bed is by construction a mesh that does not.
Issue 156 settles it: that change was verified honestly, on the only path
where it cannot fail. The lab is not retired; raising a mesh from bare is
now its whole job.

**117 answered by 0150.** A module's own code runs as supervised
processes under the module's one account. 0047's argument was for a
runtime per module, not for a container — a unit satisfies it and runs as
an account. The invariant is the account, not the process count: its
worry was a second identity to scope and seal, and processes sharing one
account create none. Designs 18 and 20 now cite it and 0047 carries a
dated pointer, which closes the third disagreement — that neither design
knew the record existed.
2026-09-30 00:39:09 +02:00

7.0 KiB

topic, status, date, deciders, reconstructed, extends, superseded-by
topic status date deciders reconstructed extends superseded-by
building it superseded 2026-09-12 jochen false 0016-the-lab.md 02-DECISIONS/0149-the-live-mesh-is-the-test-bed.md

68. The lab takes requests, one at a time, and runs each from its own copy

Superseded — 2026-09-30, by ADR 0149. Never built. The live mesh became the test bed, because the faults that cost the most are faults of a mesh that already exists — bound consumers, containers made against an older roster, an adopted machine — and a bed is by construction a mesh that does not. The rule worth keeping from below is that a run reads a copy that is not anybody's working tree.

Context

The lab is exclusive hardware, and today a person holds it. Raising a scenario takes over addresses and names on the workstation for as long as it stands, and only one scenario can stand at a time. So a run is not merely slow — it occupies the machine and the person who started it, who then waits rather than works.

Running it in the background against the working copy is worse than waiting. The obvious fix is to start a run and carry on editing. But a run reads the working copy as it goes: binaries are rebuilt from it, manifests are read out of it, and the bed's own code is loaded from it. Edit while it runs and the result describes a state that never existed — a mixture of what was there when each file happened to be read. A green result obtained that way is not evidence, and a red one costs a day to disbelieve.

Nothing today records what was asked for. A run is a command line in somebody's terminal. What commit it exercised, what it was trying to find out, and what it answered all live in scrollback, which is why the same question gets re-run rather than looked up.

Most of the parts already exist. The lab writes a receipt of its last run. The mesh already carries messages between nodes and can notify a person. The machine already runs work on a schedule. What is missing is the thing in the middle.

Considered Options

1. Leave it as it is — a person drives the lab and waits. Rejected. It is the loop ADR 0010 removed everywhere else, kept here by habit rather than by argument, and the cost compounds: because a run is expensive to start and blocks the person, fewer are run, so faults are found later and in larger batches.

2. Run in the background against the working copy. Rejected on the reasoning above. The failure is silent, which is the kind this repository exists to refuse.

3. Put the lab behind the ordinary build pipeline. Rejected for now. The pipeline builds artifacts and does not own a machine that can raise virtual machines; giving it one makes the pipeline's slowest job the lab's, and couples every push to hardware only one machine has. This may become right later; it is not the smallest thing that works.

4. A queue in front of the lab, and an isolated copy behind it. Chosen.

Decision

The lab accepts requests rather than commands. A request is recorded, queued, and answered. The person who made it is told when it is answered and does not wait.

A request names a bed and a commit, and nothing else. This is the load-bearing restriction. A request may say run this bed, at this version of these repositories. It may not say what to install, on which machine, or with which settings — because a request that could say those things would be a second way of installing a mesh, and the whole reason the installer exists is that the lab already was one (ADR 0067). The bed decides what is installed; the request only decides which bed and which version.

Requests are released one at a time. The hardware admits one standing scenario, so the queue enforces what the hardware already requires, rather than leaving it to whoever remembers.

Every run happens in a copy the lab owns. The lab checks the requested commit out into its own path and builds and runs from there. A working copy is never read by a run. This is what makes the queue safe to use while work continues, and without it the rest of this record is not worth having.

The lab is reached through tools, not only a command line. A command line is available only to whoever is sitting at the machine, which is the constraint this record exists to remove. The lab answers three questions to anything that can reach the mesh — what is standing now, what is queued or running, and what did this request answer — and accepts a request and a cancellation. An agent can therefore start a run, stop attending to it, and come back; and somebody who did not start a run can still see it, which is the difference between a shared lab and a private one.

The restriction holds at every door. A tool submits a bed and a commit, exactly as a command line does. A tool that could name a module, a node or a setting would reintroduce the second installer through a different entrance, and the entrance is not what made it dangerous.

Every run leaves a record that outlives the terminal: what was asked, which commit, when it ran, what it answered, and where its output went. A question already answered is looked up rather than re-run.

Consequences

Work continues while the lab runs, which is the point. A second session may edit freely, because nothing it edits is what the lab is reading.

A request is reproducible by construction: it names a commit, so the same request can be asked again and compared. Today two runs of "the same thing" are only as alike as the tree happened to be.

The lab gains a second copy of every repository it exercises, costing disk and needing to be kept from drifting into a place people edit by hand.

Anything that can reach the mesh can now see what the lab is doing, including an agent working on something else. That is the intended gain and also the obvious hazard: a thing that is easy to ask is easy to ask too often, and the hardware still admits one scenario at a time.

The queue becomes a thing that can fail — stuck, backed up, or lost — and a queue nobody watches is worse than no queue, because it absorbs requests silently.

How this is checked

Rule Checked by
A run never reads a working copy The runner is given a path it owns and no other; a run started while a working copy is deliberately dirtied produces a result matching the commit, not the edits.
One scenario stands at a time A second request submitted while one runs is observed to wait, not to raise.
A request cannot say what to install The request format admits a bed and a commit only. A request naming a module, a node or a setting is refused, and the refusal is exercised.
A request is answered Every queued request reaches a terminal state with a record. A request that vanishes is a failure of the queue, not a quiet nothing.
The lab can be asked from elsewhere What is standing is asked from a session that did not raise it, and the answer matches the machine. A lab that only answers its own caller has not left the terminal.