Skip to content

feat(land-lock): carry the authorised branch, and answer whether it may run (CLOUD-420) - #363

Merged
wenzowski merged 1 commit into
mainfrom
claude/landing-lease-optimization-hkmacd
Aug 12, 2026
Merged

wenzowski merged 1 commit into
mainfrom
claude/landing-lease-optimization-hkmacd

Conversation

@wenzowski

Copy link
Copy Markdown
Contributor

First of two for CLOUD-420. This is the enabling gap the issue names: the lease identifies a clone (hostname-pid-random), which a GitHub runner has nothing to compare itself against — so the lease is checkable only by the code path that already cooperates.

  • The lease body gains a branch: line, and land-lock gains authorises <branch>: read-only, side-effect free, a pure function of (lease state, branch). Exits 0 run / 3 stop / 2 could not look. Three is a third answer the usual pair cannot carry — 1 already means "held by someone else", which is a reason to stop rather than the instruction.
  • It fails open, alone among the predicates here, and that asymmetry is the design: a lease it cannot read would stop every job in the fleet, whereas waving one matrix through costs one matrix. Unreachable remote, unparseable body, and a lease with no branch: all run.
  • Shipped ahead of the CI step that reads it, deliberately. Every lease minted before this commit carries no branch:, so that fail-open row is not an edge case during rollout — it is every lease. Landing the field first means live leases already carry it when the workflow check arrives.
  • branch was already a global here meaning the lease's own ref, so the new value is land_branch. Writing the wrong one stamps batten-land-lock into every lease and looks correct in review; a test pins it.

45/45 in tests/land-lock.bats, ten of them new. Both mutants discriminate: inverting the comparison kills the run/stop pair, turning fail-open into fail-closed kills the rollout row.

Next PR: the workflow precondition, ci-local-parity's property, and ready-guard's receipt — plus a correction to the issue's design that measurement turned up, noted below.

Correction for the issue: the refinement rests on "branch protection requires only final, which concludes cancelled too". That is false — ci.yml:242 uses always(), which GitHub runs even when the run is cancelled. Proven on run 31566043914: ci cancelled, final executed and failed. The next PR changes it to !cancelled(); without that, every lease-stopped run would red final and land re-drafts on red — re-drafting healthy PRs fleet-wide, the outcome the hazard section calls disqualifying.

Refs: CLOUD-420


Generated by Claude Code

…ay run

The lease identifies a CLONE — hostname-pid-random — which a GitHub runner has
nothing to compare itself against, so the lease is checkable only by the code
path that cooperates. That is CLOUD-420's enabling gap: an agent that pushes to
an already-ready PR spends a full matrix without ever touching the lock, and
measured 2026-08-12 that was four concurrent matrices while the lease changed
hands three times, every holder honouring it.

A branch name is the one identifier both ends can see. The lease body gains a
`branch:` line and land-lock gains `authorises <branch>`, a read-only verb that
is a pure function of (lease state, branch): 0 run, 3 stop, 2 could not look.
Three is a third answer the usual pair cannot carry, since 1 already means "held
by someone else" — a reason to stop rather than the instruction.

It is the one predicate here that fails OPEN, and the asymmetry is the whole
design: a lease this cannot read would stop every job in the fleet, where waving
one matrix through costs one matrix. An unreachable remote, an unparseable body
and a lease carrying no branch all run. That last row is not an edge case during
rollout — it is every lease minted before this commit, which is why the field
ships ahead of the CI step that reads it.

The name `branch` was already taken here for the lease's own ref, so the new
value is `land_branch`; writing the wrong one would stamp batten-land-lock into
every lease and look correct in review. A test pins that. Ten rows cover the
table and both mutants discriminate: inverting the comparison kills the run/stop
pair, turning fail-open into fail-closed kills the rollout row.

Refs: CLOUD-420

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X4tzyT3Q3hXo5QFEESENYP
@linear-code

linear-code Bot commented Aug 12, 2026 •

Copy link
Copy Markdown
CLOUD-420 The landing lease is enforced only by the code path that honours it, so an agent that skips `land` still spends a full matrix

Why

CLOUD-393 serialises landing behind a lease and cuts the discarded-CI-run rate. It is enforced entirely inside mise-tasks/land. An agent that runs gh pr ready by hand, pushes to an already-ready PR, or wraps landing in its own logic spends a full four-job matrix without ever touching the lock.

That is the failure this repository names on its front page: "A new rule without a runnable gate is half a change. Prose is feedforward only." The lease is a convention honoured by the cooperating path, and the threat model is the honest agent that does the wrong thing — CLOUD-200 records a session that satisfied gh-guard and then wrapped mise run land in a bespoke retry loop it invented on the spot. Nothing stops the same shape here.

