# 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`.