**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.
120 lines
7.0 KiB
Markdown
120 lines
7.0 KiB
Markdown
---
|
|
topic: building it
|
|
status: superseded
|
|
date: 2026-09-12
|
|
deciders: jochen
|
|
reconstructed: false
|
|
extends: 0016-the-lab.md
|
|
superseded-by: 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](0149-the-live-mesh-is-the-test-bed.md).** 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](0010-delivery.md) 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](0067-genesis-is-a-pivot.md)). 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. |
|