DEV Community

Cover image for Why "1 passed in 0.01s" is a lie when AI writes the tests (and how I built a Z3 + Zig 0.17 truth gate to stop it)
newmathphys
newmathphys

Posted on Edited on

Why "1 passed in 0.01s" is a lie when AI writes the tests (and how I built a Z3 + Zig 0.17 truth gate to stop it)

Why "1 passed in 0.01s" is a lie when AI writes the tests

(and how I built a Z3 + Zig 0.17 truth gate to stop it)

  • Repository: https://github.com/newmathphys/kern
  • License: PolyForm Noncommercial 1.0.0 / Commercial (source-available)
  • Static binary: kernc-x86_64-linux-musl in the release assets (no Zig install needed)

The lie is not in pytest

Let me be precise, because the title is deliberately blunt. pytest does not lie.
It reports what happened: the test function ran to completion without raising.
That is all 1 passed in 0.01s ever meant.

The lie is in the inference. When an AI agent writes both the fix and the test,
"1 passed" is presented as evidence that the fix is correct. It is not evidence of
anything, because the test was never able to fail.

Here is the actual demo from this repo (make run-example), a withdrawal function
where the agent dropped the amount <= 0 guard:

[1] pytest:  1 passed in 0.01s              <- green. The bug ships.
[2] KERN:    contract_refuted.smt2: SAT  -> e=0 (F)  COUNTEREXAMPLE
             contract_fixed.smt2:   UNSAT -> e=1 (T)  PROVED
Enter fullscreen mode Exit fullscreen mode

The test contained no assert at all. It called the function and checked that no
exception was raised. An agent optimising for a green checkmark will write exactly
that, and it will keep writing it, because nothing in a boolean CI pipeline
distinguishes 1 passed (a real test) from 1 passed (an empty one).

What I built instead

KERN is an L0–L5 verification gateway written in Zig 0.17. A claim does not become
e = 1 because a test printed green. It becomes e = 1 only when an external
trusted checker
(Z3) proves it, or when a reproducible execution record backs it.

Three mechanisms do the work.

1. Belnap B₄ accumulator. Verdicts are not overwritten, they are accumulated:
(p, n) -> N | T | F | B. A passing test (T) joined with a counterexample (F)
yields B — conflict. The conflict is never resolved in favour of the proof. This
is JOIN_K(T, F) = B, and it is proved in Lean 4, not asserted in a comment.

2. Can-fail harness (tools/canfail.py). Every check in the repository must
prove that it is capable of failing: the harness injects a fault and requires a
non-zero exit code. Current state:

total make targets:  89
CHECK targets:       68   (must be able to fail)
CHECK with proof of "can fail":  64/68
registered fault-injection cases: 73
Enter fullscreen mode Exit fullscreen mode

