Sync working tree before initial Gitea push

Includes:
- cli.py path fix (parents[1]) for config/catalog resolution
- Library cleanup feature design docs (TODO.md, mockup)
- Audit + bug-queue markdowns from May 2026 reliability pass
- .gitignore expanded for transient artifacts
This commit is contained in:
admin
2026-05-26 22:35:42 +02:00
parent 8d6bdb81af
commit f7fc15b17c
24 changed files with 2938 additions and 41 deletions
+75
View File
@@ -2,8 +2,83 @@
## Deferred
### Deferred Lights from 2026-05-24 audit
See `D:\DEV\Project\rclone-jav\bugs-fix-queue.md` rows L-2 through L-6. Cosmetic / UX polish: Discord passive UI surface, stderr 5s stale on rc-jav stall (also L-3 mentioned above), expectedId state leak, history chip during modal, Clear button modal stay-open. None block S/M workflows.
### Library Cleanup feature (preview-first, Phase 1 only)
Design mockup: `mockups/library-cleanup-claude.html`. Scope-fenced to deterministic transforms + junk-strip on names already containing resolution OR clear garbage tokens. **NO ffprobe / resolution probing** — Phase 2 is a separate future feature.
Volume from 2026-05-26 Library Issues export: 106 files in scope. 85 cleanup-tier (resolution data present, reshape only) + ~21 junk-strip (resolution still missing after strip; Phase 2 candidates).
**Locked design decisions:**
| # | Decision | Locked value |
|---|---|---|
| 1 | Preview flow | P2 dedicated Cleanup Plan modal + P3 JSON export as side button |
| 2 | Part-suffix canonical shape | `{ID} #partN [resolution].ext` — matches CANONICAL_RESOLUTION_RE (last bracket = resolution) AND existing extract_id `#partN` convention |
| 3 | `_PARTN` cosmetic normalize (9 files) | Optional group, default deselected — extract_id already handles both forms |
| 4 | copy_suffix `(N)` conflict policy | Auto-skip + default-uncheck if stripped form exists in cache; default-check if no conflict |
| 5 | Multi-pattern transforms on one file | Composite single row; reason field lists all applied transforms |
| 6 | Revert plan artifact | Auto-save `cleanup-revert-<ts>.json` on apply, in CLI repo root |
| 7 | Progress UI during apply | Full progress bar + ETA + cancel; mirrors scan-progress polling pattern |
| 8 | Placement in extension | Library Review pane: add "Generate Cleanup Plan" button alongside existing Duplicate Review + Library Issues buttons |
| 9 | Persistent ignore list | Per-file `filename_hygiene_ignore: true` flag in cache; scan honors; cleared on cache rebuild |
**Filter UX:** chips not stacked groups. Single-select radio-style chips with tabular-nums count badges. Tier-tinted active state (green=cleanup, yellow=strip, purple=optional, red=conflicts).
**Implementation order (single multi-session feature):**
1. **Python backend — transform + strip functions** in `rcjav/library.py`:
- `_part_suffix_to_canonical(filename)``[1080p].2of2.wmv``#part2 [1080p].wmv`
- `_copy_suffix_to_canonical(filename, folder_filenames)``[1080p] (1).mp4``[1080p].mp4`, returns `(new_name, conflict_with_path | None)`
- `_bare_suffix_to_canonical(filename)``.450p.wmv`` [450p].wmv`
- `_strip_empty_brackets(filename)``TYOD-232 [].wmv``TYOD-232.wmv`
- `_strip_quality_suffix(filename)``CESD-325.HD.mp4``CESD-325.mp4`
- `_strip_bitrate_bracket(filename)``MXGS-672 [396m].avi``MXGS-672.avi`
- `_partN_to_canonical(filename)``_PART1.mp4`` #part1.mp4` (optional)
2. **Plan builder** `build_cleanup_plan(cache, config)`:
- Walk cache.json
- For each file matching a cleanup-eligible pattern, generate row with `old_path`, `new_path`, `transform_kind`, `conflict_with` (cache pre-check), `size`, `composite_reasons[]`
- Returns structured plan dict + grouped counts for chip badges
3. **Host RPC** in `rcjav-host.py`:
- `cleanup_plan` action → calls `build_cleanup_plan`, returns JSON
- `cleanup_apply` action → spawns worker thread (M-3 pattern: per-invocation Event + result holder), executes renames serially via existing `rename_files_batch`, writes progress to state file, auto-saves revert plan
- `cleanup_progress` action → reads state file (mirrors scan-progress)
- `cleanup_cancel` action → sets flag, finishes current rclone moveto, stops
4. **Extension UI** in `src/options/options-library-issues.js`:
- New "Generate Cleanup Plan" button in Library Review pane
- New modal `#cleanup-plan-modal` with chip-row + scrollable row list + footer
- Chip click handler filters visible rows (CSS class toggle)
- Per-row checkbox state managed in JS Set keyed by old_path
- Apply click → RPC + progress polling + result summary modal
- JSON export button → trigger download blob from current plan
5. **Cache flag** for ignore list:
- `find_library_issues` skips entries with `filename_hygiene_ignore: true`
- Modal row gains "Mark as intentional" action (sets the flag via small RPC)
6. **Smoke test before ship:**
- Run plan generation against the real cache.json snapshot
- Verify all 7 transform functions produce expected canonical names for ~10 sample inputs each
- Verify conflict pre-check correctly flags HFD-197 case
- Verify revert plan round-trips (apply 5 renames, import revert plan, re-apply, end state = start state)
**Out of scope (explicitly skipped):**
- ffprobe resolution probing (Phase 2, separate feature)
- Quality-mapping editor (4 files, not worth own UI)
- Bare-name renames (~775 files; no resolution data to act on)
- Cross-remote moves
- Mid-rclone-call cancellation (would risk corrupt remote state)
**Estimated scope:** ~700-900 lines across Python backend + extension UI. Single multi-session feature, NOT a bug fix. Deserves its own audit pass after implementation (mirror the 3-phase audit pattern done in May 2026 for reliability bugs).
(append below)
## Completed notes
- Scan progress cadence polish completed 2026-05-25: `rcjav/rclone_io.py` now decouples cancel checks from progress emission. Cancel checks run every 25 files. Progress emits on a dual gate: at least 25 files and 0.25s since the last emit, or a 1.0s heartbeat when the loop is still receiving rows. This does not solve full rclone stalls where no loop iterations occur.
- WinCatalog CSV/XML paths are normalized from `\` to `/` during catalog load.