Similarity requirements now scale with word length (typo.floor_ok:
single edit or ratio >= max(0.6, 1 - 3/max(len,3)), first char kept;
zsh spdist / nushell did_you_mean derivation in the source). The
fixed-cutoff gates are swapped: history_resolver._similar ->
floor_ok with the divergence cap deleted (every diverged token is
gated per-token, not counted), learned.guess_from_path and the help
resolver candidate gates -> floor_ok, so _TOKEN_CUTOFF,
_MAX_DIVERGED, GUESS_CUTOFF, _CUTOFF and their difflib plumbing are
gone; unique-survivor, no-op and which/'/'/'.'/flag guards kept.
New thefuck/danger.py is_dangerous(script) parses via bashlex
directly and fail-safes to True when bashlex is unavailable or the
script refuses to parse (the flat fallback is head-only); with a
tree it matches rm/rmdir recursive flags, dd/mkfs*/shred/wipefs/
mkswap heads, git push --force/-f (not --force-with-lease),
chmod/chown -R with a 777-style mode, kill -9, fork-bomb shapes,
pipe-to-shell tails and file redirects outside /tmp and /dev/null.
fix_command checks it before ANY auto-run, learned-db exact hits
included: dangerous candidates fall through to rules+ask.
Test-migration inventory (authorized semantic inversions):
- tests/resolvers/test_history_resolver.py: declines-3-diverged ->
corrects (cap deleted); 0.8-cutoff boundary arithmetic re-based to
floor boundaries (len-3 0.6 / len-10 0.7 / len-30 0.9);
_TOKEN_CUTOFF import removed with the constant; declines-just-
below-cutoff re-based to the len-20 floor 0.85; added a 17-char
below-floor decline.
- tests/test_learned.py: returns-none-below-cutoff re-based to a
same-first-char below-floor pair (0.6 < len-10 floor 0.7); added a
ratio-0.7 acceptance pin; single-edit-under-cutoff renamed.
- tests/resolvers/test_help_resolver.py: transposition comments
re-based to the floor; added a below-floor subcommand decline.
- tests/entrypoints/test_fix_command_learned.py: exact-learned-wins
fixture's 'git push --force' correction (now correctly refused)
replaced by benign scripts; mock_learned stubs danger benign for
platform-neutral auto-apply tests; added TestDangerOverride
(real module, all four sources: reaches select_command, nothing
auto-runs).
difflib's SequenceMatcher underrates adjacent transpositions, so the
flagship examples (gti->git 0.667, greo->grep 0.75, psuh->push 0.75)
fell below the 0.8 ratio gates and were declined. Per the plan
amendment, the token and candidate gates in the history resolver,
guess_from_path and the help resolver additionally accept a
first-char-equal single edit (one substitution, insertion, deletion
or adjacent transposition; new thefuck/typo.py), with the ratio
cutoffs, the exact-one-candidate rule and the 0.79 boundary (edit
distance >= 2) unchanged.
Consult a PATH-resolved binary's own --help (mtime-cached, LC_ALL=C,
2s timeout with kill) when a segment's first non-flag token is not a
listed subcommand, and splice the unique close match (ratio >= 0.8,
same first character). Ambiguity, sudo heads, flat-fallback artifact
heads, valid subcommands and nested levels all decline to the rest of
the chain; only <binary> --help is ever run.