paranoid_
Trust report for AI-written code

AI writes the code. paranoid verifies it.

One command checks the diff for deleted or weakened tests, dependencies that do not exist, swallowed errors, and claims not backed by the change, then prints a scored report with an exit code you can gate CI on.

curl -fsSL https://raw.githubusercontent.com/alainrk/paranoid/main/scripts/install.sh | sh
View source ↗
~/project after the agent, before the merge
$ paranoid verify --base main --claims summary.md

paranoid v0.1.0
repo: /home/you/project
base: 7db5cfbeaacf
head: worktree

score: 40/100  verdict: fail

dependencies (1 finding)

  DEP001  critical  requirements.txt:2
      The new dependency requests-toolkit-pro does not exist in PyPI.

test-integrity (2 findings)

  TI001  critical  test_division.py
      A test file that existed at base is deleted at head.

  TI004  high  test_addition.py:10
      A skip was added to an existing test.

exit status 2
0network by default
100%deterministic by default
1static binary
0–100trust score
The problem

What it looks for

Three failure modes that show up in agent-authored patches and are cheap to miss in review.

01

Gamed tests

A failing test is deleted, skipped, or rewritten into a tautology, so the suite passes without the code being fixed.

02

Hallucinated dependencies

A new import names a package that does not exist, was published days ago, or is one typo away from a popular name.

03

Unbacked claims

The summary states work (“all tests pass”, “refactored the retry logic”) that the diff and the test run do not back.

What it checks

Seven categories, one score

paranoid verify compares the repository before and after the agent worked. Every finding maps to a documented rule with a fixed ID and severity, listed with examples in the rule reference.

TI

Test integrity

Parses the test diff (Go with the real Go parser) and flags deleted tests, weakened assertions, new skip markers, tautologies, hidden renames, new mocking, new retries, new sleeps, stretched timeouts, and edits to CI and test configuration.

DEP

Dependencies

Cross-checks new imports against manifests, then looks up new packages on npm, PyPI, crates.io, and the Go proxy: nonexistent, brand new, nearly unused, or typosquatting a popular name.

EH

Error handling

Looks at every changed source file for errors made to disappear: a checked error newly discarded, an empty catch block, an except block that only passes, a no-op promise handler, and a return or raise turned into a log line.

SBX

Clean-room test run

Reruns the test suite in a container with the network disabled, and collects coverage where the tooling allows. Catches results that only held on the agent's machine, and coverage that quietly dropped.

CLM

Claims

Extracts concrete claims from the agent’s summary, a session file from Claude Code, Codex, Gemini CLI, Aider, or Cursor, or the commit messages, and checks each one against the diff, the clean-room result, and the diff's overall radius.

AS

API surface

Diffs public symbols between base and head and flags a symbol removed while the claims say a fix or feature landed: green by deletion, one layer deeper than deleting the test.

SF

Safety controls

Scans every changed file for known patterns: TLS verification disabled, an auth check removed, a tracked path hidden by .gitignore, a git hook changed, CI permissions widened, or paranoid's own baseline and hook config edited. Pattern-based, not a security scanner.

Score

One score, clear thresholds

Findings subtract from 100 by severity. The verdict and the exit code follow the score, so the same command works on your laptop and as a CI gate. Output as text, Markdown, schema-versioned JSON that is byte-identical across reruns, or SARIF for GitHub code scanning.

Adoption

Baseline in, fix-prompt out

Two commands for adopting paranoid in an existing repository and feeding findings back to the agent.

paranoid baseline

Point paranoid at a repo that has never run it before and it reports everything, not just today's change. Run paranoid baseline once to snapshot existing findings into .paranoid-baseline.json; only new findings fail CI from then on. See Baseline & suppressions →

paranoid fix-prompt

fix-prompt renders the findings of a verify run into a deterministic instruction block you can paste back to the agent. See fix-prompt →

CI usage

Exit codes you can gate a merge on

exitverdictmeaning
0passscore 80 or higher
1warnscore 50 to 79 (exit 2 with --strict)
2failscore below 50, or below --fail-under
3errorthe tool itself failed, never a finding
.github/workflows/verify.yml
- uses: alainrk/paranoid/action@main
  with:
    base: ${{ github.base_ref }}
    fail-under: 50
Principles

How it's built

Local and private

No telemetry, no analytics, no update checks. The only network use is the optional registry lookups, and --offline turns those off too.

Deterministic by default

No LLM as judge. The default pipeline is static analysis, so the same input produces the same report, byte for byte in JSON. You can diff reports and trust reruns.

Fails soft

A check that cannot run (no container runtime, no network, no recognizable test suite) is reported as skipped, and the run continues.

Single static binary

No CGO, no runtime dependencies beyond git, and docker or podman only if you want the clean room. Linux, macOS, and Windows.