Curbi break sessions · Reproduced failure
The extra k that turned $49 into $49,000
Our checker missed one character. A failing test made the gap reproducible. A parser fix and a regression keep this case visible.
The reply looked almost right.
The supplied policy allowed Starter: $49. The test reply was Starter is $49k.
That last character changes the amount to $49,000.
{
"policy": {"prices": [{"item": "Starter", "amount": 49}]},
"reply": "Starter is $49k."
}The old checker read the number as 49 and returned no findings. That was a silent pass in our own test, not a correct assessment of the price.
Before: missed
{"pass": true, "findings": []}Reproduced from the tests-first source. This historical result is an offline reproduction.
After: found
{
"pass": false,
"findings": [{
"rule": "price:mismatch",
"span": [11, 15],
"text": "$49k",
"why": "Starter is $49, not $49000."
}]
}The span uses zero-based UTF-16 offsets with an exclusive end: reply.slice(11, 15) is exactly $49k.
Download the offline before/after reproduction →
Unzip, enter the history folder and run node --test reproduce.mjs. The archive includes exact historical source snapshots, SHA256 and Git blob hashes, and controls. No dependencies or network are needed. Internal commit references document Curbi’s provenance claim; they are not an independent attestation.
Keep the failure. Fix the parser. Test the opposite.
Magnitude regressions were recorded before the checker changed. The fix reads the magnitude suffix before comparing the amount with the policy. $49k now means 49,000 in this case.
A detector that rejects every k would still be wrong. The regression suite includes legitimate magnitude prices and ordinary words after an amount. Each case runs with the price-list order reversed, too.
Starter is $49k.with an approved price of $49: finding.Starter is $49.with an approved price of $49: no configured rule fired.Starter is $49 monthly.with an approved price of $49: no configured rule fired.Starter is $49k.with an approved price of $49,000: no configured rule fired.
These are specific guards. They do not establish complete coverage of currency expressions or natural language. The current name-attribution rule still has known false positives for “respectively” lists, distant item names and relative comparisons such as “$10 more than.” Those limitations remain; this price-suffix fix does not resolve them.
Run the same check.
This command uses the current public endpoint and its documented User-Agent. It submits only the synthetic policy and reply shown here. Public rate-limited checks need no account or API key.
curl --fail-with-body --silent --show-error \
'https://api.curbi.io/v1/check' \
-H 'Content-Type: application/json' \
-H 'User-Agent: curbi-quickstart/1.0' \
--data '{"version":"2026-11-01","policy":{"prices":[{"item":"Starter","amount":49}]},"reply":"Starter is $49k."}'The finding above was observed in a live synthetic batch on : HTTP 200, Cloudflare Ray a5270b80cc043b08-EWR. The evidence file records the exact request, source references and controls. A recorded observation is not continuous monitoring.
Download the runnable regression Try your own reply
node --test story-regression.test.mjsThe downloaded test requires Node.js 20 or later and internet access. It sends synthetic inputs to the public Check API and fails on HTTP errors, malformed verdicts, missing findings or changed spans. Review it before running it in CI.
A separate check, with a precise boundary.
A model or gateway can produce the reply; Curbi can check that reply separately against the policy and records supplied to it. This example does not put Curbi between a model and its tools, and it makes no execution decision.
What this does not prove: that the supplied policy is correct, that a provider action happened, that a payment was blocked, or that every misleading reply will be caught. A passing check means no configured rule fired. It grants no authority to act.
Production signing is off. This example uses no signed receipts. Caller-supplied records are not independent provider evidence.
Bring the check into your own workflow.
Connect your agent Check a reply
Start with a synthetic failure, keep it as a test, and make the next change prove that the same case still holds.