This is the part that found the real problems. Auditing my own suite turned up
26 defects of a single class: "silently broken checks" — scripts or tests that
returned exit code 0 while the check itself was broken. Examples:

  • ./formal/check.sh | tail -3 without pipefail — the pipeline reported the status of tail, so a failing proof check looked green;
  • kernc cat image /raw/missing printed data to stderr and exited 0, so kernc cat ... > out.txt produced an empty file and no error;
  • a .gitignore rule *.log placed after !docs/evidence/*.log silently excluded every verification log — the repo published claims without evidence.

3. Independent proof-DAG checker (src/verifier/proof_check.zig). Z3's unsat
is not taken on faith. KERN parses the solver's proof DAG and re-derives:

  • no proof holes (hole / trust / sorry → immediate rejection);
  • premise binding — every nested (asserted ...) must match a clause of the input contract (premises_unbound == 0);
  • mp, unit-resolution, refl/symm/trans, and-elim, not-or-elim, monotonicity;
  • Farkas arithmetic certificates for linear integer inequalities — including the ¬(l ≤ r) ⟺ r − l + 1 ≤ 0 normalisation over ℤ (where most hand-written checkers silently get the sign or the +1 wrong);
  • the DAG must conclude false.

On the reference proof this now reports trusted: 0 — every one of the 16
steps is independently re-derived:

[PROOF VERIFIED] steps: 16 | premises bound: 1/1 | mp: 2 | rewrite (linear): 5 |
                 farkas: 1 | trusted: 0 | holes: 0
Enter fullscreen mode Exit fullscreen mode

Honest limits (this is the part most write-ups skip)

I would rather publish the boundaries than have someone find them:

  • The static gate does not raise pass@1. Measured on HumanEval+ with a real model: 0.524 base / 0.500 plus. The gate's precision is 100 % (55/55 blocks were genuine failures, 0 false blocks), but it fires before the tests, so the score is unchanged. Raising it requires execution evidence and iterative repair, not one-shot filtering.
  • zstd is declared in the format and NOT implemented. Zig's std ships a zstd decompressor only, and there is no static libzstd.a here, so linking it would break the hermetic musl build. Requesting it returns error.CodecUnsupported rather than failing quietly. deflate (0x02, a KERN extension) is implemented and tested.
  • Compression and zero-copy are mutually exclusive. Reading a compressed object needs a buffer, so the zero-copy path refuses it explicitly instead of handing back compressed bytes as content.
  • QuixBugs 31/31 is execution, not proof — those bugs are caught by running the official test cases, not by a ∀-quantified argument.
  • The Refactory numbers are a Python harness, not the KERN core. Two scripts exist; the first reported 83.2 % on buggy files and 83.7 % on correct ones — rates that coincide, so it measured nothing. The second (1705/1782 buggy at 0 false positives on 2442/2442 correct) agrees with the dataset's own test suite, which makes it close to tautological. Neither uses Z3 or the Zig core at all, and the README says so in a footnote.
  • 26 of 86 logged defects were "silently broken checks." That is not a brag — it is the base rate I measured while building the harness that catches them.

What it actually costs to adopt

No Zig install, no build step:

curl -fsSL -o kernc https://github.com/newmathphys/kern/releases/download/v2.2.0/kernc-x86_64-linux-musl
chmod +x kernc && ./kernc prove formal/example.smt2
Enter fullscreen mode Exit fullscreen mode

Or as a GitHub Action, one line:

- uses: newmathphys/[email protected]
  with:
    contract: formal/spec.smt2
Enter fullscreen mode Exit fullscreen mode

Or from an AI agent over MCP (examples/kern_mcp_server.py, stdlib only):

{"mcpServers": {"kern": {"command": "python3",
  "args": ["/path/to/kern/examples/kern_mcp_server.py"]}}}
Enter fullscreen mode Exit fullscreen mode

The MCP server exposes kern_verify_smt, kern_prove_with_checker and
kern_verify_multi_belnap. The last one returns JOIN_K(T, F) = B when two
contracts contradict each other, and refuses to collapse it into a proof.

Why the blunt title

Because the failure mode is not exotic. It is the default outcome of putting an
optimiser (an agent) next to a boolean signal (a green checkmark) with no
independent verifier in between. The agent is not malicious; it is doing exactly
what the signal rewards. The fix is not a better prompt — it is removing the
boolean and replacing it with something that cannot be satisfied vacuously.

1 passed in 0.01s is not a lie. Treating it as proof is.


Defect registry: #1–#86. 230 core tests, cross-arch runs on ARM64 and
big-endian POWERPC64, 32 Lean 4 theorems with 0 sorry, 100 % decision coverage.
Every number above is reproduced by make evidence and published under
docs/evidence/.

Top comments (4)

Collapse
 
newmathphys profile image
newmathphys •

KERN v2.7.3 — Zero-Trust Formal Verification Gateway (Zig 0.17 + Z3 + Lean 4)
• 147 Lean 4 theorems (0 sorry) · 436 core tests (x86_64, ARM64, PPC64 BE)
• 164/164 CHECK gates · 196 non-vacuous can-fail cases · 1,225/1,225 mutants killed
• NIST Juliet / SV-COMP paired benchmark: Youden J = 1.00, score 27/27 (0 penalty)
• QuixBugs symbolic diff: 40/40 DIVERGED, 0 false equivalents · AI-Traps: 6/6 caught
• Upstream bugs found & PRs submitted: TheAlgorithms/C (#1595, #1596), TheAlgorithms/Rust (#1075)
• Independently verified on release binaries (PHI-OMEGA / M: 0/1,680 translation mismatches)

Collapse
 
newmathphys profile image
newmathphys •

Here is the comprehensive, industrial-grade architectural diff and changelog comparing KERN v2.4.0 (frozen on GitHub at commit 28e6bb9) and KERN v2.5.0 (accumulated across 134+ commits on v2.5-dev up to HEAD: 1bab8c2):


🛡️ KERN v2.4.0 vs v2.5.0: Complete Architectural Diff & Comparative Analysis

Core Paradigm Shift:

v2.4.0 was a strict contract verifier requiring manual @kern: annotations.

v2.5.0 is an autonomous, zero-annotation universal repository auditor, AI security firewall, and self-verifying proof engine holding a 100.0% exhaustive mutation score across 1,225 sites.


📊 1. Metric-by-Metric Comparison

Metric / Subsystem v2.4.0 (Frozen on GitHub) v2.5.0 (v2.5-dev HEAD) Delta & Impact
Commit History Baseline (28e6bb9) +134 commits ahead Comprehensive architectural expansion
Native Zig Core Tests 299 tests 400 tests (392 passed + 8 skipped) +101 new unit tests (0 UB, 0 memory leaks)
kernx Engine Tests 38 tests 53 tests (100% pass) +15 tests (PBT, DST 500-step, Merkle Chain)
Lean 4 Formal Proofs 42 theorems in 8 files 120 proven theorems in 8 files +78 new theorems (0 errors, 0 sorry)
Mutation Testing 95.0% (sampled, 420 sites) 100.0% (1,225 / 1,225 sites) 100% exhaustive without sampling (0 survivors)
Can-Fail Discipline 82 CHECK targets (74 anchors) 122 CHECK targets (116 anchors) 100% non-vacuous coverage (138 fault cases, 0 vacuous)
QEMU Cross-Architecture 240 tests (stale log) 400 tests (ARM64 & PPC64 Big-Endian) Bit-identical results under native emulation
Supported Languages 4 (.py, .zig, .c, .rs) 7 languages (+ .ts, .js, .go) Sorbet-style type inference across 95% of software stacks
WebAssembly Engine ❌ None 85,545 bytes (kernc.wasm) 5 exports, freestanding client-side LIA solver in <0.2 ms
MCP Server Tools 5 tools 8 tools (+ xray, verify_action, rlvr) M8ven Trust Index compliance & live listing
Closed Kernel Defects Open (#123, etc.) 35 real kernel defects fixed Defects #123–#162 caught by self-testing harnesses

🔬 2. The Seven Core Qualitative Breakthroughs in v2.5.0

1. Autonomous Native LIA Solver in Pure Zig (builtin_lia.zig)

  • v2.4.0: KERN could not decide arithmetic internally. Without an external 150 MB C++ Z3 binary installed, the Truth Gate remained closed (e = 0).
  • v2.5.0: Features a custom linear integer arithmetic solver implementing Fourier-Motzkin elimination with GCD-strengthening ($\lfloor c / \gcd \rfloor$) and strict integer inequality shifting ($a < b \iff a - b + 1 \le 0$). Verified against Z3 across 100 differential systems (0 discrepancies) and 60 metamorphic transformations. Proves linear contracts 50× faster than Z3 on bare-metal systems with zero dependencies.

2. Complete Elimination of Trusted Proof Steps (trusted: 0 | holes: 0)

  • v2.4.0: The musl abs.c benchmark remained as SKIP (trusted: 15). IEEE-754 floating-point proofs relied on trusted: 213, and string theory relied on trusted: 9.
  • v2.5.0:
    • musl abs.c $\to$ trusted: 0 | holes: 0 (all 51 DAG steps verified).
    • IEEE-754 NaN $\to$ trusted: 0 | holes: 0 (reduced from 213 to 0).
    • QF_S strings $\to$ trusted: 0 | holes: 0 (reduced from 9 to 0).
    • Added sound proof rules: conservative definition introduction (intro-def with occurs-check), RAA hypothesis discharge (lemma), propositional tautology elimination (def-axiom), and discrete integer disjunctive splitting ($X \ne Y \iff X < Y \lor X > Y$).

3. Zero-Annotation Code Doctor (--xray & --gen-tests)

  • v2.4.0: Required manual # @kern:requires / @kern:ensures annotations. On unannotated or legacy code, KERN reported "0 functions checked".
  • v2.5.0:
    • --xray mode: Evaluates raw, unannotated code. Tracks AST path conditions (including path-narrowing after sequential if ...: return), mathematically proving [DEAD BRANCH] (UNSAT reachability), [REDUNDANT GUARD], and [CRASH PATH] (division by zero, integer overflows).
    • --gen-tests mode: Queries Z3 models for every reachable path, synthesizing standalone pytest suites providing 100% branch coverage out of the box.

4. Universal Repository Auditor (kernc audit-repo)

  • v2.4.0: Restricted to auditing isolated local test fixtures.
  • v2.5.0: Command kernc audit-repo <local_path | github_url>:
    • Clones remote repositories into an isolated RAM-disk (/dev/shm) with strict sandboxing (Git hooks disabled via core.hooksPath=/dev/null, LFS blobs ignored, symlink loops prevented).
    • Cleanly reaps temporary files via signal handlers on SIGTERM / SIGINT (Defect #156).
    • Generates an audit passport breaking down 7 languages, cyclomatic complexity hotspots, and standalone HTML reports (--html-out).

5. In-Browser WASM Playground (docs/index.html + docs/kernc.wasm)

  • v2.4.0: Existed solely as a native command-line binary.
  • v2.5.0: Compiles into an 85 KB freestanding WebAssembly module (wasm32-freestanding). Visitors to https://newmathphys.github.io/kern/ can paste raw code or any GitHub URL: the browser executes Fourier-Motzkin LIA and Belnap $B_4$ lattice operations directly on the client side in <0.2 ms without server roundtrips.

6. AI Threat Shield & Anti-Reward Hacking

  • v2.4.0: Protected only against algorithmic bugs in written code.
  • v2.5.0: Protects against active deception by autonomous LLM agents:
    • Anti-Cheat Gate: Static AST blocking of __eq__ -> True, sys.exit(0), and production mock patches used by AI to fake green CI runs.
    • MCP Security Auditor: Scans Model Context Protocol schemas for prompt-injection payloads, zero-width Unicode characters (U+200B), and seals configurations via mcp-tools.lock.json against dynamic rug-pull attacks.
    • FinOps / Action Firewall: Semantic RFC 9110 gatekeeper (409 Conflict, 422 Unprocessable) validating agent tool calls against financial policies before network execution.

7. Exhaustive 100.0% Mutation Testing Milestone (1,225 / 1,225)

  • v2.4.0: Tested on a random sample of 40 sites out of 420 (3.3% of the codebase). Suffered from Defect #124, where code edits shifted the PRNG seed and fluctuated scores.
  • v2.5.0:
    • Re-architected sampling to use deterministic per-site hashing: sha256(seed : file : text : mutation).
    • Exhaustively killed 1,225 out of 1,225 mutants across all 20 core modules without sampling (0 survivors).
    • Identified and fixed /dev/shm capacity exhaustion via _trim_slot_cache(), eliminating false-positive compiler kills.

🛠️ 3. Critical Kernel Defects Caught by the Self-Testing Harness

The self-testing harness (canfail, mutator, OOM injection) caught and fixed 35 real defects (#123–#162) during this cycle, including:

  • Defect #124: PRNG state shift during mutation sampling eliminated via deterministic per-site hashing.
  • Defect #128: Fixed unauthenticated object names by sealing paths into the Merkle root via sealImageRoot and computeImageMerkleRoot.
  • Defect #130: Caught a vacuous test in pcc-check where proof_concludes_false masked verification failures.
  • Defect #132: Caught a test-oracle loop where --gen-tests took the buggy function as its ground truth.
  • Defect #144: Fixed a vacuous test in ffi-bridge-check where the mutator patched the wrong verification path.
  • Defect #149: Corrected path-narrowing in --xray so sequential if ...: return statements properly invalidate unreachable subsequent conditions.
  • Defect #156: Added SIGTERM/SIGINT traps and atomic os.replace rollbacks to prevent dirty git trees when tests time out.
  • Defect #161: Prevented 57 false-positive [CRASH PATH] warnings on IEEE-754 floating-point divisions by zero (which yield ±inf, not panics).

🏁 Summary

  • v2.4.0 established that formal verification on Zig and Lean 4 is possible.
  • v2.5.0 proves that formal verification can be fully autonomous, achieve an exhaustive 1,225/1,225 mutation score, execute in an 85 KB browser WASM module, and protect production systems against AI hallucinations without requiring a single handwritten specification.
Collapse
 
newmathphys profile image
newmathphys •

Quick update — just cut v2.4.0 after running a destructive audit on the new parser, C-ABI, and allocator error paths (pushed our internal defect log from #86 to #103):
github.com/newmathphys/kern/releas...
A few low-level bugs and fixes from this sprint that might be useful to others working with Zig 0.17 and C-ABI:
Testing threadlocal in libkern.so (why zig build test wasn't enough):
In our compat.zig wrapper, if (builtin.is_test) routes I/O straight to std.testing.io at comptime. That meant our threadlocal var tls_io fallback for C/Python callers was completely bypassed during standard Zig unit tests. Writing a standalone C11 stress test (zig cc -Wall -Wextra -Werror -pedantic -std=c11 -pthread) that spawns 8 OS threads hammering libkern.so concurrently (8 × 500 kern_hash + 8 × 20 kern_smt_verify calls) verified the TLS path under actual contention, and -Wpointer-sign immediately caught a char * vs unsigned char * mismatch in include/kern.h (#100) plus missing NULL-pointer guards when len > 0 (#99).
OOM fault injection caught a classic nested-try leak (src/verifier/proof_check.zig):
Running the new S-expression proof checker under a step-by-step failing allocator (fail_index = 0..N) caught a leak in try out.append(allocator, try allocator.dupe(u8, inner)) — when append failed with OutOfMemory, the freshly duplicated slice was orphaned (#101). Also capped recursive S-expr parsing at MAX_SEXP_DEPTH = 4096 after a 2,000,000-paren input blew the stack with SIGSEGV (#98).
Z3 5.1.0 (get-model) quirk & partial unit-resolution:
Added human-readable counterexample extraction ([COUNTEREXAMPLE] amount = -1, balance = 1) when a contract is refuted (SAT). Two Z3 gotchas bit us: calling (get-model) after unsat prints an error that corrupts the stdout stream before (get-proof), and Z3 5.1.0 prints models without an outer (model ...) wrapper (just a bare list of (define-fun ...)). Also fixed our unit-resolution checker to return a 3-state verdict so partial resolution steps emitted by Z3 on (ite ...) branches verify cleanly ([PASS] withdraw_fixed on if/elif/else Python contracts).
CLI --deflate (0x02) & 100% canfail coverage:
Wired std.compress.flate into kernc build --deflate and kernc cat (3.16x compression on our test corpus, verified on read with zip-bomb bounds checking), added kern_verify_python to the stdio MCP server, and expanded the Zig mutation tester from 6 to 14 files (427 mutation sites, 97.5% kill rate, 70/70 Makefile check targets proven capable of failing).

Collapse
 
newmathphys profile image
newmathphys •

Another major update to v2.4.0 (61b341c) — we expanded the formal proofs, made the contract extractor polyglot, and closed four classic "specification gaming" traps that AI agents use to bypass verification: 

github.com/newmathphys/kern 

  1. Closing Four AI Agent Specification Traps:
  • Vacuous Preconditions (false ⟹ anything): If an agent writes a contradictory precondition (# @kern:requires amount > 10 and amount < 5), the implication requires ⟹ ensures is trivially UNSAT, tricking standard verifiers into reporting PROVED. KERN now checks precondition satisfiability first and rejects empty domains ([VACUOUS] -> B4: N, e = 0).
  • Contract Tampering (--lock / --verify-lock): An agent that cannot fix a bug might simply delete or weaken the # @kern:ensures comment. Contract fingerprints are now sealed in docs/contracts.lock.json (make contracts-lock-check fails with rc = 2 if any specification is weakened or removed).
  • Contract-Free Refactoring Equivalence (--diff-equiv): Without writing a single contract, KERN checks ∃x: f_old(x) ≠ f_new(x) over ℤ (make diff-equiv and the 5th MCP tool kern_check_equivalence) and prints the exact input where a refactored function diverges from the original.
  • Counterexample Materializer (--emit-pytest) & [RUNTIME CONFIRMED]: Every Z3 counterexample is automatically re-evaluated against the real function at runtime (eliminating translation false positives) and can be exported straight into a failing pytest regression test.
  1. Polyglot Contracts (.py, .zig, .c, .rs), Machine Bounds & Self-Verification:
  • The comment extractor now parses contracts across Python, Zig, C, and Rust, adding machine-integer bounds (i32, u32, i64, usize) and automatic division-by-zero obligations (divisor != 0).
  • Self-Verification (make self-verify): KERN now verifies its own critical offset arithmetic and the Farkas negation identity (¬(l ≤ r) ↔ r - l + 1 ≤ 0) in .zig source via Z3.
  1. Lean 4 Proofs for the Proof Checker (formal/FarkasSoundness.lean):
  • Added our 8th Lean 4 file (42 theorems total, 0 sorry), formally proving the soundness of our integer Farkas certificate normalizer, 3-valued check results (verified | bad | unverifiable), vacuous precondition rejection, and JOIN_K(x, N) = x for skipped tests (exit 2).
  1. Stratified Mutation Testing (95.0% / 100% effective) & GitHub SARIF Line:
  • Fixed a subtle bug in our test runner (compat.envVar returned null without libc -> fixed by reading /proc/self/environ, Defect #112) and ensured z3 is required during mutation runs (--require-solver, Defect #110). Across all 14 files (420 sites, 279 core tests), the stratified mutation score is 95.0% (38/40 killed, 2 provably equivalent).
  • Added SARIF 2.1.0 export (--sarif), native GitHub PR annotations (--github-annotations), a one-command pre-commit hook (--install-hook), std.crypto.timing_safe.eql for constant-time digest checks, and Ed25519 signing for the SLSA attestation (kern.intoto.sig).