Brazen Framework - Download Manager

Cross-tab download queue, resolution pipeline, and immediate downloads for Brazen user scripts

A continuación se muestran las versiones de este script en las que se actualizó el código. Ver todas las versiones.

  • v4.0.0 22/08/2026

    Breaking

    • Reactor dependency — apps must @require BrazenReactor before Download Manager; pipeline work, coordinator role, and cross-tab sync run through Reactor kernel, bus, and scheduler.
    • Monolith publish surface — split GF modules (BrazenDownloadPath, BrazenHumanInteraction, BrazenTagDiscovery, BrazenTagDiscoveryLogic, BrazenDownloadReactorBridge, BrazenDockPanelOwnership) removed; single Download Manager @require only.
    • Leadership APIisDownloadManagerLeaderTab() / requestDownloadManagerLeadership() / DOCK_DOWNLOAD_LEADER removed; use Framework isCoordinator() / requestCoordinatorRole() / DOCK_COORDINATOR.
    • Direct IDB writes — public mutations route through Reactor Commands (sendCommandkernelWriteThrough); followers must not write queue/state stores directly.
    • Cross-tab wake — legacy localStorage bridges (dm-processors-wake, dm-progress-ui-wake, selection mark mirror) removed; Reactor pipeline-pump Commands + dm.state.* patch stream only.

    Added

    • Reactor cause tracing hooks — follower applyPatches wrapped in patch:seq cause; dock paint marks dock-refresh-interface / dock-refresh-buttons with active cause.
    • Monolith consolidation (RD-13) — inlined path, human interaction, tag discovery funnel/panel, and Reactor job wiring as private/static DM methods; deleted six GF-shaped files; dock panel release uses Utilities.releaseDockPanelOwnership.
    • Reactor-native v2sendCommand, _commitCoordinatorDmState, _publishDmStateToAtoms / _reconcileBusPatches, readDmState(); all Command IDB writes in BrazenStorageRepositories.kernelWriteThrough.
    • Follower optimistic echoreactor.localEditsDirty atom + pending-command reconciliation until authoritative patch seq > sinceSeq; toggle-paused applies optimistic dm.state.paused.
    • DM UI signal effects_ensureDmUiEffects() registers dm.state.snapshot, pending queue count, currentMediaQueued, dock progress epoch, and tag-discovery refresh atoms; coalesced timer paints replace dirty-loop dock refresh.
    • Reactor pipeline jobs — resolution/download lanes on BrazenJobRegistry with coalesce, merge, and reassess gates; config.linkQueues maps to scheduler policy.
    • BrazenKernel coordinator wiring_ensureReactor() / _startReactor() boot kernel + bus + scheduler; coordinator runs lane dispatcher + short scheduler jobs; followers wake via debounced pipeline-pump Commands.
    • Unified coordinator APIisCoordinator() / requestCoordinatorRole({ steal, ifAvailable }); Web Locks replace IDB processingTabId heartbeat; sessionStorage coordinator-sticky preserves crown across same-tab reload.
    • Follower dock progress via patch stream — coordinator publishes dm.state.* progress patches; followers apply via _reconcileBusPatches and signal atoms.
    • Selection Mode Select All slide-outdock-selection-select-all on dock-selection-mode; selectAllVisibleItems() enqueues visible search tiles not already in the pipeline.
    • afterBootHydrate() — Framework hook after ruleset hydrate resyncs queue chrome when IDB was contended during init.

    Changed

    • Publish surface — Download Manager remains a single @require; no extra DM satellite scripts on Greasy Fork.
    • Command routing — coordinator bus Commands handled exclusively by BrazenKernel.handleCommand; pipeline-pump side effect via onCommandApplied.
    • enqueueDownload / dequeueDownload — build Command payloads and sendCommand; no follower queue IDB puts.
    • confirmTagDiscoveryMappings / skipTagDiscoveryInclusion / toggleDownloadManagerPaused / clearDownloadQueue — route through Reactor Commands.
    • _requestPipelineRun — followers use sendCommand instead of direct bus publish.
    • Unified EventBus — reuses ConfigurationManager.getConfigBus() instead of a second EventBus.create.
    • config-ui local lane — registered on DM registry; Framework schedules per-tab _handleConfigurationChange via scheduleConfigUiReaction (replaces coordinator config-sync scheduler job for UI).
    • Phase 3 p3-cleanup (Reactor) — removed legacy cross-tab localStorage wake bridges (dm-processors-wake, dm-progress-ui-wake); followers rely on Reactor pipeline-pump Commands + dm.state.* patch stream only.
    • Processor interrupt_processorEpoch dropped; scheduler pump and _resolvePage honor BrazenKernel.abortSignal + _documentSuspended.
    • State/count mirrors_cachedState, _cachedDownloadCount, _cachedResolutionCount removed; dm.state.snapshot / pending-count atoms are the sync read path (_getStateSync()).
    • Selection marks — sessionStorage active-id mirror removed; optimistic _selectionUiPending + IDB reconcile only.
    • _commitDmStateMirror — fixed atom write (was accidentally self-recursive).
    • DM state/count mirrors_commitDmStateMirror, _commitPendingCountSignals, _setCurrentMediaQueued sync legacy caches to signal atoms; follower patch apply refreshes count signals before dock paint.
    • Ledger compliance refresh — removed DM calls to _scheduleLedgerComplianceRefresh (Framework ledger revision effect).
    • Removed parallel DM leadership — deleted _tryClaimProcessingLeadership, _forceClaimProcessingLeadership, _isProcessingOwnerAlive, heartbeat timers, and processingTabId / processingHeartbeatAt IDB writes; retired dock-download-leader from Start/Pause slide-out (coordinator crown lives on main dock rail via Framework).
    • Lane dispatcher_runLaneProcessor / _runInterleavedDispatcher replace legacy policy classes; _signalProcessorsWake delegates to _requestPipelineRun.
    • Consumer @require order — apps must load BrazenReactor.js before Download Manager (resource override / GF publish in a follow-up).

    Fixed

    • Discovery panel re-issue after Confirm_confirmDiscoveryPanelTagTypes no longer skips untypable tags; every reviewed tag is marked via ensureTag(..., {source: 'discovery-confirm'}) so isDiscovered is set even when no type can be promoted, allowing _reconcileDiscoveryGateFromPending to clear the gate instead of re-opening the same review.
    • Redundant discovery review re-open_beginDiscoveryReview deduplicates identical active reviews (itemId + mode + tag-name signature) when the panel is already visible; _clearDiscoveryReviewState clears _activeDiscoveryReviewSignature.
    • DM progression freeze (rAF paint stall)_scheduleCoalescedDockProgressPaint uses setTimeout(16) instead of requestAnimationFrame so dock paints still run on backgrounded tabs and between long lane/processor bursts. _requestDockProgressPaint calls the paint coalescer directly (drops the redundant dm.dockProgressEpoch rAF hop that plateaued during 10–25s resolution tasks).
    • Config-change discovery refresh stormonConfigurationChange only calls _requestTagDiscoveryPanelRefresh(null) when a discovery review is active (resolutionBlocked or open discoveryPanelTags), cutting dm.tagDiscoveryRefresh fan-out from unrelated config-ui passes.
    • Config-ui during tag-discovery confirmscheduleConfigUiReaction defers while _tagDiscoveryActionInFlight so panel confirm/skip does not interleave broad config-ui reactions with DM state mutations.
    • Discovery panel blocked by coordinator state tail_beginDiscoveryReview publishes the gate optimistically via _publishDmStateToAtoms and renders the panel immediately; IDB persist + kernel broadcast run async on _coordinatorStateTail. _showTagDiscoveryPanel reads readDmState() (not _getState()); _claimTagDiscoveryPanelOwnership and known-tag writes use the same optimistic-then-async pattern on the coordinator.
    • DM progression freeze (coordinator patch skip reverted) — removed coordinator-only early return on inbound bus patch messages; _reconcileBusPatches already no-ops on the coordinator and the skip had no churn benefit while risking patch-path regressions.
    • Pending-count paint amplifier_commitPendingCountSignals skips atom writes and epoch paint requests when download/resolution counts are unchanged.
    • Follower propagation after epoch decouple_reconcileBusPatches uses a gate signature (DM_STATE_GATE_PATCH_FIELDS) so snapshot-only / version-deduped batches still repaint dock progress and restore tag-discovery / HI panels on visible followers. _reconcileFollowerVisibleUiAfterPatches centralizes visible-tab paint, selection marks, and panel restore.
    • Redundant snapshot atom writes_publishDmStateToAtoms skips atom write and coalesced paint request when the new state is JSON-equal to the last published value (no-op mutations / duplicate per-item republishes).
    • Tag-discovery panel refresh storm_requestTagDiscoveryPanelRefresh coalesces _tagDiscoveryRefreshAtom bumps via _scheduleCoalescedTagDiscoveryRefreshBump (16ms setTimeout, not rAF — rAF pauses on backgrounded tabs), merging onlyTags filters across the tick.
    • Slow discovery panel on coordinator_applyTagDiscoveryOutcome partitions unknown tags and calls _beginDiscoveryReview before full _registerResolvedTagGroups; tag registration runs deferred (unawaited) after the panel is shown or the row is queued for deferred review, removing per-tag IDB registration from the panel appearance critical path.
    • Snapshot→dock effect fan-out (Loop A core)dmDockProgress effect depends only on dm.dockProgressEpoch (legacy disposer path; paint is now driven directly by _requestDockProgressPaint_scheduleCoalescedDockProgressPaint). _publishDmStateToAtoms and _commitPendingCountSignals request a coalesced timer paint so dock progress still updates. dm.state.snapshot remains the sync read mirror for readDmState() / patch dedup only.
    • Follower dock paint storm (Loop A)_scheduleCoalescedDockProgressPaint coalesces dock progress paints to one per 16ms timer so coordinator patch bursts no longer trigger one dmDockPaint + four IDB countActive reads per message. _reconcileBusPatches skips redundant _publishDmStateToAtoms when the batch already included dm.state.snapshot (applyPatches wrote it). _paintDockProgress reads pending counts from signal atoms (getPendingDownloadCountSync / getPendingResolutionCountSync) and tracks last-painted counts for slide-out transitions instead of blocking on IDB; drops follower-path _syncPendingCountSignalsFromIdb (pending-count patches already update atoms).
    • Coordinator crown reclaim on refresh — sessionStorage sticky flag (coordinator-sticky) marks the tab while it holds the Web Lock; preserved across same-tab reload (pagehide / _documentSuspended) and cleared only on live handoff (_onReactorCoordinatorLost when not suspended). After kernel.start(), a one-shot requestCoordinatorRole({steal:true}) reclaims immediately (replaces the old DM-only ~12s timeout).
    • Coordinator crown on refresh_onReactorCoordinatorAcquired / _onReactorCoordinatorLost call refreshDockButtonStates() synchronously (mirrors manual requestCoordinatorRole) so the crown repaints as soon as the Web Lock is held or released, not only after the deferred dock-progress chain.
    • Follower config-ui storm from command patches_maybeScheduleConfigUiFromPatches no longer treats kernel.lastCommand as config-touching; only real config.* revision patches schedule follower config-ui (dock/state already handled by _reconcileBusPatches).
    • Coordinator state reload race_reloadCachedStateQuiet chains read+publish onto _coordinatorStateTail so a stale IDB read cannot regress atoms after a newer _commitCoordinatorDmState write.
    • Stale selection progress paint_renderItemProgress uses a per-item paint generation counter (_itemProgressPaintGen) to drop async paints superseded by a newer pass for the same item.
    • Confirm-tag-discovery revision storm_confirmDiscoveryPanelTagTypes wraps bulk ensureTag calls in beginTagsRevisionBatch / endTagsRevisionBatch (one tags.revision bump per panel confirm).
    • Follower patch gate never opened — follower tabs now call _requestFollowerSnapshot() after Reactor bus subscribe (and on coordinator demotion / visibility resume). Applies coordinator snapshot-response via BrazenSignals.applyPatches + _reconcileBusPatches, opening the EventBus patch stream so live dm.state.* updates reach follower dock, selection marks, and tag-discovery panels without visiting the coordinator tab.
    • Snapshot↔dock paint loop_paintDockProgress reads cached readDmState() instead of _getState() so dock paint no longer republishes dm.state.snapshot (stops ~26k snapshot writes/10s self-fire during active downloads). Narrow signature dedupe on _publishDmStateToAtoms was removed — it suppressed non-signature state fields (discovery panel, selection progression) and caused stale UI.
    • Runtime pipeline explicit UI refreshsetRuntimePipelineChangeDelegate wires coalesced read-only _requestRuntimeUiRefresh (50ms debounce): tag-discovery chrome repaint, dock progress, selection marks, discovery tag types — replaces the incidental config-ui:all refresh removed by the runtime source cut without reintroducing heavy config reload.
    • Runtime pipeline config-ui escalationconfig-ui job merge retains pending source when incoming event is a runtime-pipeline store write (defense-in-depth alongside CM source cut).
    • Selection overlay reappears after deselect (multi-tab follower)_selectionUiHidden is sticky until re-select (_enqueueSelectionItem) or selection-mode exit (_clearAllItemProgress); blocks coordinator-led _renderItemProgress repaints after local deselect. DownloadCoordinatorRepository dequeue tombstone blocks resurrecting coordinator writes (claim / commit / requeue / promote) for 30s after dequeue; enqueueResolution clears on re-select.
    • Selection overlay (first click + reconcile races)_toggleSelectionItem routes silent IDB queue rows through _enqueueSelectionItem (optimistic paint before IDB); locally-selected heuristic includes visible data-bv-dm-progress overlay; capture-phase click dedupe (__bvDmSelectionHandled); _renderItemProgress keeps pending/Queued overlays on null reconcile; _refreshSelectionMarks reconciles paints only while selection mode is active; follower tabs debounce selection-mark refresh on queue-count patches.
    • Follower optimistic pending counts_optimisticPatchesForCommand / _applyFollowerCommandOptimistic call getPendingResolutionCountSync() / getPendingDownloadCountSync() (fixes TypeError: this.getPendingResolutionCount is not a function on selection enqueue).
    • Follower tag-discovery panel restore — visible followers schedule _restoreVisibleDockPanelsIfNeeded when coordinator gate patches arrive (DM_STATE_GATE_PATCH_FIELDS via _reconcileBusPatches, debounced; skips own tagDiscoveryPanelTabId claim echo); HI watchdog restores tag discovery whenever resolutionBlocked without requiring an active HI block.
    • Config→UI local laneconfig-ui job (scope: local, coalesce 'config-ui') runs _handleConfigurationChange per tab via scheduleConfigUiReaction; foreign tabs schedule after REACTOR_CONFIG_CHANGE sync and config revision patch apply (_maybeScheduleConfigUiFromPatches).
    • Tag discovery scoped refresh_discoveryPanelHasOpenTags includes Known/Similar sections; _refreshTagDiscoveryActionChrome rebuilds tag from row data-tag-name when cache miss.
    • Tag discovery shortcut refresh_refreshTagDiscoveryPanelUi repaints action chrome row-scoped via _refreshTagDiscoveryActionChrome (no groups.replaceChildren() on attribute toggles); fixed _discoveryOpenTagNamesContainsAny / _buildDiscoveryOpenTagNames private helper call sites; initial paint and _appendTagDiscoveryFrameworkActions delegate to Framework repaintTagAttributeActionRow.
    • Queue resume stall (IndependentPolicy) — restore DM lane dispatcher (_runLaneProcessor / _runInterleavedDispatcher); Reactor pipeline-pump is send-and-forget wake only; remove BrazenScheduler runUntilIdle batching of resolution + download heads that blocked unrelated lanes on persisted mixed backlogs; coordinator acquire requeues orphan resolving/downloading rows on load.
    • Boot visibility panel release_releaseTagDiscoveryPanelOwnership / _releaseHumanInteractionPanelOwnership skip dm.state commits until isCoordinator() (fixes follower cannot write downloadManagerState when visibilitychange fires during initialize() before the Web Lock is held).
    • Tag-discovery panel cross-tab restore — visible follower tabs claim panel ownership via claim-tag-discovery-panel / claim-hi-prompt Commands; remove erroneous coordinator-only restore gates; hidden coordinator leaves panel unowned and wakes peers so resolutionBlocked no longer appears stuck while downloads finish.
    • Follower tag-discovery restorerestoreTagDiscoveryPanelIfNeeded / _reconcileDiscoveryGateFromPending no longer call _commitCoordinatorDmState on followers (read-only show from cached discoveryPanelTags; gate reconcile stays coordinator-only).
    • Boot dock idle for secondsafterDockReady() awaits _syncPendingCountSignalsFromIdb() before first progress paint; _syncFromStorage() no longer fire-and-forgets count sync; new afterBootHydrate() resyncs after Framework ruleset hydrate; coordinator acquire repaints queue chrome.
    • Clear Download Queue dock layout — slide-out clear button stays mounted while the queue rail is open; disabled when the download queue is empty instead of unmounting (avoids Start/Pause slot remount and dock jump).
    • Bookmark / tag-discovery new-tab clicks_requestPipelineRun defers through coalesced _kickProcessorsIfReady; tag-discovery names render as native <a target="_blank">; bookmarks use native tab links by default; ensureDockSlidePanelInteractive clears stuck offscreen only when the panel is visibly on-screen.
    • Slow init idle dock (~30s) — Framework no longer runs hydrateBootFieldsFromStorage() in parallel with initialize(); DM init + afterDockReady() (queue progress paint + coordinator pump) complete before ruleset hydrate so IDB contention cannot block pending queue counts. _ensureDmUiEffects() runs before the first _syncFromStorage() so signal-backed dock paint is wired on boot. Terminal-row prune on boot remains coordinator-only via _onReactorCoordinatorAcquired (removed redundant pre-Reactor call from initialize()).
    • Init tag-discovery restore on coordinator tabafterDockReady() can run before the Web Lock is held; _restoreVisibleDockPanelsIfNeeded() / restoreTagDiscoveryPanelIfNeeded() now skip dm.state writes until isCoordinator() and run from _onReactorCoordinatorAcquired() once the dock is ready (fixes follower cannot write downloadManagerState during boot).
    • Init UI freeze / late dock orientation — coordinator scheduler pump deferred via requestIdleCallback after dock ready; pump breaks when IDB queue head is unchanged after a pass (reassess skip / claim noop); failed claims throw brazenSchedulerSkip (terminal skipped, not done). BrazenScheduler.runReady yields every 8 sync starts. Framework compliance signal effects no longer wire before UI embed.
    • Interleaved HI scheduler freeze_isResolutionPipelineBlocked / _isDownloadPipelineBlocked now honor _anyHumanInteraction when linkQueues is on, matching scheduler reassess; prevents enqueue→skip→re-enqueue busy loop after UI paint when one lane holds HI and the other queue still has rows.
    • Human-interaction init TypeError_restoreHumanInteractionPanelsIfNeeded and the HI watchdog called non-existent public method names after monolith consolidation; use _maybeExpireHumanInteractionBlocks / _restoreHumanInteractionPanelsIfNeeded.
    • _resetProgressCountersIfIdle — skip until Reactor holds the coordinator Web Lock; initialize() calls _syncFromStorage() before _startReactor(), so even the sole tab is not coordinator yet and must not write downloadManagerState during that early sync (counter reset runs in _onReactorCoordinatorAcquired once the lock is held).
    • RD-9a_signalProcessorsWakeAndRunIfCoordinator delegates to _requestPipelineRun() (was stack overflow); _joinTagsForDownloadPath via _ensureDownloadPath(); removed dead _tryBeginIgnoredPinReview.
    • Reactor Core remediation (R1/R-minor) — DM UI atoms use BrazenSignals.atom() on the shared graph; scheduler nextSeq decoupled from bus patch seq; _applyDmStatePatches enforces per-field version monotonicity; _dmUiEffectDisposers torn down on pagehide; _dmStateAtom seeded from fresh _getState().
    • Cloudflare cross-tab resume regression (3.0.0 visibility restore) — after hideLocal: false tab blur kept local panel DOM but released IDB ownership, restore could skip re-slide-in (isDockSlidePanelVisible) and orphan tagReview recovery was blocked by an early !resolutionBlocked return. _showTagDiscoveryPanel / _promptHumanInteractionResume now force-show; _restoreTagDiscoveryPanelIfNeeded hides stale DOM then runs orphan recovery; HI watchdog also restores tag discovery when gated. Hidden processor owners bypass debounced storage-wake setTimeout (background timer throttling) so Done — resume on a follower restarts the leader without a focus switch.
    • Tag discovery cross-tab dismiss (regression)_showTagDiscoveryPanel / _renderTagDiscoveryPanel re-read resolutionBlocked before paint/ownership steal so a slow restore/async partition cannot re-open stale local DOM after Confirm/Skip on another tab; gate-clear restore returns after orphan recovery instead of falling through.
    • Selection Queued→Waiting flicker during resolution tag scan_resolveItemPipelineView no longer maps discoveryLanePhaseActive alone to Waiting; queued tiles wait on a confirmed tag-review block (resolutionBlocked + another resolutionBlockedItemId). Block-sensitive labels use fresh IDB state; _renderItemProgress suppresses a stale Queued→Waiting downgrade.

    Removed

    • Split-module indirection_ensureDownloadPath, _ensureHumanInteractionUi, _ensureTagDiscoveryLogic, _ensureTagDiscoveryUi, and one-line delegates to extracted classes.
    • bindKernelBridge / bridge write-through stack — deleted at swap (S3).
    • Direct queue/state *.put in DM — repos-only policy (v2 §7).
    • _publishDmStateProgressPatches — direct coordinator bus patch publish deleted; _signalProgressUiWake delegates to kernel.
    • _withState — replaced by coordinator-only _commitCoordinatorDmState.
    • _scheduleTagDiscoveryPanelRefreshLegacy — timer fallback removed (Signals required).
    • SELECTION_MARK_MIRROR_*, _selectionMarkMirror* helpers, cross-tab storage wake receiver on DM.
    • isDownloadManagerLeaderTab() / requestDownloadManagerLeadership() — use isCoordinator() / requestCoordinatorRole() (also on Framework).
    • DOCK_DOWNLOAD_LEADER — replaced by Framework DOCK_COORDINATOR on the main dock rail.
  • v3.0.0 14/08/2026

    [3.0.0] — current

    Breaking

    • Immediate download removeddownloadImmediate(), in-page immediate queue, pendingImmediateDownload, onBeforeDownload, page role immediateDownload. Apps enqueue via selection / Add to queue only.

    Added

    • Deferred tag discovery — Behaviours flag defer-tag-discovery-unattended; resolution status discoveryQueued; discoveryLanePhaseActive; progress counts both lanes.
    • BRAZEN_DOWNLOAD_PATH_FIELD_KEYS, DownloadManager.storageKey(scriptPrefix, suffix), patternIncludesChip(pattern, chip), registerSelectionDragGuard().
    • Discovery tag-type auto-sync from pattern pins.

    Changed

    • Start in Selection Mode → Framework createBehavioursTabPanel.
    • HI soft-expiry on heartbeat (~3s).
    • Legacy state cleanup on hydrate (pendingImmediateDownload, orphan discovery gate).
    • Tag discovery attribute refresh — single hub via Framework refreshTagActionSurfaces.
    • Visibility restore without panel flash.

    Fixed

    • Ignored-pin review scope/join/refresh path.
    • Selection tile progress after complete (mirror/reconcile).
    • HI panel handlers ReferenceError.
    • Filename ignore → CM hasTagSoleAttribute.

    Removed

    • OPTION_ONLY_SHOW_DOWNLOAD_MANAGER.
  • v2.1.0 24/07/2026

    Added

    • Tag discovery isDiscovered gate — known-for-discovery uses TagEntry.isDiscovered === true (not merely typed). Confirm (discovery-confirm) marks discovered and promotes type when still unset; attribute toggles may set type for colors without clearing the gate.

    Changed

    • Tags config fan-outsource === 'tags' only schedules discovery chrome refresh (optionally filtered by detail.tags / open-panel membership); skips dock progress and selection-mark rebuilds. refreshTagDiscoveryPanel(onlyTagNames?) / openTagDiscoveryContainsAnyTag support gated updates.
  • v2.0.0 22/07/2026

    Breaking

    • jQuery removedresolveItem receives HTMLElement (not jQuery). Selection / cross-tab listeners are native addEventListener.
    • Per-lane human interaction — IDB state replaces single-slot humanInteractionBlocked / humanInteractionContext / humanInteractionItemId / humanInteractionPromptTabId / humanInteractionOpenUrl with humanInteraction: { resolution, download } lane entries ({ itemId, promptTabId, openUrl, at } or null). _ensureState migrates legacy rows. Resolution and download can block and show panels at the same time.
    • Dispatcher / policies_runResolutionProcessor / _runDownloadProcessor / _runLinkedProcessors replaced by _runDispatcher(policy). linkQueues: false → IndependentPolicy (concurrent own-lane gates). linkQueues: true → InterleavedPolicy (serial selection, any-HI pauses the shared regime, opportunistic download during discovery, retractable in-flight jobs).

    Added

    • Per-lane HI panels#bv-human-interaction-panel-resolution / #bv-human-interaction-panel-download with distinct default titles.
    • Lane descriptors_ensureLanes() wraps peek / claim / process / own-lane block predicates.
    • Queue challenge Done — resume — close tab — Phase-1 media verification panel adds a secondary confirm that clears the HI lane (same as Done — resume) then window.close(); if the browser blocks close, resume still succeeded and a short manual-close note is shown. Challenge / brazen_hi tabs always use _showQueueChallengeResumePanel (including after full init) so the close-tab control is not dropped when the leader Open/Done chrome would otherwise take over.
    • Download interruption prompt — download rows set inProgress / startedAt before GM_download. On a visible full-UI leadership steal, orphan downloading rows with inProgress are deferred (not requeued) and #bv-download-interruption-panel shows a 5s timed button (hover pauses). Click marks those rows done and sets paused; timeout requeues and relaunches (previous default). The download lane stays gated while the decision is pending. Recommendation: keep a dedicated leader tab and browse in other tabs for large downloads.
    • Leader tab control — Start/Pause slide-out crown (dock-download-leader) between the progress widget and clear-queue. Active when this tab owns processingTabId (click is a no-op). Inactive click calls requestDownloadManagerLeadership(): blocks with an alert while isDownloadManagerRunning(), otherwise force-claims leadership, wakes other tabs, and refreshes dock chrome. Queue verification tabs never claim.

    Fixed

    • Open Cloudflare Challenge — reads openUrl from the sync state cache and opens the challenge tab in the click stack (no await before the anchor click) so transient user activation is preserved; cache-miss IDB fallback is best-effort with a brief panel notice when the URL is missing.
    • Tag Discovery Confirm revive — cancels the scheduled panel refresh timer on hide; _scheduleTagDiscoveryPanelRefresh / _refreshTagDiscoveryPanel no-op while _tagDiscoveryActionInFlight, so Confirm no longer re-shows the same unknown list before the gate clears.
    • Ignored-pin review scope_collectIgnoredFilenamePinTags lists ignored tags only for blocking pin types (raw tags present, join empty after ignore/substitution, and at least one filename-ignored tag). Healthy sibling pins are never included. Substitution-only empties do not block.
    • Ignored-pin continue gate — Confirm and auto-continue require !pinJoinEmpty (any still-blocking pin type), not an empty collected tags array alone.
    • Deselect during discoverydequeueDownload of resolutionBlockedItemId (when Confirm/Skip is not in flight) hides the panel, clears discovery gate state via _withState, bumps processor epoch if that item was active, and resumes processors (same unlock as Skip, without type confirm).
    • Human-interaction verification tab_isQueueVerificationTab is marker-only (brazen_hi); same-origin window.opener alone no longer misclassifies normal search/media tabs as challenge tabs.
    • Human-interaction restore / watchdog_restoreHumanInteractionPanelsIfNeeded reclaims stale promptTabId ownership and (re)shows interactive Open Challenge panels on visible ownable tabs; remote lane clear hides that tab’s panel; interactive show clears bv-dock-panel-offscreen; challenge-tab confirm resolves lane context from the marker / blocked lane (not a default 'download').
    • Selection mark flash — bounded sessionStorage active-id mirror (SELECTION_MARK_MIRROR_MAX = 4000) paints Queued overlays synchronously before async IDB reconcile; pagehide skips overlay wipe when event.persisted (bfcache).

    Changed

    • Own-lane pipeline blocks — IndependentPolicy: resolution blocked by resolution-lane HI or resolutionBlocked; download by paused, download-lane HI, or a pending interruption decision. No cross-lane coupling.
    • Mirror / Phase-1 peekspeekHumanInteractionBlockedIdb / isHumanInteractionBlockedSync / localStorage mirror mean any lane blocked.
    • Verification URLs — mark brazen_hi_ctx=resolution|download (query + hash) so challenge-tab Done clears the correct lane.
    • Ignored-pin Similar section — when discoveryReviewMode === 'ignoredPins', panel options pass similarOpen: true and similarShowCount: false so Similar starts expanded with a plain Similar tags heading (unknown-tag review unchanged).
    • Build identityBRAZEN_DOWNLOAD_MANAGER_BUILD (local-2.0.0).

    Removed

    • Foreign-HI yield_downloadYieldForForeignHi / _resolutionYieldForForeignHi and single-flight HI suppression.
  • v1.3.1 21/07/2026

    Added

    • _pruneAllTerminalQueueRows() — on initialize and leadership claim, deletes terminal queue rows (and fat resolvedPayloads) left after crashes.
    • paceResolutionInitiation() — public serialized pace for resolution / same-origin HTML fetches (apps must use this for tag-list lookups etc.).

    Changed

    • _paceResolutionInitiation — serialized via _resolutionInitiateTail (same pattern as download) so concurrent callers cannot stampede the initiation clock.
    • _resolvePagefetch + AbortController (credentials included); aborts on pagehide / processor epoch / 30s timeout.
    • Discovery partition — one tagRuntime.ensureNames for the candidate set; sync cache lookup when possible.
    • Pipeline / recoverylistByStatus instead of listAll for orphan resolving / downloading / tagReview recovery; _resolveItemPipelineView prefers _getStateSync.
    • Selection mode off / pagehide_clearAllItemProgress sweeps tile maps and selection Sets.
    • Terminal status sets — reuse IndexedDB RESOLUTION_QUEUE_TERMINAL_SET / DOWNLOAD_QUEUE_TERMINAL_SET.
    • decodeHtmlEntities — delegates to Utilities.decodeHtmlEntities.
    • Build identityBRAZEN_DOWNLOAD_MANAGER_BUILD (local-1.3.12).

    Fixed

    • Tag discovery hide — clears similar-tag cache so hidden panels do not retain prefetch rows.
  • v1.3.0 19/07/2026

    Added

    • Behaviours config flags_registerConfigFields registers OPTION_REVIEW_IGNORED_FILENAME_PINS (review-ignored-filename-pins), OPTION_SKIP_EMPTY_FILENAME_PINS (skip-empty-filename-pins), and OPTION_ONLY_SHOW_DOWNLOAD_MANAGER (only-show-download-manager, default off). Apps mount them via Framework createBehavioursTabPanel().
    • Ignored filename-pin review — optional tagDiscovery.ignoredPinReview (isEnabled). After unknown-tag Confirm (or when there are no unknowns), when any tag-type pin in the active filename/subfolder patterns had tags but the join is empty after ignore/substitution, opens the discovery panel with those ignored tags + Similar. Runs on the queue path and on immediate Download Media / Auto Download. Confirm in ignoredPins mode skips type promotion. State field discoveryReviewMode. When isEnabled is omitted, reads OPTION_REVIEW_IGNORED_FILENAME_PINS.
    • Skip empty filename pins — optional tagDiscovery.skipEmptyFilenamePins (isEnabled). On the queue path only, after unknown-tag discovery and ignored-pin review, drops the resolution item (does not promote to the download queue) when active filename/subfolder patterns include at least one tag-type pin and the post has no raw tags for any of those pins. Filename Tag Ignore List is not applied. No-op when patterns have no tag-type pins. Also gated after discovery Confirm. When isEnabled is omitted, reads OPTION_SKIP_EMPTY_FILENAME_PINS.
    • Build identityBRAZEN_DOWNLOAD_MANAGER_BUILD (local-1.3.10-hi-label) logged once on init so Tampermonkey Resource overrides can be verified against Greasy Fork pins.
    • Tag discovery Similar tags — after the panel paints, prefetches up to 10 same-type registry tags with >50% contiguous snake_case token overlap (brackets stripped); collapsed Similar section; same attribute actions as New/Known. Bounded top-10 during scan; cancels rAF/in-flight load on hide or retarget; skips IDB rescan when new/known names are unchanged (attribute refresh reuses cache).
    • Tag discovery name click — opens tagDiscovery.actions.bookmark.buildUrl in a new tab (pointer, no underline).

    Changed

    • Behaviours titlesReview Ignored Download Path Tags and Skip Media Without Download Path Tags (option keys unchanged).
    • Ignored-pin / empty-pin defaults_isIgnoredPinReviewEnabled / _isSkipEmptyFilenamePinsEnabled use the registered config flags when the optional isEnabled hooks are omitted (apps no longer need to wire hooks for the default Behaviours options).
    • Ledger membership — queue and immediate downloads use _isDownloadDuplicateAsync (IndexedDB / bounded cache), not a full in-RAM ledger Set.
    • Filename tags_ensureDownloadPathTagsLoaded / discovery panel ensureNames load only the tags needed for the current path or review panel.
    • _syncFromStorage — refreshes selection marks once (does not also call _refreshAllItemProgress, which double-painted overlays).
    • Pending counts / dock progress — use IndexedDB countActive() (status index) instead of full-queue listAll / fat resolvedPayload deserialization. Unlinked mode keeps the download completed count while resolution still has work (avoids 0/N reset between promotes). Progress increments do not reset counters mid-turn; reset runs on enqueue, processor idle settle, and sync. Pause-if-idle uses pending counts only (via _withState). Dock progress uses a dirty-flag drain paint on a cached progress node; slide-out remounts only when pending work appears or clears. Orphan downloading rows with no queued peer are requeued once via _requeueInterruptedPipelineWork so the download loop cannot silent-stall with leftovers.
    • Finish after tag discovery — increments resolution progress after promote (same as the non-review resolve path).
    • Selection reconcile — one listActiveItemIds() membership set per refresh; parallel progress paints (no serial isQueued per tile).
    • Processors — claim next work via peekNextQueued() (oldest queued via status index) instead of listAll each loop.
    • Cross-tab wake_signalProcessorsWake and the storage receiver are debounced (~150 ms). Hidden tabs resume leadership/processors only (state get); full _syncFromStorage / panel restore runs on visible tabs (focus, pageshow, or wake while focused).

    Fixed

    • Dock progress UI — paint adopts the live .bv-dock-progress-panel (and remounts Start/Pause slide-out if still detached) after chrome refresh so counters cannot freeze on a detached node when Tag Discovery is open or resolution drains first. Debounced dm-progress-ui-wake localStorage ping lets visible non-leader tabs reload completed counts and repaint without a full dock rebuild.
    • Cloudflare resume on challenge media page — queue verification / HI-blocked mediaCloudflare tabs show Done — resume on that page (Phase-1) instead of staying silent; full-init media pages may also own the resume panel after the CAPTCHA clears (verification tabs still never claim processor leadership).
    • Cloudflare open on demand — HI no longer auto-opens the verification tab; the focused-tab panel offers Open Cloudflare Challenge then Done — resume so search focus is not stolen. Legacy consumer reopenLabel “Reopen verification tab” is normalized to Open Cloudflare Challenge.
    • Media Add to Queue dock — circle+/circle× icons with active state when queued; toggle paints optimistically and re-reads isQueued so remove resets the button (also bumps processor epoch if this post was in-flight).
    • Immediate downloaddownloadImmediate still opens Tag Discovery when unknowns exist, then downloads on Confirm via the immediate pace path; it never enqueues the batch resolution/download queues. pendingImmediateDownload stays serializable (live media node in RAM only) so IDB structured clone cannot throw.
    • Tag discovery panel tags — each resolution / immediate review uses that item's unknown+known lists only (no merge with a prior review's leftovers); extract helpers may be async.
    • Ignored filename-pin review — gate uses the same filename join emptiness as the download path; lists only tags that are still filename-ignored when the panel opens; Attribute toggles keep the open list and refresh Aa/mute chrome (do not drop a row the moment ignore is cleared); Confirm / restore re-collect; when nothing remains ignored, continues download (queue promote or immediate). Queue and immediate (Download Media / Auto Download) share the same post-discovery pin-review entry.
    • Tag discovery Similar accordion — attribute / config refreshes are deferred so row DOM is not swapped mid-click (which closed the Similar <details>); completed similar cache survives hide/cancel so restore does not flash Loading and drop the count; ignored-pin review no longer wipes the similar fingerprint on every paint; similar rows ensureNames before painting action icons so ignore/blacklist/explore/substitution match the registry (New/Known already did).
    • Queue stall after leader pagination during resolutionpagehide/beforeunload hard-interrupts local processors (_processorEpoch, clear _active*ItemId), blocks late heartbeat lock-mirror rewrites (_documentSuspended), and closes IndexedDB so a bfcache'd prior page cannot pin storage. pageshow with persisted reopens IDB, invalidates thawed processor continuations, and requeues orphan resolving / downloading rows before renewing leadership. Selection enqueue failures revert the optimistic overlay instead of leaving a painted-but-unpersisted mark.
    • Load lag with large Ready queues — init and multi-tab wake no longer repeatedly getAll hundreds of fat download rows for dock counters and selection marks.
    • Processor stall after peekNextQueued — claiming work uses the status index (with getAll fallback) so queued rows are found again on the leader tab.
    • Selection click→blur lag_toggleSelectionItem no longer awaits isQueued (IndexedDB) before painting select feedback. Local track/pending state decides select vs deselect synchronously; IDB reconcile runs after the overlay is on screen.
    • Tag discovery Confirm / Skip — hide the panel immediately on click; type promotion, promote/drop, and processor wake continue in the background (ignored-pin review may reopen the panel afterward).
    • Tag discovery open on non-leader tabs — opening review (_presentTagDiscoveryReview) always _signalProcessorsWake() after gating so a focused follower can restore the panel when the processor leader is in the background (Confirm/Skip already woke; subsequent queue items did not).
    • Overnight queue memory — terminal downloadQueue / resolution rows (including fat resolvedPayload) are pruned after each item finishes; dock totals keep using completedDownloadCount / completedResolutionCount. Selection tile DOM maps and selection epochs are cleared when an item leaves the active pipeline.
    • Per-download ledger reload — queue downloads use _isDownloadDuplicateAsync (IndexedDB / bounded cache) instead of getAll before every claim.
    • _handleDownloadSucceededGM_download onload notifies the framework so apps can release remove-on-success media capture.
    • Cross-tab enqueue wake — enqueue writes a localStorage wake ping so an idle leader in another tab starts processors (IDB change notifies are same-tab only).
    • Back/forward (bfcache) resumepageshow reclaims leadership and resumes processors after the browser restores a cached page (visibility alone is not reliable).
    • Tag discovery Confirm / Skip on a follower tab — after clearing resolutionBlocked, always _signalProcessorsWake() so an idle leader resumes (local _shouldRunProcessors() is false while another tab owns leadership). Promote also wakes before kicking the download loop.
    • Confirm type promotion_confirmDiscoveryPanelTagTypes confirms via ensureTag (source: 'discovery-confirm') using lastSeenTypeEntryId or the panel row's type, so follower-tab Confirm registers typeEntryId the same as on the leader.
    • Human-interaction resume panel stranded — the Done — resume dock panel is no longer locked to processingTabId. Any focused search/media tab may steal humanInteractionPromptTabId (same model as tag discovery); hide/unload releases ownership only. Queue verification tabs never own the panel or processor leadership, so a Cloudflare tab can no longer steal the lock on leader refresh and leave the prompt missing until the ~12s stale window.
  • v1.2.2 17/07/2026

    [1.2.2] — current

    Fixed

    • Tag discovery panel across search tabs — opening another search tab no longer flashes the review panel then leaves resolutionBlocked stuck with no UI. The focused tab steals tagDiscoveryPanelTabId via _withState; hiding / unloading a tab releases ownership (not the queue gate) so the visible tab can restore; restore also runs when review is already gated even if discovery was toggled off. Framework calls restoreTagDiscoveryPanelIfNeeded() after the dock is built so init does not show the panel before layout exists.

    [1.2.1]

    Changed

    • parseDownloadTagSubstitutionLines — accepts / -> as well as - between subject and replacement (matches panel / registry projection).

    Fixed

    • GM_download conflict policy — always overwrite; never uniquify. User pattern filenames must not become file(1).ext (queue and immediate).
  • v1.2.0 16/07/2026

    Added

    • linkQueues — opt-in serial coupling of resolution and download (default false). When unlinked, the leader tab runs concurrent resolution and download loops; tag discovery (resolutionBlocked) pauses resolution only; human-interaction blocks only the pipeline in humanInteractionContext.

    Fixed

    • Queue freezes / apparent deadlock — failed item claims no longer count as progress; leadership claim failure does not busy-reenter; promote / tag Confirm kick the download processor; unlinked idle-pause waits until resolution is also idle so Ready rows are not left paused mid-batch.
    • Steal / clear races — in-tab active-item guards abort terminal puts after leadership steal or clearDownloadQueue; steal requeue skips this tab's active ids.
    • Single-flight human-interaction — a second pipeline that hits verification while another HI is open requeues and yields instead of clobbering the panel.
    • Tag discovery state — open / Confirm / restore use _withState (same lost-update class as Skip).
    • Download initiation gap — batch and immediate downloads share a serialized pace mutex.
    • Optimistic select flicker — while the IDB put is still in flight, refresh/reconcile could resolve null progress and clear the overlay. Pending selects are protected until enqueue settles.
    • Tag discovery attribute actions — panel wires onAfterToggle to refresh row chrome immediately after bookmark / ignore / substitute / blacklist / explore toggles (same path as the sidebar).
    • Dock progress panel — shown when either the resolution or download queue has pending work; Start/Pause slide-out follows the same gate. Resolution progress is always reported (including during tag discovery) so the lower bar fills correctly.
    • Resolution progress reusecompletedResolutionCount / completedDownloadCount reset when that queue alone goes idle, so a new resolution batch after downloads are still running starts at 0/N instead of inheriting the prior total.
    • Dock progress counters — increments/resets go through _withState and coerce missing counts to 0 so heartbeats cannot wipe the first resolution batch.
  • v1.1.5 16/07/2026

    [1.1.5] — current

    Changed

    • Selection click feedback — paint blur + Queued progress immediately on select (and clear immediately on deselect); IDB enqueue/dequeue runs after. In-flight toggles use a per-item epoch so a rapid second click can cancel without leaving a zombie queue row.

    [1.1.4]

    Removed

    • Selection border mark — no longer applies View Layer .bv-dm-selected (or a page setSelectionMark hook). Queued search tiles use blur + pipeline progress only.
  • v1.1.3 16/07/2026

    Added

    • handleMediaCloudflarePage() — reusable Phase-1 Cloudflare / challenge page handler (silence queue verification tabs; standalone shows themed #bv-human-interaction-panel with Done — reload). Static helpers: hasBrazenHumanInteractionMarker, isQueueOpenedVerificationTab, shouldSilenceMediaCloudflarePrompt, peekHumanInteractionBlockedIdb.

    Fixed

    • Queue Cloudflare tab revived old grey confirm — Chrome treats window.open(url, '_blank') as noopener, so window.opener was null on the verification tab; combined with CF stripping brazen_hi, silence checks failed and the consumer's Phase-1 showConfirmDialog ran beside the leader dock panel. Verification tabs now open via <a rel="opener">, URLs also get #brazen_hi=1, and peekHumanInteractionBlockedIdb() lets Phase-1 read the shared block from IndexedDB before any dialog. Cloudflare page UI lives in Download Manager / View Layer — not in consumer scripts.
  • v1.1.2 16/07/2026

    Fixed

    • Resolution pacing after Cloudflare resume — clearing the human-interaction block used a raw _putState that could wipe lastResolutionInitiationAt (same lost-update class as the tag-discovery Skip bug), so the queue could burst resolves with no initiation gap after Done — resume. Block begin/clear and processor-leadership heartbeat renew now go through _withState; resume stamps only the blocked pipeline's initiation clock so resolution and download gaps stay independent; each resolve attempt (including timedReload retries) paces before fetch.
  • v1.1.1 16/07/2026

    Fixed

    • Tag discovery Skip — clearing the review gate used a raw _putState on a stale snapshot that the processor heartbeat could overwrite, leaving resolutionBlocked stuck so new resolution items never left queued. Skip also untracked the search tile before refreshing progress, so the selection overlay stayed on Tags. Gate clear now goes through _withState; selection mark and progress are cleared like dequeue.
  • v1.1.0 16/07/2026

    [1.1.0] — current

    Added

    • Start in Selection Mode — flag OPTION_DOWNLOAD_SELECTION_MODE_DEFAULT (download-selection-mode-default, default off). When on, selection mode activates on load for pages with the selection role (still toggleable from the dock for the visit). Apps place createElement(OPTION_DOWNLOAD_SELECTION_MODE_DEFAULT) at the top of the Downloads settings tab.

    [1.0.1]

    Fixed

    • Human-interaction panel before verification window — show #bv-human-interaction-panel on the processor-leader tab before window.open, with force so a focus-steal does not skip the panel. Returning to the leader still restores via visibility as before.
  • v1.0.0 15/07/2026

    Added

    • BrazenDownloadManager — dual IndexedDB queues (resolution + download), cross-tab processors with initiation gaps, ledger claim at download time, downloadImmediate() and batch enqueue, optional tag discovery panel, dock controls (selection, enqueue, start/pause, clear, progress).
    • Path/token helpers moved from BrazenFramework (buildDownloadPathFromPatterns, substitution parsing, GM_download wrapper).
    • resolver.tagRuntime — when warmed, _joinTagsForDownloadPath applies ignore/substitution via registry attributes instead of string Set/Map.
    • Tag discovery — pattern-relevant types only for the review panel (no scan-all fallback); dock counter/progress omit resolution queue while discovery mode is on; confirm promotes seen types to typeEntryId.
    • Always register path tags_registerResolvedTagGroups on resolution and immediate download regardless of discovery toggle. Discovery onsource: 'media' (seen-only); discovery offsource: 'resolution' (page types confirmed as typeEntryId). Extract helpers stay read-only.
    • Download queue idle after batch — when pending downloads hit 0, paused is set back to true so the next batch waits for Start instead of auto-running.
    • Start/pause fixgetPendingPipelineCount() counts both queues so the play button works when tag discovery hides resolution items from the dock counter.
    • Resolution auto-runpaused applies to the download queue only; resolution runs on enqueue without manual start.
    • Human-interaction rate limitshumanInteractionBlocked state; processor-leader tab shows #bv-human-interaction-panel (dock slide panel) after opening the verification tab. timedReload returns retry and re-fetches in the same resolution attempt so a post-429 Cloudflare page escalates to human interaction.
    • Dock progress slot — download-queue only (current/total from progress.download); hidden while the download queue is empty (resolution-only work uses per-item progress on search tiles). Border matches --bv-dock-btn-bg, no inset background; counters always visible when the slot is shown.
    • Tag discovery panel — Skip / Open media / Confirm on one footer row; shows new tags then known tags (typed/color groups) with incidence counts beside actions; Skip drops the resolution item without confirming types. Reload / tab focus restores the panel when review is still pending. Play slide-out (clear + progress) opens only when the download queue has items. Config/action refreshes update panel content in place without replaying the slide-in animation. Maps framework tag-attribute actions internally (appendTagAttributeActions); consumer supplies tagDiscovery.actions incidence options only.
    • Processor UI cadence — resolution/download queue and DM state puts no longer broadcast dock/panel rebuilds. One UI reset runs at the end of each resolution or download task (_onResolutionTaskComplete / _onDownloadTaskComplete); full _syncFromStorage remains for tab focus / init only.
    • Processor leadership recoveryprocessingHeartbeatAt + stale lock steal (~12s); pagehide releases the lock; interrupted resolving/downloading items are requeued so refresh does not orphan the pipeline.
    • ledgerClaimed on download queue rows — reserve the duplicate ledger once per item; lock-steal requeues no longer re-claim and false-skip as “already downloaded”.
    • Ledger hits — queue status duplicate (selection progress label Duplicate, no alert); silent skip for immediate downloads aside from optional media restore.
    • Start/pause vs resolution — Start/Pause is disabled (and no-ops) when the download queue is empty so resolution-only work cannot be toggled; queued downloads show Ready, not Paused. Progress counters reset when both queues are idle so a new resolve no longer inherits stale completedDownloadCount (e.g. looking like 5 items after queuing 1).
    • Clear download queue — clears the download queue only (plus download-context human-interaction blocks). No longer wipes resolution, stops processors, hides tag discovery, or blanks selection marks / item progress for resolution work.
    • Ledger claim when Hide is on_shouldClaimDownloadDuplicateLedger(); download id falls back to item.itemId when the payload id is missing.
    • Skip Duplicate Downloads dock template — Framework applies applyDockTemplate('skipDuplicates') at ledger init. Download Manager only setDockSlideOut([hide-downloaded-media]) (and backfills hideDownloaded template if the hide field has no dock yet). Apps order the enable key on the rail; they do not redefine the button body.

    Fixed

    • _resolvePage — attaches a parsed Document on HTTP 4xx / transport fail rejects so rateLimitHandlers (site 429 HTML and Cloudflare challenge bodies) can detect and escalate instead of failing as a blind network error.
    • Duplicate resolution fetches_runProcessors took its in-tab lock only after an await, so enqueue + _syncFromStorage (and concurrent void starts) could run two loops over the same queued item. Lock is now synchronous; items are claimed queuedresolving/downloading before work; _syncFromStorage no longer auto-starts processors (callers / tab-focus do).
    • Start after refresh — processor leadership lived only in IndexedDB; pagehide release often never finished, so a fresh tab could not reclaim for ~12s (stale heartbeat). Start flipped paused but _runProcessors exited without leadership. Sync localStorage lock mirror is cleared on unload so leadership can be stolen immediately after refresh; concurrent _runProcessors kicks wake the running loop instead of being dropped.
    • Cloudflare as timedReload_handleRateLimit ran timedReload first and treated any HTTP status === 429 as auto-retry, so Cloudflare CAPTCHA bodies that arrive as 429 were re-fetched forever instead of escalating to humanInteraction. Human detect now runs first; timed reload matches only via its document detect.
    • Human-interaction prompt on every tab — confirm dialog was claimable by any visible tab (humanInteractionPromptTabId unset until dialog open, cleared on “Not yet”). Prompt is pinned to the processor tab at block time and only shown when processingTabId is this tab, so the verification tab does not get the dialog.
    • Human-interaction UI — dock slide panel (createHumanInteractionPanel); Done — resume / Reopen verification tab footer; no mouseleave auto-hide. Verification tabs opened by the queue stay silent (brazen_hi + localStorage mirror).
    • isDownloadManagerLeaderTab() — true when this tab owns processingTabId (for unload warnings and other leader-only UI).
    • Download initiation pacing — in-tab initiation clocks + serialized state patches so heartbeat/progress puts cannot wipe lastDownloadInitiationAt; gap applied immediately before GM_download.
    • Selection-item live progress — after queue puts stopped notifying Configuration Manager, search tiles no longer updated on claim (queuedresolving/downloading). Refresh progress immediately after claim; _refreshSelectionMarks re-tracks selected tiles so processor updates find them.
  • v1.0.0 15/07/2026