← Back to blog Feature · September 2026

Behavioral Contract Validator: does your code lie about itself?

Published September 2026 · Bugweg team · 3 min read

Most code review, human or automated, asks one question: is this a known bad pattern? The Behavioral Contract Validator asks a different one: does the implementation do what it says it does. Every function makes claims about itself, in its docstring, its return type, its comments, and those claims are a contract most reviewers never actually check against what's underneath.

A contract nobody reads

Take a function called fetchActiveSession() with a docstring that says it returns a Session object or raises SessionExpiredError. Nothing about returning None. Six months later someone adds an early return for a bad-cache case, and now the function silently returns None on a path the docstring swears doesn't exist. A linter won't flag this. The types might not even flag it if the return type was loosely annotated as Optional from the start. The only thing that catches it is comparing what the function promises against what it actually does under that specific branch.

Same story with side effects. A function named validateAndCharge() with a comment saying 'throws on any payment failure, never returns a partial result' can still have a branch where a downstream call fails, gets caught, logged, and swallowed, and the function returns a success-shaped object anyway. The name and the comment both describe a contract. The implementation, in that one branch, breaks it. This is the class of bug the Validator is built to surface: not a crash, not a syntax error, a gap between stated intent and actual behavior.

This check runs on the Team and Enterprise plans and during the free trial; it is not included in the Developer plan.

Why this isn't standard static analysis or generic LLM review

Static analysis tools check a codebase against rules about structure: unused variables, type mismatches, unreachable branches. They don't read your docstring and ask whether the implementation honors it. A generic LLM pass asked to review a diff for bugs will often catch style issues or obvious logic errors, but it isn't structured to hold an implementation up against its own declared contract, comment by comment, path by path. The Behavioral Contract Validator is built specifically for that comparison. It's the difference between checking whether something is broken and checking whether it's honest about what it does.

This matters most in exactly the places docstrings tend to drift from reality: functions that started simple and picked up edge cases over multiple PRs, error handling that got broadened without anyone updating the comment above it, return types that got loosened for convenience. None of those show up as syntax problems. They show up as a contract violation, which is a category most review tooling doesn't have a name for, let alone a check for.

The Behavioral Contract Validator is live in bugweg today, checking PR diffs for exactly this mismatch between what a function's docstring, type signature, or comment claims and what its actual behavior does. It doesn't replace static analysis or general bug review, it adds the one check neither of those was built to do: does this function lie about itself.

If you want to see where your own codebase's contracts have drifted, the fastest way is to run it through a review pass and see what surfaces on functions you haven't touched in a while. Those are usually where the docstring and the implementation have quietly stopped agreeing.

Related reading: what bug genealogy is, how the Recurrence Firewall keeps fixed bugs fixed, and the full feature list.

See it on your own repo. 3 free PR reviews — card required, never charged.

Install on GitHub
Back