m038 1a6afe86fc fix(review): operator-agnostic sanity check + invariant TODOs + dedupe
Code-review follow-ups on the pgvector spike:
- self-similarity sanity check now compares to the seed's own self-distance
  (0 for cosine/L2, ~-1 for inner product <#>) instead of a hardcoded ~0, so it
  no longer misfires if Immich ever uses a vector_ip_ops index (correctness P3).
- mark the deliberate raw-SQLite read in the probe as a spike-only exception and
  add an M1.5 TODO that the real pgvector reader belongs in shared/photoflow/immich
  and SQLite access in shared/photoflow/core (project-standards P2 x2).
- document join_and_coverage's return shape; extract a _pct() helper to dedupe the
  coverage-percentage formatting (maintainability P3 x2).
Findings doc refreshed from the latest live run (coverage now ~46%, re-run ongoing).
2026-06-27 20:50:06 +02:00

immich-photo-flow

A monorepo of small tools that clean up and structure a large Immich library into travel "memories". M1 ships the shared foundation (shared/photoflow/{immich,core,ui}) and the trip-cluster app.

Layout

  • shared/photoflow/immich — the one Immich REST client + _pipeline/ tag conventions.
  • shared/photoflow/core — SQLite store + domain models (the only SQL).
  • shared/photoflow/ui — base template, DaisyUI/Tailwind/Alpine/HTMX, shared grid+lightbox.
  • apps/trip-cluster — CLI + Flask review UI (port 8084).

Dev setup

python3.12 -m venv .venv
.venv/bin/pip install -e ./shared -e ./apps/trip-cluster \
    pytest==8.3.4 pytest-httpserver==1.1.0 pytest-playwright==0.6.2
.venv/bin/python -m pytest                 # unit + route tests
.venv/bin/python -m playwright install chromium
.venv/bin/python -m pytest apps/trip-cluster/tests/ui   # Playwright UI

trip-cluster workflow

cp .env.example .env       # fill IMMICH_URL + IMMICH_API_KEY
cd apps/trip-cluster
python categorize.py ingest --tag "Italy 2019"     # or --from/--to/--subset
python categorize.py cluster
python categorize.py serve                          # review at http://localhost:8084
python categorize.py apply                          # write approved tags back (asks to confirm)

Immich is the source of truth; SQLite is a rebuildable working layer. Content/trip tags are never namespaced; pipeline meta-tags live under _pipeline/.

S
Description
End to end photo flow tool chain
Readme
233 KiB
Languages
Python 87%
JavaScript 6.6%
HTML 6.2%
Dockerfile 0.2%