The dominant case is residue, not defiance. Measured 05:17–05:19Z on 2026-08-12: four concurrent pull_request matrices (#356, #354, #332, #302) while the lease changed hands three times, so the lease was being honoured by every session that held it and all four matrices ran anyway. land re-drafts only on red, so a landing interrupted any other way — a container reclaim, a stopped task, a lost lease, a die on a rebase conflict — leaves the PR ready permanently, and every later push to it buys a full matrix with no landing attempt in progress at all. All three of the other PRs were draft=false. The implementation is scoped to that case; an agent that skips land deliberately is the same mechanism and the smaller share.

The enabling gap. The lease identifies a clone (hostname-pid-random), which CI cannot check anything against. Adding the branch it authorises to the lease body is what makes it verifiable by the thing spending the money.

Refinement — Ready

  • Source of truth (§1). The lease ref refs/heads/batten-land-lock — a parentless commit over the empty tree whose body is land-lock / holder: / expires: / nonce: — read server-side by the workflow that is about to spend the runner. This issue adds a fifth line, branch:, and land-lock-check gains its well-formedness assertion rather than a second gate growing beside it. Not a receipt in a clone, which is exactly the artefact an agent skipping land never writes.

  • Mechanism (§3). land-lock gains a read-only verb, authorises <branch> — a pure function of (lease state, branch) reusing the existing observe / expired / released predicates. The alternative, re-parsing the body in workflow YAML, is a second authority for the ref and silently drops the read semantics the lease was pressure-tested into: a per-process observation ref, an unparseable body reading as held, and an unreachable remote that is not "free". Exit 0 run / 3 stop / 2 could not look.

    Each expensive pull_request job gains a first step, before the real checkout: a one-file sparse checkout of mise-tasks/land-lock at main (fetch-depth: 1, ~2s) and one invocation of it. The predicate comes from trunk, never from the head under test — that head has not been graded yet.

lease state action
absent, released, or expired-and-corroborated run — nobody is landing
branch: is this branch run — this is the authorised attempt
branch: names another branch stop, having spent only the spin-up
unreachable, unparseable, or carrying no branch: run, with a warning — fail open

Nothing in the table asks why a push happened, which is what makes it cover the residue case: the precondition is per job rather than per landing, so a push to a PR left ready by an interrupted land is stopped by the same row that stops a hand-typed gh pr ready.

The last row is the design and not a fallback: failing open costs one matrix, while failing closed on an unreadable ref stops every PR in the fleet, and a body minted before this change ages out within one TTL (120s).

  • A step, not a preflight job (§3), and the arithmetic that decides it. In billed minutes the two are closer than a wall-clock reading suggests: a gate job costs 1 job-minute per stopped run, because the expensive jobs never start and a skipped job bills nothing, while a first step in each job costs 7. Against that, the gate taxes every legitimate run one extra job-minute plus ~15-20s of serial spin-up. The step is therefore cheaper exactly while legitimate runs outnumber stopped ones better than 6:1, and lap length sits in the exponent of the collision model this whole line of work exists to shrink, which decides it at parity. That ratio is measurable rather than assumed; it is the number to re-check if the residue rate stays high.

  • THE HAZARD — a stop is a third answer, and the verdict layer has two (§2). A first step cannot make a job skipped; only a job-level if: can, which is the preflight job ruled out above. So the reachable conclusions are success, failure and cancelled, and checks-green reads success or neutral as green, failure and cancelled as red, and a latest-run skip as "not an answer".

    • Success or neutral grades a head green that compiled nothing, and main advances to exactly the SHA that passed. Disqualifying.
    • Failure re-drafts healthy PRs fleet-wide, since land re-drafts on red. Disqualifying.
    • Cancelled is the one that can be made correct. "This run declined to answer" is a third thing the verdict vocabulary lacks, and CLOUD-436's latest-run-per-name grouping is what makes a per-name declination readable at all.

    So: the step self-cancels the run (POST /actions/runs/{id}/cancel, actions: write on that job alone). Reading cancelled as a declination rather than as red is CLOUD-363's change, in flight on fix(tasks): read a cancelled required check as no verdict, not as red #302, which moves it into skipped's not-an-answer bucket in checks-green and in land's graded_runs together. This issue consumes that predicate rather than restating it, and that is why it is a blocker rather than a note: a stop landing first would re-draft healthy PRs fleet-wide, which is the hazard this bullet exists to avoid.

    Two consequences, both load-bearing:

    • Branch protection requires only final, which concludes cancelled too, so an unauthorised head cannot be merged while it waits.
    • Because graded_runs reads a cancelled set as ungraded, the stopped head's next land lap re-fires its ready and mints a real run, so the re-dispatch this would otherwise have to specify arrives with CLOUD-363's second half. It cannot loop: land acquires the lease before it pushes, so a land-driven push is never the one stopped.
  • Humans are unaffected by construction (§2). The "absent or released" row is what preserves them: a person pushing while no agent holds the lease sees no change. They wait only in the case where their run would have been voided anyway, which is a saving rather than a tax. fast-forward.yml is not touched.

  • Below it, for free (§3). Extend ready-guard — which already denies gh pr ready without verify and linear-check receipts — to require a lease.<branch> receipt, written by land-lock acquire into the same receipts directory. Catches the honest mistake at zero CI cost. A fail-fast convenience, not the guarantee: a hook can be unloaded (CLOUD-187) or bypassed, which is the whole reason the server-side check is the load-bearing half.

  • Above it (§3). A ci-local-parity property asserting that every pull_request job which checks the repository out carries the precondition as its first step, so a new job cannot silently omit it. The exemption is computable rather than enumerated: a job with no actions/checkout — final, the fan-in — has no work to protect.

  • Engine gap, per §2 (§3). That property is a predicate over workflow structure, which no rule kind can address, so it extends ci-local-parity instead of landing in batten.toml. The gap is CLOUD-452, linked rather than left as an exception.

Cost (§1), in the unit the invoice uses. This repository is private and every pull_request job is a GitHub-hosted ubuntu-latest runner, so the metered unit is a job-minute rounded up per job, not a second of wall clock. Measured p95 per job, 2026-08-12: ci 429s, darwin-link 97s, cross 82s, commit-lint 65s, msrv 60s, final 14s, action 12s — ~759s of runner time, which bills as 17 job-minutes per full run.

  • The tax on a legitimate run is ~2s in each of 7 jobs, which per-job rounding absorbs: 0 billed minutes, unless a job already sits within 2s of a minute boundary.
  • A stopped run still bills its floor — 7 jobs x 1 minute = 7 job-minutes against the 17 it replaces. That is ~59% of the invoice and ~86% of the wall clock: real, and smaller than a seconds-based reading implies.
  • The cheapest option for the residue case spends nothing at all, because a push to a PR left draft triggers no job: CLOUD-458. This issue is the backstop for what still leaks past that, so it must not be sized as though it carried the volume.

Local execution is the unmetered tier and nothing here moves work onto the metered one. The CI-side check exists because the local one is the half an interrupted session never reaches.

Test obligation

  • tests/land-lock.bats — the four rows above as a pure function of (lease body, branch), plus the two that must not be conflated: unreachable is not absent, and a missing branch: is not a foreign holder.
  • tests/land.bats — the composition rather than the predicate, which CLOUD-363 owns and tests: a head whose required runs were stopped by the precondition reads as ungraded, so the next lap re-fires the ready instead of re-drafting. Mutation-checked per CLOUD-418: with the stop step removed from the fixture workflow, that head grades normally.
  • tests/ci-local-parity.bats — both directions: a checkout-bearing pull_request job without the precondition is refused, and a job with no checkout is not.
  • tests/land-lock-check.bats — a lease body with no branch: line is reported.

Commit / bump (§6): feat(ci) — patch until 0.1.0 regardless of type.

Blockers (§8): blockedBy CLOUD-363 — the stop conclusion is safe only once a cancelled required check reads as no verdict rather than as red, which is in flight on #302. CLOUD-393 landed in #340, so the lease exists, and adding branch: to its body is this issue's own first step; CLOUD-436 landed in #347, supplying the latest-run-per-name grouping the declination sits on.

Acceptance

  • A PR pushed while another branch holds the lease stops within seconds instead of running a matrix.
  • A PR pushed while the lease is free, or while its own branch holds it, runs unchanged.
  • A stopped run neither reds the PR nor leaves its head unrecoverable: the branch's own next lap mints a real run without a hand-minted SHA.
  • A push to a PR left ready by an interrupted land is stopped by the same row as a hand-typed ready, with no landing attempt in progress.
  • An unreachable lease, or one carrying no branch:, runs the matrix rather than stopping the fleet.
  • A new checkout-bearing pull_request job cannot omit the precondition without failing ci-local-parity.
  • land-lock-check fails a lease body missing branch:.

Review in Linear

@sonarqubecloud

Copy link
Copy Markdown

@wenzowski
wenzowski marked this pull request as ready for review August 12, 2026 06:33
@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

@wenzowski
wenzowski merged commit bd95ca2 into main Aug 12, 2026
13 checks passed
@wenzowski
wenzowski deleted the claude/landing-lease-optimization-hkmacd branch August 12, 2026 06:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants