Plan fidelity#
Every stage of the gauntlet compares a plan, or the cloud after an apply, against what stock OpenTofu does for the same configuration. The promise behind all of them, stated once rather than left to be inferred stage by stage: an equal plan, or a refusal this documentation names in advance. Anything else is a defect.
This is a contract about shape, not a scoreboard. It says what a difference from stock is allowed to be, not how many estates currently clear. For the numbers, see How close AWS is.
What “equal” excludes#
One thing, always the same one: the marker tags choudoufu writes for
identity, tofu-estate and tofu-address (see
Identity). Stock has no argument to
write them into, so a plan that carries them and a plan that does not are not
different plans, and every stage that diffs a plan or the resulting cloud
strips both sides of these tags before comparing. Nothing else is normalised
away. A different resource count, a different argument value, a different
order of operations where order is observable: none of that is excused.
Where choudoufu is deliberately stricter#
A refusal where stock proceeds is ordinarily the plainest kind of defect: the class of divergence the gauntlet exists to catch. The one exception is a stage whose own definition commits, in advance, to refusing on purpose, so that anyone reading it before the estate runs already knows the divergence is coming and why.
Today that is plan_approval: plan -out followed by apply <planfile>
applies cleanly when the world has not moved since the plan was taken, and
refuses, naming the mismatch, when it has. Stock applies a stale planfile
anyway. choudoufu does not, by design, and the gauntlet asserts that refusal
directly rather than diffing it against stock’s more permissive behavior.
plan_approval is not active yet; it is a planned stage, listed in
live/GAUNTLET.md
so the target is visible before it starts counting toward an estate’s clear
bar. The contract it will enforce is already decided, though, which is why
it belongs here.
A refusal that isn’t written into a stage’s own definition this way gets no such pass. It is scored as choudoufu refusing where stock proceeds, and that is a defect like any other.
How a difference gets classified#
Once the marker tags are stripped, a remaining difference is one of five
things, the table
HANDOFF.md
keeps: choudoufu refusing where stock proceeds is a defect, the plans or the
resulting cloud differing is a defect, stock failing too still leaves the
estate to clear (matching stock’s failure is never the finish line), a wrong
answer from the pinned emulator is fixed in the emulator, and an instance
that would need a wrong marker to converge drops to the record rung and the
run proceeds rather than forcing one. Every row leads to a fix, an emulator
change, or a tracked rung ticket; none of them lets a difference stand
unexplained.
How the promise is enforced#
A stage that always passes proves nothing. Every stage in
live/GAUNTLET.md
that runs choudoufu at all carries a BREAK=1 control: set it, and the
crossing script deliberately introduces the exact defect the stage exists to
catch: a corrupted identity string, a second object mutated where only one
should be, a stale planfile applied instead of refused. When that happens,
the stage must fail. A check that cannot be made to fail this way is not
evidence for this contract, whatever verdict it reports on an ordinary run.
The exemption is stage 1, cold_deploy, and its own Break line says why. It
is the stock binary applying the unmodified configuration with no live
block: “Not applicable; this stage has nothing of choudoufu’s to break.” A
failure there is stock failing, which the gauntlet records as such rather
than counting against this contract. Every other stage carries a control;
live/GAUNTLET.md’s Break lines are the list, and they are rendered from
tools/gauntlet/stages.go rather than maintained here.