Team policy file
.paranoid.toml at the repo root is the only other
file paranoid reads besides command-line flags. It is optional,
and it has a small, fixed set of keys.
paranoid has no general configuration system. An unknown key, an unknown table, or a key with the wrong type is an execution error (exit 3) that names the offending key.
The keys
fail-under = 80
strict = true
[[disable]]
rule = "TI012"
reason = "flaky under load, tracked in issue #142"
expires = "2026-12-01"
[sandbox]
image-go = "golang:1.26"
image-python = "python:3.12-slim"
image-node = "node:22-slim"
[formal]
allowed_axioms = ["Classical.choice"]
[formal.llm]
provider = "anthropic"
model = "claude-opus-5-5"
[formal.llm.proof]
provider = "openai"
model = "my-local-prover"
base_url = "http://localhost:11434/v1"
api_key_env = "LOCAL_LLM_KEY"
| Key | Type | Meaning |
|---|---|---|
| fail-under | integer | This repo's own --fail-under default |
| strict | boolean | This repo's own --strict default |
| [[disable]].rule | string, required | A rule ID to suppress everywhere it would fire |
| [[disable]].reason | string, required, non-empty | Why the rule is disabled |
| [[disable]].expires | string, optional | RFC 3339 or a bare date; once passed, the rule fires again |
| [sandbox].image-go | string | Container image pin for a detected Go suite |
| [sandbox].image-python | string | Container image pin for a detected Python suite (pytest or unittest) |
| [sandbox].image-node | string | Container image pin for a detected npm/pnpm/yarn suite |
| [formal].allowed_axioms | list of strings, on one line | Axioms FV010 accepts in addition to the defaults (Lean: propext, Classical.choice, Quot.sound; Rocq: none). Each entry must be a non-empty string. sorryAx, Lean.ofReduceBool, and Lean.trustCompiler are rejected with an error, because allowing them would hide a hole. Only read with verify --formal-check |
| [formal.llm].provider [formal.llm.proof].provider [formal.llm.spec].provider | string | anthropic, openai, or gemini. Default anthropic |
| [formal.llm*].model | string | Model name. Default claude-opus-5-5 for anthropic. The other providers have no default, so a model is required |
| [formal.llm*].base_url | string | An http or https URL, without a user name or password. For openai this is how you point at a local or compatible server |
| [formal.llm*].api_key_env | string | The NAME of the environment variable that holds the key. Default ANTHROPIC_API_KEY, OPENAI_API_KEY, or GEMINI_API_KEY |
[[disable]] is an array of tables: repeat the block
to disable more than one rule. [sandbox] and
[formal] may each appear at most once. Both are optional; a file with only
fail-under and strict is valid, and so
is an empty file.
LLM settings: [formal.llm]
These tables set the provider for the online
paranoid formal subcommands. They are never read by
verify, which does not call an LLM. See
Online features and providers.
[formal.llm]is the default for every task.[formal.llm.proof](proof search) and[formal.llm.spec](spec drafting) override it, field by field.- A task table that names a different provider than the winning one does not lend its model, base URL, or key variable to it. Each provider keeps its own.
- The flags
--provider,--model, and--base-urlbeat the file. - Keys are never in this file. A key such as
api_key,key,token, orsecretis an error.api_key_envmust be a variable name, not a key. The error does not repeat the value. - Each of the three tables may appear at most once. Unknown keys and unknown tables are errors.
Run paranoid formal providers to see what the file resolves to.
Precedence
For both fail-under and strict, the flag has the highest precedence, then the file, then the default:
- The command-line flag wins whenever it is given on the command line, even if the value matches the built-in default.
- Otherwise,
.paranoid.toml's value wins, when the file sets that key. - Otherwise, paranoid's own default applies:
fail-under50,strictoff.
--sandbox-image always wins over a
[sandbox] pin, the same rule. A pin only applies to
the language DetectSuite already chose (a Python
pin does nothing on a Go repository); it never changes which
suite is detected.
Every command that runs the verify pipeline (verify,
baseline, fix-prompt) honors an
auto-detected policy file the same way. Only verify
exposes --no-policy today; the other two commands
cannot opt out of it individually yet.
How a disabled rule appears in the report
A [[disable]] match is reported the same way as a baseline match (see Baseline &
suppressions): the finding leaves findings and
the score, and appears in the report's suppressed
section with the entry's reason. The one difference
is the source field on each suppression entry,
"policy" instead of "baseline"; text
and markdown output label it suppressed-by-policy
rather than suppressed-by-baseline. An entry whose expires date has
passed stops suppressing: its finding comes back into the report
and the score, and the report still lists the expired match.
Matching is by rule ID alone, not by file or evidence text the
way a baseline entry matches: a [[disable]] entry
disables that rule everywhere in the diff, not one specific
finding of it. Disabling a rule this way is broader than
baselining one finding; use the baseline file instead when you
want to carry forward one specific, already-reviewed finding.
See Report & schema for the exact JSON shape.
Loading
| Flag | Meaning |
|---|---|
| --no-policy | Ignore .paranoid.toml, even when present at the repo root |
.paranoid.toml loads from the repo root only, the
same rule the baseline file follows: no path-override flag, no
walking up parent directories, no global file outside the repo.
A missing file is not an error, there is nothing to load.
A file that exists but fails to parse is always a hard error
(exit 3), naming the key or table that broke it.
Using this in CI
Commit .paranoid.toml at the repo root; the GitHub
Action needs no new input for it, since the file is read from
the checked-out repository itself, the same way
.paranoid-baseline.json already is.
[[disable]] and [sandbox] apply exactly
as they do outside CI. fail-under does not: the
action always passes --fail-under explicitly (that
input's own default is 50), so a repo's fail-under
key never takes effect through the action; strict
is unaffected, since the action only adds --strict
when its own strict input is true. See
Exit codes & CI.
.paranoid.toml is not watched by SF006, the rule
that flags a change to .paranoid-baseline.json or
a hook configuration file. An agent under audit could add a
[[disable]] entry for a rule that would otherwise
flag its own work, and this would not be surfaced the way
editing the baseline file is.