chore(dedupe): collapse low-risk redundancies from code review#244
Merged
Conversation
Backend: * drop the duplicate `/filetree/home` endpoint from `routers/album.py`; `routers/filetree.py` already serves the canonical one (whichever router was included last had been winning) * extract `_compute_curation()` and `_validate_curation_request()` — `/curate` (async background task) and `/curate_sync` were carrying ~150 lines of identical Monte Carlo / mapping / selection logic. The async path passes a small `on_iteration` callback to drive its ProgressTracker * route the three index endpoints (`delete_image`, `move_images`, `copy_images`) through the existing `get_embeddings_for_album` helper instead of each re-instantiating `Embeddings` directly * add `_l2_normalize(x, axis, eps=1e-12)` to `embeddings.py` and use it in all three numpy-normalize sites — also closes the no-epsilon NaN risk in `find_duplicate_clusters` * add `_normalized_filtered_embeddings()` shared loader for FPS / KMeans (npz open + valid mask + normalize); each function is now ~15 lines shorter and the "load" half is provably identical Frontend: * delete the duplicate `createPathField` in `album-manager.js` (defined twice with identical bodies — the second shadowed the first) * share the exported `scoreDisplay` singleton in `seek-slider.js` instead of constructing a second `ScoreDisplay`. The duplicate instance was double-binding the star click handler on `#scoreText`, so a bookmark toggle fired twice and immediately cancelled itself Net: +172 / −263 across 6 files. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Low-risk batch of redundancy fixes from the code review. Net +172 / −263 across 6 files.
Backend:
/filetree/homeendpoint fromrouters/album.py—routers/filetree.pyalready serves the canonical one. Whichever router was included last had been silently winning._compute_curation()and_validate_curation_request()./curate(async via background task) and/curate_syncwere carrying ~150 lines of identical Monte Carlo / mapping / selection logic. The async path passes a tinyon_iterationcallback to drive itsProgressTracker.delete_image,move_images,copy_imagesinrouters/index.pythrough the existingget_embeddings_for_albumhelper instead of three near-identical inlineEmbeddings(embeddings_path=..., encoder_spec=...)constructions._l2_normalize(x, axis, eps=1e-12)inembeddings.pyand used it at all three numpy-normalize sites — also fixes the no-epsilon NaN risk infind_duplicate_clustersthat the review flagged._normalized_filtered_embeddings()shared loader for FPS / KMeans.get_fps_indices_globalandget_kmeans_indices_globalshared a ~30-line "open npz / build valid_mask / normalize" preamble — that part is now in one place.Frontend:
createPathFieldinalbum-manager.js(defined twice, byte-for-byte identical — the second shadowed the first).new ScoreDisplay()inseek-slider.jswith the exportedscoreDisplaysingleton fromscore-display.js. The second instance was double-binding the star click handler on#scoreText, so bookmark toggles fired twice and immediately cancelled themselves.Deferred to follow-up PRs
The bigger structural items from the review (FastAPI
Depends()forvalidate_album_exists/get_embeddings_for_album/check_album_lock,state.jssetter generator,fetchJson()helper,makeDraggable()extraction, encoder base-classclose(),update_index/update_index_asyncunification,InvokeMetadataViewstrategy class) are intentionally left out of this batch — each is its own reviewable change.Test plan
ruff check photomap tests— cleannpm run lint+npm run format:check— cleanpytest tests/backend— 257 passed (same count as before)npm test— 288 passed across 18 suites/curate(async) and/curate_syncboth return identical-shaped responses for the same request🤖 Generated with Claude Code