Skip to content

Gate Execution Economics

A fleet’s cost per landing is a governance property, not a performance detail. The decision set is recorded in ADR-121, Gate Execution Economics for an N-Party Fleet (arc42 §9, docs/09-architecture-decisions/ADR-121-gate-execution-economics.md). This page is the operator-facing summary of that record.

A gate-attempt ledger scan over 2026-08-21 to 2026-09-02 — grouping ledger events by work unit, head commit and lifecycle stage, and taking each group’s wall span — reports 286 runs, a median of 487 s and a p90 of 1326 s, and a distribution that is flat for the whole window: it does not respond to change size, to fleet composition, or to several landed point improvements. A cost that ignores the size of the change is not a testing cost — it is a fixed toll, produced by admission, selection, and reuse decisions that were each made locally and never reconciled with one another.

Never-skippable coverage

No decision may let a change land without a gate result that actually observed that change. Faster is never a reason for less observed.

Fail closed on uncertainty

Any reuse, cache, or detection path that cannot prove its precondition from a complete, content-derived fingerprint executes the full work instead.

Evidence is attributable

Every admission, selection, reuse, fallback, and capability-absence decision is recorded in the gate-attempt ledger with the inputs that produced it.

Alongside them stands a standing negative-control requirement: every reuse or narrowing path ships an executable test that makes a real, behaviour-changing edit inside the path’s claimed-safe region and proves the path misses — that the affected gate still executes and still fails. A performance measurement is never a negative control.

#Decision
D1Weighted admission replaces both host ceilings — the fixed-capacity gate-execution semaphore and the capacity-1 whole-run build-output hold.
D2One workspace-graph test oracle with printed selection evidence; a zero match fails closed instead of running the whole workspace.
D3Evidence reuse across heads and across the done-side rebase, bound to a normalized content fingerprint and an untouched graph neighbourhood.
D4Content-addressed build outputs with atomic activation; isolation is the default, declaration is the contract.
D5Incremental typecheck and lint with fail-closed cache validation bound into the prep fingerprint.
D6Input-hash-bound cached test results count as attestation evidence under five stated conditions, and otherwise the test executes.
D7A neutral remote gate-capacity port: local and remote providers are indistinguishable to the caller, and the default needs no network.
D8The N-party landing-queue protocol, with a coordination-epoch clock and three explicit consensus classes.

Sequencing is binding: D4 before D1; D2 before D3 and D6 (until D2 lands, both reuse paths use the conservative whole-workspace over-approximation); D1 before D7.

Most decisions name an existing work unit that owns their implementation by dependency — no work unit is moved between initiatives to carry one. Two have no owner, and the record says so rather than implying otherwise:

  • D7 (the remote port) becomes a phase-3 work unit when the measured p90 over the next 30 recorded gate runs after D1 lands — or the metrics command’s default window, whichever set is larger — is still above the advisory prep latency target. The advisory target is the threshold deliberately, not the phase-4 enforced budget: waiting for a release to fail would make the port permanently unreachable.
  • D4’s general half. WU-3934 (done) delivered content-addressed outputs, atomic activation and verified reuse for this workspace’s own CLI output only, and WU-3987 (done) has since landed digest-based freshnessbigint stats plus a per-file content digest — after this decision’s second trigger fired: the mem-504a fail-closed case recurred, on the integration target itself. What remains unimplemented and unowned is declared output roots for arbitrary toolchains, content addressing for them, and opt-in serialization for a declared shared root; that becomes a phase-3 work unit when a workspace declares an output root name-based detection cannot resolve. Until then D1’s conservative key carries the uncertainty.

Graph neighbourhood (D3). For a change set, the neighbourhood is the union of its dependency closure (everything the change can observe) and its importer closure (everything that can observe the change), plus the tests selected from either. Reuse requires that nothing moved inside it — in both directions — and the negative control tests both.

