Skip to content

v3.22.0: honest answers from surfaces that were guessing

Latest

Choose a tag to compare

@BartWaardenburg BartWaardenburg released this 01 Sep 19:49
· 2 commits to main since this release
Immutable release. Only release title and notes can be modified.
v3.22.0
79a0e8d

Fifty commits since v3.21.0. The theme this cycle is honesty about what the tool knows: several surfaces were reporting a confident answer they had not earned.

A type-aware pass that cannot finish no longer takes the run with it

The semantic pass has a fixed two-minute ceiling, and a project large enough to reach it lost its entire report: every CLI surface exited 2 regardless of typeAware.require, whose default is best-effort. The LSP already degraded correctly for the identical failure, so the same condition produced a warning through one surface and a hard error through the other.

check, watch, health and the combined run now warn and finish with the syntactic findings, recording the reason in _meta.type_aware.warnings for CI to assert on. Syntactic analysis reports a superset and the semantic pass only removes candidates it confirms are used, so continuing is the conservative outcome.

fallow fix is the deliberate exception and still stops. It removes code, and the extra entries in the unrefined set are precisely the ones a working semantic pass would have proven live, so widening a deletion is the opposite of conservative. Its error now names both ways forward.

The ceiling is settable with FALLOW_TYPE_AWARE_TIMEOUT_SECS, and VS Code exposes it as a setting. This stops the hard failure; it does not make the semantic pass fast enough to finish on a very large project on Windows.

Thanks @VariableVince for the report.

Branching outside every function is no longer invisible

No frame was pushed at module scope, so decision points outside every function contributed nothing to any complexity number. Module-scope ??, || and ?. scored zero too, not just if ladders, which made "this change removed branching" unprovable: a fall was equally consistent with a branch having been hoisted out of a function.

A synthetic per-file unit now carries that branching into the aggregates and the review brief's conservation check. It is deliberately aggregate-only and never produces a finding, because "extract helper functions" is meaningless advice for module scope.

Measured across five real projects, the effect is smaller than expected: two showed zero movement in any vital sign and no health score moved by more than 0.2. Well-factored TypeScript keeps its boolean operators inside functions, where they were already counted.

Hoisted dependencies in a monorepo

A private sibling workspace is not installed from a registry, so a consumer that depends on it inlines its source and the package manager resolves that sibling's packages from the consumer's manifest. Nothing in the consumer imports them, so each was reported unused, with advice to move the dependency to the workspace that imports it. Following that advice breaks the build.

Fallow now walks the private-sibling closure and credits what those siblings import. A published sibling brings its own dependency tree and is deliberately not followed. Previously private was not consulted at all: the old behaviour was not conservative, it was uninformed.

Thanks @simmo for the report.

React Native Storybook

.rnstorybook is now recognized end to end: the config, the swapped application entry, the generated requires module, and deviceAddons for on-device addons. Web Storybook projects are unchanged, verified byte for byte against nine real ones.

Thanks @PrinceD96, who reported the gap and implemented it, and who also fixed the Lefthook binary resolution this cycle.

Migration tables

fallow migrate reads a config from another tool and maps it onto fallow's. A systematic diff against the upstream sources found 143 gaps across the two tables. The serious category is not the missing entries: sixteen keys were claimed as auto-detected when no fallow plugin covers them, so migration was telling users their tooling was handled when it was not. Those now report honestly. Unknown keys no longer vanish silently either, and the covered table is pinned to the plugin registry rather than to a hand-kept list.

Fallow still has no Marko plugin, so only the table side is fixed there.

Thanks @VariableVince for the report, and for the hunch that more than one entry was missing.

Analysis lenses in the codebase map

fallow viz covered four analyses; everything else rendered as nothing, and an analysis that was switched off looked identical to one that ran and found no problems. Six primary lenses plus an adaptive More menu now carry an explicit availability state with a reason, so a missing analysis reads as missing data rather than as zero findings.

Also in this release

Cooperative cancellation for in-process analysis, bounded Code Mode output and call traces, a sandbox constructor escape closed, minimumVersion for config files, SvelteKit 3 conventions, and several fixes where a published surface claimed more than the code delivered: a plugin roster that had silently lost an entry, a skill contract describing a feature that had changed, and a path redaction that missed rooted Windows paths without a drive letter.

Full Changelog: v3.21.0...v3.22.0