Skip to content

Releases: FavioVazquez/mollify

mollify 0.1.6

Choose a tag to compare

@FavioVazquez FavioVazquez released this 07 Jul 03:49
0d980f7

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

Choose a tag to compare

@FavioVazquez FavioVazquez released this 06 Jul 18:54
b3dfde5

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 quoted cast() type args are honored. flask now has zero certain unused-imports and mollify fix proposes nothing there (was 2 destructive edits).
  • Cross-platform report identity — every location.path is 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 (new windows-latest matrix).
  • unused-parameter interface-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-function package rollup — deliberately-untyped packages (60%+ of 20+ eligible public functions) get one likely package-level finding; per-function findings demote to uncertain.
  • Security noise calibration — candidates in test/docs/example trees cap at uncertain and are tagged in the reason.
  • Robustness — engine panic isolation (a crashing engine degrades to a single engine-panic finding), 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

Choose a tag to compare

@FavioVazquez FavioVazquez released this 02 Jul 19:20
3b9a6f4

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
    --path spelling 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-baseline write exits 1 (was: success message + 0); a missing or
    invalid --baseline with --fail-on-regression exits 1 (was: gate silently
    disabled); a nonexistent --path exits 2 (was: clean 100/100 report);
    trace/inspect/list/metrics reject formats they don't implement with
    exit 2 (was: silent human output); inspect with no matching file exits 1.
  • unresolved-import is now likely, not certain: a relative import may
    resolve to a C extension or build-generated module the .py walk can't see.

Fixed

  • fix --apply corrupted 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-.py files outright).
  • fix --apply could delete live, dynamically-dispatched code: a symbol
    invoked from another module via getattr(lib, "_handler_" + name)() was
    graded certain; a dynamic sink anywhere in the project now caps
    unused-export confidence, mirroring unused-file.
  • fix --apply preserves 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-level with/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 else branch of an if TYPE_CHECKING: guard are no
    longer treated as type-only (and if not TYPE_CHECKING: now works);
    TYPE_CHECKING guard detection is exact instead of substring-based.
  • Decorated def/class line numbers point at the definition, not the first
    decorator.
  • cold-code can now actually fire for imported modules: the def line —
    executed at import time — no longer counts as evidence the body ran.
  • The duplication engine reads notebook code cells, not raw .ipynb JSON
    (near-identical scaffolding produced bogus clone families).
  • Dependency hygiene: dev-group tools (black, mypy, pre-commit…) are exempt
    from unused-dependency (deptry parity); psycopg2/psycopg2-binary and
    friends are alternative providers instead of a forced alias (no more paired
    unused+missing false positives); namespace tops (google, azure, …) are
    never guessed as missing-dependency without 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.0 no longer parses as 2), and
    .postN/.devN order per spec instead of comparing equal to the release.
    specs_intersect finds narrow gaps like (>2.0, <2.0.1).
  • Determinism: import→dist mapping and requirements/pins collection no longer
    depend on filesystem read_dir order; hotspot/coverage/git fallback
    matching is anchored at path-separator boundaries (app.py no longer claims
    myapp.py's churn, coverage, or diff hunks) with deterministic tie-breaks;
    non-ASCII filenames survive git's core.quotePath.
  • inspect <file> matches path fragments at separator boundaries only
    (inspecting b.py no longer returns lib.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 -32700 response; requests without a
    method get -32600; mollify_fix apply errors surface as tool errors.
  • LSP: unknown requests get -32601 instead of hanging the client;
    didClose clears stale diagnostics; diagnostic ranges are never reversed
    and cover the final line; a malformed Content-Length header no longer
    kills the server mid-session.
  • OSV querybatch pagination: truncated advisory sets are no longer cached
    as authoritative.
  • --save-baseline keeps stdout pure JSON (status note moved to stderr, the
    report is still emitted); quality_score is recomputed after
    --gate/--min-confidence/--baseline filtering so the envelope is
    internally consistent.
  • Update-check cache writes atomically (temp file + rename).

Changed

  • mollify-types contract enums are #[non_exhaustive] (adding a report
    kind/category is no longer a breaking Rust change), and the load-bearing
    Confidence/Severity orderings are documented and locked by tests.
  • Docs/CI hygiene: AGENTS.md no longer documents a nonexistent
    mollify graph --format flag; the GitLab CI example uses
    artifacts:reports:sarif; the advisory-database docs describe the actual
    live-by-default behavior; bump-version.sh works 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: mollify

If 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

Choose a tag to compare

@FavioVazquez FavioVazquez released this 01 Jul 21:24
9a71aa9

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__.py now resolve. A package's
    __init__.py has the package itself as its dotted name, so the resolver was
    dropping one segment too many — .aa resolved to aa instead of pkg.aa.
    This cascaded into spurious unresolved-importunused-file
    unused-export across re-exporting packages (the dominant FP source). Package
    self-references no longer create a circular-dependency.
  • session.exec(...) no longer flagged dangerous-eval (CWE-95). The
    security rule matched any trailing .exec/.eval segment; it now matches only
    the eval/exec/compile builtins, not ORM/driver methods.
  • pytest test_*/Test* are no longer unused-export. They are treated as
    reachability roots within test paths, honoring
    [tool.pytest.ini_options].testpaths.
  • from __future__ import … is no longer unused-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 inside main() (e.g. uvicorn)
    isn't falsely unused-dependency; module-scope unused-import is unaffected.
  • [project.scripts] entry points are reachability roots — the target
    module isn't unused-file and the named function isn't unused-export.
  • First-party test helpers imported by bare leaf name (conftest, sibling
    modules on a test path) are no longer missing-dependency.
  • commented-code no longer fires on prose that opens with a keyword
    (e.g. # from zero (...), doubled.); from … now requires a real import.

Changed

  • Quality score is weighted by confidenceuncertain findings penalize
    the 0–100 score far less than certain ones, so a report dominated by
    low-confidence review items no longer reads as a failing grade. Still
    deterministic.
  • mollify init writes a richer, documented starter .mollifyrc.json
    (five-area severities, type-health off by default, complexity knobs,
    inline _comment docs).

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's exclude_dirs,
    and .gitignore for the named directory, letting users opt a directory
    back into scanning on a per-invocation basis. Does not override the
    pyvenv.cfg virtualenv 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: mollify

Full changelog: https://github.com/FavioVazquez/mollify/blob/v0.1.3/CHANGELOG.md

mollify 0.1.0

Choose a tag to compare

@FavioVazquez FavioVazquez released this 26 Jun 18:32
11c3035

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.