Slopmeter v0.3.0
Slopmeter v0.3.0 adds configured clone boundaries and persistent review decisions. It also makes clone-driven rankings and callable complexity easier to interpret.
No scoring change: the default remains py-2026.3 / M4 version 3. Calibration resources, weights, thresholds, and default exclusions are unchanged. Running v0.2.0 and this implementation on identical source produced identical raw metrics, scores, callable facts, coverage, clone groups, and pattern findings. No project-specific tuning was applied.
Configure architectural boundaries
Create slop.toml in the directory you use as the scan root:
[[boundaries]]
name = "provider-a"
prefix = "src/providers/a"
[[boundaries]]
name = "provider-b"
prefix = "src/providers/b"Or put the declarations in pyproject.toml:
[[tool.slop.boundaries]]
name = "provider-a"
prefix = "src/providers/a"
[[tool.slop.boundaries]]
name = "provider-b"
prefix = "src/providers/b"- Prefixes are project-relative paths, not globs. Names and normalized prefixes must each be unique. Absolute paths, parent traversal, and glob syntax are rejected.
- The longest matching path-component prefix wins. A declaration for
src/providers/aoverrides a broader declaration forsrc/providers. A prefix forsrc/providers/adoes not matchsrc/providers/another. - Config is loaded from the scan root. A subdirectory scan does not inherit its parent's config. Adjust declarations to the root used by that scan.
- When both files define boundaries, the
slop.tomllist replaces thepyproject.tomllist.
Clone reports then show:
| Relation | Meaning |
|---|---|
within-boundary |
Every occurrence belongs to the same declared boundary. |
cross-boundary |
Every occurrence is assigned, across two or more boundaries. |
unknown |
At least one occurrence is unassigned. |
View the labels with slop findings --root . --lang py --metric m3 or slop explain PATH --root ..
Labels annotate real duplicates. They do not suppress findings, lower scores, change rankings, or establish whether extraction is appropriate. Preserve deliberate isolation when the architecture requires it, with a review reason.
Retain clone review decisions
First inspect a clone group and copy its ID from findings. Replace CLONE_ID below:
slop findings --root . --lang py --metric m3
slop review set CLONE_ID --root . --store reviews.json --disposition no-change --reason "These adapters evolve under separate contracts." --next-step "Recheck each adapter when the contract changes."
slop score . --lang py --reviews reviews.json
slop findings --root . --metric m3 --reviews reviews.json --json
slop review show --root . --store reviews.json --json- Dispositions:
actionable,defer, orno-change. A reason is required; the next step is optional. - Only
review setwrites. Ordinary scans andreview showread the explicitly selected store. Stores are not discovered or created automatically. currentmeans the retained clone evidence, member-file hashes, boundary policy, and clone measurement definition still match.stalemeans the previous decision needs review. Even a comment-only change can invalidate it. This release hashes whole member files, so an unrelated edit in one can also require review.missingmeans evidence is absent or unavailable. It is not proof of a fix.- Re-running
review setfor the same group ID replaces its saved decision. Reinspect changed evidence before doing this.
Review annotations do not hide evidence or change scores. Persistence currently covers clone groups on the current snapshot side. Use separate stores for independent scan roots. Stores contain relative locations, hashes, and review text, not source code. Keep private review stores local unless separately approved for sharing.
Clearer evidence presentation
- File and tree rankings include clone percentages, including at narrow widths.
- Callable rows label retained
massas full-CC mass. Explanations separately show effective CC, effective mass, the M4 numerator, threshold, and selected basis. Pattern findings (0)explicitly counts pattern rules; it does not imply that complexity or clone evidence is absent.- A production callable whose threshold crossing comes from assertions gets a classification-review hint. It remains production-classified, and its score is unchanged. Inspect intent before moving tests or changing file-level classification.
Report compatibility and limitations
New JSON reports add exact source_sha256 values to file results. Configured clone groups gain boundary_context; loading a review store adds review_results. Older reports remain readable, but reports without source hashes cannot create or confirm a current source-bound decision. The existing callable mass field retains its full-CC meaning.
Python remains the only implemented language. The reference corpus still has the same six historical projects. These features improve review context; they do not establish a representative service-specific calibration or turn the score into a CI quality gate.
Validation
GitHub CI passed static checks and all nine test/package jobs across Windows, macOS, and Linux with Python 3.12, 3.13, and 3.14. A cross-platform golden fixture was corrected to use explicit LF source bytes; production source hashing remains byte-exact.
- 1,290 deterministic tests passed with 96.98% branch-inclusive coverage before the version-only release update.
- 50 dependency-learning tests passed. The 73 new workflow and integrity checks also passed on Python 3.13 and 3.14.
- All 40 release-version, boundary-config, and review-CLI checks passed.
- The v0.3.0 wheel and source archive passed four isolated installation checks.
- Regression tests cover unchanged scores, current/stale/missing reviews, source edits, policy changes, imported-report tampering, locks, and atomic-write failures.
Install
Download the wheel below and run:
python -m pip install --upgrade ./slop_measure-0.3.0-py3-none-any.whl
slop score . --lang py --scope all --top 10Requires Python 3.12 or later. SHA256SUMS.txt covers the wheel and source archive. This is a GitHub release, not a PyPI publication.