A verifier for autonomous scientific code caught every seeded defect, after two of its own tests were made able to fail
A standalone verifier that checks a scientific computation's recorded outputs against independent rules and re-runs valid computations, evaluated on a corpus of valid cases and seeded defects.
Keywords: scientific software; verification; reproducibility; AI agents; negative controls; mutation testing
Abstract
AI agents that write and run scientific code can report results that are wrong in ways a reader cannot see: unit errors, heating values on the wrong basis, energy balances that create energy, or outputs read from a failed solver. We built a standalone verifier that checks a computation's recorded outputs and provenance against independent rules and re-runs valid computations to confirm they reproduce. It was evaluated on a corpus of 2 valid cases, which were re-executed, and 7 seeded defects, which were checked as recorded output files without re-execution, each with an expected rejection code recorded in advance. The verifier rejected every defect with the expected reason and accepted both valid cases. It also withstood 6 failure probes and 5 path-escape attempts with no silent acceptance. During evaluation, two of the tests applied to the verifier itself were found to be uninformative: one passed for the wrong reason and one could not fail by construction. Both were rebuilt with negative controls. We argue that a check provides evidence only if it has been shown capable of failing.
1. Introduction
Automated agents increasingly generate and execute scientific code. Their errors are often silent: a number is produced, formatted and reported, but it rests on a unit off by a factor of a thousand, a fuel quantity on the wrong heating-value basis, or the output of a solver that did not converge. Reproducibility practice holds that a computational result should be re-executable and checkable [1]. This study asks whether executable evidence, re-running the computation and testing its outputs against independent rules, exposes such failures, and how the checks themselves should be validated, a question with a long history in mutation testing [2].
2. Methods
2.1 Corpus
The corpus contains 2 valid cases, water heated by a known amount (502.32 kJ) and a gas heat input on a stated higher-heating-value basis (380.0 MJ), each with an independent hand calculation. It contains 7 defects, each seeded into a copy of a valid case's recorded outputs, with the expected rejection code recorded before the verifier was run (Table 1). The defect cases are checked statically, from their recorded files; only the valid cases are re-executed.
2.2 Robustness probes
Two replays of the valid cases compared file hashes between runs. The 6 failure probes covered a process that hangs and must be terminated with its children, a process that exits with an error, one that writes no output, malformed output, a non-finite value and a corrupted byte. The 5 path-escape attempts to read or write outside the case directory used relative paths, an absolute path and a symbolic link.
2.3 Validation of the checks
Each probe counts as passing only if the rejection names the expected reason; a rejection for any other reason is treated as a silent acceptance. Checks whose result could be guaranteed by construction were given negative controls.
3. Results
3.1 Seeded defects
The verifier rejected all 7 defects with the expected reasons (0 missed) and rejected 0 of 2 valid cases (Table 1, Figure 1). Each defect was rejected for its own reason rather than by a generic failure; the truncated output containing a NaN token returned two codes, being both non-finite and missing its provenance record.
Table 1. Seeded defects and the rejection reasons returned.
| Case | Class | Seeded defect | Rejection reasons returned |
|---|---|---|---|
| D1 | unit | kJ reported as MJ, factor 1000 off | unit mismatch |
| D2 | thermal basis | LHV total 342.0 MJ labeled HHV | heating-value basis mismatch |
| D3 | loss | output 115 MJ exceeds input 100 MJ | tolerance exceeded |
| D4 | solver status | status infeasible read as valid | non-optimal solver status |
| D5 | balance | mass out 95 kg vs in 100 kg | tolerance exceeded |
| D6 | provenance | provenance record absent | provenance record missing |
| D7 | corrupted output | truncated JSON with NaN token | non-finite value; provenance record missing |
3.2 Replays, failure probes and path escapes
Two replays of the valid cases hashed 6 files each and found 0 mismatches. Each failure probe was rejected with the expected code; 0 of 6 were silently accepted. All path-escape attempts were refused before any file was accessed; 0 of 5 were accepted.
3.3 Two uninformative checks and their repair
The byte-flip probe was intended to show that a single corrupted byte is detected by its hash. In its original form it ran in a scratch directory containing only the output file, so the verifier rejected the case for a missing file before reading the corrupted byte. The probe passed without testing corruption. It now stages the complete valid case with a correct manifest, flips one byte, and passes only if the rejection reports a hash mismatch or corrupt JSON.
The check that every benchmark claim links to an independent answer counted 0 orphans across 7 links. That result was guaranteed by how the claims were generated. The check now includes a negative control: a fabricated claim about a nonexistent case is passed through the same interface and must be flagged.
4. Discussion
Executable evidence reliably detects the mechanical failure classes represented in the corpus, provided the checks are themselves validated. The two repairs illustrate the principle: a check earns trust by being shown to fail on an input it should reject, and a check whose pass is guaranteed by construction provides no evidence. Executable evidence does not, however, judge whether the scientific question, model or assumptions were appropriate.
5. Limitations
- The corpus of 9 cases shows that these failure classes are detected, not that all failures are.
- The verifier runs local, trusted case directories, not adversarial code.
- Solver failures are detected from reported status; no optimizer runs inside the verification loop.
- Evidence was obtained on one operating system and architecture.
6. Conclusions
A verifier combining output checks with re-execution rejected all 7 seeded defects, checked from their recorded outputs, with the expected reasons, and reproduced and accepted all valid cases. Detecting defects by re-executing faulty code was not tested. Validating the checks with negative controls was necessary for these results to be meaningful.
References
- Peng RD. Reproducible research in computational science. Science, 334(6060):1226-1227, 2011.
- Jia Y, Harman M. An analysis and survey of the development of mutation testing. IEEE Transactions on Software Engineering, 37(5):649-678, 2011.