Checks runs your organisation's rules on every change the agent proposes and on every commit, before anything is written. It reports what it found, what it checked and what it could not check, and it refuses a change only when your organisation's signed policy says so.
What runs
- The Neural Inverse checks engine, in-process. This is the Editor's engine, run unchanged: tree-sitter structural rules for C and C++, Python, JavaScript and TypeScript, plus secret detection on every file. It runs the Editor's rule packs and uses its fingerprints, control evaluation and policy decisions, so the Editor, the CLI and CI produce the same findings with the same fingerprints.
- An external engine (optional). A SARIF-emitting tool your organisation qualified, such as a coding-standard checker or a commercial static analysis tool, configured with
checks.engine.command. - Imported SARIF (optional). Reports your own tools already produced, found through
checks.importglobs and mapped onto the changed files.
The CLI hosts these analysers. It is not a compliance tool and does not claim compliance with MISRA, CERT, IEC 62304, ISO 26262 or any other framework. Findings are evidence toward your own process; rule packs and their mappings to frameworks come from your organisation.
Principles
- Deterministic or labelled. Every finding comes from a deterministic analyser. Nothing a model produces is a finding, and nothing a model produces can block.
- Only signed rules block. The Editor's baseline pack ships unsigned, so its findings are advisory. Packs in your organisation's Ed25519-signed policy are signed, and their controls can block. Rules in a workspace are labelled "unsigned · advisory" and never block.
- Only new findings count. The gate runs on the previous and the proposed contents and compares fingerprints, so a finding that was already there never blocks an unrelated edit.
- Coverage is explicit. Every run lists the files it checked, the files it checked only in part, the files it skipped and why, and each analyser's version, time and errors. An engine timeout is shown, never ignored.
- No local dismissals. Waivers come only from your organisation's signed policy. Each names an approver and an expiry, and stops applying when it expires.
- Analysers never run commands from workspace files. Project settings cannot set the engine command, and an executable inside the workspace is refused.
Fingerprints
A finding's fingerprint (ni/v1) is a SHA-256 over the rule id, the rule version, the repository-relative path, the snippet with whitespace collapsed, and the occurrence index of identical snippets in the file. Line numbers are not part of it, so reformatting or moving code does not change the fingerprint, and every machine computes the same value. Secret findings use the detector and the redacted value as the snippet, so a secret is never stored or reported.
The agent gate
For edit_file, multi_edit, write_file and apply_patch, the tool first computes the full new contents. Before the approval card appears, or before the edit is applied in auto-edit and full-auto, the gate:
- writes the proposed and previous contents to a temporary overlay folder that mirrors the repository paths (the workspace is not touched, and the overlay is deleted afterwards);
- runs the analysers within the time budget (
checks.budgetMs.agent, default 3 seconds); - asks the organisation's policy decision point about the edit; for example, a signed control can forbid agent edits under
safety/**or require a person to approve them; - evaluates the signed packs' controls on the new findings at the
agentAcceptgate.
| Outcome | What you see |
|---|---|
| Advisory findings | In the approval card under the diff, with severity, rule, line, message and control ids. Also added to the tool result as a short note, so the agent can fix them |
| Blocked | Refused in every mode, including full-auto. The agent gets a result naming the rule and the line. In ask mode the card says "Blocked by org policy" and offers no allow option |
| Needs approval | You are asked, even in auto-edit or full-auto. In an unattended run it is denied |
| Coverage problem | A warning, for example an engine timeout or a rejected policy bundle. checks.failClosed in managed policy decides whether an analyser error blocks |
The commit gate
neuralinverse checks hook install # adds .git/hooks/pre-commit
neuralinverse checks hook install --force # replaces an existing hook (a backup is kept)
neuralinverse checks hook uninstall
The hook runs neuralinverse checks run --staged --gate commit. An existing hook is never overwritten without --force; it is moved to pre-commit.ni-chained and runs first, and uninstalling restores it. /commit runs the same gate before it asks the agent to commit.
Command line
neuralinverse checks run # working-tree changes against HEAD (new findings only)
neuralinverse checks run --staged # staged changes against HEAD
neuralinverse checks run --all # every file, all findings
neuralinverse checks run src/ lib/x.c # these paths, all findings
[--format text|json|sarif] [--gate agent|commit] [--out report.sarif]
neuralinverse checks status # engine and packs, policy, waivers, last run
| Exit code | Meaning |
|---|---|
| 0 | The change passes |
| 1 | The change is blocked |
| 2 | Blocked only because an analyser failed under checks.failClosed |
In a session, /checks lists the gate runs of the session and /checks all adds coverage. Every gate run is recorded in the audit log as a checks_gate event with fingerprints, rule ids and severities, never code or messages.
Settings
| Key | Who may set it | Meaning |
|---|---|---|
checks.enabled | user, managed | Turn the gate off (default on) |
checks.budgetMs.agent, .commit | user, managed | Time budgets (default 3000 and 60000 ms) |
checks.maxFileBytes | user, managed | Larger files are skipped and reported (default 1 MiB) |
checks.policyBundle, checks.trustedKeys | managed only | Older names for governance.policyBundle and governance.policyKeys. Organisation governance verifies the bundle and supplies the gate's signed packs and waivers |
checks.engine.command, .args, .versionArgs, .env, .maxOutputBytes, .enabled | user, managed | External SARIF engine. Arguments are an argv array; {root}, {filelist} and {out} are substituted |
checks.engineSigned, checks.importSigned | managed only | Treat external or imported findings as signed, so they can block |
checks.import | user, managed, project | Globs of SARIF reports from your tools (advisory unless importSigned) |
checks.block.agent, .commit | managed only | Lowest severity of a signed external or imported finding that blocks: critical, high, medium, low, info, off |
checks.failClosed | managed only | An error or timeout of a signed analyser blocks |
checks.waivers | managed only | Waivers for external and imported findings: { id, scope: fingerprint|file|component|repo, fingerprint?, path?, component?, ruleId?, approver, reason, expires } |
If a project file sets a key it may not set, the key is ignored and a warning is shown. The severity of external findings comes from SARIF properties.severity (critical, high, medium, low), then a numeric security-severity, then the SARIF level (error is high, warning is medium, note is low). Findings of the built-in engine block only through the signed packs' controls.
Example managed policy:
{
"governance": {
"policyBundle": "/etc/neuralinverse/policy-bundle.json",
"policyKeys": [{ "keyId": "acme-2026", "publicKey": "<raw Ed25519 public key, base64>" }]
},
"checks": {
"engine": { "command": "/opt/qual/bin/scan", "args": ["--sarif", "--root", "{root}", "--files", "{filelist}"] },
"engineSigned": true,
"block": { "agent": "high", "commit": "critical" },
"failClosed": true
}
}
Limits
- The overlay contains only the changed files. Rules that need the rest of the repository, such as cross-file analysis, see only those files.
- The CLI evaluates only the
no-findingsconditions of the signed controls. Conditions that need ledger facts, such as reviews, requirement links and test results, are evaluated by the Editor and byni-checksin CI. - A renamed file is checked as a new file at its new path, so its findings count as new.
- Standalone binaries need the tree-sitter WASM files; see Install and update.
- Signed packs and waivers come from organisation governance bundles, which the organisation policy delivered by Govern sign-in does not yet carry. Deliver the bundle with
governance.policyBundle, the shared governance folder or the repository.