Commit Graph

5 Commits

Author SHA1 Message Date
Sucukdeluxe
f1e35f5f41 Fix: Mega "bis Tagesreset gesperrt" parkt das Paket bis zum Reset statt es den ganzen Tag alle 2 min neu zu versuchen
Wenn ALLE Mega-Debrid-Accounts wegen wiederholt leerer/Server-loser Antworten
bis zum Tagesreset geparkt waren (in-memory untilRestart-Park aus Runde 3),
warf unrestrictWithAccounts einen reinen Klartext-Fehler ohne Maschinen-Token.
Im Manager-Catch fiel dieser durch parseMegaDebridCooldownRetry (kein
mega_debrid_cooldown:-Praefix) und isMegaDebridTransientResolveFailure und
landete im generischen isUnrestrictFailure-Zweig — nur weil der Text
"mega-debrid" enthaelt. Folge: das Item wurde den ganzen Tag etwa alle zwei
Minuten neu versucht (120s-Cap) und fuetterte dabei recordProviderFailure den
Provider-Circuit-Breaker, statt einmal bis zum Tagesreset zu parken. Bei
Standard-Einstellungen (retryLimit=0=unendlich) heilte es sich zwar um
Mitternacht selbst (kein Stranding), war aber unnoetige Log-Flut und Churn und
unterlief genau die untilRestart-Park-Absicht aus Runde 3.

Cross-Layer-Synthese-Pass (adversarisch verifiziert) hat parallel die
Advisor-Hypothese eines Key-Mismatch (Manager cool't aufgeloesten
"megadebrid-api", Fallback-Suche liest rohen "megadebrid") WIDERLEGT:
normalizeProviderOrder speichert immer den aufgeloesten Key, also faellt
Write/Check/Clear/Read auf denselben Key — der Routing-Fix (986fbab) ist fuer
den Mega-Fall nachweislich sicher.

Fix (konservativ, spiegelt den bereits korrekten mega_debrid_cooldown-Zweig):
- debrid.ts emittiert beim untilRestart-Park jetzt den Token
  mega_debrid_reset_park:<msBisReset>: (Delay aus megaDebridDailyParkExpiry,
  deckt sich exakt mit dem in-memory Park-Ablauf).
- download-manager.ts: neue reine parseMegaDebridResetPark (kein 15min-Clamp,
  26h-Cap) + Catch-Branch VOR der Cooldown-Klassifikation, der bis zum
  Tagesreset queued OHNE recordProviderFailure (ein geplanter Park ist kein
  Provider-Fehler).
- Token enthaelt weiter "mega_debrid" → jeder Fall-through landet schlimmstenfalls
  im heutigen Verhalten (sichere Untergrenze).

Tests: 5 neue (parseMegaDebridResetPark: parst/embedded/kein-15min-Clamp/Cap+Junk,
plus cooldown-Parser ignoriert den neuen Token) + die all-parked debrid-Assertion
prueft jetzt den Token. Volle Suite 881 gruen, tsc unveraendert.
2026-06-17 10:16:16 +02:00
Sucukdeluxe
986fbab04f Fix: Provider-Cooldown-Fallback fuehrt die Kette jetzt wirklich mit dem Ersatz-Provider an (Routing-Slice)
Wenn ein Provider in den Manager-Cooldown laeuft (>=20 Fehler in Folge) und
auto-Fallback aktiv ist, berechnete der Manager zwar einen Ersatz-Provider
(findFallbackProviderNotInCooldown), warf ihn dann aber weg: der unrestrictLink-
Aufruf bekam keinen Hint, also baute debrid.ts die Provider-Kette frisch aus
providerOrder und fuehrte erneut mit dem ausgebremsten Provider 1 an — ein meist
in den 60s-Timeout laufender, verschwendeter Versuch, bevor ueberhaupt der
gesunde Provider drankam.

Jetzt wird der Ersatz-Provider als bevorzugter Lead durchgereicht. Die Kette
wird UMSORTIERT, nicht beschnitten: der ausgebremste Provider bleibt als letzter
Notnagel in der Reihenfolge, sodass kein Link gestrandet werden kann. Sind ALLE
Provider im Cooldown, erreicht der Aufruf unrestrictLink ohnehin nicht (der
else-Zweig queued einen Retry). Greift damit nur, wenn ein Provider bereits
nachweislich degradiert ist — strikt besser, wenn aktiv, und ohne Timeout-,
Cancel- oder Budget-Vertrag anzufassen.

- debrid.ts: reine leadProviderChainWith(order, preferred) (export) + optionaler
  4. Param preferredLeadProvider an unrestrictLink; Reorder direkt nach Aufbau
  der Reihenfolge.
- download-manager.ts: Ersatz-Provider in preferredLeadProvider festhalten und
  an den unrestrictLink-Aufruf durchreichen.
- Tests: Integration (ohne Hint fuehrt realdebrid, mit Hint fuehrt debridlink) +
  drei reine Helper-Tests fuer die No-Stranding-Invariante.

