fix(recovery): plans are checked by where paths end up; suggestions are valid #150

Merged
james.maes merged 2 commits from fix/149-recovery-plans into main 2026-11-10 20:53:40 +00:00
2 Commits
Author SHA1 Message Date
james.maesandClaude Fable 5.2 2bf2d1c529 fix(recovery): folders by original path, linear cost, one policy for clashes
Follow-up to the independent review of this branch.

- The pre-flight dropped a destination whenever another destination lay
  "inside" it, which hid real clashes: a file renamed onto a name that
  another rename uses as a folder passed, and the engine then rejected the
  plan. A renamed path now counts as a folder only when another renamed
  ORIGINAL path lies inside it.
- Two folders given the same name were merged or left out depending on
  whether one of them held another invalid name. They are now always a
  clash: reported by the pre-flight, both skipped by the automatic plan.
- The pairwise comparison took a minute for 50,000 paths, in the dialog's
  click handler too. Folder membership is now a set lookup.
- A replacement that names another folder is a problem, since only the
  name is applied. Problems name the rows they come from and are reported
  once.
- An overlong name is cut between characters, never through one.
- --sanitize-paths prints where each renamed path lands and counts only
  the renames that are applied.
- Tests: the automatic plan against the real engine; file and folder
  clashes; a problem on a folder above a destination (the branch that ends
  the loop); a name that needs three rounds to settle; 50,000 paths.

Refs #149

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
2026-11-10 14:53:35 -06:00
james.maesandClaude Fable 5.2 5e2b4e44f3 fix(recovery): plans are checked by where paths end up; suggestions are valid
Two defects in how rename choices for Windows-invalid paths were prepared
before they reached the engine:

- The Resolve dialog's pre-flight validated each replacement as typed. A
  renamed entry inside a renamed folder is written with the folder's
  original name in front, so the check saw the invalid name and refused a
  plan the engine accepts; only skipping the file got past it.
- --sanitize-paths trusted the suggested names. Two paths can be given the
  same suggestion, and some suggestions were themselves invalid: "x?."
  became "x?", and "COM3.txt" became "COM3.txt_", which is as reserved as
  the name it replaces. The repository then failed to sanitize.

Now:

- PathRecovery.EffectivePathOf says where a path ends up once the renames
  of it and of the folders above it are applied (nowhere, when it or a
  folder above it is skipped). The pre-flight validates those places.
- Every suggested name is put through the rules until it passes, and a
  reserved device name is fixed in its base name ("COM3_.txt").
- The automatic plan moved next to the planner
  (PathRecoveryPlanner.FromSuggestions) and skips what its renames cannot
  place, so its result always passes the pre-flight.

Closes #149

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
Signed-off-by: James Maes <james@kof22.com>
2026-11-10 14:19:24 -06:00