Refusal by Design: Implementing 15 Failure Safeguards in AI for Mycroft
A multi-month trend tool for the Mycroft Finance Investigator refuses to compare any month of data unless it passes 15 distinct verification checks, rejecting rather than merely flagging failures.
Most AI tools are judged on what they can produce. This one is built around what it refuses to produce, and treats that refusal as the actual engineering achievement. The multi-month trend investigation for the Mycroft Finance Investigator compares three months of verified finance data, but the interesting part isn't the comparison itself, it's that the engine attempts to refuse the task 15 separate times before it will compare anything at all.
The rule everything else rests on
Before any numbers get compared, a month can only enter the comparison if three conditions hold: it has to be the same entity and period that the plan claims, its source files have to still hash to what the run log originally recorded, and the editor has to independently recompute the same figure. If any one of those three fails, the run is rejected outright, not flagged for review. That distinction, rejected rather than flagged, is what makes the feature's shape unusual. It doesn't read three finished reports and summarize them. It reopens three previously verified runs, rehashes their source files, and re-derives every number from scratch. Only after that does it describe what moved between months. It trusts nothing it's handed, including its own earlier output.
What the tool actually reports
Once data clears every check, the output is direct: actual EBIT of $261,000 in January, $230,000 in February, and $265,000 in March, a $31,000 deterioration followed by a $35,000 improvement. The movement column labels each shift as "deteriorated" or "improved," and nothing more. It never states why the numbers moved, and it never projects what comes next. That silence is deliberate, not a gap the team ran out of time to fill.
Fifteen refusal paths inside one loader
The actual engineering effort went into building 15 distinct conditions inside a single loader function, each one capable of stopping the run cold rather than letting a doubtful number through. The tamper check at the center of this is ten lines: for every source file the run log claims to have verified, the loader rehashes it on disk and compares the result. If the file is missing, the run stops. If even a single byte has changed since that run was recorded, the run stops. There is no branch anywhere in that logic that logs a warning and continues anyway. That tamper check is just one of the 15. Others reject a log pulled from a different workflow, a period that doesn't match what the plan specified, a run whose human approval gate has already closed, an empty mismatch, a missing source file, and an EBITDA figure that no longer reproduces when recalculated. Every one of them ends the run rather than letting it proceed with a caveat.
Proving the detector actually discriminates
A recurrence detector that flags everything is worthless, so the system is tested against a case designed to show it doesn't do that. Revenue, cost of goods sold, and operating expenses are all adverse across all three months, and the engine correctly marks that pattern as recurring. Payroll, by contrast, is favorable in every period, and the same detector correctly returns no, it isn't recurring. That contrast is the evidence that the detector is discriminating based on the actual data pattern rather than defaulting to a blanket answer.
Pattern, not cause
The report is explicit that recurrence is a mathematical pattern, not a causal explanation, and the field meant to hold a causal explanation ships intentionally blank, with a named owner responsible for filling it in later. The system is allowed to find the pattern. It is not allowed to claim it knows why the pattern exists.
What "49 tests passing" doesn't mean
Even with 49 tests passing, the recipe is still marked draft, and the materiality threshold used during development remains an unapproved fixture rather than approved policy. That's framed as the specific failure this whole design guards against: a finance tool that quietly lets its own demo-stage threshold slide into policy without anyone explicitly approving it. Passing tests doesn't automatically mean a system is ready to ship its assumptions as fact.
The audit prompt
The closing challenge is a direct exercise: take a report your own system generates, list every number on it, and for each one ask what would have to be true for that number to be wrong, and whether your code currently checks for it. The uncomfortable finding most teams hit running this exercise is that most pipelines verify their inputs once at the start and then trust every number derived from them indefinitely afterward, rather than rechecking at the point where the number is actually used.
Key takeaways
- The system rejects failed data outright rather than flagging it, refusing to compare a month unless entity, hash, and recomputation all check out.
- Fifteen distinct refusal conditions live inside one loader function, including a ten-line tamper check that rehashes every source file on disk before trusting it.
- A working discriminator test, adverse categories flagged recurring, favorable payroll cleared, proves the detector isn't just flagging everything by default.
- The tool reports mathematical patterns explicitly, with no forecast, no recommendation, and no causal explanation offered.
- Forty-nine passing tests did not promote the development-stage materiality threshold into approved policy, which is treated as correct, careful behavior rather than incompleteness.
Who this is for
This is for anyone building AI systems that touch financial or other high-stakes numeric reporting and needs a concrete model for designing refusal, not just accuracy, into the system. It's a detailed build log from Adwait Changan for the Mycroft Financial AI project at Humanitarians AI, with the code and full audit trail published in pull request 17 for anyone who wants to see the implementation directly.
Chapters
- 0:00Re-deriving financial reports vs. summarizing existing text
- 0:50Designing 15 distinct refusal paths to stop doubtful data cold
- 1:40Deep dive into the 10-line loader tamper-checking code
- 2:25Forcing mathematical patterns over causal explanations
- 3:10The danger of promoting demo materiality thresholds into policy
Full transcript(auto-generated, with timestamps)
Re-deriving financial reports vs. summarizing existing text
[0:00]Hi, I am Edwait Changen and this video is about the multi-month trend investigation I built this week for the Mikraftoft Finance Investigator. Three months of verified finance data compared, but the interesting engineering is not the comparison. It is that the engine tries 15 separate times to refuse before it will compare anything at all. Here is the rule the whole feature rests on before any numbers. A month may enter the comparison only if three things hold. It is the same entity and period the plan claims. Its source files still hash to what the run log recorded and its editor recomputes to the same figure. Fail one and the run is rejected not flagged which makes the shape of the feature unusual. It does not read three finished reports and summarize them. It reopens three verified runs, rehashes their sources and reerives the numbers from scratch. Then and only then it describes what moved. It trusts nothing it was
Designing 15 distinct refusal paths to stop doubtful data cold
[0:50]Handed including its own earlier output. And this is the actual output. actual EBA 261,000 in January, 230 in February, 265 in March. A 31,000 deterioration, then a 35,000 improvement. Notice the movement column. It says deteriorated and improved. It never says why, and it never says what comes next. Which brings me to the part I actually spent the week on, not the comparison. The refusing 15 distinct conditions inside one loader function, each of which stops the run cold rather than letting a doubtful number through. Here is the tamper check itself 10 lines from that loader. For every source file the run log claims to have verified, rehash it on disk and compare. If the file is gone, stop. If a single bite changed since that run, stop. There is no branch in here that logs a warning and carries on. And that
Deep dive into the 10-line loader tamper-checking code
[1:40]Is one of 15. It also rejects a log from another workflow, a period that does not match the plan, a run whose human gate was already closed, an empty mismatch, a missing source file, and an ebitita that no longer reproduces. six of the 15 and every one of them ends the run. Now the test that actually matters, a detector that flags everything is worthless. So look at payroll. Revenue, cost of goods and operating expenses are adverse in all three months and the engine marks them recurring. Payroll is favorable in every period and the same detector returns. No, it discriminates. It does not decorate. And then the line I care most about the report states what it computed. It states that recurrence is a mathematical pattern, not a causal explanation. And the current explanation field ships intentionally blank with a named owner. The system is allowed to
Forcing mathematical patterns over causal explanations
[2:26]Find the pattern. It is not allowed to say why. 49 tests pass and the recipe still says draft. The materiality threshold is still an unapproved fixture. That is not incompleteness. A finance tool that quietly promotes its own demo threshold into policy is exactly the failure I was designing against. So, the verdict, the multi-month trend investigation compares three verified months of synthetic finance data and reports actual EBIT moving from 261,000 to 230 to 265,000. It identifies revenue, cost of goods, and operating expenses as recurring adverse categories and clears payroll, which is how you know the detector discriminates. Every figure is rederived from source files whose hashes are rechecked at read time behind 15 refusal
The danger of promoting demo materiality thresholds into policy
[3:12]Paths. It supplies no forecast, no recommendation, and no cause. 49 tests pass. The recipe still says draft, and the human gate is still open. Your turn. Here is the prompt. Take a report my system generates and list every number on it. For each one, tell me what would have to be true for that number to be wrong and whether my code currently checks it. Then tell me which checks I am missing. Run that against something you have built. The uncomfortable part is the last question. Most pipelines verify their inputs once at the start and then trust every number derived from them forever. That was the multi-month trend investigation for the MROT finance investigator. The code and the full audit trail are in pull request 17. I'd wait Changen for humanitarians AI.
More from Mycroft Financial AI
3:47Fencing the AI: Why Our Finance Agent Cannot Approve Itself
2:17Mycroft Update on Survivorship Bias: Why Excluding Failures Distorts Backtests
3:17Mycroft Update: Why Your AI Agent Ignores Your Code
1:54Building Regex Claim-Splitting Logic for Patent Parsing in Mycroft
3:18Deterministic What-Ifs in Mycroft: Scenario Analysis Without AI Guessing
6:18