Operator-flagged fixes and a DRY refactor. CI green (run #750, 408fcd4). No schema change (alembic head stays 0042).
Fixes
fix(cleanup) — fandoms no longer flagged "unused" (fb05c5e).find_unused_tags only checked image_tag + series_page references, so every fandom (never applied to an image — a character carries it via fandom_id) looked unused, and the FK is ondelete=SET NULL, so deleting one would strip the fandom off all its characters. Now excludes tags referenced as a character's fandom_id and tags referenced by a series_chapter (all-placeholder series). Genuinely orphaned fandoms still sweep.
Observability + tuning (video ML)
obs(ml) — tag_and_embed logging (b1778ca). The task logged nothing and SoftTimeLimitExceeded stringifies to empty, so a timeout gave zero clue which file or why. Now logs start (id/path/mime/bytes/video?), per-phase timing, and re-raises a timeout WITH context so the activity names the file + phase. Other errors are logged then re-raised unchanged (preserves autoretry).
tweak(ml) — video frame samples 10→6 (f2fbe2a). Fewer frames into the max-pool = less noisy video tags + smaller sampling budget. Deeper quality/perf review tracked in Scribe #747.
DRY
refactor(ui) — unified confirm-dropdown Enter (408fcd4). New useAcceptOnEnter composable: Enter on an open menu picks; Enter on a closed menu triggers the modal's primary action instead of re-opening the dropdown. Applied to the tag-merge picker (the reported one), alias picker, post→add-to-series, and the two fandom dialogs (refactored off their copy-pasted handlers). One behavior, one place.
Operator-flagged fixes and a DRY refactor. CI green (run #750, `408fcd4`). No schema change (alembic head stays 0042).
## Fixes
- **`fix(cleanup)` — fandoms no longer flagged "unused" (`fb05c5e`).** `find_unused_tags` only checked image_tag + series_page references, so every fandom (never applied to an image — a character carries it via `fandom_id`) looked unused, and the FK is `ondelete=SET NULL`, so deleting one would strip the fandom off all its characters. Now excludes tags referenced as a character's `fandom_id` and tags referenced by a `series_chapter` (all-placeholder series). Genuinely orphaned fandoms still sweep.
## Observability + tuning (video ML)
- **`obs(ml)` — `tag_and_embed` logging (`b1778ca`).** The task logged nothing and `SoftTimeLimitExceeded` stringifies to empty, so a timeout gave zero clue which file or why. Now logs start (id/path/mime/bytes/video?), per-phase timing, and re-raises a timeout WITH context so the activity names the file + phase. Other errors are logged then re-raised unchanged (preserves autoretry).
- **`tweak(ml)` — video frame samples 10→6 (`f2fbe2a`).** Fewer frames into the max-pool = less noisy video tags + smaller sampling budget. Deeper quality/perf review tracked in Scribe #747.
## DRY
- **`refactor(ui)` — unified confirm-dropdown Enter (`408fcd4`).** New `useAcceptOnEnter` composable: Enter on an open menu picks; Enter on a closed menu triggers the modal's primary action instead of re-opening the dropdown. Applied to the tag-merge picker (the reported one), alias picker, post→add-to-series, and the two fandom dialogs (refactored off their copy-pasted handlers). One behavior, one place.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
find_unused_tags only excluded tags with image_tag or series_page references, so
it flagged every fandom as 'unused' — fandoms are NEVER applied to images (a
character carries its fandom via tag.fandom_id), and the FK is ondelete=SET NULL,
so deleting one silently strips the fandom off all its characters
(operator-flagged 2026-06-08: artist-OC fandoms showing as unused).
Exclude tags referenced as a character's fandom_id, and (same class of gap) tags
referenced by a series_chapter (an all-placeholder series has chapters but no
pages yet). A genuinely orphaned fandom with no characters is still swept.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The task logged nothing and SoftTimeLimitExceeded stringifies to empty, so a
timeout surfaced as a bare 'SoftTimeLimitExceeded()' with no clue which file or
why (operator-flagged 2026-06-08).
- Log start (id/path/mime/bytes/video?), per-phase timing (load_models, video
probe/sample/infer, tag, embed, persist), and a success summary.
- Track a + file ; on SoftTimeLimitExceeded log it and re-raise
SoftTimeLimitExceeded WITH that context (keeps the 'timeout' task_run status
but gives the activity a real error_message: which file, which phase, elapsed).
- On other exceptions, log context then re-raise the ORIGINAL (preserves
autoretry for OSError/DBAPIError/OperationalError).
Now a stuck run names the culprit — most likely a slow video (frame sampling is
up to 10x60s ffmpeg) or a huge image; the phase log will say which.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Operator: 10-frame max-pooled tagging on video produces a lot of noisy tags, and
the sampling burns time/GPU. Drop the VIDEO_ML_FRAMES default to 6 (still env-
overridable). Fewer frames = less per-frame noise into the max-pool and a smaller
frame-sampling budget. Quality/perf of the whole video path is being reviewed
separately.
Operator-flagged (again) on the tag-merge picker: Enter on the dropdown re-opens
it instead of accepting the selection. I'd already patched this twice (fandom
picker + fandom set dialog) with copy-pasted capture-phase handlers, so DRY it.
New composable useAcceptOnEnter(accept): tracks the menu state and, on a
capture-phase Enter, lets Vuetify pick when the menu is open but calls accept()
(and blocks the re-open) when it's closed. Applied to every confirm-style picker:
- TagsView merge-into picker (the reported one)
- AliasPickerDialog
- PostSeriesMenu add-to-existing
- FandomPicker + FandomSetDialog (refactored off their bespoke handlers)
One behavior, one place to change it.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Operator-flagged fixes and a DRY refactor. CI green (run #750,
408fcd4). No schema change (alembic head stays 0042).Fixes
fix(cleanup)— fandoms no longer flagged "unused" (fb05c5e).find_unused_tagsonly checked image_tag + series_page references, so every fandom (never applied to an image — a character carries it viafandom_id) looked unused, and the FK isondelete=SET NULL, so deleting one would strip the fandom off all its characters. Now excludes tags referenced as a character'sfandom_idand tags referenced by aseries_chapter(all-placeholder series). Genuinely orphaned fandoms still sweep.Observability + tuning (video ML)
obs(ml)—tag_and_embedlogging (b1778ca). The task logged nothing andSoftTimeLimitExceededstringifies to empty, so a timeout gave zero clue which file or why. Now logs start (id/path/mime/bytes/video?), per-phase timing, and re-raises a timeout WITH context so the activity names the file + phase. Other errors are logged then re-raised unchanged (preserves autoretry).tweak(ml)— video frame samples 10→6 (f2fbe2a). Fewer frames into the max-pool = less noisy video tags + smaller sampling budget. Deeper quality/perf review tracked in Scribe #747.DRY
refactor(ui)— unified confirm-dropdown Enter (408fcd4). NewuseAcceptOnEntercomposable: Enter on an open menu picks; Enter on a closed menu triggers the modal's primary action instead of re-opening the dropdown. Applied to the tag-merge picker (the reported one), alias picker, post→add-to-series, and the two fandom dialogs (refactored off their copy-pasted handlers). One behavior, one place.🤖 Generated with Claude Code