two issues:
1. slskd search gave up at 22s (then stopped the search), but slskd gathers peers
over its full ~60s window — so most movie searches were killed before results
arrived. now waits up to 55s but returns early once results SETTLE (12+ hits, or
no new hits for ~12s) so fast searches don't burn the whole window. matches the
music side's longer wait.
2. the automations page re-rendered the WHOLE system section every 8s poll
(replaceChild) → blink + wiped the socket's live progress. now it skips the
rebuild unless something structural changed (added/removed/toggled/ran); live
progress comes via socket, the countdown ticks locally.
the API returns system automations newest-created-first, so a re-seeded row
(e.g. the just-migrated movie/episode processors) jumps to the top and jumbles
the grouping. the video page now re-sorts its System list by an explicit order:
scans (fill) → processors (drain) → library scan/sync → maintenance. scoped to
the video page only (music ordering untouched); unknown/future actions fall to
the end keeping API order. string-contract test pins the scan<proc<maint order.
The video automations page had no way to CREATE automations and its card cog did
nothing — it called the music global showAutomationBuilder(), which swaps views
inside the (hidden-on-video) music page, so the builder 'opened' on the music tab
instead. Now the video side has its own builder.
- index.html: the video automations subpage gets its own list-view + builder-view
(vauto- prefixed ids) and a '+ New Automation' button, swapping exactly like the
music page. Save/Cancel/Back reuse the shared builder functions.
- stats-automations.js: the builder is now context-aware. A builder context holds
the element ids + blocks endpoint + owned_by + reload callback. Music context is
the default and byte-identical (all 17 id lookups go through _bEl() resolving the
music ids). showVideoAutomationBuilder() sets a video context (vauto- ids,
/api/video/automations/blocks, owned_by='video'); editAutomation() routes the
card cog to the right builder by active side. Opening clears BOTH builders'
canvases so cfg-* ids can't collide. Save tags owned_by from context and calls
the context's reload. A generic config_fields renderer/reader (video-gated so
music keeps its bespoke renderers) drives video block config like the mode select.
- video-automations.js: exposes window._reloadVideoAutomations so a save refreshes
the video list.
11 wiring tests (test_video_automations_builder.py); node --check clean; music
builder path unchanged.
Per Boulder — the music system automations target music resources and don't belong on
the video side. The page now filters to owned_by='video' (a tag the upcoming video
automations will carry); none exist yet, so the System section is hidden and the empty
state reads 'Video automations coming soon — separate from the music ones'. The hub +
layout stay (video hub content + video automations come next). Balance clean.
The Automation Hub's Pipelines / Singles / Quick Start / Tips panes are music content
(playlist pipelines, music recipes/guides). The video side will get its own content
there; for now those four panes are emptied to a 'Video … coming soon' placeholder
(scoped to the detached hub element, no id clash). Reference stays — it's generic
automation reference. Hub tabs + structure otherwise unchanged. Balance clean.
Stopped hand-rolling the cards/section and now call the music page's GLOBAL builders
(_buildAutomationSection / renderAutomationCard / _buildAutomationHub from
stats-automations.js) — so the System section, every automation card, AND the
Automation Hub (Pipelines/Singles/Quick Start/Tips/Reference tabs) render byte-for-byte
identical to the music page. The System section uses a unique id (no clash) and is the
only thing re-rendered on refresh; the hub is built once (static). Run/toggle go through
the reused music card handlers; we re-sync the section after. Balance clean.
Was a bespoke .vauto- header; now mirrors the music automations page structure 1:1 —
.page-shell.automations-container > .dashboard-header (sweep + automation.png icon +
header-title/subtitle) > .automations-stats ('N Active · N System') > .automations-list
holding the protected '.automations-section.section-protected' System group (chevron +
label + count + collapse, persisted) with the same .automation-card rows. Reuses every
music class; driven by video JS via data-vauto-* hooks (no #id clash). Removed the dead
.vauto-* CSS. Balance clean.
Adds an Automations nav entry + page to the video side. The automation engine is
app-wide, so this surfaces the SAME system automations the music side runs — filtered
to is_system, EXCLUDING Refresh Beatport Cache and any user/playlist-pipeline ones.
Reads the shared /api/automations (no music imports), reuses the music .automation-*
card look, and supports run-now + enable toggle (system automations aren't editable).
Polls every 5s while the page is open. Frontend-only; balance clean.
Next: the library-refresh/scan automation wiring (Boulder has questions on how server
scanning works first).