paranoid_
Report

Sessions and claims

The claims stage extracts concrete claims from a summary file, an agent session file, or commit messages, and checks each one against the diff and the clean-room result.

Where claims text comes from

The strongest available source wins, in this order:

  1. --claims <file>: any free-text file, read as-is.
  2. --session <file>: an agent session file; format auto-detected. If the file's format cannot be parsed, paranoid falls back to the range's commit messages.
  3. If neither flag is given at all, the claims stage does not run.

The commit-message fallback only triggers when a --session file is given but its format fails to parse. With neither flag, the claims stage does not run at all, not even as a skipped check, and CLM001 to CLM005 do not appear in that run's findings.

Supported agents

--session <file> accepts any of the formats below; paranoid auto-detects which one a file is from its content, trying the parsers in a fixed order (most specific format first) so a file never needs a --format-style flag to say what wrote it.

AgentSession flagWhat gets extracted
Claude Code--session path/to/session.jsonlAssistant turns from the session JSONL (modern block-array shape and the legacy plain-string shape)
Codex CLI--session path/to/rollout.jsonlAssistant text from response_item payload lines
Gemini CLI--session path/to/checkpoint.jsonText of every "model"-role turn (Gemini's name for the assistant), from a JSON array or one turn per line
Aider--session path/to/.aider.chat.history.mdThe assistant's reply text between one "#### " user line and the next
Cursor--session path/to/exported-chat.mdText following an Assistant/Cursor speaker marker, up to the next marker

--claude-session <file> is a hidden alias for --session.

None of these five formats is a documented, versioned API; each vendor can change its session file's shape at any time. Every parser is shape-gated and fails soft: a line or block it does not recognize is skipped, never an error, and a file that yields no usable text at all falls back to a weaker claims source (commit messages, then a skipped check) instead of failing the run. Treat every extraction as best-effort.

Claims rules (CLM)

RuleSeverityWhat it catches
CLM001mediumThe agent claims to have changed a file the diff never touches
CLM002criticalThe agent claims tests pass, but the clean-room run failed
CLM003lowA claimed action names an identifier the changed files never mention
CLM004mediumThe agent claims N new tests; the diff contains fewer
CLM005lowThe diff touches far more files than the claims describe

CLM005 needs a diff of at least 6 files (lockfiles and manifests the deps package already recognizes, like package-lock.json and go.mod, never count either way) before it looks at the ratio, and fires when more than 60% of those files are neither a path the claims mention nor a file containing an identifier the claims name. Full rule text, including known false positives, is on the rules page.

API surface, gated on claims

Two more rules, AS001 and AS002, only run when claims are present at all. They diff public symbols (Go, Python, JS/TS) between base and head and flag a symbol removed while the claims say a fix or feature landed, cross-checked against the whole head tree so a symbol that merely moved does not fire. With no claims source, this stage records a skipped check, "api-surface: no claims provided (pass --claims or --session to enable this check)", rather than silently passing. See the API surface rules.