Blog · 4 September 2026 · The foldrun team
Capability is structural
A publisher step applied 140 links nobody had approved. The sandbox held; the gate held; the step simply had the tool. What we changed so it could not happen again.
On the morning of 2026-09-04 a link-desk run reached its publisher step, read a proposal file, and applied a hundred and forty internal links across a customer’s site. It stopped before committing, because the step after it was a gate and the gate held. Nothing was published. It was still the worst run we have had.
What went wrong
The proposal file it read was Thursday’s. Friday’s run had produced a new, smaller proposal — six links, on addresses a person had approved — and written it to a different path. The publisher’s instructions said to read “the proposal”; its tool was apply_links, which took a file and applied everything in it. Given the wrong file, it did the right thing with it.
Every layer we are proud of worked. The pod could not reach anything it should not. The gate before publish caught it. The run record shows exactly which file was read and which links were applied. And none of that mattered, because the step had a tool that could apply an unbounded list of changes, and a model that was confidently wrong about which list.
The fix was not a better prompt
The first instinct is to fix the instruction: “read Friday’s proposal, the one at this path.” That would have worked until the next ambiguity.
The fix was to take the capability away. apply_links now refuses to run without --only, a list of the specific addresses it may touch. A wrapper script, apply-fix-links.sh, exists solely to make that refusal impossible to bypass from a prompt. The approved addresses come from the gate — the human’s decision, recorded — and only the step after the gate holds the tool that applies them.
Two tools where there was one: propose_links, which any step may run and which writes nothing; and apply_links --only, which one step may run and which writes only what the gate named.
The principle
A step can do only what its file grants. That is a sentence from our security page and it sounds like a slogan. Its operational meaning is this: when a run does something you did not want, the question is not “what should the model have understood?” It is “why did the step have that tool?”
An agent with no tool that writes cannot write, whatever it is told or tricked into. A tool that takes an explicit list cannot apply an implicit one. A capability that only exists after a gate cannot be exercised before it. These are properties of the folder, and a person reading the folder can check them without running anything.
What we changed in the platform
The desk fix was local. The platform change was to make the pattern easy to see: the run page now shows, per step, which tools it held, which it called, and how many times a file path was refused. A step that holds a write tool it never calls is a smell; a step that was refused twelve times is a step arguing with its confinement. Both are now one glance.