Releases: FavioVazquez/mollify
Release list
mollify 0.1.6
Pre-announcement precision series: second and third calibration sweeps, full docs-vs-code audit, and resulting engine fixes. See CHANGELOG.md for full details.
mollify 0.1.5
Calibration and portability fixes from the first real-world corpus evaluation: every engine run against pinned checkouts of requests, flask, rich, MediaCrawler, and MoneyPrinterTurbo, with every certain finding hand-audited. Fingerprints are unaffected — existing baselines survive.
Highlights
- unused-import calibration — PEP 484 redundant-alias re-exports (
from x import Y as Y),# noqa/# noqa: F401, try/except availability probes, cross-module re-export consumers, and quotedcast()type args are honored. flask now has zerocertainunused-imports andmollify fixproposes nothing there (was 2 destructive edits). - Cross-platform report identity — every
location.pathis root-relative with/separators on all OSes; fingerprints and baselines port between Linux, macOS, and Windows, pinned in CI by a cross-OS golden fingerprint contract (newwindows-latestmatrix). unused-parameterinterface-bound suppression — dunder methods,@abstractmethod/@overload/@override, overrides of in-project base methods, external-base classes, and decorated callbacks are never flagged (100 corpus hits on flask were override/callback signatures).untyped-functionpackage rollup — deliberately-untyped packages (60%+ of 20+ eligible public functions) get onelikelypackage-level finding; per-function findings demote touncertain.- Security noise calibration — candidates in test/docs/example trees cap at
uncertainand are tagged in the reason. - Robustness — engine panic isolation (a crashing engine degrades to a single
engine-panicfinding), UTF-8-aware dupes tokenizer (no more OOM on Unicode identifiers), chaos + fuzz test suites. - Housekeeping — offline advisory sample moved to
cookbook/advisories.sample.json; ureq 3 / toml 1.x migrations; docs sweep.
219 tests green on Linux + Windows. Full details in CHANGELOG.md.
Install: uvx mollify audit · pip install mollify · cargo install mollify-cli
mollify 0.1.4
What's new in 0.1.4
Fix release from a full-repository code review (docs/code-review-2026-07-01.md):
every crate was read end-to-end, and every fix below was verified against a
reproduction before landing. Contains breaking changes — fingerprints and
several CLI exit codes changed; regenerate any saved baselines after upgrading
(see Breaking below).
Breaking
- Fingerprints changed wholesale — regenerate baselines (
--save-baseline).
Fingerprints now hash the root-relative path (they no longer vary with
--pathspelling or checkout location, so CI baselines finally transfer to
laptops), drop line numbers in favor of symbol/content identity plus an
occurrence index (edits above a finding no longer churn it), and use the
full 64-bit hash (16 hex chars). - CLI exit codes are stricter where CI trust demanded it: a failed
--save-baselinewrite exits 1 (was: success message + 0); a missing or
invalid--baselinewith--fail-on-regressionexits 1 (was: gate silently
disabled); a nonexistent--pathexits 2 (was: clean 100/100 report);
trace/inspect/list/metricsreject formats they don't implement with
exit 2 (was: silent human output);inspectwith no matching file exits 1. unresolved-importis nowlikely, notcertain: a relative import may
resolve to a C extension or build-generated module the.pywalk can't see.
Fixed
fix --applycorrupted Jupyter notebooks: finding lines are relative to
the concatenated code cells, so notebook findings are no longer
auto-fixable (and the fix planner refuses non-.pyfiles outright).fix --applycould delete live, dynamically-dispatched code: a symbol
invoked from another module viagetattr(lib, "_handler_" + name)()was
gradedcertain; a dynamic sink anywhere in the project now caps
unused-export confidence, mirroringunused-file.fix --applypreserves CRLF line endings and no longer aborts the whole run
(losing the applied count) when one file fails I/O.- Dead-code false positives from resolver gaps: module constants used only in
function signatures (parameter defaults/annotations, return annotations,
lambda defaults); imports inside module-levelwith/for/while/match
suites; symbols used only via lazy in-function imports; sibling modules of a
root-level__init__.py; names shadowed by Python-3-scoped comprehension
targets;__all__ += […]/.extend(…)extensions. - Runtime imports in the
elsebranch of anif TYPE_CHECKING:guard are no
longer treated as type-only (andif not TYPE_CHECKING:now works);
TYPE_CHECKING guard detection is exact instead of substring-based. - Decorated
def/classline numbers point at the definition, not the first
decorator. cold-codecan now actually fire for imported modules: thedefline —
executed at import time — no longer counts as evidence the body ran.- The duplication engine reads notebook code cells, not raw
.ipynbJSON
(near-identical scaffolding produced bogus clone families). - Dependency hygiene: dev-group tools (black, mypy, pre-commit…) are exempt
fromunused-dependency(deptry parity);psycopg2/psycopg2-binaryand
friends are alternative providers instead of a forced alias (no more paired
unused+missing false positives); namespace tops (google,azure, …) are
never guessed asmissing-dependencywithout an installed env; URL/VCS
requirement lines no longer produce mangled names (#egg=respected, pip
comment rules honored). - PEP 440: epochs compare correctly (
2!1.0no longer parses as2), and
.postN/.devNorder per spec instead of comparing equal to the release.
specs_intersectfinds narrow gaps like (>2.0,<2.0.1). - Determinism: import→dist mapping and requirements/pins collection no longer
depend on filesystemread_dirorder; hotspot/coverage/git fallback
matching is anchored at path-separator boundaries (app.pyno longer claims
myapp.py's churn, coverage, or diff hunks) with deterministic tie-breaks;
non-ASCII filenames survive git'score.quotePath. inspect <file>matches path fragments at separator boundaries only
(inspectingb.pyno longer returnslib.py's findings).- Unconstrained declared deps (bare
flask) are matched against advisories
again instead of being silently skipped. - MCP protocol: version negotiation no longer echoes arbitrary client
versions; malformed JSON gets a-32700response; requests without a
methodget-32600;mollify_fixapply errors surface as tool errors. - LSP: unknown requests get
-32601instead of hanging the client;
didCloseclears stale diagnostics; diagnostic ranges are never reversed
and cover the final line; a malformedContent-Lengthheader no longer
kills the server mid-session. - OSV
querybatchpagination: truncated advisory sets are no longer cached
as authoritative. --save-baselinekeeps stdout pure JSON (status note moved to stderr, the
report is still emitted);quality_scoreis recomputed after
--gate/--min-confidence/--baselinefiltering so the envelope is
internally consistent.- Update-check cache writes atomically (temp file + rename).
Changed
mollify-typescontract enums are#[non_exhaustive](adding a report
kind/category is no longer a breaking Rust change), and the load-bearing
Confidence/Severityorderings are documented and locked by tests.- Docs/CI hygiene:
AGENTS.mdno longer documents a nonexistent
mollify graph --formatflag; the GitLab CI example uses
artifacts:reports:sarif; the advisory-database docs describe the actual
live-by-default behavior;bump-version.shworks on BSD/macOS sed;
Dependabot covers GitHub Actions and Cargo; the report hook can no longer
fail the action on malformed JSON.
Install / upgrade
uvx mollify@0.1.4 audit # or: uv tool install mollify
pip install --upgrade mollify
cargo install mollify-cli # binary: mollifyIf you use --save-baseline in CI, regenerate your baseline after upgrading — fingerprints changed (see Breaking above).
Full changelog: https://github.com/FavioVazquez/mollify/blob/v0.1.4/CHANGELOG.md
mollify 0.1.3
What's new in 0.1.3
Precision release: a real-world audit surfaced a cluster of false positives whose
root causes are fixed here (on a fixture reproducing the audited patterns, the
score moved from 20/100 to 95/100). Two new ADRs document the core graph-semantic
changes (ADR-0002,
ADR-0003).
Fixed
Precision pass from a real-world audit (running mollify on an external Python
package) that surfaced these false positives:
- Relative imports in a package
__init__.pynow resolve. A package's
__init__.pyhas the package itself as its dotted name, so the resolver was
dropping one segment too many —.aaresolved toaainstead ofpkg.aa.
This cascaded into spuriousunresolved-import→unused-file→
unused-exportacross re-exporting packages (the dominant FP source). Package
self-references no longer create acircular-dependency. session.exec(...)no longer flaggeddangerous-eval(CWE-95). The
security rule matched any trailing.exec/.evalsegment; it now matches only
theeval/exec/compilebuiltins, not ORM/driver methods.- pytest
test_*/Test*are no longerunused-export. They are treated as
reachability roots within test paths, honoring
[tool.pytest.ini_options].testpaths. from __future__ import …is no longerunused-import(it has a compiler
effect and is never unused).- Lazy/in-function imports now count toward dependency usage and
reachability, so a dependency imported only insidemain()(e.g.uvicorn)
isn't falselyunused-dependency; module-scopeunused-importis unaffected. [project.scripts]entry points are reachability roots — the target
module isn'tunused-fileand the named function isn'tunused-export.- First-party test helpers imported by bare leaf name (
conftest, sibling
modules on a test path) are no longermissing-dependency. commented-codeno longer fires on prose that opens with a keyword
(e.g.# from zero (...), doubled.);from …now requires a realimport.
Changed
- Quality score is weighted by confidence —
uncertainfindings penalize
the 0–100 score far less thancertainones, so a report dominated by
low-confidence review items no longer reads as a failing grade. Still
deterministic. mollify initwrites a richer, documented starter.mollifyrc.json
(five-area severities,type-healthoff by default, complexity knobs,
inline_commentdocs).
Added
--include <DIR>flag on all 8 analysis commands (audit,dead-code,
deps,arch,complexity,dupes,types,security; not
coverage/supply-chain, which aren't path-scoped). Repeatable; overrides
the builtin discovery denylist (.venv,.git,__pycache__,
node_modules,build,dist, etc.),.mollifyrc.json'sexclude_dirs,
and.gitignorefor the named directory, letting users opt a directory
back into scanning on a per-invocation basis. Does not override the
pyvenv.cfgvirtualenv guard — an included directory that is itself a
virtualenv stays excluded.
Install / upgrade
uvx mollify@0.1.3 audit # or: uv tool install mollify
pip install --upgrade mollify
cargo install mollify-cli # binary: mollifyFull changelog: https://github.com/FavioVazquez/mollify/blob/v0.1.3/CHANGELOG.md
mollify 0.1.0
First public release of Mollify — a deterministic, Rust-native Python code-intelligence engine.
Install
uvx mollify audit # one-off via uv (no install)
uv tool install mollify # or: pip install mollify
cargo install mollify-cli # from crates.io (binary: mollify)Every channel ships the same self-contained binary with agent integrations embedded.
Highlights
- 8 analysis engines (dead code, dependency hygiene, architecture, complexity, duplication, type health, security, supply chain) emitting evidence, not decisions — each finding carries a confidence tier, reason, and stable fingerprint.
- 21 CLI commands; output as human / JSON / SARIF / GitHub annotations / JUnit XML.
- MCP server (
mollify mcp, 16 tools) and LSP (mollify lsp). - Deterministic: identical input → byte-identical output.
See CHANGELOG.md for the full list.