v3.29.0: raw V8 coverage, parse-error gate, complexity rule levels, deprecated export consumers
·
30 commits
to main
since this release
Immutable
release. Only release title and notes can be modified.
Features
health --coveragereads raw V8 coverage. Give it aNODE_V8_COVERAGEdirectory or one V8 coverage JSON file, and CRAP scores use measured coverage without a conversion step. The dumps of all test processes add up. A transpiled script maps back to its sources through the source map in the dump.health.coverage,FALLOW_COVERAGE,fallow auditand the MCP tools take the same inputs. The newsummary.coverage_input_formatfield isistanbulorv8(#2906).- A run can fail when fallow cannot parse a source file. The new
--fail-on-parse-errorflag and thefailOnParseErrorconfig key add aparse-errorgate ondead-code,health,auditand barefallow. The gate is off by default, andgate_outcomes["parse-error"]names each file with its parser error count. Thanks @fpresta0607 for the report (#2727). - Complexity findings can warn without failing the run. The new rules
complexity-cyclomatic,complexity-cognitiveandcomplexity-crapaccepterror(the default),warnoroff, also per file throughoverrides[].rules. Each complexity finding in the JSON output gets an optionaleffective_severity. Thanks @jwenger-notion for the report (#2783). fallow dead-codecan list the files that still use@deprecatedexports. The opt-indeprecated-export-in-usefinding gives aconsumer_count, a sample of up to 10 consumers and the deprecation message. Turn it on with"deprecated-exports-in-use": "warn"inrulesor--deprecated-exports-in-use. An unused deprecated export now hasdeprecated: trueon itsunused-exportfinding (#2598).- The review brief shows how many CODEOWNERS owner groups a change touches.
fallow reviewandfallow audit --briefget anownershipsection when the project has a CODEOWNERS file. It gives owner group counts, unowned changed files and independentslices. The briefschema_versionmoves from 10 to 11 (#2599). - Module Federation credits
sharedpackages and runtime remotes, and traces name the config. A package thatsharednames is no longer an unused dependency (#2794). LiteralregisterRemotesandloadRemotecalls register their remotes in a file that imports them from@module-federation/runtimeor@module-federation/enhanced/runtime(#2795).--trace-fileand--trace-dependencyname the Federation config and key in a newsourcesarray (#2796). --changed-sincestates how many analyzed files it kept. Thechanged-sinceentry ofrequest_outcomesnow hasscope_size, so a change to a README only givesscope_size: 0. The GitHub Action, the GitLab template, the PR and MR comments and the MCP warning state the empty scope (#2800).- A foreign baseline names the command that wrote it.
baseline_stalenessnow hassaved_bynext tounrecognised_format: true. The GitHub Action has a newbaseline-saved-byoutput (#2801). - Security candidates record strict origin checks.
fallow securityrecords anorigin-equality-guardcontrol when a file on the import trace compares.originstrictly with a known string and exits on a mismatch. The control is a hint for verification, not proof. It does not suppress a candidate or lower its severity.
Changed
- The rule, not the band, sets the CI level of a complexity finding.
errorgives::error, SARIFerrorand CodeClimatemajor.warngives::warning, SARIFwarningand CodeClimateminor. The band stays in the title and the message (#2783). --fail-on-issuesalso raiseswarncomplexity findings toerror. This applies tofallow healthand barefallow, also through--ci.fallow auditkeeps its own verdict (#2824).- JSON output always states whether the run passed. Bare
fallow,dead-code,check,health,securityandauditnow always includegate_outcomeswith the default rule of the command and itsstatus. No exit code changes. - The GitHub Action flags the legacy summary renderer, and a failed native render no longer falls back to it. For fallow before 3.4.2, the step log shows a notice and the job summary shows a footnote. The legacy renderers get no new finding types. On 3.4.2 or later, a failed native render writes a warning.
Bug fixes
- Dockerfiles with non-ASCII text no longer crash the run. A short line with a multi-byte character, for example in an embedded SQL seed script, now counts as an ordinary line. Thanks @ga-h-usuba for the report (#2896).
- CI formats state the rule severity of each dead-code finding. A finding with rule
errornow gives::erroringithub-annotations, and SARIF and CodeClimate read the per-fileoverrides[].rulesseverity. Error annotations come first, so themax-annotationscap keeps them. Thanks @jwenger-notion for the report (#2782). - Severity levels agree across commands and saved reports.
fallow dead-codenow uses theoverrides[].rulesentry for catalog and dependency-override findings, the same asfallow audit. Prop-drilling, thin-wrapper and duplicate-prop-shape findings show as SARIFwarningat most, because they never fail the run (#2826).fallow report --fromkeeps the saved level of each finding (#2827). - Nuxt
autoImportscredits global components, local layers and OG image templates. Global components and@nuxt/contentcomponents are now entry points, also when a package layer such asdocusregisters@nuxt/content(#2847, #2851). Fallow now credits OG image templates that a string names (#2849). Local layers are part of the project, and auto-import names from#componentsnamespace imports now credit their files (#2752). A name now credits only the files of the app that uses it and of its layers. - Module Federation reads more config shapes. Fallow now reads options behind an
export const, a spread,Object.assign, a wrapper call or a relative import (#2757). Anexposestarget in a sibling workspace is an entry point, and fallow reads runtime calls in.vueand.sveltescripts (#2757, #2876). A shape that fallow cannot read records aplugin-config-unreadablediagnostic. - Bundler entries resolve like the bundler resolves them. A bare rollup, rolldown or vite
inputsuch asmy-lib/clientcredits its package. An entry without an extension matches the file or the directory index (#2753). Fallow now reads webpack configs inconfig/,build/orwebpack/, and applies rspackcontextand rsbuildrootto entries (#2753). Fallow reads an absolute config path under the project root as that path (#2806). - Storybook
storiespatterns resolve against the.storybook/directory. A pattern such as../src/**/*.mdxnow matches, and@(ts|tsx)groups work (#2831). A central docs app now credits stories in a sibling workspace, and fallow now reads the object form{ directory, files, titlePrefix }(#2842). - Save and report files stay inside allowed directories. The save flags,
--output-fileand--sarif-fileexit 2 when the resolved file is outside the allowed directories (#2805, #2861). These are the project root, its Git work tree, the CI workspace,RUNNER_TEMPand the system temp directory.-o /dev/nullstill discards a report, and-o NULnow discards it on Windows (#2877). When.fallowresolves outside the project, the run does not use the cache and prints a note (#2861). - Flags that did nothing now exit 2.
--baselineand--save-baselineon a subcommand without a baseline, such asfallow list, now exit 2 (#2802, #2807).dupes,healthand a bare run without dead-code reject--sarif-fileand point to--format sarif --output-file(#2861, #2877). - Bare
fallownow applies dupes and health baselines. Usefallow --dupes-baseline <file>andfallow --health-baseline <file>.--fail-on-stale-baselinenow checks all three baselines. - Export tags attach to the right export. A JSDoc block before a decorator now attaches to the decorated export (#2835). In code without semicolons, a tag such as
@publicno longer applies to later exports. - A re-export through an unresolved import counts as used when a file imports the name. Before, the re-exported name was also an unused export. A re-exported name that no file imports is still an unused export (#2870).
- Inline suppressions work for component events. A
fallow-ignore-next-lineorfallow-ignore-filecomment forunused-component-emit,unused-component-input,unused-component-outputorunused-svelte-eventnow drops the finding. - Template complexity counts operators inside a template literal. In an Angular, Vue or Svelte template, a ternary,
&&,||or??inside${}now adds complexity (#2798). fallow auditshows a dependency finding only when its manifest changed. The changeset must touch thepackage.jsonor the catalog file that declares the dependency. An edit that only removes a tag such as@expected-unusedor@publicnow counts the finding as introduced. The MCPaudittool treats findings in renamed files as inherited, the same as the CLI.- The MCP tools and the Node API match the CLI. A bad
FALLOW_DIFF_FILEorFALLOW_CHANGED_SINCEnow gives anot-appliedentry inrequest_outcomes, notisError(#2799). Clone groups across workspaces and hidden duplicate exports now follow the CLI. The four MCP tools that can write a baseline declarereadOnlyHint: false, andcode_executerefuses the save parameters (#2755). - Health reports cover more repository layouts.
health --hotspotsworks when the project root is a subdirectory of the Git repository. A branch without commits gives ahotspots-skippeddiagnostic with the causeno-commits(#2803). With--type-aware-require complete,gate_outcomesofhealthandauditnow show a failed check. fallow listnames the entry points that the analysis uses. On a Nuxt project withautoImports: true,fallow list --entry-pointsno longer names every component as an entry point (#2804).- The human summary line follows the result of the run. A run that passes with
warnfindings now shows a yellow⚠, and the red✗shows only when a gate fails (#2824). The health headers print1 filefor a count of one (#2808). - Editor complexity lenses match
fallow health. The code lens now applieshealth.thresholdOverridesand thecomplexity-cyclomaticandcomplexity-cognitiverules withoverrides[].rules(#2825). - Security candidates need a complete URL authority and skip constant
writeHeadheaders. A server-side request forgery candidate now needs a complete URL authority in the fixed prefix. AwriteHeadcall with constant headers is no longer a header-injection candidate. Findings for different sinks on the same line have distinct IDs. - The VS Code extension keeps working before its release is published. The previous verified binary stays in place until the new one downloads. With
fallow.autoDownloadon, the extension retries in the background. - Other fixes.
report --fromrenders a clean--group-byrun (#2830). The GitHub Action checks thebaselineinput for control characters (#2756). The git hook falls back toorigin/main, thenorigin/master(#2758). The hidden-directory message gives a remedy that fixes the run (#2797). Traces pick the file at the exact path you name, and programmatic duplication follows thedupesproduction mode. Fallow no longer warns that acircular-dependencyoverride has no effect.
Performance
fallow guardcompiles each rule-pack scope once per run. Zone validation no longer compiles the boundary zone globs a second time.
Upgrade notes
- Strict JSON validators: the dead-code
summaryhas the required keydeprecated_exports_in_use, and the envelope has adeprecated_exports_in_usearray.schema_versiondoes not change. - This release invalidates the parse, extraction, graph and churn caches, so the first run after the upgrade is cold.
- Complexity findings with the default rules change CI level. A
moderatefinding is now::errorand SARIFerror. CodeClimatecriticalandminorbecomemajor. Set acomplexity-*rule towarnto keep them as warnings. - Dead-code findings with rule
errornow give::erroringithub-annotations. gate_outcomesis now always in the JSON output. The GitHub Action outputgates-failedand the GitLabFALLOW_GATES_FAILEDvariable are non-empty on every run with findings, also when the job stays green. Check the gate names, not a non-empty value.- Every security finding ID changes. Regenerate candidate files and their verdicts together. SARIF alerts can reopen once.
- These flags now exit 2:
--baselineand--save-baselineon subcommands that do not use them, and--sarif-fileondupes,healthor a bare run without dead-code.--dupes-baselineand--health-baselinewith a subcommand also exit 2. - A save or report file outside the allowed directories now exits 2 before the analysis. Move the path into the project root, the CI workspace or a temp directory.
- New findings can appear:
unused-exportin code without semicolons, unused files in Nuxt projects withautoImportson, and higher template complexity.fallow auditno longer reports a dependency finding when the manifest did not change. Runfallow dead-codeto see it. - An older fallow rejects
failOnParseErroras an unknown key. SetminimumVersionwhen you commit it. - After you turn a complexity kind
off, save the health baseline again. - MCP:
code_executenow refusessave_baseline,save_regression_baselineandsave_snapshot. Call the standalone tool for the write.
Full Changelog: v3.28.0...v3.29.0