auditlint
Static analysis for paired and independently sampled statistical comparisons.
The checks operate on code shape rather than subject matter. A paired comparison is detected from two columns of the same object pulled out in parallel. An independently sampled comparison is detected from the same object filtered on the same column to two different literal values. The same logic applies to a clinical trial, a product experiment, a model version comparison, or a demographic comparison, and the test suite verifies all four. A plain checklist covering the same four checks without any tool is in CHECKLIST.md.
Checks
Test selection is checked against the apparent pairing structure of the arguments passed to it. An independent-samples test on matched observations discards their correlation and understates the precision of the comparison; a significant result is not undermined by this, a non-significant result is not well supported by it. A paired test on two independently filtered groups asserts a row correspondence the code has not established, since the arrays were built by filtering to different values rather than by aligning matched rows.
Fit and evaluation calls on the same object are checked for shared data. A distance, score, or threshold estimated from a sample and then applied to that same sample understates the variability the estimate would show on new data.
Hypothesis tests called more than once, including once per iteration of a loop, are checked for a false discovery rate or family-wise error correction. Reporting a family of tests without correction inflates the probability that at least one reaches significance by chance.
Scope
Analysis is single file and static. A data alignment step or leakage mitigation defined in a different module is not visible. A transform such as .copy() between a fit call and its evaluation produces different source text for what is, at runtime, the same data, and is not detected. A test call inside a helper function invoked from a loop is not recognised as looped, since loop membership is determined at the call site. These boundaries are encoded as assertions in the test suite.
Findings are JUST CANDIDATES for confirmation against the surrounding code.
Installation
pip install auditlint
Usage
auditlint path/to/script.py
auditlint path/to/directory
auditlint path/to/directory --fail-on blocking
--fail-on accepts blocking, flag, or none, and controls the exit status for use in a build pipeline. --json emits machine-readable output.
Claude Code plugin
/plugin marketplace add cindysteward/auditlint
/plugin install auditlint@auditlint
/auditlint:review path/to/directory
Installing the plugin also adds a file-save reviewer. Editing a Python file that calls a recognised statistical test, or that fits and evaluates a model, triggers the scanner automatically, gated on what the file does rather than on its name.
Extending recognised functions
A .auditlint.json file placed in a target file's directory, or any parent directory up to 6 levels up, adds to the recognised function names.
{
"paired_tests": ["custom_paired_test"],
"independent_tests": ["custom_rank_test"],
"correction_markers": ["storey_qvalue"],
"leakage_mitigation_markers": ["nested_cv"]
}
Pre-commit
- repo: https://github.com/cindysteward/auditlint
rev: v0.1.0
hooks:
- id: auditlint
Security
The Claude Code hook runs a local Python script on every file save. It reads the file it was given, parses it with the standard library ast module, and writes a small cache under ~/.claude/auditlint_cache/. No network access, no modification of the file under review.
Licence
MIT.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file auditlint-0.1.0.tar.gz.
File metadata
- Download URL: auditlint-0.1.0.tar.gz
- Upload date:
- Size: 8.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
65d450f9136d0997ff063b9e2db5cd8e3a200f1c214bcb7e6eb4095b8f00ee5b
|
|
| MD5 |
251672c7ec7970dcd7c76d806148c2b5
|
|
| BLAKE2b-256 |
32c52112e44574bd8a3e1c6c4878b14c873d29e8c2381953c0bcaec60f24de6b
|
File details
Details for the file auditlint-0.1.0-py3-none-any.whl.
File metadata
- Download URL: auditlint-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
twine/7.0.0 CPython/3.11.9
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fade29c327a0c2b73c755ea6d659c5c15697bf2196a0df04c3f46b0facb6d021
|
|
| MD5 |
9d9c0e1c04afa648452bc5b62a6b55db
|
|
| BLAKE2b-256 |
0ec6ced7bd4655e38ef386dacdcaee1cd8a52ec35a84fd69f540c407b8479ba2
|