Skip to content

fix: the fast-forward verdict reaches land, and filing joins the gated paths - #390

Merged
wenzowski merged 5 commits into
mainfrom
claude/groom-cloud-491-qv83e7
Aug 13, 2026
Merged

fix: the fast-forward verdict reaches land, and filing joins the gated paths#390
wenzowski merged 5 commits into
mainfrom
claude/groom-cloud-491-qv83e7

Conversation

@wenzowski

Copy link
Copy Markdown
Contributor

Three commits, three issues, one landing lease. Each commit stands alone and
carries its own Refs: trailer; fast-forward landing preserves their SHAs, so
this is one PR rather than three racing for the lease.

ci(fast-forward) — CLOUD-507

run-name: fast-forward #${{ ... }} had an unquoted #, which opens a YAML
comment. The value GitHub received was the bare string fast-forward — measured
across all 30 issue_comment runs in a 2h42m window, one distinct value, all
four successes included. land's select(.display_title == env.FF_KEY) has
therefore been empty on every lap, for every PR, since it landed in ac212b2.
An empty answer reads as "not answered yet", so a fast-forward that concluded
failure left the lap polling indefinitely while holding the fleet-wide lease.

Quoted, and ci-local-parity gains the property that would have caught it: a
key's value carrying an unquoted # that swallows a ${{. The naive form
(raw vs. parsed interpolation count) flags 4 files with 3 false positives; the
tightened predicate flags exactly fast-forward.yml:17 and nothing else across
all 20 workflows. That measurement is in the comment beside the pattern.

