Repository navigation
witnesses.yml: ask for the rustfmt component, and stop the run step declaring it consumes nothing - #8874
Conversation
…eclaring it consumes nothing
gunbc#8860 went red on a merged head with the witness floor passing
10130/10130, failed=0, zero FAIL identities. The failure was a different
phase in the same step:
required-ci: phases_run=3 failed=1
required-ci: FAILED PHASE regen refused: normalize candidate wt_b.rs:
spawn rustfmt: No such file or directory (os error 2)
The regen phase writes the emitted mirror as a FIXED POINT of the formatter,
so it must spawn rustfmt. witness_floor_toolchain_step never asked for it:
its `with` block carried only `cache: false`. The job therefore inherited
whatever the runner's resolved default toolchain happened to carry, passing on
runners whose default has rustfmt and failing on ones whose default does not,
with no relationship to the diff under test.
gunbc.fleet_workflow_steps ci_setup_rust_step already passes this same key to
this same action. This step was the one that did not.
THE OBVIOUS READING OF THAT ERROR IS WRONG, AND THIS REPOSITORY ALREADY PAID
TO LEARN IT. I first diagnosed it as "that runner has no rustfmt", which is
what the error says and is not what it means.
gunbc.host_toolchain_components toolchain_completeness_authority_note records
the same error on the same host class 2026-07-25: rustfmt WAS present on the
machine; the job principal carried two rustup toolchains and defaulted to the
one without it. A COMPONENT IS A PROPERTY OF A TOOLCHAIN, NOT OF A MACHINE, so
installing it on the host converges green while the gate keeps failing.
WHY NOTHING CAUGHT IT. witness_floor_run_step was declared capability_neutral
while its regen phase spawns rustfmt. A step that consumes a capability while
declaring it consumes none is invisible to the closure check BY CONSTRUCTION:
the check was honest and had nothing to catch, because the consumer said it
consumed nothing. RustfmtCapability already existed in the vocabulary and was
simply unused here.
Four changes, not one. The components line alone fixes today's symptom and
leaves the false declaration standing for the next tool that gets spawned:
1. witness_floor_toolchain_step passes components: rustfmt
2. its role becomes provides_only([CargoCapability, RustfmtCapability])
3. witness_floor_run_step declares consumes_only([RustfmtCapability])
4. witnesses.yml regenerated through the artifact gate
CargoCapability is deliberately NOT declared on the run step: it invokes the
prebuilt claim_executor binary and does not shell out to cargo. Listing it
would trade one false declaration for another.
fleet-desired.yml also gains the component, and that is correct rather than
collateral: gunbc.fleet_desired_admission_workflow REUSES
witness_floor_toolchain_step, so one authority feeds both emissions. The change
is additive -- adding a provided capability cannot falsify any consumer's
declaration -- so no closure elsewhere can break on it.
Verified: 0 blocking errors, and the live consumer
workflow_capability_closure_witness the_live_witness_floor_job_closes_its_capabilities
returns true. That witness folds the job this module actually emits, not a
transcribed fixture.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
What this PR fixes, and what it does not — written before attempt2 landsIt fixes a declaration that was lying. The toolchain step really did not ask for It is NOT established to fix the spawn failure. Run Two readings I held tonight are both dead. It is not "one host lacks rustfmt": srv2-01 ran main green at 05:20 and this head red at 06:26, and its slots are serialized so there is no overlap. It is not the runner lottery either, for the same reason. A rerun cannot settle it, and I am saying so before its result exists. So the state of this PR is: correct modeling that does not close the failure it was prompted by. That is still correct modeling — a red rerun would not make the declaration true again, and a green one would not make it the fix. The spawn failure is being pursued separately with an instrument, because — sent from fierce-lynx-647 |
First probe output from #8877, and it bears on this PRThe toolchain probe in #8877 ran green for the first time (run On srv2, runner Two things follow. The shim is on PATH and the binary exists in the active toolchain. On a host in this state,
What this does not establish: one host, one green run, and the failure did not occur on it. This is a baseline plus one discrepancy, not a diagnosis. What it means for this PR: Not proposing a change to this PR on that basis. Recording the lead where the fix lives so it is not re-derived from scratch if the failure returns. — sent from fierce-lynx-647 |
The symptom
gunbc#8860 went red on a merged head while the witness floor passed 10130/10130,
failed=0, zero FAIL identities. A different phase in the same step failed:The regen phase writes the emitted mirror as a fixed point of the formatter — the repair DESIGN records for the two-consumers-normalizing-one-artifact contradiction — so it must spawn
rustfmt.witness_floor_toolchain_stepnever asked for it: itswithblock carried onlycache: false. The job inherited whatever the runner's resolved default toolchain happened to carry, so it passed on some runners and failed on others with no relationship to the diff under test.gunbc.fleet_workflow_stepsci_setup_rust_stepalready passes this same key to this same action. This step was the one that did not.The obvious reading is wrong, and this repository already paid to learn it
I first diagnosed this as "that runner has no rustfmt" — which is what the error says and is not what it means.
gunbc.host_toolchain_componentstoolchain_completeness_authority_noterecords the identical error on the identical host class on 2026-07-25: rustfmt was present on the machine; the job principal carried two rustup toolchains and defaulted to the one without it.So "install rustfmt on that host" is the fix that converges green while the gate keeps failing. The fix belongs in what the workflow asks for.
Why nothing caught it
witness_floor_run_stepwas declaredcapability_neutralwhile its regen phase spawns rustfmt. A step that consumes a capability while declaring it consumes none is invisible to the closure check by construction — the check was honest and had nothing to catch, because the consumer said it consumed nothing.RustfmtCapabilityalready existed in the vocabulary and was simply unused here.Four changes, not one
The
componentsline alone fixes today's symptom and leaves the false declaration standing for the next tool that gets spawned.witness_floor_toolchain_steppassescomponents: rustfmtprovides_only([CargoCapability, RustfmtCapability])witness_floor_run_stepdeclaresconsumes_only([RustfmtCapability])witnesses.ymlregenerated through the artifact gateCargoCapabilityis deliberately not declared on the run step: it invokes the prebuiltclaim_executorbinary and does not shell out to cargo. Listing it would trade one false declaration for another.Evidence
The live consumer
workflow_capability_closure_witnessthe_live_witness_floor_job_closes_its_capabilitiesfolds the job this module actually emits, not a transcribed fixture:trueRustfmtCapability, consumer still declares itfalseThe RED is the point. This PR exists because a check was structurally blind, so a green alone would prove nothing — it would repeat the same error one level up. The control confirms the closure is genuinely discriminating for this capability.
Also: 0 blocking errors, and regen leaves the tree clean.
Why a second workflow moved
fleet-desired.ymlalso gains the component. That is correct rather than collateral:gunbc.fleet_desired_admission_workflowreuseswitness_floor_toolchain_step, so one authority feeds both emissions. The change is additive — adding a provided capability cannot falsify any consumer's declaration — so no closure elsewhere can break on it.This PR is the fix; #8877 is the instrument. Neither substitutes for the other.
Stated here so a reviewer meeting both does not read either as covering the other's ground.
This PR asks for the
rustfmtcomponent and makes the run step declare that it consumes it. That is the repair: it is what makes the component present, and it is what lets the capability closure refuse the shape that produced the failure.#8877 adds a step that records the toolchain environment — PATH, the cargo bin directory,
rustup which rustfmt, the toolchain list. That step fixes nothing and refuses nothing. It exists becausespawn rustfmt: No such file or directory (os error 2)reports the syscall and nothing about the environment that produced it, so the failure destroys its own evidence and every occurrence is exactly as unreadable as the last. If this fix turns out to be incomplete, or the failure returns from a different cause, the probe is what makes the next occurrence diagnosable on its first sighting rather than its third.So: the probe landing is not evidence that the rustfmt question is handled — this PR is. And this PR landing does not retire the probe, because a fix removes one cause and an instrument reads whatever the next one turns out to be.