Repository navigation
feat(storage): add the motion score column (M1, schema v19) - #443
Merged
Merged
Conversation
Groundwork for the last Milestone 15 facet. This package only adds the column and threads it through the read and write paths; nothing computes a score yet, so every existing row reads back as NULL. Mirrors the aesthetic_score precedent rather than living in the metadata JSON: the motion score is a derived measurement, not a value the video container holds, and a real column keeps the future facet predicate on an index instead of json_extract. The upsert uses coalesce(excluded.motion_score, files.motion_score) for the same reason the other derived fields do -- a rescan re-reads container metadata and passes no score, which must not wipe a measurement that has already been written. The seven SELECT lists that feed map_row gain the column in the same position it appears in the row mapper, and the two total_count readers shift from index 13 to 14. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The migration exporter writes a self-contained DDL + data bundle for the collaboration backends. Its files table is built column by column, so a column that exists locally but not in the export would be silently dropped on a real migration run. Adds motion_score to both dialects' DDL, the row reader and the batched INSERT. The value is written verbatim so a measured score survives the cross-database move, and an unmeasured clip exports as NULL rather than 0 -- the same distinction the local schema makes. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5 <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.
First of the four packages in docs/MOTION_SCORE_DESIGN.md. This one is schema and plumbing only — nothing computes a score yet, so every existing row reads back as
NULL.What landed
v19 migration — a nullable
files.motion_score REALwithidx_files_motion_score. Appended toMIGRATIONS; the eighteen applied entries are untouched andLATEST_VERSIONfollows the array length to 19.Domain and TS mirror —
ImageFile.motion_score: Option<f64>with#[serde(default)]so older payloads still deserialize, and the matching optional field insrc/types.ts.Read/write paths — both upsert variants carry the column,
map_rowreads it at index 9 (shiftingis_favorite,is_nsfw,stack_id,stack_order), the sevenSELECTlists that feedmap_rowinsert it in the same position, and the twototal_countreaders move from index 13 to 14.Upsert preservation —
coalesce(excluded.motion_score, files.motion_score). A rescan re-reads container metadata and passes no score, so without this a scan would silently wipe a measurement.Migration export —
motion_scoreadded to both MySQL and PostgreSQL DDL, the row reader, and the batchedINSERT. The exporter builds itsfilestable column by column, so a column missing here would be dropped on a real cross-database migration.Why a column and not metadata JSON
The score is a derived measurement, not something the video container holds. Putting it in
metadatawould mix values the scanner writes with values the media writes, and it would force the future facet ontojson_extractinstead of an index.Tests
Three new regressions:
v19_adds_a_nullable_indexed_motion_score— the column is nullable, the index exists, and an unmeasured row readsNULLrather than0.upsert_preserves_an_existing_motion_score— writes 42.5, rescans withNoneand a changed size, asserts the size updated but the score survived.motion_score_exports_in_both_dialects— both DDLs carry the column, the measured value is written verbatim, and an unmeasured clip exports asNULL.Existing coverage also holds: 49
ImageFileliterals across the workspace gained the field, and the full suite passes.Verification
cargo test --workspace— all green (101 storage tests, including the three new ones).cargo clippy --workspace --all-targets -- -D warnings— clean.cargo fmt --all -- --check— clean.cargo doc -p omera-domain --no-deps— no broken-link warnings.pnpm run test:stack— 356 passed, 0 failed, 2 skipped.node scripts/generate-ipc-reference.mjs --check— 169 signatures verified (no IPC changes in this package).node scripts/generate-release-notes.mjs --check— passes.M2 (the scoring engine) and M4 (the facet and UI) can now proceed in parallel; M3 needs this package first.
🤖 Generated with Claude Code