Skip to main content
TL;DR: CrossHair symbolic execution has real-world limitations. QWED addresses these with bounded model checking, depth limits, and graceful fallbacks. Every result is a DiagnosticResult — see the Code engine reference for the full field map.

The path explosion problem

Symbolic execution explores all possible execution paths. This works great for small code, but real-world code has:

When CrossHair works

When CrossHair fails

QWED’s bounded model checking solution

We implemented depth limits to prevent path explosion:

Fail-closed verification results

Updated in v5.3.0. verify_code() and every other SymbolicVerifier public method now return a DiagnosticResult. The legacy dict shape (result["status"], result["is_verified"], result["functions_checked"]) is gone. See the Code engine migration guide for the field-by-field mapping.
verify_code() is fail-closed: absence of proof is never reported as success. In fact, this engine never emits VERIFIED — CrossHair’s search is timeout-bounded, not a completeness proof, so a clean run maps to UNVERIFIABLE with constraint_id = "symbolic_verifier.no_counterexample_found". Treat symbolic-engine output as a bug hunter, not an authority.

Result fields

DiagnosticStatus
DiagnosticStatus.UNVERIFIABLE for any incomplete or counterexample-producing run, or DiagnosticStatus.BLOCKED when verification could not be attempted at all (parse error, no functions, CrossHair missing). Read developer_fields["constraint_id"] for the specific reason.
boolean
Convenience alias for status is DiagnosticStatus.VERIFIED. Always False for this engine.
string
Layer 1 agent-safe summary of the outcome. Safe to surface to models — no rule IDs, detection logic, or internals.
string | None
Layer 3 proof reference. Always None for the Code engine.
string
Structured reason code. One of:
  • symbolic_verifier.no_counterexample_found — clean CrossHair run, still UNVERIFIABLE because completeness was not proven.
  • symbolic_verifier.counterexample_found — CrossHair disproved a check.
  • symbolic_verifier.timeout — verification did not converge within timeout_seconds.
  • symbolic_verifier.incomplete_coverage — at least one function could not be checked.
  • symbolic_verifier.no_typed_functions — no functions carried the type hints CrossHair requires.
  • symbolic_verifier.no_verifiable_functions — the source contained no functions.
  • symbolic_verifier.syntax_error — the code could not be parsed.
  • symbolic_verifier.crosshair_not_available — the CrossHair engine is not installed.
  • symbolic_verifier.verification_error — verification did not complete cleanly.
string
"symbolic" for standard runs, "bounded_symbolic" for verify_bounded() runs.
integer
Total functions found in the submitted code.
integer
Functions that were actually run through symbolic execution. A skipped function does not count as checked.
integer
Functions that were proven by CrossHair without counterexamples.
integer
Functions skipped because they cannot be analyzed (for example, no type annotations).
integer
Functions that could not be proven, including skipped functions and functions whose verification raised an error.
integer
Number of concrete counterexamples produced by CrossHair.
integer
Number of per-function timeout issues reported.
array
Per-function issue records with type (unverifiable, counterexample, timeout, or error), function name, and description.

Why untyped code fails closed

CrossHair requires type annotations to perform symbolic execution. Functions without type hints are reported as skipped and unverifiable, and the overall result fails closed:
Mixed code that contains both typed and untyped functions also fails closed — a single skipped function is enough to keep is_verified = False and produce constraint_id = "symbolic_verifier.incomplete_coverage". Code that contains no functions at all returns BLOCKED with constraint_id = "symbolic_verifier.no_verifiable_functions". Pre-verification exits (crosshair_not_available, syntax_error) return the same fail-closed shape — is_verified is False and function counters are absent from developer_fields — so callers can rely on constraint_id and agent_message regardless of how verification ended.

Configuration guide

Conservative (fast, less coverage)

Balanced (default)

Thorough (slow, more coverage)

Fallback strategy

When symbolic execution fails, QWED falls back to:

Honest benchmarks

We tested CrossHair on different code types:

Best practices

Do use symbolic execution for

  • ✅ LLM-generated utility functions
  • ✅ Mathematical calculations
  • ✅ Validation logic
  • ✅ Simple transformations
  • ✅ Code with clear contracts

Don’t use symbolic execution for

  • ❌ Entire applications
  • ❌ Code with external dependencies
  • ❌ Deep recursion algorithms
  • ❌ Real-time systems
  • ❌ Code with I/O operations

API reference

Bounded model checking

verify_bounded() applies loop and recursion bounds to the code before verification, then delegates to verify_code(). Every result sets developer_fields["verification_mode"] = "bounded_symbolic" and includes the applied bounds and the underlying complexity analysis. If the bounds transform itself fails (for example, the AST cannot be unparsed after transformation), the method returns BLOCKED with constraint_id = "symbolic_verifier.bounds_transform_error" instead of silently falling back to the original code:

Fail-closed result semantics

SymbolicVerifier.verify_code() treats absence of proof as failure. The engine never emits VERIFIED — a clean CrossHair run is UNVERIFIABLE with constraint_id = "symbolic_verifier.no_counterexample_found". Code that contains no functions, contains untyped functions, or mixes typed and untyped functions cannot ever appear as verified.

Result reason table

Typed function — no counterexample found

Untyped function — fails closed

CrossHair requires type hints. Untyped functions are reported as skipped and unverifiable rather than silently passing:

Mixed typed and untyped — fails closed

Even if some functions verify, a single skipped function prevents an overall pass:

Code with no functions — fails closed

Source that contains only top-level statements has nothing to prove and is reported as BLOCKED:
Do not gate downstream behavior on is_verified alone — for the Code engine it is always False. Downstream authority checks must inspect result.proof_ref, which this engine intentionally leaves as None. Use developer_fields["constraint_id"] for the specific reason and developer_fields["functions_checked"] to distinguish “no counterexample found” from “no symbolic proof was performed.”

Summary


“My guess would be that technique falls apart at depths required in real world coding environments.” — Reddit criticism. We agree. That’s why we have bounds and fallbacks.