v3.4.2: suppression inventory, native GitHub output, monorepo CI paths, member-crediting accuracy
Suppression governance
fallow suppressions: a read-only inventory of every active suppression marker, grouped per file with line, kind, level, and reason, plus project totals and a stale count cross-referenced from this run's findings. Teams governing tech debt (and agents that should distrust a "clean" verdict) no longer grep forfallow-ignoreby hand. Ships with--format json(newsuppression-inventoryenvelope) and full workspace/changed/file scoping; always exits 0.- MCP tool
list_suppressionsexposes the same inventory to agents on the MCP surface, returning the JSON envelope verbatim. - Every "To suppress:" hint in the human footer now names a token fallow actually parses. Eight sections printed tokens the parser does not recognize, so following the hint suppressed nothing and then surfaced a stale-suppression finding on top. Hint tokens now derive from the issue registry, backed by a roundtrip guard test. Thanks @slyeargin for catching the unused-files case in #1820.
Native GitHub workflow output
--format github-annotationsand--format github-summary: inline PR annotations (::error/::warning/::noticeworkflow commands) and job-summary markdown straight from the CLI, no bundled action required. Both are log-based, so they render on fork PRs without a write token.fallow report --from <results.json>: analyze once withfallow --format json -o results.json, then render annotations and the job summary from the saved envelope, byte-identical to the direct run.
Monorepo CI paths
- Behavior change: CI-facing formats emit repository-root-relative paths when
--rootis a subdirectory. GitLab's Code Quality widget matched nothing and inline review discussions were rejected when the analyzed project lived in a package subdirectory, becausecodeclimate,review-github, andreview-gitlabaddressed files relative to--root. All CI formats now share one namespace, detected via the git toplevel; pass--report-path-prefix ''to restore the old output. Single-package repositories are unaffected. See docs/backwards-compatibility.md for the classification rationale. --annotations-path-prefixis now--report-path-prefixand governs every CI-facing format; the old name keeps working as an alias.--diff-fileresolves the diff's path namespace from the diff itself, so changed-file filtering works in monorepo packages for bothgit diffconventions; a diff that parses but touches no analyzable files filters to zero findings, and an unplaceable diff warns and reports at full scope instead of producing a plausible-looking empty report. Renamed files keep theirold_pathinreview-gitlab. Thanks @Jerc92 for the diagnosis and the patch in #1808.
unused-class-members accuracy
Four extraction gaps produced false positives on dependency-injection-style code, reported across three issues by adopters running the rule on real codebases:
this.#dep.method()receivers through#-private class fields now credit the target class cross-module, and same-named fields on sibling classes in one module no longer collide on a shared binding key (previously last-write-wins: only the class declared last credited its dependency's members). Thanks @martijnwalraven for the report with its isolation matrix (#1821).- Members reached through a local (non-exported) subclass, factory results read without a named binding (
f().member,const { member } = f()), and opaque destructures now credit correctly. Thanks @Jerc92 for the fixes in #1811. - Playwright page-object methods used through a
mergeTests(...)-wrapping helper are credited, including imported<base>.extend(...)wrappers. Thanks @committedpazz for the follow-up report (#1795). - Iteration over array-typed parameters (
items: Item[]) andPromise.all(arr.map(cb))results now types the iteration variable, sofor...ofand.mapmember accesses credit the class. Thanks @vethman for the report (#1793).
Fixes and improvements
fallow audit's base-snapshot cache no longer appears ingit worktree listor IDE repo views; snapshots are unregistered immediately after materialization, and entries from earlier versions deregister automatically on the next audit with warm caches preserved. Thanks @AlonMiz for the report (#1815).- Generated configs point
$schemaat the localnode_modules/fallow/schema.jsonwhen present: offline, no VS Code trust prompt, always version-aligned. Non-npm installs keep the remote fallback. Thanks @vethman for the report (#1794). - The repository Dockerfile's pinned version and checksums now track releases automatically via a post-release job (#1817).
- Reusable analysis sessions share parsed-module storage across warm queries, and contract regeneration promotes committed outputs as a transaction.
- The
fallownpm launcher and Node bindings now require Node.js 22 or later.
Full Changelog: v3.3.0...v3.4.2