Threads · 01 / 18 · Sep 7, 2026 · Apache-2.0

A cap in the wrong unit is not a cap you forgot to check

It is one you cannot compare. The action degrades to "ask a human" every single time, nothing errors, and nobody reports it — because asking a human is exactly what a careful system is supposed to do.

The test is a counter that stays at zero

A retention offer is measured in percent and in days at the same time. Somebody configures it the only way the system allowed — a ceiling in dollars — and the naive check is happy:

expect(boundedNaive(retentionOffer, { cap: "500.00" })).toBe(true);   // "it has a ceiling"

Now count how many times that ceiling is ever compared against a value:

const r = runWithCounter(retentionOffer, enDolares, bounded);
expect(r.ran).toBe(false);
expect(r.comparisons).toBe(0);   // ← the demonstration

Zero. A real number, configured with real intent, that was never once looked at. The action asks for permission forever, and nothing errors — no throw, no log, no red anything. That is the entire failure, and it is why it survives for months.

Why this is not "a cap you forgot to check"

A weak cap is one you can compare and set too high. This is different in kind: 500.00 and 20% for 30 days do not live on the same axis. There is no comparison to run, so no amount of code fixes it — you have to change the unit.

The tell is the direction of the failure. A weak cap fails open: things run that should not. This fails closed: nothing runs, which looks like caution right up until someone works out why the feature was never used and turns the guard off entirely.

Two rules that fall out of it

A half-set cap is not a cap.

bounded(retentionOffer, { named: { max_discount_pct: { enabled: true, value: 20 } } })  // → false

Bounding the discount and leaving the extension open would let an unbounded extension through because the other half happened to be bounded. All of the keys, or none.

A switch that is off bounds nothing, and a value with no switch is not a decision anyone made.

declared({ enabled: false, value: 20 })  // → false
declared({ enabled: true })              // → false
declared({ enabled: true, value: 0 })    // → true — zero IS a decision: bound it to nothing

Fail closed: what is not understood does not cap. And note the last line — zero has to count, or "bound this to nothing" becomes unexpressible and someone works around it with a -1.

And it does not cost the ordinary case

bounded(refund, { cap: "500.00" })  // → true

An action with one unit — money, the case every ceiling was designed around — behaves exactly as before. The fix adds a path, it does not replace one, which is what makes it safe to adopt in a system that already has ceilings configured.

Where this comes from

Found in niiko, on a retention offer, and it had been silently unreachable for as long as the feature existed. The engine that came out of it is published as @vorluno/ratchet.

The prior question — why does autonomy attach to the capability and not to the agent? — is per-capability-autonomy.

License

Apache-2.0 — see LICENSE. This is a demonstration, not a package. Copy what you need.


Built by Vorluno — a software studio from Panamá.

// next threadA gate that answers two questions lies about both