67 lines
4.2 KiB
Markdown
67 lines
4.2 KiB
Markdown
# Why gates are code
|
|
|
|
Chemenu has three hard limits - the Mass-Update Gate, the Publish-Remote Gate, and the
|
|
Iteration Budget Gate - and all three live inside `tools/wikitool`, not in a paragraph of
|
|
instructions an agent reads and follows. The rules themselves, and what to do when one trips,
|
|
are in [AGENTS.md § Gates](../AGENTS.md#gates) and [instructions/gates.md](../instructions/gates.md).
|
|
This page is only about the design choice underneath them: why code, and why these three
|
|
mechanisms in particular.
|
|
|
|
## A suggestion an agent can talk itself past
|
|
|
|
An instruction like "don't publish too much at once" or "don't loop forever" lives in the same
|
|
place as every other piece of guidance a session is holding - alongside the task, the user's
|
|
last message, and whatever context made the moment feel urgent. Under pressure, or with a
|
|
plausible-sounding reason ("this batch is different, it's mechanical"), that guidance can be
|
|
reasoned around without anyone deciding to break a rule. Nothing enforces it; it just competes
|
|
for attention with everything else in the context window, and sometimes loses.
|
|
|
|
A check compiled into the tool doesn't have that problem, because it isn't part of the
|
|
conversation at all. It runs before the command dispatches, regardless of how convincing the
|
|
case for skipping it seemed a moment earlier. The difference isn't that code is smarter than a
|
|
well-written instruction - it's that code doesn't get talked into anything.
|
|
|
|
## Why three different mechanisms, not one
|
|
|
|
The three gates ask three different questions, and each one's shape follows from what kind of
|
|
question it is.
|
|
|
|
The Mass-Update Gate asks *is this change too large to publish unreviewed* - a judgment that
|
|
varies changeset by changeset, so it clears with a `--confirm` token tied to the specific
|
|
output the user just read. Approval is scoped to that one publish.
|
|
|
|
The Publish-Remote Gate asks something underneath that: *is this even the right repository*.
|
|
That's not a per-push judgment, it's a standing property of the checkout - true or false for
|
|
every publish that checkout will ever attempt, not just this one. A confirm token would let an
|
|
agent clear it once and then treat the answer as settled, which is exactly backwards for a
|
|
question whose answer shouldn't move at all mid-session. The only way past it is the user
|
|
editing `.wikitool-remotes.json` directly, outside the gate's own flow.
|
|
|
|
The Iteration Budget Gate asks a third kind of question - not "is this instance correct" but
|
|
"has this session stopped making progress." That's read from the shape of the call history
|
|
itself (call count, repeated identical calls), not from anything about the content of any one
|
|
call.
|
|
|
|
## Numbers that come from measurement, not intuition
|
|
|
|
The iteration ceiling didn't start where it sits now. It used to run 15-25, borrowed from a
|
|
general rule of thumb, until four real ingest runs measured 24, 26, 29 and 30 calls apiece -
|
|
every one of them an ordinary workflow doing nothing wrong, and every one of them at or past
|
|
where the old ceiling would have refused it. A limit that the normal case keeps tripping stops
|
|
functioning as a limit; it becomes background noise a session learns to route `--override-budget`
|
|
around as a matter of course, and the whole point of a hard-coded check is that it isn't supposed
|
|
to feel routine.
|
|
|
|
That's the deeper reason these numbers live in a tool rather than in prose: prose is read once
|
|
and remembered loosely, but a threshold enforced every call is tested by every call, and a
|
|
threshold that fails its own test gets noticed and re-measured rather than quietly ignored.
|
|
|
|
The suite's coverage floor is the same argument run forwards instead of backwards. The ceiling
|
|
above was wrong first and measured afterwards; the floor was withheld on purpose until the number
|
|
existed - measured, then watched across 38 runs while the code grew by a quarter, and only then
|
|
written down as 85 against an observed 87.0%. The two points of daylight are the same
|
|
consideration as the ceiling's headroom: a limit the ordinary case keeps tripping stops being a
|
|
limit. A coverage floor set at the measured number goes red on the next thin command wrapper,
|
|
which is not a regression, and a threshold that goes red for a non-reason gets lowered rather
|
|
than earned - the failure mode above, reached from the other direction.
|