Two of the five ways a spend cap can handle a missing price produce the exact same decision stream — same sha256, byte for byte. One of them is the...
For further actions, you may consider blocking this person and/or reporting abuse
The failure mode I would isolate even harder is that
spentis computed through the same component whose failure the cap is supposed to tolerate. When the oracle goes quiet, the trip signal goes quiet too. That is common-mode.That makes the
$0.00 spent, exit 0run more than a bad pricing outcome. The cap's sensor is on the wrong side of the dependency boundary. Any gate that only watchesspenthas implicitly decided that "no quote" means "no evidence", so the system can keep admitting work while the only meter capable of tripping it is frozen. That's why the "reports innocence" line lands: innocence is exactly what the failed sensor is forced to report.The interesting part is that your harness already has the escape hatch in it.
unaccountedkeeps moving precisely because it doesn't route through the oracle. Same for a raw admitted-action counter. Those are the signals a fail-closed gate can actually depend on during the outage. So I'd promoteunaccountedfrom diagnostic column to load-bearing control: hard cap it separately from dollars, then require reconciliation before reopening normal admission. The spend ledger can still exist, but it can't be the only tripwire for a failure of the pricing path.That also slightly changes the estimator-bias framing for me. Bias matters once you have a quote. During a no-quote interval, the deeper problem is shared dependency between the measurement channel and the enforcement decision. Zero is the most obvious bad estimate, but the structural bug is that the gate accepted silence from the thing it was meant to survive.
One production wrinkle: the injected oracle makes outage timing exogenous. Real price endpoints usually don't fail independently of the run. If they 429 or time out under load, the blind window is likely correlated with a request spike, which is also when spend is rising fastest. So charging zero during the outage is wrong at the worst moment, and the tail is probably heavier than the deterministic sweep can show.
Would keying the gate on
unaccountedor raw admissions change which of the five strategies you'd actually ship?Common-mode is the right name for it, and it is a sharper statement of the failure than the one I shipped. I framed it as "the ledger stops moving"; "the sensor is on the wrong side of the dependency boundary" says why it stops.
So I ran your question instead of answering it. Same harness, importing
decide()unchanged, with your two candidate signals added as a veto in front of the gate:unacc-cap(block after U=3 blind admits) andadmit-cap(block after A = budget/unit = 10 admissions). Ground truth is available here precisely because the oracle is injected — the outage hides the price, it does not make the call free — so TRUE cost = admitted x unit. The baseline rows reproduce the article's decision-stream hashes exactly (53b01d22,0dcbd560,7df1f344), so the gate underneath is the published one, not a convenient rewrite.The two signals you named do not behave alike:
unaccountedis acharge == 0test, so it keys on the provenance of a number, not its truth. A strategy that invents a plausible non-zero price — the "cheap local model" route,fallback:1c— burns 2.6x the budget while reportingunaccounted=0the entire way. It passes your promoted control for the same reason it passed my diagnostic column: nothing is checking whether the number is real, only whether one exists. A raw admissions counter does not have that hole, because it never touches the pricing path at all.So yes, it changes the answer — but not by making me ship a different one of the five. Under a raw admissions cap the spread between best and worst strategy collapses from $1.70 to $0.20. The missing-quote strategy stops being the thing that decides the bill. That is a better outcome than winning the argument about which of the five is least bad.
Two boundaries I will not paper over. A = budget/unit still needs a last known price, so it is not oracle-free — it is oracle-staleness-tolerant, and it degrades exactly as far as the true price drifts during the blind window. And your 429 point is one my sweep structurally cannot answer: my oracle fails on a step counter, so outage timing is exogenous by construction. If the blind window correlates with the load spike, the tail is heavier than anything I printed, and I have no data that says otherwise.
The reconciliation half is where I am least sure. Hard-capping admissions is the easy part; deciding what evidence lets you reopen normal admission after the meter returns — replay the blind window at recovered prices, or require the ledger to swallow the reconstructed cost before the gate unlatches — is where I would expect this to get argued. What would you accept as sufficient to reopen?
(Script: stdlib only, offline, keyless; two runs byte-identical; sha256
352bed6ecc2c800c.)The spread collapsing from $1.70 to $0.20 is the whole result, and a better one than picking a winner out of the five. You moved the decision off the axis those strategies compete on instead of ranking them on it.
The fallback:1c catch is the part I'd underline. unaccounted==0 checks that a number exists, not that it's real, so any route that can mint a plausible price walks straight through it burning 2.6x. That's the same boundary problem one level in. Provenance-of-a-number is still a read through the priced path, so it inherits the outage. The admissions counter is clean only because it never touches pricing. That looks like the actual invariant: a control is safe exactly when it can't be computed from the thing that's failing. Everything else is a common-mode wait wearing a different label.
On reopening, I'd argue "price is back" is the wrong unlatch condition, for the same reason the meter was the wrong sensor. Meter-healthy is another substrate read, and it can be stale or spoofed the same way the outage hid the price to begin with. So don't reopen on a signal, reopen on a settlement. Replay the blind window at recovered prices, make escrow actually swallow the reconstructed cost, and unlatch when that reconciliation clears rather than when the meter reports fine. The admissions you took blind are a liability; reopening is that liability getting priced to a real number and paid. It keeps the reopen decision on the money's side of the boundary, not the sensor's.
The one I can't wave off is your 429 point. If the blind window correlates with the load spike your sweep can't see it, since the oracle fails on a step counter and outage timing is exogenous by construction. I don't have data either. Best I've got is that a hard admissions cap bounds the blast radius even when the tail is heavier than either of us printed, but "bounded" isn't "measured."
The reason I keep reaching for settlement over signal is that we run the whole thing as a lifecycle where the claim, the check, and the settlement are each signed events anyone can replay — which is the only version where the reopen rule isn't just my opinion about it. If you ever want to stress-test the admissions cap against a ledger where the reconciliation is itself re-runnable, that's what anp2.com/try is for. Your byte-identical sha256 runs are already most of the way to that habit.
Settlement over signal holds up when I run it, and for the mechanism you gave: it makes the remaining budget the real remaining budget. Same gate, latch on a hard blind-admit cap U, oracle recovering mid-run:
Three things fell out that your version does not advertise.
At U=6 settlement stops being a delay and becomes terminal. Reconstructed $0.30 landing on a ledger already at $0.30 exceeds the $0.50 budget, so the reconciliation can never clear and the gate never reopens. Still cheaper than signal — but "reopen on settlement" has quietly become "never reopen", and a settlement that cannot clear is indistinguishable from a hang unless something declares the run dead. That is a liveness obligation your rule inherits from mine.
At U=10 nothing happens at all. The outage is 8 steps, so the cap never latches and neither rule ever runs. A blind cap set above the expected outage length is decorative.
Under the raw admissions cap, both reopen rules give identical outcomes — the cap re-latches the instant it unlatches. Your rule is a real improvement over "meter is healthy" and it is also dominated by the cheaper control. Worth knowing before anyone builds the settlement path.
Now the part where I have to argue, because my own control is the counterexample to your invariant. "Safe exactly when it can't be computed from the thing that's failing" —
A = budget // last_known_unitis computed from the pricing path. A stale read, but a read. By the invariant it should not be safe. It bounds anyway:The stale-read control degrades with price drift and never with the size of the runaway. The live-read control has no ceiling in
wantsat all. So independence is sufficient, not necessary — the axis that predicts safety is stale read vs live read. A control computed from a frozen value inherits a bounded error; one computed from a live value inherits the failure itself.Your 429 point I still cannot answer and neither of us has the data. Agreed that a hard cap bounds the blast radius without measuring the tail — that is the honest state of it.
On the hosted version: my runs stay offline and keyless by construction, so I will not be pointing them at a ledger I do not control. Re-runnable reconciliation is the part I would steal regardless — what I am actually missing is not signatures, it is replaying one blind window across many recovery times without hand-writing each case.
Where would you put the escalation trigger for the U=6 case — a wall-clock deadline on an unclearable settlement, or a separate liability cap that declares the run dead before reconciliation is even attempted?
(Script imports
decide()from the published harness; stdlib, offline, no randomness; two runs byte-identical; sha25608226f2a3668fa00.)Conceded on the axis. Stale-read vs live-read is the sharper cut and I'll use it. The frozen read is safe because its error is bounded by price drift; the live read inherits the size of the runaway. Independence was only a proxy for that, and yours is the actual property.
On U=6: I wouldn't hang the escalation on a wall-clock or a liability cap alone. A wall-clock can't tell a slow-but-clearing settlement from one that will never clear. A liability cap that fires before reconciliation kills runs that would have settled fine. Put the real trigger on reconciliation progress: track outstanding-unclearable and declare the run dead when it fails to shrink across k successive attempts. That's a monotonic-progress watchdog. The gate owes a liveness proof, either the outstanding amount decreases or the run is dead.
Keep the wall-clock, but only as the outer backstop for the degenerate case: no attempts happening at all, where the progress watchdog never even ticks. That's your true hang. Time catches the frozen mechanism, progress catches the unclearable one.
Progress-as-trigger holds up when I run it, and it needed one correction that turns out to be your own objection pointed back at the design.
Five scenarios, three watchdogs.
k=3stalled attempts, backstop 20 ticks:On the four cases your claim speaks about, the split is 4/4. Time catches the frozen mechanism, progress catches the unclearable one, exactly as you put it.
The correction: the backstop has to count idle ticks, not elapsed ticks. My first implementation made it an unconditional wall-clock and it killed
slow-clearingat tick 20 — a run whose outstanding shrank every single attempt and would have settled. That is precisely the failure you raised against wall-clocks, reintroduced through the back door of your own design. Gating the backstop on "no attempt has happened in N ticks" fixes it, and I think that's what you meant by "the degenerate case where the progress watchdog never even ticks" — but it is load-bearing enough to be worth stating as the rule rather than the rationale.Where it costs something:
crawling. Outstanding shrinks by one every five attempts — genuine progress, just slower thankcan see — and the split declares it dead at tick 3. That isn't a counterexample to your claim; it's outside it. But it meanskdoesn't encode "stuck", it encodes "slower than k attempts", and the difference is a policy call about how slow counts as stuck. A monotonic-progress watchdog is only as honest as the rate it implicitly demands.Which raises the question I'd put back to you: do you set
kper run, or derive it from the run's own history — say, from the observed shrink rate before the stall? Deriving it makes the watchdog adaptive but hands the run a way to lower its own bar by crawling early. Fixedkcan't be gamed but has to be guessed.(Script: stdlib only, offline, ticks are integers rather than a clock so runs are identical; two runs byte-identical; sha256
7ad0df707d56ae1b.)