paranoid_
Report

Baseline and suppressions

On a repository that has never run paranoid, verify reports every finding in the range, not only the latest change. A baseline snapshots those findings so only new ones fail CI.

.paranoid-baseline.json is the only file paranoid reads besides command-line flags. It never changes which rules run and never tunes a threshold. It only records which findings were already reviewed and carried forward, the same job a linter's baseline file does elsewhere. It is data, not configuration.

Adopt paranoid on an existing repo

Run this once, from the repo root:

paranoid baseline --base <the oldest point you care about>

This runs the exact same checks as verify and writes every finding it sees to .paranoid-baseline.json, with no reason and no expiry. Commit that file.

From then on, verify auto-loads it: any finding that still matches one of its entries moves out of the report's findings and into a suppressed section instead, and the score ignores it. New findings, the ones an agent introduces after adoption, still fail the run exactly as before. Nothing is hidden: the suppressed section always lists what was suppressed and why, in every format, even when it is empty.

A baseline entry is matched by rule ID, file, and a fingerprint of the finding's evidence text, not by line number, so it survives unrelated edits elsewhere in the file. It does not survive the evidence text itself changing, or the finding moving to a different file.

Flags that control it

FlagMeaning
--baseline <file>Load this file instead of the auto-detected .paranoid-baseline.json at the repo root
--no-baselineIgnore any baseline file, including the auto-detected one

A baseline file that exists but cannot be parsed is always a hard error (exit 3), whether it was auto-detected or named explicitly. Only a genuinely missing file at the auto-detected path is silently treated as "nothing to suppress"; a missing file named explicitly by --baseline is still an error, since you asked for that file by name.

Hand-suppressing one finding

You can also hand-edit .paranoid-baseline.json to suppress one specific finding you have reviewed and accept, instead of baselining everything. Every entry may carry a reason and an expires date (RFC 3339, for example 2026-12-01).

{
  "baseline_version": 1,
  "tool_version": "v0.1.0",
  "created_at": "2026-08-20T10:00:00Z",
  "entries": [
    {
      "rule_id": "DEP003",
      "file": "package.json",
      "fingerprint": "a1b2c3...",
      "reason": "internal package, low downloads expected",
      "expires": "2026-12-01"
    }
  ]
}

paranoid baseline never sets reason or expires itself, so if you set expires by hand you must also set reason, non-empty. A permanent hand-added suppression (no expires) is not required to have one, though it is good practice to always say why.

Once expires passes, that entry stops suppressing: the finding comes back into the report and the score, and the report still lists the expired entry so you see it happened.

Re-running paranoid baseline writes a fresh, full snapshot from scratch and discards any reason or expiry you added by hand. Treat it as a reset, not a merge.

What the report shows

The report's suppressed block has a count (findings actually removed from scoring) and a list of entries: every baseline entry that matched a finding this run, whether it suppressed it or had already expired. An expired match is exactly as visible as an active one, distinguished by one field, and its finding is simultaneously back in findings and counted in the score. See Report & schema for the exact JSON shape.

A .paranoid.toml [[disable]] entry can also add entries to the same suppressed block; each entry's source field says which one matched it, "baseline" or "policy", and text/markdown output labels them suppressed-by-baseline and suppressed-by-policy so the two are never confused. See Team policy file.

baseline command flags

paranoid baseline [path] accepts the same --base, --head, --offline, --sandbox, --sandbox-image, --sandbox-timeout, and --compare-base flags as verify, so a baseline is generated from exactly the range you would otherwise verify. It always writes a full snapshot to .paranoid-baseline.json at the repo root; there is no output path flag. It exits 0 on success and 3 on any error; it has no score of its own, so nothing maps to exit 1 or 2.

Using this in CI

Generate and commit .paranoid-baseline.json once, locally, before turning on CI enforcement or the GitHub Action. The Action needs no extra input for this: verify auto-detects the committed file at the repo root the same way it does outside CI. See Exit codes & CI.