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.
A fleet’s cost per landing is a governance property, not a performance detail. The decision set is recorded in the architecture decision record Gate Execution Economics for an N-Party Fleet. 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 |
|---|---|
| D1 | Weighted admission replaces both host ceilings — the fixed-capacity gate-execution semaphore and the capacity-1 whole-run build-output hold. |
| D2 | One workspace-graph test oracle with printed selection evidence; a zero match fails closed instead of running the whole workspace. |
| D3 | Evidence reuse across heads and across the done-side rebase, bound to a normalized content fingerprint and an untouched graph neighbourhood. |
| D4 | Content-addressed build outputs with atomic activation; isolation is the default, declaration is the contract. |
| D5 | Incremental typecheck and lint with fail-closed cache validation bound into the prep fingerprint. |
| D6 | Input-hash-bound cached test results count as attestation evidence under five stated conditions, and otherwise the test executes. |
| D7 | A neutral remote gate-capacity port: local and remote providers are indistinguishable to the caller, and the default needs no network. |
| D8 | The 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.
D7 is planned for a later phase:
bigint stats plus a per-file content digest —
has since landed, after this decision’s second trigger fired: a fail-closed
case recurred on the integration target itself. What remains unimplemented 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.
wu:prep runs every ratchet suite whose declared scan paths touch the diff, so a
landing cannot break main from a rule it never ran. Correct selection is not enough on its own:
a suite that reads the whole repository costs the same for a one-file change as for a release, and
selecting 30 of 40 suites made a one-file prep take about 85 seconds.
The static ratchet phase therefore hands the diff to the suites it runs. It writes the work unit’s
added, changed and deleted paths, plus the commit they are measured against (the merge base with
origin/main), to a private scope file, names it in LUMENFLOW_RATCHET_CHANGED_FILES_SCOPE_FILE for the
one test process it starts, and removes it afterwards. A suite that reads the scope behaves in
one of two ways:
Three rules keep it safe. Unset, which is the post-land sweep, the release cut and a developer running a suite by hand, every suite scans everything. A scope that is named but unreadable is an error, never an empty scan. A suite whose own file, or a module it imports, changed keeps a full scan, because its matchers may have moved and every file has to be judged again.
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.
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.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.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.
| Class | Who must agree | Examples |
|---|---|---|
| A | The lease holder of each affected initiative | Granting, returning, revoking a landing window; accepting a readiness signal; scope narrowing inside its own initiative |
| B | Every lease holder (unanimity, fail-closed) | Changing the protocol itself; freezing the integration target; cross-initiative landing order; fleet-wide gate admission defaults |
| C | The owner | Skipping 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.
A gate run’s locks and ledger rows belong to the run, not to whatever process started it:
lockRoot option (not a
CLI flag) places the run’s admission pool, build-output lock and stale-lock
sweep under a directory the caller owns. In-process test runs use it, so they
never queue behind the host-wide locks that real lifecycle runs hold..git or workspace.yaml at or
above it (temp directories are never climbed past) refuses with the remedy
instead of waiting on the machine-wide build-output lock. A real checkout
whose build-output roots cannot be keyed still falls back to the machine-wide
lock, as before.Every vitest run in the repository asks for host admission, so a hand-started test cannot saturate the cores unseen. The request is sized by what the run executes:
vitest run <file> with one to three existing test files
takes one admission unit. A run with no file filter, or with more files, keeps the larger
scoped weight.A lock owner is identified by its pid plus its process start time, never by the
pid alone. Windows reissues a freed pid quickly and keeps lock
directories in %TEMP% across reboots. If a run is killed with taskkill /F,
or the machine loses power, another long-lived process can take over its pid.
That process no longer keeps the dead run’s locks alive:
wu:prep for that work unit is running, delete the named directory.The 2026-10-06 amendment decides that gate capacity follows the measured machine instead of a fixed product cap. It is a decision, not yet behaviour:
gates.execution_lock.concurrency becomes an
optional cap that can only lower it.Today’s behaviour stands until each part lands: capacity is still capped at 16 units and a full run still takes the whole ceiling. The statement below tracks what has landed.
Implemented today: weighted gate admission 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 (superseded by the 2026-10-09 amendment; deletion planned);
a build-output writer lock of capacity 1 with a 60-minute fail-closed wait (the
build-output exception, not capacity admission), 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 that
records gate-run cost alongside claim-to-done phase/size-band medians and
lifecycle command wall time, refusing only on a claim-to-done or lifecycle
command regression against the prior release, never on gate-run cost alone. 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, 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; the gate capacity clause now points to the 2026-10-09 amendment, which removes the gate lock and its admission pool: live memory and disk start guards with a bounded defer budget, operating-system priority classes at exec and slowdown-aware deadlines, under invariants S1-S7 and the lock deletion (Release A in observe mode, then Release B after calibration); the 2026-10-06 capacity clauses it supersedes are listed in its supersession table; and a neutral remote gate-capacity port with one operator-declared reference adapter; and the N-party landing-queue protocol with its coordination-epoch clock and three consensus classes.