Session scope (D3 versus D6). The same-session restriction applies to lifecycle authority artifacts — checkpoints and receipts — because those decide who may land. A hash-bound test result answers a different question, whether an assertion observed this exact content, so it is admissible whichever session, owner, or machine produced it, provided all five D6 conditions hold. Verifiable provenance is what replaces session identity there, and a remote provider’s cache is admitted on exactly those same five conditions.

The protocol governs landing order for any number of orchestrators in any harness, over LumenFlow’s existing coordination primitives. It introduces no new transport and no lock: exclusivity is a grant with an expiry.

  • The clock is a coordination epoch, not a wall clock. Every party derives the same monotonically increasing epoch, per integration target, from the durable signal log: an epoch closes when a queue-affecting event is recorded by any party other than the current grantee, evaluated against the state immediately before the event applies — so a custodian granting a window to itself still closes an epoch. Grantee heartbeats mark presence within an epoch and never close one, so a grantee cannot keep its own window alive by talking. A heartbeat discharges the obligation for the epoch open at its own recorded position in the log — not the epoch it cites — so every party computing revocation or custody release independently gets the same answer. A cited epoch that disagrees with that position is never a well-formedness failure — detecting it needs the log — but what follows differs by class. For a heartbeat it is a substantive-validity failure and the heartbeat discharges nothing, because a heartbeat’s whole content is its claim to be present in a particular epoch. For every epoch-closing class the position-derived epoch simply governs and the citation is repaired, not refused: emitters predict the epoch they will open, contention can overtake that prediction, and refusing on that basis would reject honest traffic exactly when the queue is busiest.
  • Why a sole party’s window cannot expire. Not because the clock is frozen: a single party’s own readiness signal and self-grant are emitted while it is not yet the grantee, so they do close epochs. It is because once it holds the window, every message it emits is a grantee message, and with no other party to emit a queue-affecting event nothing closes an epoch for as long as the window is held. The clock cannot advance while that party is the one being measured, which is the property that matters.
  • Two tests, and only one drives the clock. Well-formedness is structural — every element of the message class’s minimum, present and syntactically valid, checkable from the message alone — and it is what closes an epoch. Anchoring additionally requires every cited identifier to resolve in shared durable state, and it governs whether a party may act. A well-formed but unanchored message closes its epoch and is refused for action, so the clock never forks on a resolution only some parties can do. Acceptance is a Class A judgement and a separate logged message: it governs queue membership, never the clock.
  • Only some identifiers are resolvable. Anchoring applies to signal ids (a window id is a grant’s own signal id), work-unit ids, initiative ids, lease or party ids, and the owner’s authorization id — each names a record the log holds or projects. Commit identifiers are content: syntactically checked, never a bar to anchoring, and compared against a branch tip only under the epoch-boundary divergence rule. Without that carve-out no grant or heartbeat could ever anchor, and no window would ever be granted.
  • Readiness evidence must be shared, and it fails closed. Gate-attempt ledgers are per-worktree, so a bare ledger id means nothing to a peer. A readiness signal therefore publishes the gate-attempt records themselves — id, gate, outcome, declared commit, result digest — into the shared log, and those records are elements of its class minimum. A signal carrying only bare ledger ids is therefore not well-formed: it closes no epoch and cannot be granted against. For a conforming signal, non-anchoring can arise only from its work-unit id or pinned initiative ids, both of which are resolvable.
  • A window closes just before its own closing message applies, so a return or a landing completion is not emitted by “the grantee” in pre-event state and both close an epoch as enumerated, instead of being dead letters.
  • The queue is derived, not stored. Every party computes the same total order: priority first, then the readiness signal’s timestamp as recorded by the coordination store, then work-unit identifier as a deterministic tiebreak. The queue is the set of readiness signals that are unretired and unrejected — acceptance is not a membership precondition, and a custodian may grant to an unaccepted head, so a silent lease holder cannot stall every landing. Entries leave only by logged message: landing completion, rejection, retirement, or a recorded revocation, which retires the signal it answered — without that a revoked entry would have no eviction path and the custodian would re-grant to the same silent party forever. A declared head that no longer matches its lane branch tip is a reason to retire, evaluated at an epoch boundary, never an eviction on unlogged observation.
  • A readiness signal carries its evidence, and that evidence must pass — work unit, declared head, the cheap gates’ gate-attempt records published into the shared log, the pinned affected-initiative set (pinned for the same reason a Class B roster is, so the Class A conjunction cannot drift), and the recorded priority. Each carried record must show a terminal pass of that gate against the declared head: never a skip, never a partial run, never a timeout, never another outcome, never another head — the same shape D6 condition 2 uses. That test is well-formedness, decided from the message alone, so a signal carrying a failing, skipped or wrong-head record closes no epoch and joins no queue rather than sitting at the front of one.
  • One landing window per integration target, granted by the custodian, naming grantee, base commit, expiry epoch, and the readiness signal it answers. The expiry epoch is derived, not chosen: grant_epoch + window_span, where window_span is workspace-declared with a default of 3 and a range of 2 to 10 — never below the revocation threshold, or a window could expire before the evidence to revoke it could exist. It is re-derived from the position-derived grant epoch, so the carried number is repaired along with the citation; honouring a carried expiry after contention overtook the grant’s predicted epoch would shrink the effective span below its own bound and leave two readers disagreeing about whether the window is still open. The cited pair is range-checked as well-formedness only. The window id is the grant’s own signal id, so every later citation of it resolves in the shared log by construction. Custody is a role any lease holder may serve; a custody change inherits an open window rather than voiding it.
  • A window that closes without a landing does not strand its entry. On a return the readiness signal stays queued but is passed over for the next grant — returning is penalty-free, so retiring the courteous case would be perverse. On expiry, which has no message of its own, the custodian records a retirement with reason expired; until then the entry is passed over too. On revocation the signal is retired outright. “The next entry” in all three cases is the queue front re-derived after the closure applies, skipping anything currently passed over — so an ever-heartbeating, never-landing party is retired by expiry rather than holding the front.
  • Well-formed is necessary, not sufficient. A message is also refused when it is substantively invalid — claiming an authority its emitter does not hold (a grant or revocation from a non-custodian), asserting a transition the log does not support (a takeover before the threshold), or arriving out of order (a grant for a target that already has an open window). Like anchoring, this governs action, not the clock.
  • Bootstrap and contest resolve in a fixed order. A target with no custodian is claimed by stating the observed absence; every epoch-closing message cites the epoch it itself opens, so a bootstrap claim that is the target’s first message cites epoch 0. Contests then resolve: validity first — a bootstrap claim whose asserted absence the log contradicts, or a takeover before the threshold, is substantively invalid and never enters the comparison, however late it is; then recency by position-derived epoch, not by the cited number, because position is the objective fact and a citation is only an assertion; then the lowest lease-or-party identifier, reachable only when two parties predicted the same next epoch concurrently and the store has not yet ordered them. The tiebreak is a concurrency rule and never overturns an order the store has established. Later-wins governs a takeover race, and being recorded after something is never itself a ground for refusal — a valid takeover is by definition ordered behind the claim that installed the custodian it replaces, so only the asserted state can invalidate a message.
  • Takeover after two consecutively closed epochs without a heartbeat — from the grantee, its window is revoked; from the custodian, custody is released. The epoch in which a grant or custody claim was made never counts, so every party gets one full epoch of grace before the clock can be used against it.
  • Queueing constrains landing only. It never withholds a claim, never blocks a gate run, and never serializes unrelated lanes.

