- A version no longer hides behind an original that duplicates resolve
demoted (visible_version_clause, hidden_version_rows).
- Recording a link drops the version's faces, CLIP data and clip failures
(covers link-at-ingest and link_versions --apply).
- The display file must live in the original's library; otherwise the
original shows, and PUT /image/versions/display answers 400.
- link_new_files looks up hashes in chunks of 500 and logs errors.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
XMP (PNG iTXt DerivedFrom, native chunk reader) then file-name convention
links at ingest; unlinked name candidates are retried each tick. Versions
are hidden from /photos (SQL for the recursive listing, hidden-row set for
the walk and tag branches), /memories, reels, /photos/exif, the GPS summary,
unified search and the media gauges while their original is reachable in the
view; include_versions=true lists them. /photos gains the parallel arrays
photo_display_paths / photo_version_counts, memories / search hits /
/photos/exif rows gain display_path / version_count, all skipped when empty.
GET /image/versions and PUT /image/versions/display (library optional).
Tags and favorites on a version path bind to the original; faces, CLIP and
duplicate grouping skip version hashes; insight generation redirects to the
original. Orphan GC and the back-ref refresh cover the new tables.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
photo_versions links a version's content_hash to its primary original's;
photo_version_references keeps provenance-only reference photos;
photo_version_display holds the global display choice. VersionDao covers
linking (chains flatten to the root), the display choice, per-original
summaries for /photos, the hidden-row set for non-SQL listings, and the
copy of the original's date/GPS/camera onto version rows. Also the SQL
predicate listings use to hide a version while its original is reachable.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>