fix(land): cut the cost of a lap without weakening a verdict (CLOUD-399, 345, 376, 404, 413, 418, 420, 470, 475, 476) - #375
Conversation
CLOUD-399 `land` cannot converge at current fleet cadence: 16 laps, 5 `/fast-forward` comments, every one lost the race to a moving `main`
Why Measured 2026-08-11 landing #306 (a one-file The cause was measured, and it is not latency. Over every
The bot answered all 248 attempts within 23 seconds. 248 attempts in 30 minutes producing 5 merges is a thundering herd, ~2% success per attempt — not a slow bot. That retires candidate #2 (instrument bot latency and wait on the merge): the quantity it proposed to measure is 12s. Candidate #1 shipped. The landing queue is CLOUD-393's rolling lease, landed in #340. Re-sampled 2026-08-12: the baseline holds (245 failure : 6 success over the same window), and lease turns are honoured by every session that takes one. What remains is candidate #3, plus a cost inversion the lease exposed.
Refinement — Ready
Test obligation
Commit / bump (§6): Blockers (§8): none. CLOUD-393 landed in #340 and supplied the queue this issue's diagnosis called for. Acceptance
|
A survey that classifies a corpus needs cases whose answer is known because getting them wrong is a mistake already made, and the run must fail when one misclassifies. Round one of this survey matched policy files by filename and was wrong in both directions; round two was built to make that unrepresentable and reproduced the same blind spot in a new costume, fetching only paths guessed in advance. The canaries are what caught it. The transferable half is the sentence about instruments: absence of evidence is a claim about the instrument before it is a claim about the world. The corollary for any classifier is that a name may decide what gets read, and only the text decides what a thing is. Refs: CLOUD-315
The command shipped with the framing the memory beside it had already dropped: "the honest signal that you are past it is a rising re-verify rate", plus a pointer to `mem:workflow/agent-fanout` for "the current cap", which that memory no longer states in those terms. Two authorities disagreeing about the same fact, in the file whose §1 was "one authority each, no duplication" — and the command is the reachable one, so a dispatcher invoking `/plan-fleet` got the superseded model while the memory it points at carried the current one. Replaced with the cost table the memory already holds: re-verifying is free because `land` laps without a model turn, and what actually costs is a rebase conflict, CI minutes on a voided run, and tokens. Objective restated as pace of landed work per token, with the saturated-queue target and the CSMA/CD framing, and the CI-minutes row now names CLOUD-369 as unbuilt rather than implying a control exists. Refs: CLOUD-367
…nheriting a spent window Two defects in `plan-hold`, both measured 2026-08-12 in one session. THE ANSWER WAS INVISIBLE. `plan-hold-guard` gates `PreToolUse` on `ExitPlanMode|AskUserQuestion`; `plan-hold-release` listens on `UserPromptSubmit`. Those are different event classes, and a human answering either of those two tools produces a TOOL RESULT, not a prompt. So for the exact case the mechanism exists to serve, the release could never fire: a hold armed, an `AskUserQuestion` answered, the hold still live afterwards, ended by removing its sentinel by hand. CLOUD-451's third acceptance bullet, unmet since it landed. `plan-hold-release-tool` is the missing half, on `PostToolUse` over the same two tools the guard already names. No classifier: `plan-hold-release` must decide whether a prompt came from a person because `UserPromptSubmit` carries machine turns too, while here the provenance is structural — the event fires only after a tool whose whole purpose is to ask a human. The `tool_name` check is belt to the matcher's braces, because a matcher widened later would otherwise turn every tool call into a release. CLOUD-435's cost argument does not reach it for the reason it does not reach `plan-hold-guard`: these two tools fire at most once per turn, and it is invoked by path, so no task-runner startup is paid. THE WINDOW ERODED SILENTLY. A second launch answered "already held" and exited, which keeps one sleeper and hands the new handoff whatever is left of the old one's cap. Some answers reach neither release path — a reply typed mid-turn arrives `<`-wrapped and reads as a machine turn — so that handoff's hold never releases, the next inherits a partly spent window, and eventually one is guarded by a hold about to cap and the container is reclaimed while somebody is reading. Nothing blocks, so nothing announces it. A second launch now releases the incumbent and arms fresh: at most one sleeper still, and every handoff gets the whole cap. Released, never signalled — a killed hold wakes nothing. Deliberately NOT touching `plan-hold-release-check`'s `<`-prefix classifier. The mid-turn false negative is real, but widening a literal without measuring it over real transcripts is the mistake CLOUD-252 and CLOUD-323 exist to prevent. The erosion fix removes its compounding cost; the false negative itself stays recorded on CLOUD-485. Refs: CLOUD-485
Every bound in this memory was a bound on landing, and its cap of 2 is derived from land contention. An agent that researches, reviews, or drafts never lands, so that derivation says nothing about it — and the silence read as absence of a constraint rather than absence of a derivation. Eight drafting agents were launched into it. The binding constraint for that shape is per-agent fixed cost, which is paid once per agent and multiplies with N. The measured floor now has a home: 63,848 tokens for one agent to fetch a single issue and run one lint, for near-zero work. Each prompt named eight artifacts as required reading, so that floor was paid eight times over before anything happened. Three rules follow — digest rather than cite, checkpoint at each unit's own gate because scratch dies with the container, and pilot one unit through its durable write before widening — and the section says outright that none of them is gated, because the predicate they need measures a session's real spend and that is out of tree (CLOUD-95). Assumed enforcement is worse than stated absence. Also corrects the implementer contract in the same file: it still listed a hand `gh pr ready` before `land`, which is the defect CLOUD-247 named, and `land` has been the only readier since. Refs: CLOUD-289
…wo exhaustions (CLOUD-399) `LAND_MAX_LAPS` bounds CI matrices (~17 job-minutes each); `LAND_LOCK_MAX_WAITS` bounds lease waits (a conditional poll, no runner). Both defaulted to 8, which authorised ~2 runner-hours of metered spend against ~16 minutes of free waiting — and measured on #302, the expensive budget drained first. Laps to 2, waits to 64, so the defaults express many free waits and few paid laps. Neither is a clock; both stay env-overridable. Both exhaustions also ended in `exit 1`, so a saturated fleet ("wait, and land later") and a runaway branch ("main moves faster than a lap takes") were indistinguishable to anything but a human reading stderr. They now carry their own codes through `die_with`, which `die` delegates to so the other eighteen call sites are unchanged. The stop-count sensor counts both spellings. Counting only `die "` would have read the split as two stops removed, and would have let a future `die_with` stop be added completely uncounted — the exact blindness that assertion exists to prevent, reintroduced by the change that split the helper. Refs: CLOUD-399
…one (CLOUD-475) One flat durable class counted `save_comment` as a home with no term for the target's state, so a turn that finds a defect in landed code, comments it onto the Done issue that shipped it, and files nothing scored durable and passed. The board then has no open row, no sweep visits it, and no gate notices: the finding is durably RECORDED and permanently UNSCHEDULED. The gate written to catch a stranded finding was cleared by the exact act that strands it. "Refuse a comment on a Done issue" is uncomputable here — no tracker credential exists in a hook, as for `claim-check` — so the predicate keys on the call shape the transcript already carries: `save_issue` with no `id` OPENS a row and is open by construction; `save_comment` and `save_issue` with an `id` ANNOTATE one that may be terminal. A home needs at least one opening. Memory and document writes keep their standing. Written once before against the single-pass scan and stranded there; this is the same rule re-anchored onto the two-pass structure CLOUD-479 landed. The `#id`/`#noid` stamp rides pass 2's existing jq, so nothing slurps the transcript and no turn is built whose verdict is discarded — the cost property that rewrite bought is untouched. The two classes are matched in one alternation, never two greps joined by `||`, which `pipefail-grep-check` refuses and is right to. The refusal names the practice, not the rule: an author who commented the finding correctly believes they wrote it down, so "not durable" reproduces the confusion. What they are missing is an open row. Refs: CLOUD-475
…use (CLOUD-345) When a PR merges GitHub deletes the head branch, but a plain fetch never removes `refs/remotes/origin/<branch>` — so the tracking ref survives, still naming the SHA that landed. Reusing that branch name then hits a `--force-with-lease` whose expectation names a ref the remote does not have, and the push is rejected as `stale info` forever: no number of laps clears it, because every lap re-fetched without pruning. Both of `land`'s fetches prune now, including the merged path — which is the instant the phantom is minted. The rejection named the one cause that was usually not true, and named it toward the dangerous action. "Someone else moved the branch" describes a concurrent writer, whose correct response is caution; the common case is our own merge having deleted the branch, where `git log HEAD..origin/<branch>` is empty and every check an operator would run says forcing looks safe, for the wrong reason. The split is mechanical — absent from the remote is a different state from present at an unexpected SHA — and `--force-with-lease` is still what pushes in both, so the lease is not traded for a worse bug. The suite keeps the concurrent-writer row as the anti-vacuity half: a genuine rival must still get today's caution and must never be told to prune. Refs: CLOUD-345
…D-420) `set -euo pipefail` became `set -uo pipefail` to keep the header's promise — "AND IT NEVER EXITS NON-ZERO" — and nothing exercised the case that promise exists for. Eighteen cases covered `gh` and fetch failures; every one handed the script a working `RUNNER_TEMP`. The whole setup chain was unguarded: the `RUNNER_TEMP` fallback, `mkdir -p`, the redirect, `chmod +x`, `git init`, `remote add` and `config --local`. It reached fail-open by accident of the `*)` arm at the bottom, which then reported `land-lock answered <rc>` — attributing a workspace failure to a predicate that was never consulted, on the line a human reads when the fleet misbehaves. Guarded explicitly now, with the same verdict (run) and the cause named honestly. Two rows cover it: a `RUNNER_TEMP` that cannot hold a directory still exits 0, and the message no longer blames land-lock. Both go red with `-e` restored, which is what makes them a test of the promise rather than of the happy path. Refs: CLOUD-420
…t once (CLOUD-418, CLOUD-376, CLOUD-470) These three land together because they cannot be split: the mutation rows added here name the very cases the other two changes add, and a `#MUTANT` row naming a case that does not exist yet fails the sweep by design. CLOUD-418 — `mise run mutant`. The obligation was "a rule ships with a runnable gate" — a gate that EXISTS. Nothing required evidence it DISCRIMINATES, and a test passing on both the fixed and the broken code satisfied every other rule here. That failed four times (CLOUD-235, CLOUD-352, CLOUD-401), the last one live: a concurrency test written for a real race was green, and stayed green when the bug was restored. Now a declared one-line corruption is applied to a throwaway copy and the named case must go red. The enforced set is data: `$MUTANT_GATES`. A gate IN it with no declaration fails — that is the anti-vacuity term, without which the task reports success over a set it never touched. A gate not in it is a filed row (CLOUD-480), never a silent exemption. Seeded with the five gates this bundle touches, so its "mutation-checked per CLOUD-418" obligations are cashed rather than cited. It mutates a copy of the WORKING tree, never the tracked file — mutating in place staged a mutant into a pushed commit on 2026-08-12 — and refuses two evasions an inert or misnamed row would otherwise buy. Both were hit on its first run, and one exposed a test written minutes earlier that did not discriminate. CLOUD-376 — `CI_ANSWERED_CONCLUSIONS` in mise.toml [env]. `checks-green` and `land`'s `graded_runs` each hand-maintained a conclusion list, in agreement only by a paragraph of comment in each file — precisely the guarantee that had already failed, since `neutral` was missing from one until #302 added it and nothing detected the gap. The catch-all is gone with it, so an unknown conclusion holds the poll open instead of being reported red against a head nothing judged. CLOUD-470 — the declination is asked of `land-lock authorises`, the same verb the runner's own precondition consults, rather than re-derived from a raw `conclusion == "cancelled"` read. Two authorities for one fact is the CLOUD-351 shape. What that verb cannot answer is recorded in the code rather than papered over: it judges the lease now, so a `cancel-in-progress` cancellation is no longer caught — that is a superseded run, not a declined one. Refs: CLOUD-418, CLOUD-376, CLOUD-470, CLOUD-480
…e (CLOUD-413) Measured on PR #323: 24 laps across three invocations, never merging, and not one lap failed for any of the three reasons `land` is documented to stop on. Several refusals were a 403 rate limit, which `land` could not tell from "main moved" — so its response to being rate-limited was to generate more of exactly the request that was rate-limited, each retry costing a `verify`, a CI run and another comment. The comment POST now asks with `-i` and reads the response's own headers, which is where the delay is stated: `Retry-After` if present, else `X-RateLimit-Reset` when remaining is 0, else a floor. Reading a second endpoint for that number would be one more request against the limit that just refused this one. The body split is `main-watch`'s idiom, since `gh` cannot filter a response it is also printing headers for. Nothing here gains a clock. The bound stays `LAND_ANSWER_MAX_UNKNOWNS`, a count — the one place `mem:github-rest-etiquette` says a retry cap belongs — and the pause is a delay before re-asking on a path that had already decided to lap. Lapping with no delay was never backoff; it was the same request again. The exhaustion message also stops telling the reader to run `gh api rate_limit` for a number the code was already handed, and states the reset time instead. Over those 24 laps its old diagnosis was wrong twice over: 7 of 8 laps in one invocation reached green CI, and several refusals were the limit rather than `main` at all. Refs: CLOUD-413
…UD-448) `tests/land-lock.bats` carried an acknowledged residual: the steal case graded seconds between the previous holder's expiry and the steal, and both ends of that delta are instants on one clock, so a deschedule landing between them inflated it. Under the parallel runner that fired on roughly 2 of every 4 `verify` runs, and it blocked CLOUD-274's landing directly — `land` refused to push on a `verify` whose only failure was this case, behaving exactly as designed over a signal that was wrong. A flaky gate is a bypassed gate. The case's own header named the fix and deferred it: report the number of PROBES `acquire` spent, which is a count on no clock at all. `acquire` now does. The promise was never really about seconds — "a dead lease costs one extra beat" IS "the steal lands on the first post-expiry probe" — so the assertion states that directly and no amount of load can move it. The seconds stay in the sentence because they are what a human reads; nothing grades them. Not retried, not serialised, not widened: all three were ruled out on the issue, and each would have encoded the flake as expected behaviour. Refs: CLOUD-450, CLOUD-448
…8, CLOUD-376) Four defects that cancelled out, so none of them was visible. `tests/checks-green.bats`'s CLOUD-376 row asserted the output does not contain "red" — against a message that reads "requi-red check(s) with no verdict". It could never pass, and it did not: it was red from the commit that added it. The mutation aimed at that case targeted `!($2 in isanswer) ? 3` in the RANKING expression, which only decides an unorderable pair. The case's fixture is orderable, so the mutant could not change its outcome. The row never discriminated; it read as caught only because the case was permanently red. `mutant` itself never checked the other half. It refuses an unappliable mutation, an inert one and a filter naming no case — but not a case that was already failing, which makes every mutation aimed at it read as caught. That is the vacuous pass this task exists to refuse, one level up from where it was refusing it. And `tests/mutant.bats` writes bats fixtures containing `@test` lines at column 0, which the `test:bats` count gate reads as cases of its own: 1333 of 1337 reported, failing a gate whose whole job is to notice a suite that ran fewer tests than it declares. Tab-indented heredocs now, so a file this suite WRITES is not counted as a case this suite HAS. So: the assertion names the verdict (`is not green`, and the exact no-answer line) rather than a substring of it; the row targets the verdict site, where flipping it really does turn the case red; the harness runs the named case unmutated first and reports `case-already-red` rather than counting it; and the count gate sees eleven cases, which is how many there are. Costs one filtered bats run per row, which is what an anti-vacuity term is worth. Refs: CLOUD-418, CLOUD-376
12b8b46 to
6261a5b
Compare
|
|
/fast-forward |
… the board Two shapes that reached something expensive with nothing checking them. They land together because both declare mutants and both widen $MUTANT_GATES. CLOUD-488 — run-shape-guard refuses a `git commit` that cannot obtain a message. `githooks(5)` runs pre-commit BEFORE git asks for the message, so a commit that can never get one still spends the entire gate and only then exits with "Aborting commit due to empty commit message". Measured landing #375: git add -A && git commit -F - >log 2>&1 && mise run land >l2 2>&1 <<'EOF' The heredoc binds to the LAST element of the `&&` list, so `land` got the message and `git commit -F -` got the harness's /dev/null. ~4 minutes of gate on a doomed commit, and killing it took `kill -9` on the process group because hk's children carry its command line. Judged per element, which is what makes it decidable: the opener is in the command string and absent from the element that needed it. A heredoc that genuinely binds here is allowed, as is `< file` and `<<< "$msg"` — any redirect into that stage is a message source, so one test covers all three. The second shape is a `git commit` naming no message flag at all, which opens $EDITOR in a non-interactive call and blocks until the harness kills it. `git -C <path> commit` is deliberately NOT caught: CLOUD-199 measured that a guard with false positives gets bypassed, and a false negative is the direction to be wrong in. CLOUD-512 — nothing gated a move to In Review. graph-check already decides it correctly and CLOUD-309 bound it to the release sweep; the transition itself passed through nothing, so a wrong label survived until somebody thought to run the gate. Measured 2026-08-13: a sweep after #375 put CLOUD-480 In Review on a `Refs:` trailer that named it as the still-open gap. It sat wrong for 4.5 hours, and graph-check refused it in one invocation once asked. The gate was never wrong; it was never consulted. This adds a TRIGGER, never a second predicate — a copy of `in-review-no-pr` here would be the CLOUD-351 shape. A hook has no tracker credential, so the guard cannot look an issue up and does not try: graph-check records which ids it judged, on the success path only, and the guard demands the id be among them. Keyed to the SET rather than the turn, because a bare "graph-check ran" receipt is satisfied by judging one clean issue and then sweeping fifteen — which is the sweep this exists to stop. Bounded in age for the same reason issue-read-guard's read is, and the two tests are one grep over whole LINES: a stale line naming this issue and a fresh line naming others must not combine. graph-check's tests now run in a throwaway repo. Run from this checkout they minted adjudications into the real .git/batten-receipts/ — receipts that would have authorised a live session's moves over fixture ids. Found on the first green run of the new rows. Not in this change, and each for a stated reason: CLOUD-454's `mention-without-relation` is parked, because the measurement its own §2 demanded falsified it — the rule fires on 0 of 50 in-set mentions, since Linear DERIVES relatedTo from a mention rather than recording it separately (measured on CLOUD-480, where four relations appeared from a comment's prose alone), so it would ship as a rule that cannot fail. CLOUD-427 is Rust core with a much heavier test obligation, and CLOUD-480 now spans ~80 files in the directory this change edits. Refs: CLOUD-488, CLOUD-512
…locks
Closes CLOUD-613
Closes CLOUD-723
Closes CLOUD-1112
CLOUD-613 asked one question and reserved it for its owner: is heredoc binding
worth a permanent parser surface, or does the predicate stay in bash forever?
Answered on 2026-08-28 — model it. This is that.
THE PREDICATE IS NARROWER THAN "MODEL HEREDOCS", which is what makes the surface
affordable. `run-shape-guard.sh:372-440` decides per element: `git commit` with
`-F -` and no redirect in that same element. So the parser owes two things and
not a shell — drop heredoc bodies before tokenizing, and record per-segment
redirect binding — and both fall out of the character walk `hook::segments`
already makes.
Doing it INSIDE that walk rather than as a pre-scrub is the load-bearing choice.
A pre-pass has no quote state to consult, so `echo "<<EOF"` reads as an opener
and starts a skip to a delimiter that never comes: the rest of the command
vanishes, the gate stops looking, and the suite stays green over it. The same
position decides quoting, redirection and openers, once.
BOTH DIRECTIONS, AND THE SECOND IS A LIVE DEFECT. CLOUD-723 is this parser
getting heredocs wrong the other way: every `pipeline` row decides over these
segments, so a `;` inside a heredoc BODY split the list and `verdict-not-
discarded` refused a correct command. It fired twice in one session, both times
on the command that was writing the rule down. One parser, one fix, and the
maintenance surface the reserved question worried about is bounded by having the
two directions asserted against each other.
THREE PREDICATES, over `input.call.segments` rather than a hand-rolled scrub:
unsatisfiable-commit `git commit -F -` with nothing bound to ITS OWN element
reads /dev/null — and `githooks(5)` runs `pre-commit`
before git asks for the message, so the whole gate is
spent first (~4 minutes measured, CLOUD-488, PR #375).
foreground-sleep the harness kills a foreground call at ~2 minutes, so a
patient poll FAILS (CLOUD-482, exit 143 and 144).
background-timer a backgrounded `sleep N; tail log` exits on the clock,
never on the event — 490 in one session against 523 of
524 tasks that notified on exit; 2 changed a decision
(CLOUD-821).
The last two are CLOUD-1094's `run-in-background` finding its first consumer.
THE ALLOW IS THE LOAD-BEARING HALF of all three, and each has its own
discriminating negative: `git commit -F - <<'EOF'` in one element, and — for the
wait rules — the same loop twice, differing only in posture.
WHICH IS WHY CLOUD-1112 IS FIXED HERE RATHER THAN CARRIED. That posture pair did
not work: `do sleep 1` resolves to the program `do`, because the look-through
table covers `env`/`timeout`/`sudo`/… and no shell KEYWORD, so the sleep in a
loop body is never reached. `run-shape-guard.sh`'s `resolve()` answers the same
way, and its comment that an element-scoped loop test "would deny every correct
wait" presumes an element it never reaches.
The instinct was to port the gap, on the rule that a migration moves a predicate
rather than changing it — and `filed-over-own-diff` refused the row filed about
the file this branch edits, which is what forced the premise to be checked. It
does not hold: CLOUD-613's acceptance turns on the backgrounded allow being LOAD-
BEARING, and with the gap ported that clause passes VACUOUSLY, the loop being
allowed because nothing resolves the sleep rather than because the exemption
works. Shipping a vacuous acceptance is CLOUD-418's defect, so `keywords` — `do`,
`then`, `else`, `elif`, `time` — is looked through exactly as the wrappers are.
`until`/`while`/`if`/`for` stay out: they introduce a condition list, and
`waits_on_condition` reads them as words.
Two verdicts move, both stricter: a FOREGROUND conditional wait now refuses, and
a backgrounded `for i in $(seq 60); do sleep 10; done` refuses as the timer it
is. This is the one place the two authorities deliberately disagree while both
are live, and it is in the denying direction, so no call gets a weaker answer
from the pair than it had from the guard alone. The bash cannot be repaired —
`shell-retirement` admits only whole-file deletion — and CLOUD-856 retires it.
TWO READINGS THAT LOOK LIKE STYLE AND ARE VERDICTS:
`segment["input-redirect"] == false`, never `not segment["input-redirect"]`.
Rego reads an absent key as undefined and `not undefined` HOLDS, so the negated
spelling denies every commit on an engine that stopped emitting the field. The
comparison allows there — the direction a miss is supposed to fail in.
`input.call["run-in-background"] != true`, never `== false`. `null` is "the host
said nothing", most hosts say nothing, and the shape refused is a WAIT whose
posture being unknown is the case to be strict about. The bash spells it
`[[ "$background" != true ]]` and the two must not diverge while both are live.
A NEWLINE STAYS WHITESPACE, not a separator, and bash disagrees. Promoting it
would change every landed `pipeline` verdict — `mise run verify` on one line and
anything on the next becomes a discarded status — which is a decision about
`verdict-not-discarded`'s reach rather than about heredocs. The cost is stated
rather than absorbed: shell following a heredoc's terminator joins the segment
its opener was written in. It under-denies, never the reverse.
THE BASH IS UNTOUCHED, and that is the ratchet rather than an oversight.
`shell-retirement` admits DELETING a governed file and refuses SHRINKING one, and
`run-shape-guard.sh` keeps a fourth family whose blocker is CLOUD-856. So it
cannot lose these three until it can lose all four, and both authorities decide
them until then. CLOUD-1108 is that gap's row; the predicates here are written
from the bash's own decision table so the two cannot answer differently while
both are live. CLOUD-613's acceptance moved the deletion clause to CLOUD-856
accordingly.
The rule row is renamed `commit-message-obtainable` -> `run-shape`: a row named
for commit messages now also refuses a foreground sleep, and the module is what
it registers.
Refs CLOUD-843, CLOUD-856, CLOUD-1094, CLOUD-1108, CLOUD-199, CLOUD-418
…locks
Closes CLOUD-613
Closes CLOUD-723
Closes CLOUD-1112
CLOUD-613 asked one question and reserved it for its owner: is heredoc binding
worth a permanent parser surface, or does the predicate stay in bash forever?
Answered on 2026-08-28 — model it. This is that.
THE PREDICATE IS NARROWER THAN "MODEL HEREDOCS", which is what makes the surface
affordable. `run-shape-guard.sh:372-440` decides per element: `git commit` with
`-F -` and no redirect in that same element. So the parser owes two things and
not a shell — drop heredoc bodies before tokenizing, and record per-segment
redirect binding — and both fall out of the character walk `hook::segments`
already makes.
Doing it INSIDE that walk rather than as a pre-scrub is the load-bearing choice.
A pre-pass has no quote state to consult, so `echo "<<EOF"` reads as an opener
and starts a skip to a delimiter that never comes: the rest of the command
vanishes, the gate stops looking, and the suite stays green over it. The same
position decides quoting, redirection and openers, once.
BOTH DIRECTIONS, AND THE SECOND IS A LIVE DEFECT. CLOUD-723 is this parser
getting heredocs wrong the other way: every `pipeline` row decides over these
segments, so a `;` inside a heredoc BODY split the list and `verdict-not-
discarded` refused a correct command. It fired twice in one session, both times
on the command that was writing the rule down. One parser, one fix, and the
maintenance surface the reserved question worried about is bounded by having the
two directions asserted against each other.
THREE PREDICATES, over `input.call.segments` rather than a hand-rolled scrub:
unsatisfiable-commit `git commit -F -` with nothing bound to ITS OWN element
reads /dev/null — and `githooks(5)` runs `pre-commit`
before git asks for the message, so the whole gate is
spent first (~4 minutes measured, CLOUD-488, PR #375).
foreground-sleep the harness kills a foreground call at ~2 minutes, so a
patient poll FAILS (CLOUD-482, exit 143 and 144).
background-timer a backgrounded `sleep N; tail log` exits on the clock,
never on the event — 490 in one session against 523 of
524 tasks that notified on exit; 2 changed a decision
(CLOUD-821).
The last two are CLOUD-1094's `run-in-background` finding its first consumer.
THE ALLOW IS THE LOAD-BEARING HALF of all three, and each has its own
discriminating negative: `git commit -F - <<'EOF'` in one element, and — for the
wait rules — the same loop twice, differing only in posture.
WHICH IS WHY CLOUD-1112 IS FIXED HERE RATHER THAN CARRIED. That posture pair did
not work: `do sleep 1` resolves to the program `do`, because the look-through
table covers `env`/`timeout`/`sudo`/… and no shell KEYWORD, so the sleep in a
loop body is never reached. `run-shape-guard.sh`'s `resolve()` answers the same
way, and its comment that an element-scoped loop test "would deny every correct
wait" presumes an element it never reaches.
The instinct was to port the gap, on the rule that a migration moves a predicate
rather than changing it — and `filed-over-own-diff` refused the row filed about
the file this branch edits, which is what forced the premise to be checked. It
does not hold: CLOUD-613's acceptance turns on the backgrounded allow being LOAD-
BEARING, and with the gap ported that clause passes VACUOUSLY, the loop being
allowed because nothing resolves the sleep rather than because the exemption
works. Shipping a vacuous acceptance is CLOUD-418's defect, so `keywords` — `do`,
`then`, `else`, `elif`, `time` — is looked through exactly as the wrappers are.
`until`/`while`/`if`/`for` stay out: they introduce a condition list, and
`waits_on_condition` reads them as words.
Two verdicts move, both stricter: a FOREGROUND conditional wait now refuses, and
a backgrounded `for i in $(seq 60); do sleep 10; done` refuses as the timer it
is. This is the one place the two authorities deliberately disagree while both
are live, and it is in the denying direction, so no call gets a weaker answer
from the pair than it had from the guard alone. The bash cannot be repaired —
`shell-retirement` admits only whole-file deletion — and CLOUD-856 retires it.
TWO READINGS THAT LOOK LIKE STYLE AND ARE VERDICTS:
`segment["input-redirect"] == false`, never `not segment["input-redirect"]`.
Rego reads an absent key as undefined and `not undefined` HOLDS, so the negated
spelling denies every commit on an engine that stopped emitting the field. The
comparison allows there — the direction a miss is supposed to fail in.
`input.call["run-in-background"] != true`, never `== false`. `null` is "the host
said nothing", most hosts say nothing, and the shape refused is a WAIT whose
posture being unknown is the case to be strict about. The bash spells it
`[[ "$background" != true ]]` and the two must not diverge while both are live.
A NEWLINE STAYS WHITESPACE, not a separator, and bash disagrees. Promoting it
would change every landed `pipeline` verdict — `mise run verify` on one line and
anything on the next becomes a discarded status — which is a decision about
`verdict-not-discarded`'s reach rather than about heredocs. The cost is stated
rather than absorbed: shell following a heredoc's terminator joins the segment
its opener was written in. It under-denies, never the reverse.
THE BASH IS UNTOUCHED, and that is the ratchet rather than an oversight.
`shell-retirement` admits DELETING a governed file and refuses SHRINKING one, and
`run-shape-guard.sh` keeps a fourth family whose blocker is CLOUD-856. So it
cannot lose these three until it can lose all four, and both authorities decide
them until then. CLOUD-1108 is that gap's row; the predicates here are written
from the bash's own decision table so the two cannot answer differently while
both are live. CLOUD-613's acceptance moved the deletion clause to CLOUD-856
accordingly.
THE ROW ID STAYS `commit-message-obtainable`, which now names the first predicate
to arrive rather than the set. Renaming it reads as `rule-removed` to
`config-lint`, whose only route is a `Weakens:` clause groomed into the issue
BEFORE the work starts — and asserting one inside the change that performs it is
exactly what that gate refuses. The row's comment carries the correction; the
module file is the honest label. Tidiness is not worth laundering a weakening.
Refs CLOUD-843, CLOUD-856, CLOUD-1094, CLOUD-1108, CLOUD-199, CLOUD-418



Follow-up bundle on #372, landing as one cycle. Every saving comes from spending
fewer runs to get the same independent verdict on the exact SHA that lands — no
guard is weakened, and no unknown is converted into an answer.
What is here so far
land-lock's answer.mise run mutant: a declared one-line corruption applied to a throwaway copy must turn a named case red. The enforced set is data; gaps are filed (CLOUD-480), not silent.CI_ANSWERED_CONCLUSIONSdeclared once and read by both readers. The catch-all is gone, so an unknown conclusion holds the poll open instead of reading red.land-lock authorises— the verb the runner consults — instead of a second predicate over the run list.finding-sink-checkdistinguishes opening a row from annotating one, so a finding commented onto a Done issue no longer scores durable.Still in flight on this branch: CLOUD-413 (honour the rate-limit headers rather
than a guessed margin), CLOUD-404 (a provisioning flake is "could not look", and
the failed jobs are re-run rather than the lap re-bought), CLOUD-383 (the FIFO
rendezvous that removes the last bash-4 construct), CLOUD-476 (
hk installperformed and asserted), and the CLOUD-448/450 residual.
Verification
Suites green locally at each step:
tests/land.bats(89),tests/checks-green.bats,tests/ci-wait.bats,tests/ci-lease-precondition.bats(21),tests/finding-sink-check.bats(21),tests/mutant.bats(10).mise run mutantreports six declared mutations across five gates, every one caught.Draft, so CI does not run yet.