Each class carries its own minimum, and a message is never refused for failing a different class’s minimum. A readiness signal, its acceptance or rejection, its retirement, a grant, a heartbeat, a landing completion, a custody claim, a custody withdrawal, a Class B proposal, and a Class C action each have their own — so a governance proposal is never refused for lacking a commit id it could not have, and no epoch-closing transition exists without a minimum that makes it checkable. Where a fleet has no lease holders, the identifier a custody claim or an acceptance carries is the party’s own identifier rather than a lease id, so the lease-less clause is executable rather than merely stated.

ClassWho must agreeExamples
AThe lease holder of each affected initiativeGranting, returning, revoking a landing window; accepting a readiness signal; scope narrowing inside its own initiative
BEvery lease holder (unanimity, fail-closed)Changing the protocol itself; freezing the integration target; cross-initiative landing order; fleet-wide gate admission defaults
CThe ownerSkipping or weakening a never-skippable gate; any ownership override; weakening an attestation invariant or removing a negative control

The classes are not disjoint, so precedence is strict: C > B > A. A decision falling in more than one class is governed by the highest, and the lower class’s assent never substitutes — though where the mechanism structurally needs both, both are required. Plainly: lease holders may amend the protocol by Class B unanimity, but any amendment that weakens an attestation invariant, removes a negative control, or narrows a never-skippable gate additionally requires the owner under Class C. Coordination is theirs to change; the invariants are not theirs to vote away.

