v1.10.1 "Argentique"
The panorama feature, reviewed
1.10.0 shipped panorama detection. This is what a full review of it found — eight defects that the test suite, the linter and the type checker all passed over, and the duplication that let several of them happen. The detector's geometry held up; everything here was in the wiring around it.
Two of them were the kind that only show up at scale or at a seam. A sweep immediately followed by another shared its boundary frame between both sets, and the later one won the write — so the earlier set quietly served one frame fewer than it had found. And confirming a panorama that reached you through the burst feed recorded exactly the comparison pairs this feature exists to suppress: a sweep arrives shredded across several burst groups, such a group is typed burst, and the confirm branched on that type rather than on what the frames actually were.
Changed
- A scan no longer pays a whole-library panorama pass. Detection ran over every candidate run on every scan,
--recompute-averageand--recompute-burst, holding the library lock throughout — measured at about seven minutes on a 126k-photo library — and--watchpaid it again per settled batch, so importing ten photos cost the same as importing the library. Coverage is unchanged: every run is still resolved and every label still rewritten, but only runs holding a photo scanned since the last pass are re-measured, the rest read back from their stored labels. Editing any threshold invalidates that watermark, and--detect-panoramasstill measures everything — that is what the command is for. - The
sequence_overridegallery filter no longer scans the library. It was a correlatedEXISTS, so SQLite walked all 126k photos probing a table a handful of rows long: 195 ms per page against 0 ms for the uncorrelated form it is now.
Fixed
- A "correction pending" badge now stops saying pending. The badge, the culling chip and the re-run banner keyed on the mere existence of an override row — but a correction is stored for as long as it applies, so they never cleared, and the only way to silence them was to delete the correction they were describing. The detector now stamps each override when it acts on it.
- Two panoramas shot back to back no longer share a frame. Where one sweep ended and the next began, the boundary frame was emitted in both sets and the second won the write.
- Confirming a panorama served through the burst feed no longer teaches the ranker anything. The keep-whole kind is read from the labels now rather than taken from the request, which also means a client cannot ask for the no-pairs treatment for a set that is not one. A set reached through its own granularity still routes on its declared kind, and is still marked reviewed through whichever feed it came by.
- Undoing a re-labelled panorama restores the correction it replaced instead of deleting it, which had left the detector free to re-apply the misread you had already fixed.
- Auto-cull is no longer offered where it cannot work. In the panorama, HDR and bracket views the button sent a scope the server rejects and failed with a bare error; keeping one frame per set is meaningless for sets that are kept whole.
--detect-panoramasreports its own failure rather than exiting 0 on a crash. The containment was written for a scan tail, where a failed labelling step should not abort work that succeeded — but it also covered the command whose entire purpose is that pass.
Internal
The detector's eighteen settings were enumerated in four places with nothing keeping them in step, and had already drifted — the client's own interface was a key short, so any request built from its type rather than echoed back from the server would have been rejected. Names and types now come from one table, bounds from another beside it, the request body is derived, and an import-time check fails the pair rather than a user's save. The panorama icons were hardcoded at four sites against a map whose docstring claimed a single source, drift an earlier commit had already had to repair once.
Upgrade notes
- A column is added to
photo_sequence_overrides(applied_at), automatically, on the next start. Existing corrections carry no stamp, so they read as pending until a detection run applies them — run--detect-panoramasonce (or the viewer's re-run action) to settle them. - The first pass after upgrading measures the whole library, since the incremental watermark starts empty. Later scans are the cheap ones.
- Nothing else to run; no config changes.
Still unverified
The seven-minute figure is an extrapolation from two independent samples of a 126k library (150 and 200 candidate runs), not a timed full pass — "minutes, not seconds" is solid, the exact number is not. The applied_at stamping and the schema migration were verified against synthetic and existing-schema databases rather than a production library.
Full changelog: https://github.com/ncoevoet/facet/blob/master/CHANGELOG.md