Repository navigation
v3.37.0: resumable mutation runs, CSS classes from template files, and signed Windows binaries
LatestFeatures
-
fallow health --cssreads server-side template files as class references. Fallow now reads.liquid,.njk,.hbs,.handlebars,.twigand.blade.phpfiles, and each class-like word in them counts as used. A class that only a Shopify Liquid section applies is no longer anunreferenced-css-class. A class prefix before a{{echo, as ingrid--{{ columns }}, also counts. The{{rule also applies to.vue,.html,.mdand.astrosources with dynamic class syntax, so these sources can report fewer classes. Use the new top-levelmarkupExtensionskey to add other template extensions, for example["tpl", "erb"]. These files do not join source discovery, so they never become unused files. Thanks @james2doyle for the report. (#3917) -
The npm package now ships
rule-pack-schema.json. Point the$schemaof a rule pack at./node_modules/fallow/rule-pack-schema.jsonto get a schema that matches the installed version. The package also exports the file asfallow/rule-pack-schema.json. Thanks @hckhanh for the report and @tahodev for the change. (#3851) -
An interrupted
fallow mutationrun keeps its finished results, and--resumecontinues it. Each run writes each killed and retry-confirmed survived mutant to.fallow/mutation/journal.jsonlwhen its result is final, also with--no-cache.fallow mutation --resumereuses these results and runs only the other mutants. When the journal comes from other inputs, the run exits 2 withFALLOW_MUTATION_RESUME_MISMATCHand names each input that differs. A resumed mutant hasresumed: true, and the report has aresumeobject. A complete run removes the journal, and a partial run keeps it. (#3783)
Changed
-
A bare machine run that exits 0 on a failing gate now says so on stderr. Bare
fallowin a machine format exits 0 on findings, butfallow dead-code --format jsonexits 1 on the same findings. Before, nothing showed why. Now the run prints one stderr line, also under--quiet, that names each failing findings gate and the flag that enforces it. The exit code and stdout do not change. Thanks @Smrtnyk for the report. (#3826) -
The exit-code contract no longer says that exit 0 means a clean run.
fallow schema(exit_codes), the fallow skill and the npm README now say that 0 means no enforced gate failed. Exit 1 means findings, not a tool failure. A bare machine run gates on findings only with--fail-on-issues. To see a failing gate that did not set the exit code, readgate_outcomes. -
fallow mutationgives no mutant for a pure condition whose only effect is a logging call. Anifstatement such asif (count > 0) { console.info("Items", count); }no longer gives mutants. The condition must be pure, and each branch must hold onlyconsole.*ordebug(...)calls with pure arguments. In a file that declares or importsconsoleordebug, the conditions that call that name keep their mutants. (#3719)
Bug fixes
-
thin-wrapperandduplicate-prop-shapeset toerrornow fail the gates. Aterror, these rules count in issue totals, the dead-code and audit gates, and CI reports. A rule atwarndoes not fail a gate, also with--fail-on-issues. Thanks @luciocabrera for the report. (#3867) -
A CommonJS
postcss.config.cjsno longer reports itsmodule.exportskeys as unused exports. When a plugin credits onlydefaultfor a CommonJS module, Fallow now credits every key ofmodule.exports. The fix applies to the CommonJS config files of all plugins that read the default export. Thanks @waldoluisribeiro for the report. (#3876) -
fallow securityresolves a string enum member in the same module. Fallow no longer reports a template literal such as`<meta name="${MetaName.BUILD_NUMBER}">`that goes to an HTML sink as non-literal HTML. Enums and constants that you import from another module stay unresolved. The first run after the update parses all files again. Thanks @Smrtnyk for the report. (#3854) -
Component export queries no longer stop type-aware refinement for the whole run. Fallow now gives Vue, Astro, Svelte and MDX query files an
unsupported-syntaxabstention. Supported TypeScript and JavaScript queries in the same batch continue to resolve. (#3763) -
fallow dead-codefollowschild_process.forktargets built from the module directory. A file thatfork(path.join(path.dirname(fileURLToPath(import.meta.url)), "child.ts"))starts is no longer an unused file.path.resolve,__dirname,import.meta.dirnameand a constant that holds the module directory also work. Thanks @VariableVince for the report. (#3919) -
Fallow now reads config values from a same-file constant. A config can keep part of its value in a top-level constant, for example
projects: [UNIT]. Fallow now uses the value of the constant, so the setup files of such a Vitest project are no longer unused files. The fix applies to all plugins that read config files. Thanks @Smrtnyk for the report. (#3852) -
fallow dead-codeno longer reports a class member as unused when an array pattern or a getter on a held object is its only read. An array pattern around an object pattern, such asconst [{ m }] = [service], now credits the member. Fallow also credits the member for asrc.k.mread through a getter on an object literal that a variable holds. Both forms now credit the member without--type-aware. (#3799) -
Package scripts and CI steps that run a local shell helper now credit the commands of that helper. For
bash scripts/build.shor./scripts/release.sh, Fallow reads the helper without running it. A binary that the helper runs makes its package used, and a file that the helper runs withtsxornodebecomes an entry. Fallow follows nested helpers and literalcdsteps. Thanks @VariableVince for the report in #3918. (#3886) -
fallow dead-codenow credits a store member that a helper reads through a store alias declared in a function body. An alias such astype X = ReturnType<typeof useXStore>in a function body or block now credits the store member. An inner type of the same name still shadows the alias. (#3550) -
Deeply nested defaults in an object pattern no longer make extraction hang. In a declaration such as
const { k: { k: { m } = s } = s } = s, the work doubled at each level of nesting. A step budget now bounds the walk of one declaration. -
fallow dead-codenow credits Expo config plugins that come from a local array binding. An app config can hold itspluginslist in a top-levelconstorlet. Fallow now reads that list, its spreads, andpush,unshiftorsplicecalls on it. Anexpoobject with a type assertion, such assatisfies ExpoConfig, now also counts. (#3883) -
--production --type-awareno longer credits an export that only a test file uses. A type-aware reference from a file outside the analysis scope no longer removes a dead-code finding. Thanks @Smrtnyk for the report. (#3869) -
Audit cleanup preserves unrelated Git worktree registrations. When Fallow removes old snapshots, it keeps each user worktree registered while its directory is temporarily unavailable. (#3884)
-
Extraction is no longer slow on malformed input. Incomplete
scriptandstyletags in Astro and incomplete template tags in Vue and Angular no longer cause repeated scans. An unfinished multiline import or export in MDX no longer makes the parser run again for each line. CODEOWNERS lookups with long patterns no longer use too much memory or time. Results and source offsets do not change. -
Type-aware refinement on the
tsrsbackend no longer fails on public APIs with many non-generic interfaces. The semantic sidecar now asks for type arguments only on type references.tsrsnow gives the same result astypescript-go. Thanks @Smrtnyk for the report and the reproduction. (#3872) -
Programmatic and MCP audits no longer show their base snapshot in
git worktree list. The API, the MCPaudittool and the pull-request decision output now remove the Git registration of the base snapshot, asfallow auditdoes. They also remove snapshots that a stopped process left behind. (#3885) -
fallow dead-codeno longer reports the default export of a local OxlintjsPluginsfile. Oxlint loads the default export of each local plugin file. WithincludeEntryExports, Fallow reported this export as unused, and now it credits the export. Other exports of the plugin file stay reportable. Thanks @Smrtnyk for the report. (#3871) -
fallow dead-codeno longer reportstsrsandfallow-type-awareas unused devDependencies. Fallow loads these type-aware backend packages at run time, and now credits both by name. Thanks @Smrtnyk for the report. (#3873) -
fallow dead-codecredits the packages in tsconfigcontentMappers. TypeScript 7.1 loads eachcontentMappers[].packageto map files such as.vueor.astro. The TypeScript plugin now credits the package name. Thanks @Smrtnyk for the report. (#3870) -
fallow securityfollows per-path overrides for its dead-code note. In a file where an override setsunused-filesorunused-exportstooff, a sink no longer shows the unused note or the delete action. Thanks @Smrtnyk for the report. (#3853) -
fallow securityno longer reports module-relative paths as path-traversal candidates. A path fromimport.meta.url,import.meta.dirname,import.meta.filename,__dirname,__filenameorprocess.cwd()with only literal segments cannot contain caller input. An example isfs.readFileSync(path.join(__dirname, "template.html")). Fallow also trusts a module-scopeconstthat holds such a path. (#3711) -
fallow securitynow checks everypath.joinandpath.resolvesegment. Before,path.resolve(".", input)gave no candidate. The matcher now checks each argument and reports one candidate for each call. (#3712) -
fallow health --csscredits classes that plain.jsand.tsDOM code applies. Fallow now readsel.className = ...,el.classListcalls,el.setAttribute('class', ...)andclass:orclassName:object properties. A template value such as`panel-${kind}`credits itspanel-prefix. Fallow now scans a.jsfile that holds JSX the same as a.jsxfile. Thanks @osazemeu for the report and the reproduction. (#3865) -
fallow mutationnow runs Vitest projects in ahappy-domorjsdomenvironment when the cache is outside the project. Before, such a project failed its baseline withCannot find module '/@fs/.../vitest-setup.mjs'whenFALLOW_CACHE_DIRwas outside the project. (#3793) -
fallow dead-codecredits a member access on the declared return type of an instance method. A call such asmanager.current()?.onDown?.(), wherecurrent(): Tool | undefined, now creditsTool.onDown.SelectTool.onDownis no longer an unused class member. Thanks @Smrtnyk for the report. (#3868) -
fallow dead-codeno longer reports an aliased asset import as an unlisted dependency when the alias is in a referenced tsconfig. Fallow now removes./and..segments fromincludeandexcludepatterns before it matches them. Thepathsof that config now apply. Thanks @agneym for the report and the public reproduction. (#3946) -
A tsconfig in a directory whose name holds glob characters now applies to its files. A directory such as
app/[id]or{a,b}no longer changes the meaning of anincludepattern. As intsc, only*and?are wildcards in an entry.
Security
-
The Windows binaries now have an Authenticode signature from Fallow B.V. Windows 11 Smart App Control blocked the unsigned
fallow.exefrom the npm package. The release now signs each Windows executable and the Node addon. The signed files ship in the GitHub release archives, the npm packages and the VS Code extension. The Ed25519 signatures do not change. Thanks @Rednas83 for the report. (#3807) -
Git commands in an audit base snapshot no longer read a repository from the base commit. A base commit could supply a repository whose config runs commands, for example through
core.fsmonitor. The.gitfile now names an absolute path that cannot exist. Each Git command in a snapshot now gets aGIT_DIRthat does not exist. Fallow also setssafe.bareRepository=expliciton every Git command that it starts. -
fallow hooks installvalidates the detected default branch name. Without--branch, a craftedorigin/HEADname could put shell code into the generated hook. The command now applies the same ref validator as--branch. When the name fails, the command prints a warning and usesmain.
Full Changelog: v3.36.0...v3.37.0