feature/library-handoff-and-gc #69
31
CLAUDE.md
31
CLAUDE.md
@@ -270,6 +270,37 @@ without disappearance flips through pass 1 (lib-A row retired) and
|
||||
pass 2 (back-refs follow), with pass 3 noting nothing because the
|
||||
hash is still present in `image_exif` (lib-B's row).
|
||||
|
||||
**Known gap: in-place content changes (future Branch D).** The
|
||||
maintenance pipeline assumes a `(library_id, rel_path)`'s bytes are
|
||||
stable for as long as the file exists at that path. If a user edits
|
||||
a file in place (crop, re-export) without renaming, the watcher's
|
||||
quick scan walks the file (mtime is recent) but `process_new_files`
|
||||
short-circuits because `(library_id, rel_path)` already has an
|
||||
`image_exif` row — no re-hash, no re-EXIF, no face redetection. The
|
||||
row's `content_hash` keeps pointing at the original bytes. Tags /
|
||||
faces / insights stay attached to the original hash and continue to
|
||||
display because the rel_path back-ref still resolves; new faces
|
||||
introduced by the edit are never detected.
|
||||
|
||||
The right place to fix this is a **stale-content detection pass**
|
||||
that compares `image_exif.last_modified` / `size_bytes` to
|
||||
`fs::metadata` for rows the quick scan would otherwise skip. On
|
||||
mismatch, recompute the hash, update `image_exif`, and apply the
|
||||
"content branched" semantics:
|
||||
- **Faces** re-run (faces are fully derived from bytes).
|
||||
- **Tags** migrate to the new hash (user intent — "this photo is
|
||||
vacation" survives a crop). Insights migrate forward as a
|
||||
starting point and are flagged for re-generation.
|
||||
- **Favorites** (when migrated to hash-keyed) follow the path /
|
||||
user intent.
|
||||
|
||||
The interesting case is the operator who keeps an unedited copy in
|
||||
the archive library and edits the local copy: post-detection, the
|
||||
archive copy stays on the original hash, the local copy branches to
|
||||
the new hash, and the two histories cleanly split. Apollo's
|
||||
`derived.db` cache will need an invalidation hook for the changed
|
||||
hash — design it alongside Branch D.
|
||||
|
||||
### File Processing Pipeline
|
||||
|
||||
**Thumbnail Generation:**
|
||||
|
||||
Reference in New Issue
Block a user