Four rows in tests/ci-local-parity.bats: the refusal, plus three
false-positive guards (a whole-line comment mentioning ${{ }}, a quoted value
containing both, and a trailing # with no interpolation after it).

fix(hooks) — CLOUD-505

Every path onto the board is gated except the one that creates rows.
claim-check, claim-guard, issue-guard, ready-lint, graph-check — and
filing, nothing. Measured cost on 2026-08-13: a session blocked behind a starved
lease spent ~45 minutes re-deriving a cause that was already filed, reported
twice to a human that no answer was available, and opened a duplicate of an
issue two searches return in seconds.

issue-search-check reads a list_issues payload on stdin and mints a
branch-keyed receipt; issue-search-guard denies a save_issue create that
has none. It contains no similarity judgement — that would be the model verdict
non-negotiable 3 forbids — so it cannot tell you whether you are filing a
duplicate, only refuse to let the question go unasked. A search returning zero
hits still mints the receipt; that is the load-bearing case, since zero hits is
the honest outcome for a genuinely new finding.

The matcher is suffix-anchored (.*save_issue) and the guard body matches on
the suffix too, so a prefix-anchored matcher degrades to "never fires" rather
than "fires on the wrong tool" (CLOUD-178: three live connector spellings).
Updates are never gated, via finding-sink-check's proven has("id") test.

fix(land) — CLOUD-456

CLOUD-456 names two independent limits on the same read and only the key was
closed. per_page=100 was still a literal: at the measured 13 runs/minute one
page is ~7.7 minutes and a lap routinely outlives it, so this lap's own run can
fall off the page — which reads as a silent bot, byte-identical to the failure
above.

The verdict read now pages until a page comes back short. That terminates
because created>=SINCE bounds the set server-side, so the depth is derived
from the window rather than from a page size. The 20-page ceiling is a runaway
backstop: 2000 runs is ~2.5 hours at the measured rate, so reaching it means the
created fence stopped being honoured.

Shown able to fail

mutant is green at 12/12 declared mutations, including a new
verdict-first-page-only row that collapses the short-page break and reddens
the depth case — an unmatched filter and an unanswered bot are otherwise the
same bytes, which is how CLOUD-507 survived a landed fix for a day. Both new
gates are added to MUTANT_GATES; the suite is split into
issue-search-check.bats / issue-search-guard.bats because mutant derives a
suite from the gate's own name.

mise run verify green on this HEAD, rebased on origin/main. Suite at
1469/1469.

Note

CLOUD-507's own effect is not observable during this PR's landing: an
issue_comment run uses the default branch's workflow, so display_title
stays bare until this merges. Commit 3's tests are offline fixtures precisely so
they do not depend on that.


Generated by Claude Code

CLOUD-406's third instance, and the last half of it not already landed.

Measured on run 31538830648: Sigstore's TUF metadata endpoint was down, so
`mise install` failed, and two cases went red on a tree that touched neither the
hook nor the toolchain. Their properties are ORDER (doctor runs after install,
before the preflight — CLOUD-218) and OUTPUT (the hook emits no `{"async": true}`
— CLOUD-196). Neither asserts anything about the install succeeding. The
`[ "$status" -eq 0 ]` line was the only coupling, and it is load-bearing for
neither: the hook's `step` helper sets `fail=1` and CONTINUES, so every call is
recorded in `$CALLS` whether the install worked or not.

The stub now intercepts bare `install` the way it already intercepts
`run doctor` and `run container-preflight`, and the cases that genuinely need a
real one opt back in.

THE OLD RATIONALE WAS HALF TRUE, AND THE FALSE HALF IS WHAT COST A RED CHECK.
The header claimed the real exec is what keeps "the two lockfile assertions"
non-vacuous. One of them greps the hook's source text for
`MISE_LOCKFILE=false mise install` and touches no toolchain at all. The other —
"running the hook leaves the tracked lockfile untouched" — genuinely does need
one, because a stubbed install writes no lockfile and so could not observe the
CLOUD-223 residue. So this is the issue's option 2 rather than option 1: keep
exactly one case exercising the real install, plus the end-to-end green case, and
stop everything else depending on it.

ESTABLISH THE PRECONDITION, NEVER RETRY THE MEASUREMENT. `real_install_or_skip`
runs `mise install` directly before the hook. A failure THERE is a statement
about the container's egress, so it skips with that reason; past it, the hook's
own install cannot fail for a provisioning reason, so a red from the case that
follows is a real defect. That is the discriminator option 2 asks for, and the
same split `lock-check` took one layer up. Idempotent and warm, so the second
install costs milliseconds.

Shown able to fail, in every direction the acceptance names:

  egress denied (`mise install` forced to exit 1)
    -> 8 pass, and cases 7 and 9 SKIP with the reason named.
       The two cases that went red on run 31538830648 now pass.

  hook stops calling `mise install`
    -> cases 4 and 8 redden.

  doctor moved outside the synchronous window
    -> case 4 reddens.

So the property CLOUD-218 bought survives, which is the half the issue was
explicit about: deleting the assertion is not the fix.

The recovery half of CLOUD-406 needs no commit — CLOUD-404 landed it as
`nonverdict-scan` plus `absorbed_transient`/`charge_transient` on `land`'s red
arm, in a stronger form than §2 specified, and §2's premise that the
discriminator "must not be built" is now false. Recorded on the issue.

Refs: CLOUD-406
@linear-code

linear-code Bot commented Aug 13, 2026

Copy link
Copy Markdown
CLOUD-491 A live `plan-hold` did not stop a container restart, and nothing records that it was live — the hold ships with no sensor

Why

CLOUD-451 landed plan-hold on the premise that "the container is idle, so it is reclaimed" — so occupying the container with a backgrounded no-op defers the reclaim. Its acceptance is "a plan left open for longer than the observed reclaim window survives, with the human's typed input intact."

Measured 2026-08-12, ~22:12 UTC. A hold was armed (mise run plan-hold, backgrounded, task bfu2m1iit) and the container was restarted anyway. The harness's own restart notice named the four tracked tasks it killed:

- Wait for verify to finish (baf3psi7z)
- Wait for local CI reproduction to finish (bcbzgem2e)
- Re-commit with the message file and land (bge0bb5ib)
- Arm plan hold before exiting plan mode (bfu2m1iit)

So the container went down with four live tracked tasks, one of them a full land mid-CI-wait. The new container came up at 1 minute uptime with 14.6 GB of 16 GB free and 24 GB of disk available, and no OOM line reachable — the restart was not resource pressure on this side. The human's approval button was gone, which is the exact damage CLOUD-451 exists to prevent, and the landing work survived only because it had been committed.

Reproduced 2026-08-12, ~23:45 UTC, in the session grooming this issue: a hold was armed, and the container was restarted roughly a minute later, killing it. Two independent instances now, and the second one left artifacts the first did not — see the measurements below.

The finding is not "the hold is wrong". It is that the hold cannot be graded. A mechanism that occupies the container leaves no record of having done so, so from inside there is no way to distinguish the hold having been live and reclaimed anyway from the hold having already exited from a platform event no occupancy could defer. All of them produce the same observation — a fresh container — and the issue's acceptance is written in terms nobody can check after the fact. That is the sensor-without-a-gate shape inverted: a mechanism with no sensor. It is why an instance can be reported but not diagnosed, and why the honest first move is evidence rather than a bigger hammer.


Measured 2026-08-12 ~23:30–23:46, and it changes the mechanism

The first draft of this issue assumed one kind of container replacement. There are two, they are indistinguishable from inside without a sensor, and they have opposite consequences for any sensor built from a local file.

1. The 23:30 boot destroyed everything. btime was 1786577404 (23:30:04Z), and

find /home /root /tmp /var/tmp -xdev -newermt "21:00" ! -newermt "23:29"  →  0 files

A session was demonstrably alive at 23:28 — this issue's own last edit — and nothing it wrote survived anywhere writable. .git/index was dated 23:30:11, seven seconds after boot, sitting over an image base layer from 2026-08-06. A fresh container on a fresh disk: the clone is reconstructed at boot.

2. The 23:45 boot preserved the disk. btime 1786578317 (23:45:17Z), and 20,184 files from the previous container survived — target/, and .git/batten-holds/ itself. A restart of the same disk.

Same appearance from inside, opposite consequences. A heartbeat file under $GIT_DIR is readable across (2) and does not exist at all across (1) — so the three-case taxonomy this issue shipped with has no room for the second event class, and its predicate last_heartbeat > btime - poll cannot tell a fresh container from no hold was ever armed. Both present as an absent file, which the draft defined as silence. Shipped as written, the sensor would pass a bats suite that fakes boot time in a tmpdir and report nothing in the case that actually destroyed the plan.

3. The surviving hold directory was empty. .git/batten-holds/ came through the 23:45 restart present and empty, mtime 23:42:15, with a hold armed shortly before. The sentinel is gone. plan-hold-check's header asserts "a container reclaim does not run traps", and this artifact was at first read as consistent with its negation — the hold's own trap erasing the only record that a hold was live. Measurement 4 supersedes that reading: 23:42:15 is a boundary, not a trap firing. The trap remains a candidate and the heartbeat must still not be trap-removed, but it is no longer the leading explanation.

4. The last 182 seconds of writes did not survive, and this falsifies the predicate this issue shipped with. Every surviving pre-boot write stops at 23:42:15 — the MCP logs of four different servers, Serena's log, target/.rustc_info.json, and .git/batten-holds — while the container demonstrably kept serving tool calls until ~23:45. From the newest surviving file to btime: gap=182s. Whether the cause is a disk snapshot boundary or unflushed page cache cannot be determined from inside, and it does not need to be: either way the tail of a per-poll heartbeat is lost exactly when the sensor needs it.

So the first draft's predicate — epoch ≥ current btime − poll, a 5 s tolerance — reads the surviving last heartbeat as three minutes stale and answers "did not span" for the very event it exists to catch. Widening the tolerance to cover 182 s does not rescue it: a window that large also swallows a hold that legitimately exited minutes earlier, which collapses the already-exited case and with it the point of the sensor. The predicate has to stop being a time comparison.

The heartbeat question, stated so it can be settled rather than argued. Two different things are called a heartbeat here and only one is cheap:

  • A heartbeat as EVIDENCE — the hold records its liveness to an out-of-tree file each poll. Costs one date and one append per 5 s, no model call, no tokens.
  • A heartbeat as KEEP-ALIVE — something that periodically wakes the session, on the theory that the reclaim clock is driven by agent turns rather than container activity. Each wake is a model call, metered in AGENTS.md's most expensive category, and AGENTS.md separately bans timers for babysitting. It must not be adopted on a hunch.

The first is a prerequisite for deciding the second. Ship the sensor, read it, then decide. The activity-versus-existence question — every wait in this repo that survives does I/O, and this one does not — is CLOUD-500, deliberately blocked on this issue for that reason.

What the sensor must distinguish, and how

The hold records why it stopped, not merely when it last ran — absence of an intentional-exit record is the signal, and absence is the one reading robust to losing the tail. Two line kinds in one appended file: h <epoch> <btime> per poll, and x <epoch> <btime> released|capped on an intentional exit. The verdict reads the last line only.

last line exit case
h, recorded btime ≠ current 0 a hold was live when this container replaced the last one
x 1 the hold ended on purpose — the un-released window of CLOUD-485, or the cap
h, recorded btime = current 1 this boot's own hold; it spanned nothing
absent, a prior boot recorded 1 disk preserved, no hold was ever armed here
absent, no prior boot recorded 2 fresh container — no local evidence is possible, and saying so is the honest answer
unparseable 2 cannot look; never 0

The residual error is bounded and in the conservative direction: a hold released inside the lost-write window reads as "was live".

The residue probe of the first draft does not work either, and is replaced. It separated the last two rows by whether prior-container residue exists, naming target/ and .git/batten-contract. Measured: every batten-* directory mtime is post-boot on a demonstrably preserved disk, because a directory's mtime updates on each add or remove; and target/ is rebuilt by session-start's build:release on a fresh container too. Recursive file mtimes do stratify — 36 files dated 08-12 against 21 from the 08-06 image bake — but separating those strata needs the bake date, which is not a stable predicate. In its place, session-start appends the current btime to $GIT_DIR/batten-boots once per session. A recorded btime other than the current one proves the disk is preserved, which makes the distinction exact rather than heuristic.

Refinement — Ready

  • Source of truth (§1). Two local readings, no network: the hold's own heartbeat file, and the container's boot time (/proc/stat's btime, with uptime -s as fallback). Both are properties of this machine, so the predicate stays a gate rather than a guess. The heartbeat lives at $GIT_DIR/batten-hold-heartbeatoutside batten-holds, because both plan-hold's incumbent-release loop and plan-hold-check live's reaping loop iterate "$dir"/* and delete every file whose first line is not numeric; the <dir>/heartbeat an earlier draft of this clause specified would be eaten on the first check. The path is spelled once, in mise-tasks/plan-hold-check beside hold_dir() — the discipline tests/plan-hold.bats already pins with its "spelled in exactly one place" case, and every other caller asks for it.
  • Mechanism as a computable predicate (§2). plan-hold appends h <epoch> <btime> on every poll it already performs — no new loop, no new interval — and x <epoch> <btime> released|capped on each of its two intentional terminal paths. The x record is written only there, never in the trap … EXIT INT TERM, because that is the entire mechanism: a hold killed by the container going down leaves its last line as an h, and no time comparison is needed to see it. Pairing the boot time into each line is what tells this boot's own hold from a previous one's. The heartbeat is never trap-removed. A new plan-hold-check spanned sub-verb (so the path stays spelled once) resolves the table above from the last line. sync -d follows each append — it cannot defeat a snapshot boundary, but it closes the unflushed-cache case for one syscall per poll. Reported once, as a pointer — the verdict and the recorded epoch, never a plan or a prompt body.
  • Effect (§3). read. One append per poll to a file under $GIT_DIR, which claim-guard treats as machinery rather than work. No new batten verb and no SURFACE change; the new spellings are sub-verbs of plan-hold-check, whose header usage block and dispatcher error string are the one authority for that list. Growth is bounded — 4 h ÷ 5 s ≈ 2,880 lines ≈ 58 KB — and append is chosen over rewriting a single line because a rewrite can tear at exactly the moment that matters.
  • Output & exit contract (§5). The reading is 0 (a hold spanned the restart) / 1 (it did not) / 2 (cannot look), matching plan-hold-check's existing table, with the fresh-container case landing on 2 rather than a false 1. The session-start report is one line, pointer-only, and lands in .claude/hooks/session-start.sh after container-preflight, on a line that never sets fail — a restart verdict must not halt a session. plan-hold itself keeps exit 0 on both terminal paths — it is not a gate and this does not make it one.
  • Commit / bump (§6). fix(plan-hold) — patch until 0.1.0.
  • Test obligation (§7). Mutation-checked per CLOUD-418, which sets the file layout and not merely the rows: mutant derives its suite as tests/$gate.bats, so the predicate is only gateable once plan-hold-check has its own suite. It gets one — tests/plan-hold-check.bats — following the convention claim-check, land-lock-check and stop-posture-check already keep and this task alone breaks; the existing predicate rows migrate into it, which the bats-tests-not-deleted ratchet permits because its scope is the tree. Both plan-hold and plan-hold-check join MUTANT_GATES. A testability constraint: /proc/stat cannot be faked, so the boot-time reader must be injectable (BATTEN_BOOT_TIME, defaulted from /proc/stat) or no row can discriminate and the suite ships as coverage. Fixture rows for every line of the verdict table, plus: an empty file reads as absent; the report emits one line carrying no plan text; plan-hold-check live does not delete the heartbeat — a regression row for the siting collision above; and an unknown verb exits 2, a dispatch arm with no coverage today that this change adds to. Two rows that are not fixtures, because they are what the mechanism claims: a hold kill -9ed leaves an h as its last line even though its trap runs, and a hold released or capped leaves the matching x. The declared mutations — rewriting the x write to emit h, and collapsing the h/x discrimination in the reader — must turn those rows red.
  • Blockers (§8). None. relatedTo CLOUD-500 — the activity-versus-existence hypothesis, which waits on this sensor by design. Relations: CLOUD-451 is the mechanism this grades and its acceptance is the claim in question; CLOUD-485 is the other reason a hold may not be live when it is believed to be, and the two must not be conflated when reading the evidence; CLOUD-425 is the general "a background task cannot be asked what it is doing" gap this is one instance of; CLOUD-388 is the corpus question for any transcript-side reading of the same event, and measurement 1 above is its filesystem instance — a fresh-disk replacement leaves no local corpus either.

Acceptance

  • After a container restart, the session can say whether a hold was live when it happened — from a local reading, without a transcript.
  • The cases are distinguishable, and the report names which. In particular a fresh container is reported as "cannot look", never as "no hold was live".
  • The reading costs no model call and no network.
  • The rows fail when the h/x discrimination is removed.
  • The verdict does not depend on a heartbeat written inside the lost-write window — the property measurement 4 falsified in the first draft.

Measured in the session that also filed CLOUD-488; the plan whose approval button was destroyed was the one grooming CLOUD-427. The 23:30–23:46 measurements and the empty-hold-directory artifact were added in the grooming session, which was itself restarted twice while doing it.

Review in Linear

claude added 3 commits August 13, 2026 03:09
YAML opens a comment at an unquoted ` #`, so

  run-name: fast-forward #${{ github.event.issue.number }} @${{ ... }}

parsed to the bare string `fast-forward` and both interpolations were discarded
before GitHub saw them. Measured: all 30 `fast-forward.yml` runs with
event=issue_comment between 2026-08-12T21:47Z and 2026-08-13T00:29Z reported a
display_title equal to the workflow NAME, including all four that concluded
success. run-name had been on main for six hours before the earliest of those,
so it was not deployment lag.

What it cost: land builds FF_KEY and selects .display_title == env.FF_KEY, so
that selection was empty on every lap, for every PR, always. An empty answer
resets answer_unknowns rather than charging it, so max_unknowns can never trip
on that path and the only remaining exits are the PR leaving OPEN and main
moving. A fast-forward that succeeds still lands through the fallback; one that
concludes failure or skipped is invisible and the lap polls forever holding the
fleet-wide landing lease. That is CLOUD-235's original defect restored for the
refusal case, with the success case masking it.

Nothing could have caught it. A comment is legal YAML: actionlint and zizmor
both pass, and review reads the line as the thing it was meant to be.

The gate is anchored rather than counted, and the difference is measured. The
obvious predicate - compare the raw `${{` count against the count surviving a
YAML parse - flags 4 of this repo's 20 workflows and 3 are prose comments
legitimately discussing `${{ }}`. A gate that is 75% false positives gets
switched off. Requiring a `key:` before the `#` and an interpolation after it,
with whole-line comments and quoted values skipped, flags exactly the one real
defect and nothing else.

The quoted-value exclusion was found by the gate refusing its own repair on the
first run, which is the cheapest way to find it.

Refs: CLOUD-507
Every path ONTO the board is gated except the one that creates rows.
`claim-check` refuses an issue already claimed, `claim-guard` an edit with
no claim receipt, `issue-guard` a PR naming no issue, `ready-lint` an
unrefined block, `graph-check` an incoherent frontier. Filing has none,
and the cost is not a redundant row: measured 2026-08-13, a session
blocked behind a starved landing lease spent ~45 minutes re-deriving a
cause that was already filed and searchable, reported twice to a human
that no answer was available, and filed a duplicate of an issue two
searches return in seconds.

The obvious gate is forbidden. Scoring a candidate against open issues
and refusing above a threshold is a model verdict, and a gate resolves to
a command and an exit code over an object it decides. So this does not
judge similarity and cannot tell you whether what you are filing is a
duplicate — it refuses to let the question go unasked.

The shape is `claim-check`'s, borrowed wholesale: no tracker credential
exists in a hook, so the agent searches, `issue-search-check` records
that the search happened, and `issue-search-guard` demands the record.
The receipt is keyed by branch, like the claim receipt and for the same
reason — a search attests to a decision about what to file, and every
filing on that branch continues to serve it.

A search returning nothing still mints the receipt. That is the
load-bearing case, not an edge one: zero hits is the commonest honest
outcome for a genuinely new finding, and refusing it would make the gate
punish the behaviour it exists to produce.

The matcher is suffix-anchored (`.*save_issue`), never prefixed on
`mcp__Linear__` — CLOUD-178 measured the same connector under three live
spellings, and a rule naming one matches none of the others silently. The
guard body matches on the suffix too, so a prefix-anchored matcher
degrades to "never fires" rather than to "fires on the wrong tool".

Updates are never gated; the create-vs-update discriminator is
`finding-sink-check`'s proven `has("id")` test. Both gates carry a
`#MUTANT` row and both are added to `MUTANT_GATES`; the suite is split in
two because `mutant` derives a suite from the gate's own name.

Refs: CLOUD-505
CLOUD-456 names two independent limits on the same read, and only the
first was closed. The key (`display_title == $FF_KEY`) says WHICH run is
this lap's; the depth says whether this lap's run is in the page at all.
A keyed filter over a window that has already rolled past the run returns
empty, which the poll reads as "not answered yet" — byte-identical to a
silent bot, which is the reading CLOUD-399 recorded as "the bot is slow"
while the bot was in fact answering inside 23 seconds.

`per_page=100` was still a literal. At the measured 13 runs/minute one
page is ~7.7 minutes of history and a lap routinely outlives it. So the
verdict read now pages until a page comes back short, which terminates
because `created>=SINCE` bounds the set server-side: the pages walk a
finite window, not all history. The depth is derived from the window,
which is what the acceptance asks for. The 20-page ceiling is a runaway
backstop and nothing else — 2000 runs is ~2.5 hours at the measured rate,
far outside any lap's `SINCE`, so reaching it means the `created` fence
stopped being honoured rather than that the window is that deep.

Two cases in `tests/land.bats`, the pair §7 asks for: this lap's run on
page two behind 100 strangers is still read as a refusal, and a walk that
meets a short page stops there rather than reaching back to an earlier
lap's own run — the livelock the `SINCE` stamp exists to prevent. A
`#MUTANT` row collapses the short-page break into an unconditional one,
so the depth row is proven able to fail (CLOUD-418); an unmatched filter
and an unanswered bot are otherwise the same bytes, which is how this
survived a landed fix for a day.

The structural sensor gains the other half of that coupling: the
`run-name:` line must carry BOTH interpolations, not merely exist. A line
that survives a `grep -c '^run-name:'` while its value is truncated to
the bare workflow name is exactly what CLOUD-507 was.

Refs: CLOUD-456
@wenzowski
wenzowski marked this pull request as ready for review August 13, 2026 03:09
@wenzowski
wenzowski force-pushed the claude/groom-cloud-491-qv83e7 branch from e42c45d to 49b3414 Compare August 13, 2026 03:09
@wenzowski
wenzowski marked this pull request as draft August 13, 2026 03:20
All 15 rows of the two new suites passed `verify` here and failed CI with
`fatal: empty ident name`. A developer machine carries a global git
identity and a runner does not, so `git commit` inside the fixture repo
worked locally and could not work there — the verify/CI disagreement
`land` refuses to land through, and it cost a full CI run to discover.

Every other fixture suite in this tree already sets the identity per
fixture (`claim-guard.bats`, `claim-check.bats`, `contract-drift.bats`,
and the `-c user.email=` spelling in `claimed-keys.bats` and
`deferral-check.bats`); these two were the only ones inheriting it.
Reproduced with `GIT_CONFIG_GLOBAL=/dev/null GIT_CONFIG_SYSTEM=/dev/null`,
which is green at 15/15 with the identity set and is what the CI log shows
red without it.

Refs: CLOUD-505
@wenzowski
wenzowski marked this pull request as ready for review August 13, 2026 03:29
@sonarqubecloud

Copy link
Copy Markdown

@wenzowski

Copy link
Copy Markdown
Contributor Author

/fast-forward

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