Commander: "Rippy wird zwar sauber beendet aber startet NICHT neu in der
neuen version."
Ursache, auf drei Beinen belegt:
1. Bibliothek: electron-updater startet den Installer per
spawn(..., { detached: true }) (BaseUpdater.js, an der installierten
Fassung nachgelesen). `detached` setzt unter Windows KEIN Breakaway.
2. Leine: leine.ts setzt KILL_ON_JOB_CLOSE, und Kinder erben die
Mitgliedschaft. Der Installer war damit Mitglied der Arbeitsgruppe.
3. Platte: pending\RippySetup-5.1.3.exe lag geladen da (18:11:47),
installiert war weiter 5.1.2. Der Download klappte, nur die
Installation nicht.
Der Installer starb also in genau der Sekunde, in der Rippy sich
beendete, um ihm Platz zu machen.
Fix — die Leine bleibt, der Installer klinkt sich aus:
* leine.ts setzt zusaetzlich JOB_OBJECT_LIMIT_BREAKAWAY_OK. Das aendert
fuer sich genommen NICHTS: Kinder erben weiter, ausser sie verlangen
das Ausklinken selbst. Kern, makemkvcon und HandBrakeCLI bleiben
angeleint, die rc10-Waisen-Falle (Paragraph 3.3) ist unveraendert zu.
* Neu: ausserhalbDerLeineStarten() startet EIN Programm per CreateProcessW
mit CREATE_BREAKAWAY_FROM_JOB. Liegt in leine.ts, weil dort die
Arbeitsgruppe verwaltet wird — und weil Waechter R1 koffi nur dort und
in kern/laufwerk/win32.ts erlaubt.
* update.ts installiert jetzt SELBST: autoInstallOnAppQuit ist aus, der
Installerpfad kommt aus downloadUpdate() (laut AppUpdater.d.ts "Paths to
downloaded files"), die Argumente sind die von electron-updater
gemessenen (--updated /S --force-run). Gestartet wird beim Beenden
(will-quit) und ueber den Knopf.
* Neu kommandozeile.ts (pur, ohne koffi/Electron): CreateProcessW nimmt
EINE Zeichenkette. Ohne die Regeln von CommandLineToArgvW zerfiele ein
Pfad wie "C:\Users\Tobi Neu\..." in zwei Argumente.
BEWIESEN, nicht behauptet — neu: beweise/leine-breakaway.js
OHNE Ausklinken (so macht es electron-updater)
lebt nach dem Tod des Elternprozesses: NEIN -> WIE ERWARTET
MIT Ausklinken (so macht es Rippy ab 5.1.4)
lebt nach dem Tod des Elternprozesses: JA -> WIE ERWARTET
Der erste Messlauf zeigte ein falsches Negativ: Der Enkel starb an der
sterbenden KONSOLE des Elternprozesses, nicht an der Arbeitsgruppe. Erst
mit CREATE_NO_WINDOW (eigene Konsole) misst der Versuch, was er messen
soll. Diese Lehre steht als Kommentar im Code und der Flag ist auch im
echten Aufruf gesetzt.
237 Tests gruen (vorher 230), Typpruefung sauber. Version 5.1.4.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Beweise — die Messungen zu KONZEPT-WINDOWS.md § 3
Diese zwei Skripte sind die Grundlage für die Entscheidung, Rippy v5 in TypeScript/Node zu bauen. Sie beantworten die einzige Frage, an der das ganze Konzept hängt:
Kann Node überhaupt alles, was Rippy am Laufwerk braucht?
Wäre die Antwort nein gewesen, wäre das Konzept wertlos gewesen. Deshalb sind sie zuerst gelaufen — vor der ersten Zeile Konzept.
AGENTS.md Regel D: „Externe Schnittstellen NIE aus dem Kopf."
Nachstellen
npm install koffi
node laufwerk.js
Gemessen am 30.08.2026 mit Node v24.19.0, koffi 3.1.6, an einem HL-DT-ST BD-RE BU40N (USB) mit eingelegter Blu-ray.
laufwerk.js — Win32-Laufwerkszugriff
Ruft dieselben Steuercodes auf wie src/rippy/drives/win_ioctl.py im
Docker-Zweig. Nur lesend — kein Auswerfen, kein Verriegeln.
1. GetLogicalDrives + GetDriveTypeW -> optische Laufwerke: [ 'G' ]
2. CreateFileW \\.\G: (Zugriff 0) -> offen
CreateFileW \\.\G: (GENERIC_READ) -> offen
3. IOCTL_STORAGE_QUERY_PROPERTY -> Hersteller: HL-DT-ST | Modell: BD-RE BU40N
| Rev: 1.03 | Serial: 0025114C0149
4. IOCTL_STORAGE_CHECK_VERIFY2 -> Medium eingelegt
5. IOCTL_CDROM_DISK_TYPE -> Win32-Fehler 50
6. IOCTL_DISK_GET_LENGTH_INFO -> 33.759.690.752 Bytes (33,76 GB) => Blu-ray
Punkt 5 ist kein Fehlschlag. Fehler 50 ist ERROR_NOT_SUPPORTED — genau
das, was der Python-Treiber an diesem Laufwerk auch sieht (SAVEPOINT.md,
v4.0-rc11, Abschnitt „Das Laufwerk"). Node verhält sich identisch. Die Lehre
steht im alten Code und gilt weiter: Die Disc-Einordnung darf sich nicht auf
IOCTL_CDROM_DISK_TYPE verlassen — die Größe ist der verlässliche Weg.
Punkt 2 zeigt die Unterscheidung, die in rc11 teuer war: Zugriff 0 fragt das
Gerät, GENERIC_READ fragt das Medium. Bei einer gestörten Disc
scheitert das zweite und das erste geht weiter — wer nur eins probiert, hält
ein antwortendes Laufwerk für tot.
leine.js — die Prozess-Leine (Job Object)
Stellt den Befund aus SAVEPOINT.md v4.0-rc10 nach: Windows räumt
Kindprozesse nicht auf. Ein hart beendeter Rippy hinterlässt ein
makemkvcon, das das Laufwerk festhält, und jeder spätere Rip scheitert.
Das Skript setzt eine Arbeitsgruppe mit JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,
startet ein langlebiges Kind und lässt sich dann hart abschießen —
taskkill /F ohne /T, also genau das, was bei einem Absturz und beim
Drüber-Installieren passiert.
1. CreateJobObjectW -> Arbeitsgruppe angelegt
2. SetInformationJobObject -> KILL_ON_JOB_CLOSE gesetzt
3. AssignProcessToJobObject -> dieser Prozess hängt in der Gruppe
4. Kindprozess gestartet, PID 16040
vor dem Abschuss: Eltern lebt: True Kind lebt: True
taskkill /F /PID 29488 -> ERFOLGREICH
danach: Eltern lebt: False Kind lebt: False
Nachstellen (PowerShell):
$p = Start-Process node -ArgumentList "leine.js" -PassThru -RedirectStandardOutput out.txt
Start-Sleep 3
$kind = (Select-String -Path out.txt -Pattern 'KIND-PID=(\d+)').Matches[0].Groups[1].Value
taskkill /F /PID $p.Id
Start-Sleep 2
Get-Process -Id $kind -ErrorAction SilentlyContinue # muss LEER sein
sqlite-main.js + sqlite-kern.js — node:sqlite in Electron
Beantwortet die Frage, die in der ersten Fassung des Konzepts als ⚠️ offen
stand: Electron baut sein Node mit eigenen Flags — ist node:sqlite dort
überhaupt vorhanden?
Gemessen am 30.08.2026 mit Electron 44.0.0, und zwar im
utilityProcess — dem Kontext, in dem Rippy v5 seine Datenbank betreiben
wird (kern/speicher/db.ts), nicht bloß im Node-Modus der Binary:
KERN-ANTWORT: {"ok":true,"wert":"geht","node":"24.18.1"}
Kern beendet mit 0
Antwort: ja. Die im Konzept vorgesehene Rückfallebene better-sqlite3
wird nicht gebraucht. (Zur Einordnung: In Node 24.19.0 pur war dieselbe
Messung zuvor ebenfalls grün.)
Nachstellen:
npm install electron@44 --no-save
node node_modules/electron/install.js
./node_modules/electron/dist/electron.exe sqlite-main.js
Die zweite Zeile ist kein Versehen — siehe nächster Abschnitt.
npm 11 blockiert Install-Skripte — und das trifft Electron selbst
npm warn allow-scripts koffi@3.1.6 (install: node ./cnoke.cjs -P . --prebuild --release)
koffi lädt trotzdem — es bringt vorgebaute Binärdateien mit. Electron
trifft die Sperre härter: Sein Install-Skript lädt die eigentliche
Programmdatei herunter; wird es geblockt, liegt nach npm install ein
Paket ohne dist/electron.exe da, und nichts startet. Am 30.08.2026
beim sqlite-Beweis selbst hineingelaufen; node node_modules/electron/install.js
holt die Binary nach. Beides gehört in die Bau-Anleitung, sonst sucht eines
Tages jemand an der falschen Stelle.