Skip to main content

sort-claim-audit

Offline audit of documented sort-order claims against Python source.

A standard-library-only CLI for checking documentation contracts with static AST evidence. It runs no project code, makes no network requests, and never opens .env contents. Symlinked files and directories are skipped.

Usage

python3 -m pip install .
sort-claim-audit path/to/project
python3 -m sort_claim_audit path/to/project --json
sort-claim-audit path/to/project --ignore 'vendor/*' --ignore 'generated.py'
sort-claim-audit path/to/project --fail-on HIGH --verbose
sort-claim-audit --version

The path defaults to the current directory. --json emits a single JSON object with findings, verified_claims, claims, production and test-only evidence, scan errors, and threshold-based status. Findings include rule, severity, claims with document locations, and evidence with source locations. --verbose adds the full report to text output. Repeatable --ignore globs match relative POSIX paths; matching directories are pruned. Default failure threshold is MEDIUM; HIGH leaves MEDIUM findings visible while exiting 0. Exit codes: 0 PASS, 2 FAIL, 1 usage or invalid-root error.

Claims

Only root README.md and docs/**/*.md supply claims. Fenced code is excluded; inline code counts as prose. Matching is case-insensitive with word boundaries, using exactly these phrases (no optional words or extra hyphen variants):

SORTED:
sorted output
outputs are sorted
results are sorted
sorted results
sorts results
sorts output
sorted by
in sorted order
sorted alphabetically
sorted numerically
in ascending order
in descending order

UNSORTED:
unsorted
not sorted
in insertion order
preserves input order
preserves insertion order
in original order
keeps input order

Negation is asymmetric: a sentence containing no, not, never, without, doesn't, don't, or isn't suppresses the SORTED family. The insertion-preserving phrases still count in that sentence because those phrases can themselves express negation. Bare sorted or sort nouns are not claims; naming a flag or a sort key does not establish a contract. Each family collapses to one audit decision, with all its matching claims retained. Contradictory families are checked independently.

Rules

| Rule | Severity | Trigger |
| --- | --- | --- |
| documented-sorted-claim-false | HIGH | SORTED family, no production sorting and no test sorting |
| documented-sorted-claim-false-test-only | MEDIUM | SORTED family, sorting confined to tests/fixtures |
| documented-unsorted-claim-false | HIGH | UNSORTED family and production sorting |
| documented-unsorted-claim-false-test-only | MEDIUM | UNSORTED family, sorting confined to tests/fixtures |

With no production Python source, either family produces its own HIGH finding with no-source evidence. Otherwise SORTED with production sorting is verified; The insertion-preserving family with no sorting anywhere is verified. No claims means PASS regardless of source evidence. All relevant evidence appears in a finding; evidence is deduplicated by file, line, and kind.

Evidence table

AST call Evidence kind
Bare builtin-shaped sorted(items), including key/reverse arguments sorted
Attribute call items.sort(), on receivers, including key arguments; excludes numpy module calls sort

Production excludes tests/ and fixtures/ directories, test_*.py and *_test.py files, docs/ and examples/ directories, and symlinks. Test/fixture evidence is collected separately; docs and examples never supply evidence. Build outputs, virtual environments and .git are skipped. Read/parse failures are reported in errors; an unreadable or syntactically invalid source cannot supply evidence.

Differentiation

  • determinism-claim-audit checks run-to-run stability, never ordering.
  • schema-claim-audit checks field names, never record order.
  • streaming-claim-audit checks how much is read at once, never output order.
  • config-claim-audit checks documented default values, never ordering.
  • bandit/ruff check code issues, never documentation promises.
  • The sort command and sorted documentation provide sorting primitives, never documentation-versus-code truth.

Honest limitations

Exact phrases only: paraphrases and output-specific context are not inferred. This is a whole-tree presence check, not data-flow analysis. Dead code counts. Sorting whose result is discarded still counts: the tool checks that sorting happens, not that its result reaches an output. Shadowed builtin names and unrelated receiver methods can count because the AST table is syntactic.

reversed() alone is reversal, not sorting. Variables, parameters, and attributes merely named sort or sorted do not count. Neither key= nor itemgetter alone counts. sort=True passed to another API does not count. heapq.nsmallest, heapq.nlargest, and bisect are outside the evidence table: heap order is not a full-output ordering guarantee. Third-party numpy/pandas sorting semantics (such as np.sort and DataFrame.sort_values) are out of scope. Conventional np/numpy module names and explicit numpy import aliases are excluded. Other methods spelled .sort() match the generic syntactic rule; receiver types and third-party object aliases are not inferred.

Markdown handling covers backtick and tilde fences and ordinary punctuation sentence boundaries, not a full Markdown parser. Files are decoded as UTF-8. The scanner follows no symlinks and reads only documentation and Python source within the supplied tree. It never imports audited modules.

Development

PYTHONPATH=src python3 -m unittest discover -s tests -v
python3 -m build
python3 -m venv /tmp/sort-claim-audit-check
/tmp/sort-claim-audit-check/bin/python3 -m pip install dist/*.whl
/tmp/sort-claim-audit-check/bin/sort-claim-audit tests/fixtures/good/sorted --json
PYTHONPATH=src python3 -m sort_claim_audit . --json

The build produces wheel and sdist. MANIFEST.in includes the test fixtures in the sdist. If an isolated build fails offline, use python3 -m build --no-isolation. Runtime dependencies: none. Python 3.9+. Licensed under MIT.

Metadata

Release files for sort-claim-audit 0.1.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for sort-claim-audit 0.1.0
File Size Uploaded Provenance Actions
sort_claim_audit-0.1.0.tar.gz 11.6 kB Without provenance Details for sort_claim_audit-0.1.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for sort-claim-audit 0.1.0
File Interpreter ABI Platform Actions
sort_claim_audit-0.1.0-py3-none-any.whl Python 3 none any Details for sort_claim_audit-0.1.0-py3-none-any.whl

Total release size: 20.1 kB

Release files / sort_claim_audit-0.1.0.tar.gz

Download URL sort_claim_audit-0.1.0.tar.gz
Size 11.6 kB
Tags Source
SHA-256 checksum
How to use checksums
effb49b521b44999358c5439542e6e75920d0e4584570c3196dbcfa00e93b426
BLAKE2b-256 checksum
How to use checksums
513882dc8dc08c8b0b942cb14a0c582848f9ebbdd744769cd3bc1b89f2f01fb3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Release files / sort_claim_audit-0.1.0-py3-none-any.whl

Download URL sort_claim_audit-0.1.0-py3-none-any.whl
Size 8.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
a6406a5894c317161a41df271df8aee1e3fc42a893125d8bf2d863374e2519fc
BLAKE2b-256 checksum
How to use checksums
cfae5bded164f3ab3e40f4bb664e7d4adf83b45b98d9ecdf7d41ed803a6b4c57
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.3

Security for sort-claim-audit 0.1.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Release history Release notifications | RSS feed

This release

0.1.0 This release

2 release files No provenance

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page