Zwei verbleibende HIGH-Punkte sind bewusst NICHT autonom geaendert, sondern als
Produkt-/UI-Entscheidung in tasks/entscheidungen-offen.md vorgelegt (globaler
60s-Failover-Timeout; gespiegelter Mega API/Web-Schalter).
2026-06-17 06:23:44 +02:00
Sucukdeluxe
cbb84f29d8 docs(tasks): Runde-3-Audit dokumentiert (3 Fixes v1.7.217, 5 charakterisiert/vorgelegt) 2026-06-17 05:56:06 +02:00
Sucukdeluxe
c8ea2f6765 Fix: Startup-Dedup ersetzt keine gute kanonische Datei mehr durch ein kleineres Duplikat
Beim Start gleicht das Tool Duplikat-benannte Dateien ("Name (1).ext") gegen die
kanonische Datei ("Name.ext") ab. Im Zweig "Duplikat rangiert hoeher und das
kanonische Item ist nicht 'completed'" wurde bisher bedingungslos
fs.rmSync(kanonisch) + fs.renameSync(Duplikat → kanonisch) ausgefuehrt — ohne die
echten Dateigroessen zu vergleichen. Der Rang mischt den persistierten STATUS mit
der Disk-Existenz; nach einem Absturz kann der Status von der Realitaet abweichen.
War die kanonische Datei auf der Platte tatsaechlich vollstaendig/gut, ihr Item
aber z.B. "failed"/"queued", waehrend das Duplikat-Item ein veraltetes
"completed" ueber einer kleineren/partiellen Datei trug, wurde die gute
kanonische Datei geloescht und durch das schlechtere Duplikat ersetzt —
unwiederbringlicher Verlust der besseren Datei. Zusatzrisiko: rmSync erfolgreich,
renameSync wirft EXDEV → kanonisch weg, nichts installiert.

Fix:
- Size-Guard: Ist die kanonische Datei >= dem Duplikat, wird sie behalten und das
  (kleinere/gleich grosse) Duplikat verworfen. Eine kleinere Datei kann eine
  groessere nie ueberschreiben.
- Sichere Reihenfolge fuer den echten Austausch (kanonisch kleiner): kanonisch →
  ".dedupbak" umbenennen, dann Duplikat → kanonisch; bei Fehler (EXDEV o.ae.)
  wird die kanonische Datei aus dem Backup wiederhergestellt. Kein Loss-Fenster
  mehr. Erst nach Erfolg wird ".dedupbak" entfernt.

Test: kanonisch 1024 B (gut) + Duplikat 256 B (partiell), primaeres Item "failed"
(Duplikat rangiert hoeher) → die kanonische Datei bleibt mit 1024 B erhalten.
Ohne den Size-Guard wird sie durch die 256-B-Datei ersetzt (rot bewiesen). Volle
download-manager-Suite (168) gruen, tsc unveraendert 6.
2026-06-17 05:13:40 +02:00
Sucukdeluxe
3bd6e3b23e Härtung Download/Rotation (Audit-Batch 1): Scheduler-Freeze, Cooldown-Respekt, Daily-Reset, Kategorisierung
Aus einem adversarisch verifizierten Multi-Agent-Audit (14 confirmed/11 refuted):

#1 HIGH Scheduler-Freeze: findNextQueuedItem hatte keinen activeTasks-Guard.
Wird ein Item zurueckgesetzt/ueberschrieben, waehrend sein alter Task noch in
einem nicht-abbrechbaren await parkt (z.B. Integritaets-Check), liefert
findNextQueuedItem dasselbe Item, startItem lehnt es ab ohne activeTasks zu
verkleinern → der SYNCHRONE Admission-Loop dreht endlos → Event-Loop friert
permanent ein. Fix: `if (this.activeTasks.has(itemId)) continue;`. Repro-Test
(ohne Fix haengt sogar der vitest-Timeout — Freeze bewiesen).

#2/#3 MED mega_debrid_cooldown:<ms> wurde verworfen: kein Parser (nur das
debrid_link-Analogon) → Item lief in den generischen 5s-Exponential-Backoff
und fragte cooled Accounts im Sekundentakt erneut an. Neuer
parseMegaDebridCooldownRetry (nimmt das frueheste Cooldown-Ende ueber alle
Accounts) + Handler VOR transient/generic → Item wartet die echte Cooldown-Zeit.

#7/#8 MED Mega per-Account Tages-Usage wurde am Tageswechsel nie zurueckgesetzt
(ensureProviderDailyUsageFresh ruecksetzte nur provider/debrid-link), und weil
es den Tagesschluessel zuerst weiterstellte, lief auch der Reset in
addMegaDebridAccountDailyUsageBytes ins Leere → Accounts blieben den ganzen Tag
faelschlich "am Limit" und schrumpften das (neue) Pro-Account-Umwandlungslimit.
Fix: megaDebridAccountDailyUsageBytes im Tageswechsel mit zuruecksetzen.

#14 LOW classifyAccountFailure: rate_limit-Branch vor quota (quota matchte
"limit" in "rate limit" → Fehl-Kategorisierung).

852/852 gruen, tsc unveraendert (6). #4 (empty→until-restart) bewusst deferred.
2026-06-17 04:22:20 +02:00