A landing work unit spanning several initiatives needs Class A assent from each affected lease holder. One with no initiative lease falls to the custodian of its integration target. With no lease holders at all, party count and lease count are treated separately: at one party, its owner is its own Class A authority; with several parties and still no lease, custody opens to any landing party under the same contest rule, until the first party to take an initiative lease supersedes it.

Implemented today: weighted gate admission (WU-3975) that replaced the fixed capacity-2 semaphore, declaring a run’s weight from its resolved execution plan against a measured processor and memory ceiling and failing closed to the conservative grant whenever measurement is unavailable, with a declared gates.execution_lock.concurrency still able to cap a workspace below that ceiling and never above it; a build-output writer lock of capacity 1 with an unbounded wait, keyed on the resolved build-output root and falling back to a machine-wide key whenever detection is unresolved or spans several checkouts, now acquired per build-producing gate rather than held around the whole run, so a read-only allowlist gate never acquires it at all; a gate-attempt ledger that records every gate execution; prep evidence bound to a mutable branch head and disabled by default configuration; two test-selection oracles with a whole-workspace zero-match fallback; a hard-coded full-workspace typecheck command alongside a configured affected-only command no gate reads; runner worker counts pinned below the host’s capacity; an advisory-only prep latency budget alongside an opt-in per-prep enforced budget that ships disabled; and a release-time throughput regression ratchet in the pre-release checks. The release-time regression gate is that ratchet; the per-prep budget is an operational guard a workspace opts into, and D7’s creation trigger depends on neither of them.

Planned by ADR-121, not yet implemented: a single workspace-graph test oracle, supplied as a declared pack-owned capability, with printed selection evidence and no zero-match fallback; evidence reuse across heads and across the done-side rebase, bound to a normalized content fingerprint and an untouched graph neighbourhood in both directions; content-addressed build outputs with atomic activation and declared output roots, of which only this workspace’s own CLI output has landed; incremental typecheck and lint with fail-closed cache validation; input-hash-bound cached test results admitted as attestation evidence under five stated conditions; a neutral remote gate-capacity port with one reference adapter; and the N-party landing-queue protocol with its coordination-epoch clock and three consensus classes. Every decision except the remote gate-capacity port and the general build-output capability is owned by an existing work unit named in the record, by dependency; those two have no owning work unit, and each is created in phase 3 only when its stated trigger fires. No work unit is moved between initiatives.

  • Gates Reference — the gates that run today and how they are scoped.
  • Trajectory Supervision — the gate-attempt ledger this record extends from productivity to cost.
  • Product Policies — cross-platform parity, documentation parity, and vendor neutrality, all binding on this record.
  • Metrics & Flow — where the throughput measurements come from.