drogna

A demonstration harness. Every number in it is invented.

ADR-0040: a run arrives by having run

Status: Accepted Date: 30 August 2026 Feature: 120 (start conditions, chosen on a welcome page) Requirements: SRD-v2 FR-11 (provisioning runs the components' own code paths); FR-09 (the clock's step); FR-36 (stop and start); FR-65 (prompted events); FR-10 and AT-04 (replay from the manifest) Engages: ADR-0030 (the composition root); ADR-0032 (addressability goes below the panel); ADR-0029 (the HTTP seam is a fetch shim)

Context

Every visit began at the epoch. The archive and one now-cast existed because provisioning authors them on the clock's first sample; everything else — a track, an assimilation, a staged package, a word from shore — existed only if the reader left the page running. Feature 120 offers four situations to begin in instead, and each of them is a claim about what the run holds.

There are two ways to make such a claim true, and the whole of this decision is which.

The cheap one is a fixture: write observations into the observation store, forecast fields into the coverage store, and open the console over them. It is fast, it is exact, and SRD-v2 FR-11 has forbidden it since the beginning — seed data is authored by the same components and seams that author it during a run, so the guards a run enforces (validation against the masters, digest checks at publication, publication atomicity) are the guards the seed data passed through. V1 paid for the other answer once and wrote the rule down.

Decision

A start condition is a script of operator actions, and the run arrives in that situation by having actually run there. The composition root pins the clock, then drives the run forward through the operator plane's own HTTP endpoints — stop a component, publish a demand, prompt an event, step the clock — and mounts the shell when the script is spent.

Every one of those is a control a reader can work by hand in the Operator tab. Every request crosses the release gate. Every message the run produces on the way is on the broker, where the Messages tab can read it back. Nothing writes to a store, and the pre-roll driver does not know what a holding is.

The script is configuration, not code

A condition names the platform's initial vector and an ordered list of legs, in run.json, against config.start-conditions.schema.json. Three things follow that would not follow from a script in TypeScript.

It is reviewable as a claim: the card's prose and the leg list sit in one document, and a test holds the first to what the second actually leaves behind.

It is replayable. AT-04 puts operator commands outside its claim, and says a demanded run replays identically only when the same demands are issued at the same ticks. A condition's demands and prompts are issued at ticks the configuration fixes, so that proviso is met by construction and the pre-roll is back inside the claim — which is why the manifest carries the condition, and why the run id does.

It is extensible without touching the driver. A fifth situation is a fifth entry.

The choice travels in the query string

?start=<id>, beside the hash rather than inside it. ADR-0032 made the hash a view address with an opaque remainder belonging to the panel; a condition is neither. Putting it there would have meant a second grammar in views.ts or a link that opens the wrong tab. In the query string the two compose without either knowing about the other, and ?start=loitering#/view/map is a link to the map of a run on station — which is what D16 wanted addressable views for.

An address that names a view is not interrupted

Views have been addressable since feature 101 so a pull request or a blog entry can point a reader at the thing being discussed. A welcome page in front of such a link puts the work of finding it back on the reader, which is the work the link was supposed to save. So an address naming a view boots the default condition and goes straight there. Only a bare visit is asked.

The planner is held back, and it is the only one

Measured leg by leg, a tick inside the work area cost about 3 ms with the planner running and one pre-roll reached 25 seconds; with the planner alone stopped and the whole loop live, the four conditions cost 1.1 to 5.2 seconds. The planner's route search is the dearest thing in a tick and it runs every 600.

It is also the right one to hold back, and not only because it is dear: it recommends. It publishes a plan and changes nothing else, so no card's promise depends on it, and it replans within 600 ticks of the console opening — live, where a reader can watch it, which is where that work belongs. Everything else runs through every pre-roll, which is what makes each condition a run rather than an arrangement.

Consequences