fix: Resolve SAFETY BLOCK for files in library root (#201)#202
fix: Resolve SAFETY BLOCK for files in library root (#201)#202deucebucket merged 3 commits intodevelopfrom
Conversation
…r library root files Windows mapped drives (e.g. R:\) resolve to UNC paths (\\server\share) but library path comparisons in the processing layers used raw config paths without .resolve(), causing the match to fail. The fallback then used parent.parent which went above the library root for loose files. Fixed all 4 locations to resolve both sides before comparison, and added smart fallback that checks if the path is a file before deciding depth.
There was a problem hiding this comment.
🔍 Vibe Check Review
Context
Fixes SAFETY BLOCK error when processing audiobook files placed directly in a library root directory on Windows, where mapped drives resolve to UNC paths causing relative_to() mismatches.
Codebase Patterns I Verified
- Library matching pattern: 4 locations in
app.py,layer_ai_queue.py,layer_audio_credits.pyiteratelibrary_pathswithrelative_to()— all 4 are fixed in this PR - Fifth location missed:
library_manager/pipeline/layer_content.py:116-125has the identical unfixed pattern — no.resolve(), and usesparent.parentfallback build_new_path()inpath_safety.py:688-694already resolves bothresult_pathandlib_pathinternally, so passing a pre-resolvedlib_pathfrom the fix is safeis_file()fallback logic is correct: loose files in library root need.parent(1 level), directories need.parent.parent(2 levels)
✅ Good
- Fix is correct and well-targeted —
.resolve()on both sides ofrelative_to()is exactly right for the Windows mapped drive → UNC path mismatch - The
is_file()guard for the fallback is a clean way to handle loose files vs Author/Title directories - Applied consistently across all 4 changed locations
- CHANGELOG entry is thorough and explains the root cause clearly
- Version bump is consistent across
app.py,README.md, andCHANGELOG.md
🚨 Issues Found
| Severity | Location | Exact Code Quote | Issue | Fix |
|---|---|---|---|---|
| HIGH | layer_content.py:118 |
book_path.relative_to(Path(lp)) |
Same unresolved relative_to() bug exists here — no .resolve() on either side. Will trigger the same SAFETY BLOCK on Windows mapped drives. |
Add .resolve() to both book_path and Path(lp) matching the pattern in the other 4 locations |
| HIGH | layer_content.py:125 |
lib_path = book_path.parent.parent |
Same parent.parent fallback bug for loose files exists here — unfixed. |
Add the same is_file() guard: if book_path.is_file(): lib_path = book_path.parent else: lib_path = book_path.parent.parent |
📋 Scope Verification
| Issue | Problem | Addressed? | Notes |
|---|---|---|---|
| #201 | SAFETY BLOCK error for files in library root on Windows mapped drives | Fixed in 4 of 5 locations — layer_content.py has the identical bug unfixed |
Scope Status: SCOPE_PARTIAL
📝 Documentation Check
- CHANGELOG.md: ✅ Updated — thorough entry explaining root cause
- README.md: ✅ Version badge updated
🎯 Verdict
REQUEST_CHANGES
The fix is correct everywhere it's applied, but library_manager/pipeline/layer_content.py:116-125 has the exact same bug (unresolved relative_to() + parent.parent fallback) and was not included. Apply the same two changes there to complete the fix across all code paths.
Missed 5th location with identical unresolved relative_to() and parent.parent fallback — caught by vibe-check review.
There was a problem hiding this comment.
🔍 Vibe Check Review
Context
Fixes SAFETY BLOCK errors when processing loose audio files sitting directly in a library root (e.g. R:\book.mp3) by adding .resolve() to path comparisons (fixing Windows mapped drive vs UNC mismatch) and replacing blind parent.parent fallback with an is_file() check.
Codebase Patterns I Verified
- Path resolution:
build_new_path()inpath_safety.py:690-691already resolves bothresult_pathandlib_pathfor its safety check — the PR's caller-side.resolve()is consistent with this - Library path matching: The
for lp in config.get('library_paths', [])+relative_to()pattern is used in 5 locations; PR fixes all of them - Watch folder handling:
layer_ai_queue.py:467-468already uses.resolve()for watch folder matching — the PR brings library path matching to the same standard - Fallback pattern: All 5 locations had the same
parent.parentfallback; all 5 are updated consistently
✅ Good
- Fix applied consistently across all 5 locations where the pattern exists (app.py x2, layer_ai_queue.py, layer_audio_credits.py, layer_content.py)
- The
is_file()fallback logic is correct: loose files in root need.parent(one level), directories in Author/Title structure need.parent.parent(two levels) - Non-existent paths fall through to
parent.parent(same as before), so no regression for edge cases - CHANGELOG entry is thorough and explains the root cause clearly
- Version bump consistent across app.py, README.md, and CHANGELOG.md
🚨 Issues Found
No issues found.
📋 Scope Verification
| Issue | Problem | Addressed? | Notes |
|---|---|---|---|
| #201 | SAFETY BLOCK error for files in library root on Windows (mapped drive → UNC mismatch + parent.parent going above root) |
✅ | Both root causes fixed: .resolve() for path comparison and is_file() guard for fallback |
Scope Status: SCOPE_OK
📝 Documentation Check
- CHANGELOG.md: ✅ Updated with detailed explanation
- README.md: ✅ Version badge updated
🎯 Verdict
APPROVE — Clean, focused bug fix. Both root causes identified in #201 are addressed consistently across all affected code paths.
🤖 Ruthless review by vibe-check
Summary
R:\) resolve to UNC paths (\\server\share) but config paths were compared without.resolve(), causing library matching to failparent.parent), which went above the library root for loose files sitting directly in a librarylayer_ai_queue.py,layer_audio_credits.py, andapp.pyTest plan
Closes #201