re-separate rename/organize, canonical --resort for AI folders

rename-ai-snaps is rename-only again (+--include-renamed, +--only-generic);
extract-ai-meta is the shared recursive metadata engine emitting canonical
model/lora dest paths; organize-images does all sorting, gains --resort for
idempotent tree re-sorts (used to fix ~10K old-scheme folders on the NAS).
This commit is contained in:
2026-07-30 21:04:37 -07:00
parent 1c1dbf7f21
commit 32859a5df0
6 changed files with 611 additions and 311 deletions

110
FIX-AI-FOLDERS.md Normal file
View File

@@ -0,0 +1,110 @@
# FIX-AI-FOLDERS — Re-sort plan
## Problem
~17K files under `/Volumes/miniShare1/Pictures/Images/AI/` were sorted by an older
scheme. Two scripts currently create `AI/{model}/{lora}/` folders with **different
sanitizers**, fragmenting the tree:
| | `organize-images` (`clean()`) | `rename-ai-snaps` (`sanitize_dir_name`) |
|---|---|---|
| `Pony XL\trserkanWildpony_v20.safetensors` | `Pony XL\trserkanWildpony_v20/` or `Pony XL-trserkanWildpony_v20/` (its `\\``-` fix only catches *double* backslashes) | `trserkanWildpony_v20/` (strips path prefix, `_`-sanitizes) |
| spaces | kept (`FLUX Handsome Male Model_1.0/`) | → underscores |
Legacy artifacts also exist: `None/` and `unknown/` folders (at Images root and inside
`AI/`), plus loose files at the `AI/` root.
Additional blockers:
- `rename-ai-snaps` **skips all `schmeeve-AI-*` files** — 17,178 of 17,255 files in
`AI/`. As-is it would touch almost nothing.
- `rename-ai-snaps` is PNG-only (fine: `AI/` is 99.97% PNG; 5 jpgs reported, not moved).
- All 30 sampled `AI/` files still carry full ComfyUI `prompt` metadata — a
metadata-driven re-sort is viable.
- `Unsorted/` sweep: 0 of 120 sampled files (jpg/png/webp) have ComfyUI metadata —
they are web downloads, not ComfyUI outputs. Only files with real `prompt`
metadata qualify for moving.
- `nas_mount_base()` does not know `/Volumes/miniShare1`.
- `~/.local/bin/organize-images` is stale (older than repo copy).
## Requirements (user decisions)
1. **Scope:** Everything — `AI/`, `None/`, `unknown/`, plus sweep `Unsorted/` and
`Screenshots/` for PNGs with real ComfyUI metadata.
2. **Filenames:** Keep existing names, **except** generic names (`ComfyUI_*` etc.)
which get a proper keyword-based rename.
3. **Architecture:** Re-separate concerns — `rename-ai-snaps` renames only (the
folder-moving added in `e85fce1 "model first"` was a mistake), `organize-images`
does all sorting. Fix its sanitizer; sync the stale `~/.local/bin` copy.
## Plan
### 1. `rename-ai-snaps` → rename-only
- Strip the move/folder logic (`output_root`, `mkdir`, `shutil.move`, model/lora
folder computation). Keep metadata extraction, keyword scoring, and
interactive/batch renaming **in place** (filename changes only, never directory
changes).
- Default: skip `schmeeve-AI-*` as today. New flag `--include-renamed` for
corpus-wide renames later.
### 2. `extract-ai-meta` → shared, recursive metadata engine
- Add `-r` recursive walk; relative-path keys instead of bare basenames.
- Port the robust extraction from `rename-ai-snaps` (`_strip_model_name`,
`UNETLoader`/extra checkpoint classes, generic `*lora_name*` fields). It currently
only knows `CheckpointLoaderSimple` and keeps backslash path prefixes — the cause
of `Pony XL\…` folders.
- Keep its connected-LoRA check (excludes disconnected LoRA nodes).
- Add a `prompt_present` flag per file so `organize-images` can classify AI files
**without** `mdls`, dimension heuristics, or filename guesses.
### 3. `organize-images` → all sorting, canonical scheme
- **Canonical sanitizer** (single implementation; fixes the `\\` bug and space
handling): strip path prefix → spaces → `_` → non `[a-zA-Z0-9_.-]``_`
collapse. `Pony XL\trserkanWildpony_v20.safetensors``trserkanWildpony_v20`
everywhere.
- **New `--resort` mode:** recursively walk `AI/` (including `schmeeve-AI-*` files),
compute canonical `AI/{model}/{lora}/` per file, move only what's misplaced.
**Filenames never touched.** Files already correct are skipped (idempotent).
Missing model → `unknown/`; no loras → `no-lora/`.
- **Sort `None/` and `unknown/`:** pass as targets; files with metadata route into
`AI/{model}/{lora}/`, files without go to `AI/unknown/`.
- **Sweep `Unsorted/` + `Screenshots/`:** only files with actual ComfyUI `prompt`
metadata move into `AI/{model}/{lora}/`.
- **Generic-name hook:** before moving files matching `ComfyUI_*`/hash-style names,
invoke `rename-ai-snaps -n` on them (its skip-rule already protects
`schmeeve-AI-*`).
- **Collision policy:** destination exists → append `_1`, `_2`… (never overwrite,
never delete).
- **Performance:** one metadata scan → JSON manifest in a temp file; move logic
reads the manifest (no per-file `mdls`/`sips` subprocess storms).
- Keep dry-run default, `-e` to execute, `--limit` for batching.
### 4. Verification
- Full dry-run first: summary counts per destination folder + sample moves.
- Spot-check that `Pony XL\…`, `Pony XL-…`, `None/`, loose-root files land
correctly; confirm already-correct files are untouched; re-run dry-run
post-execute to confirm ~0 remaining moves (idempotency proof).
### 5. Deploy + docs
- Copy updated scripts to `~/.local/bin/` (fixes stale `organize-images`) and
`~/Dropbox/bin/`.
- Add a short "Image pipeline" section to `AGENTS.md` documenting the restored
separation: `rename-ai-snaps` = rename, `organize-images` = sort,
`extract-ai-meta` = shared engine.
## Untouched
- `Unsorted/` web downloads (no metadata = no move), `Screenshots/` non-AI files,
non-PNGs in `AI/` (5 jpgs — reported, not moved).
- Nothing is ever deleted; worst case is a `_1` suffix.
## Note
With `schmeeve-AI-*` names kept as-is, a handful may not match what today's keyword
scorer would produce — but placement will be correct, and any folder can be
re-renamed later with `rename-ai-snaps --include-renamed`.