Ampel / ampel (push) Successful in 1m48s
Commander: "das funktioniert nicht, du kannst gerne am lebenen objekt
pruefen". Der Dialog blieb bei "Rippy liest die Titel der Disc ..."
stehen, ohne Fehler, ohne Ende.
Ursache, am lebenden Objekt gemessen: NICHT der Info-Lauf.
makemkvcon -r --noscan info dev:G: -> 0,8 s, TCOUNT:0
MSG:5042 "konnte keine verwendbaren optischen Laufwerke finden"
Der Lauf antwortet also sofort. Der Fehler lag in MEINEM Code von 5.2.0:
istFensterNachricht() kannte 'titel-lesen' und 'rip-ueberspringen' nicht
— beide standen in der FensterNachricht-Union, aber nicht im Pruefer.
Der Kern verwarf sie mit `if (!istFensterNachricht(frage)) return`.
STILL. Genau die R4-Wunde, vor der die Hausordnung warnt.
Auf drei Ebenen behoben:
1. Der Pruefer kennt beide Nachrichten.
2. Eine verworfene Nachricht ist jetzt LAUT: console.error plus
kern-fehler ins Fenster mit der Art, die verworfen wurde.
3. Neuer Waechter-Test (waechter.test.ts): Er liest das Schema und
vergleicht JEDE `art: '...'` der Unions mit dem jeweiligen Pruefer;
dazu prueft er, dass der Kern nicht mehr still verwirft.
GEGENPROBE gemacht: Mit zurueckgenommener Reparatur schlaegt er fehl
("expected [ 'titel-lesen' ] to deeply equal []"), mit Reparatur ist
er gruen. Kein Deko-Test.
Dazu: Der Info-Lauf reicht die URSACHE durch (DiscInfo.ursachen aus den
kritischen MSG-Nummern). Kam nichts heraus und MakeMKV hat einen Grund
genannt, steht im Dialog der Grund statt "keine Titel gefunden" — beim
5042-Zustand also die Abhilfe (Disc neu einlegen, Laufwerk ab- und
anstecken, notfalls neu starten) statt eines Fingerzeigs auf die Disc.
Neu test/messung.titelwahl.test.ts — faehrt am echten Laufwerk genau den
Weg des Kerns nach (Info-Lauf, Vorauswahl, Dialog-Fehlertext).
Zweimal in dieselbe Heredoc-Falle getappt (AGENTS.md warnt davor):
Escape-Sequenzen wurden halbiert, ein rohes CR landete in makemkv.ts.
Beides korrigiert; der Hygiene-Waechter haette das CR auch gefangen.
260 Tests gruen (vorher 257), Typpruefung sauber. Version 5.3.1.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
67 lines
3.2 KiB
TypeScript
67 lines
3.2 KiB
TypeScript
// MESSUNG am ECHTEN Laufwerk: Was bekäme der Auswahl-Dialog zu sehen?
|
|
//
|
|
// RIPPY_MESSUNG_DISC=G npx vitest run test/messung.titelwahl.test.ts --reporter=verbose
|
|
//
|
|
// Der Anlass (01.09.2026): Der Dialog blieb ewig bei „Rippy liest die
|
|
// Titel der Disc …". Ursache war NICHT der Info-Lauf, sondern der
|
|
// Nachrichten-Prüfer: `istFensterNachricht` kannte 'titel-lesen' nicht,
|
|
// der Kern verwarf die Anfrage — still. Gemessen wurde danach:
|
|
//
|
|
// makemkvcon -r --noscan info dev:G: -> 0,7 s, TCOUNT:0
|
|
// MSG:5042 „konnte keine verwendbaren optischen Laufwerke finden"
|
|
// MSG:2024 „Unknown device - 'G:'" · MSG:5010 „Öffnen der Disk schlug fehl"
|
|
//
|
|
// Der Info-Lauf HING also nie. Diese Messung fährt genau den Weg des
|
|
// Kerns nach — Info-Lauf, Vorauswahl, und was als Fehlertext im Dialog
|
|
// stünde. Sie läuft nur auf Verlangen und nur unter Windows.
|
|
import { describe, expect, it } from 'vitest'
|
|
|
|
const buchstabe = (process.env.RIPPY_MESSUNG_DISC ?? '').replace(/:$/, '').toUpperCase()
|
|
const messen = /^[A-Z]$/.test(buchstabe) && process.platform === 'win32'
|
|
|
|
describe.skipIf(!messen)('Titelwahl am echten Laufwerk', () => {
|
|
it('liest die Titel und baut die Vorauswahl', { timeout: 320_000 }, async () => {
|
|
const { finden } = await import('../src/kern/werkzeuge/katalog')
|
|
const { titelInfoLesen } = await import('../src/kern/rip/makemkv')
|
|
const { titelVorauswahl } = await import('../src/kern/rip/titelwahl')
|
|
const { discTitel } = await import('../src/kern/metadaten/discmerkmale')
|
|
|
|
const programm = finden('makemkv', '')
|
|
expect(programm.length, 'makemkvcon nicht gefunden').toBeGreaterThan(0)
|
|
|
|
const geraetepfad = `\\\\.\\${buchstabe}:`
|
|
const merkmale = discTitel(geraetepfad)
|
|
console.log(`MESSUNG Disc sagt: "${merkmale.titel}" · Folgen ${merkmale.folgen} · Serie ${merkmale.istSerie}`)
|
|
|
|
const start = Date.now()
|
|
const info = await titelInfoLesen(programm, geraetepfad)
|
|
console.log(`MESSUNG Info-Lauf: ${((Date.now() - start) / 1000).toFixed(1)} s, ${info.titel.length} Titel`)
|
|
if (info.ursachen.length > 0) console.log(`MESSUNG Ursachen: ${info.ursachen.join(' · ')}`)
|
|
|
|
const wahl = titelVorauswahl(info.titel, {
|
|
istSerie: merkmale.istSerie,
|
|
folgen: merkmale.folgen,
|
|
})
|
|
console.log(`MESSUNG Einordnung: ${wahl.einordnung} (unsicher: ${wahl.unsicher})`)
|
|
for (const t of wahl.titel) {
|
|
const min = Math.floor(t.dauerS / 60)
|
|
console.log(
|
|
`MESSUNG ${t.gewaehlt ? '[x]' : '[ ]'} Titel ${t.nr} | ${min}:${String(t.dauerS % 60).padStart(2, '0')} min` +
|
|
` | ${(t.groesseBytes / 1e9).toFixed(2)} GB | ${t.kapitel} Kap. | ${t.rolle} | ${t.grund}`,
|
|
)
|
|
}
|
|
// Was im Dialog als Fehler stünde — genau die Regel aus kern/index.ts.
|
|
const dialogFehler = info.titel.length === 0 && info.ursachen.length > 0 ? info.ursachen.join(' · ') : ''
|
|
console.log(`MESSUNG Dialog-Fehlertext: ${dialogFehler.length > 0 ? dialogFehler : '(keiner)'}`)
|
|
|
|
// Der Lauf muss ANTWORTEN — leer sein darf er, hängen nicht.
|
|
expect(Date.now() - start).toBeLessThan(300_000)
|
|
})
|
|
})
|
|
|
|
describe.skipIf(messen)('Titelwahl-Messung übersprungen', () => {
|
|
it('läuft nur mit RIPPY_MESSUNG_DISC=<Laufwerksbuchstabe> unter Windows', () => {
|
|
expect(true).toBe(true)
|
|
})
|
|
})
|