# Verifikation: ereigniszustellung-und-hostgrenzen Stand nach Behebung: 05.09.2026, aktueller Arbeitsbaum auf `57d6386`. **Alle fünf Verifikationsbefunde sind behoben.** Die ursprünglichen sechs Review-Proben bestehen unverändert in ihren Erwartungen; zusätzlich wurden sie in die Workspace-Regressionen übernommen und um verwandte Pfade ergänzt. | Dimension | Ergebnis | | --- | --- | | Vollständigkeit | 12/12 Tasks erledigt; ursprüngliche Zuordnung der 9 Delta-Requirements und 33 Szenarien um Korrektur-Nachweise ergänzt. | | Korrektheit | 419 Workspace-Tests und alle sechs separaten Review-Proben bestanden; keine offenen V1–V5-Befunde. | | Kohärenz | Gemeinsame Zustellung auch während Eingabe und nach Menüschluss; synchrone LOAD-Wirkungen getrennt, klassische Quellpriorität erhalten. | ## Korrekturen und Regressionen | Befund | Behebung | Nachweis in `crates/tb-vm/tests/events.rs` | | --- | --- | --- | | V1 | Fortsetzbarer Konsolenleser für INPUT, LINE INPUT, INPUT$ und RANDOMIZE ohne Argument. Frame hält Teiltext/Restlänge, Stack hält Operanden und Referenzen. Trap-Unwinding erhält gemeinsam genutzte Locals; Fehler und RETURN label verwerfen abgebrochene Eingaben. | Ursprüngliche Signalprobe; Teiltext/BYREF/Ausdruck, verschachtelte Eingaben mit STOP/CONT, Timer, Redo, lokaler Fehlerhandler, RANDOMIZE und RETURN label. | | V2 | Implizite Objektaufrufe stellen ausschließlich notwendige LOAD-Handler zu. Deren Rückkehr zieht keine unabhängigen Forms-Ereignisse vor. | LlGg mit Control-Argument, Property-Lesen/-Schreiben, Refresh und LOAD; bestehende Load-vor-Show- und Unload-Tests. | | V3 | Nach dem Schließen des Menüs wird die gemeinsame Auswahl vor jedem erneuten Warten wiederholt. | Esc bei Zeit 0, UEVENT zugestellt nach genau einem Warteaufruf; bestehende Menüsperrtests einschließlich Forms-Timer. | | V4 | Modale und modellose Schleifen beenden bei EOF erst, wenn kein Handler mehr zugestellt wurde. | Ursprüngliche MouseDown/Unload-Probe; jeweils zwei Mausereignisse vor EOF ergeben MM in beiden Schleifen. | | V5 | Getrappte Tasten am Queue-Anfang werden vor der klassischen Quellenauswahl gemeldet. | Gleichzeitiges KEY/UEVENT ergibt KU; Maus vor getrappter Taste bleibt MK. | ## Ursprüngliche Befunde — historischer Stand vor der Behebung Die folgenden Ist-Beobachtungen und Ursachen dokumentieren den fehlgeschlagenen Review vor diesen Korrekturen. Alle fünf sind durch die Nachweise oben geschlossen. ### V1 — Während blockierender Eingabe werden eintreffende Traps nicht zugestellt (hoch) **Reproduktion:** `ON SIGNAL(2) GOSUB H`, `SIGNAL(2) ON`, danach INPUT. Der Host liefert erst im blockierenden `next_event(true)` Signal(2), beim nächsten Aufruf Eingabeende. Der Handler H würde `PRINT "H"` und END ausführen. **Ist:** INPUT, LINE INPUT und INPUT$(1) enden jeweils mit Fehler 62, H läuft nicht. Ohne nachfolgende Eingabe kann die Laufzeit stattdessen erneut blockieren, obwohl der Signal-Trap schon ansteht. **Soll:** Vor dem erneuten Blockieren muss der erlaubte Zustellpunkt genutzt werden; H beendet das Programm, Ausgabe H, kein Fehler 62. **Ursache:** Der einmalige VM-Check vor der Eingabeinstruktion genügt nicht. [RtState::naechste_taste](../../../../crates/tb-runtime/src/builtins.rs#L209) pumpt innerhalb seiner Schleife weitere Ereignisse und blockiert erneut, ohne zur VM-Zustellung zurückzukehren. Dasselbe betrifft die drei genannten Eingabefunktionen über ihren gemeinsamen Leser. **Vertrag:** `ereignissteuerung` / Abschließende Liste der Zustellpunkte, Signal-Trap auf Betriebssystemsignalen; Design D2; Task 2.1. **Korrektur:** Blockierende Eingabe so fortsetzbar machen, dass nach einem Nicht-Tasten-Ereignis und vor dem nächsten Host-Warten die gemeinsame VM-Zustellung laufen kann. Eingabepuffer, Referenzen und Operanden erhalten. ### V2 — Control-Argumente stellen wartende Forms-Handler mitten in einer Anweisung zu (hoch) **Reproduktion:** Fokuswechsel Text1 → Text2. Text1_LostFocus ruft als erste wirksame Anweisung `CALL Mark(Text1)` auf; Mark hängt L an eine gemeinsame Variable, LostFocus danach l. Text2_GotFocus hängt G und g an. **Ist:** `GgLl`. **Soll:** `LlGg`. **Ursache:** [Instr::PushObject](../../../../crates/tb-vm/src/interp.rs#L1344) ruft nach dem Ablegen eines bereits geladenen Control-Objekts bedingungslos `dispatch_next_form_event` auf. Dadurch läuft GotFocus noch vor dem eigentlichen CALL, obwohl weder DOEVENTS noch modales Warten vorliegt. Der Schutz am ersten Stmt-Eintritt und `forms_frei` werden damit umgangen. **Vertrag:** Fokus, Tabreihenfolge und Access-Keys / Handlerwirkungen in Fokusreihenfolge; Abschließende Liste der Zustellpunkte; Design D1/D2; Tasks 1.2 und 2.1. **Korrektur:** Unabhängig wartende Ereignisse aus Objekt-Opcodes heraus nicht zustellen. Notwendige synchrone Load-/Unload-Wirkungen gezielt behandeln; alle Aufrufer von `dispatch_next_form_event` gegen dieselben Zustellregeln prüfen. ### V3 — Menüschließen während SLEEP führt zu erneutem Warten trotz bereitem Trap (hoch) **Reproduktion:** Menü offen, UEVENT anstehend, `SLEEP 60`. Der erste Host-Warteaufruf liefert Esc bei unveränderter virtueller Zeit 0. **Ist:** Esc schließt das Menü; die VM wartet ein zweites Mal bis Hostzeit 60.000 ms. Erst dann läuft der UEVENT-Handler. **Soll:** Nach Esc läuft der freigegebene Handler ohne zweiten Warteaufruf und beendet SLEEP sofort. Bei einer Wartephase ohne eigene Deadline droht entsprechend Warten auf ein weiteres externes Ereignis. **Ursache:** Die klassische Trap-Auswahl in [Vm::zustellen](../../../../crates/tb-vm/src/interp.rs#L625) erfolgt vor der Eingabeverarbeitung. Nachdem Esc die Menüsperre aufgehoben hat, kehrt die Methode ohne erneute Auswahl zurück; [SLEEP](../../../../crates/tb-vm/src/interp.rs#L707) ruft unmittelbar wieder `warten` auf. **Vertrag:** Menüsystem / Traps ruhen im geöffneten Menü und werden danach fortgesetzt; Abschließende Liste der Zustellpunkte / SLEEP endet durch Ereignis; Design D2/D3; Tasks 2.1/2.2. **Korrektur:** Nach einer Eingabe, die die Zustellbarkeit verändert, bereite Ereignisse vor jedem weiteren blockierenden Warten erneut auswählen. ### V4 — Modale Schleife verliert bereits angenommenes Ereignis unmittelbar vor EOF (hoch) **Reproduktion:** `Form1.Show 1`; nach der zweiten Anzeige liefert der Host MouseDown und unmittelbar danach Eingabeende. Der MouseDown-Handler hängt M an und entlädt das Formular. **Ist:** VM meldet Ended, die gemeinsame Variable bleibt leer; der Handler wurde nicht ausgeführt. **Soll:** Das vor EOF eingetroffene Mausereignis wird noch wirksam, Ergebnis M, Formular entladen. **Ursache:** In der [modalen Run-Schleife](../../../../crates/tb-vm/src/interp.rs#L890) setzt `zustellen` einen Handlerframe auf. Direkt danach wird ungeachtet von `dispatched` wegen `rt.ende` zurückgekehrt. Das Ereignis ist bereits aus der Queue entfernt und wird stillschweigend verloren. **Vertrag:** Mausereignisse in Zellenkoordinaten / Reihenfolge bis zur beobachtbaren Handlerausführung; Design D1/D2; Tasks 1.2/2.1. **Korrektur:** EOF als Ende der Eingabequelle behandeln und bereits angenommene Ereignisse/Handler geordnet abarbeiten, bevor die modale Ausführung endet. ## Ursprüngliche weitere Designabweichung ### V5 — Gleichzeitig wartende klassische Quellen erhalten eine andere Priorität (mittel) **Reproduktion:** KEY(15) ON und UEVENT ON. Vor demselben Zustellpunkt liegen eine passende Taste in der Eingabequeue und ein gemeldeter UEVENT vor. Die Handler hängen K bzw. U an. **Ist:** `UK`. **Soll:** `KU` gemäß der bestehenden klassischen Quellpriorität. **Ursache:** [Vm::zustellen](../../../../crates/tb-vm/src/interp.rs#L631) wählt bereits gemeldete Traps aus, bevor die wartende Taste durch `taste_trappen` gemeldet wird. Die Prioritätsauswahl in Traps sieht die Taste deshalb noch nicht. Früher erfolgte die Tastenprüfung vor der gemeinsamen Trap-Auswahl. **Vertrag:** Design / Non-Goals: keine Änderung der festgelegten Priorität gleichzeitig fälliger klassischer Quellen; D1/D2; Task 2.1. **Korrektur:** Fälligkeitserfassung und Trap-Auswahl so koordinieren, dass die bestehende Quellpriorität erhalten bleibt, ohne die Reihenfolge zwischen Maus- und Tasteneingaben wieder nach Quellarten umzusortieren. ## Abdeckung und positive Nachweise | Delta-Requirement | Nachweis / Einschränkung | | --- | --- | | Ereignisquellen mit Zeit vom Host | Host-Warteschnittstelle, eingefrorene virtuelle Zeit, klassischer Timer und Forms-Timer-SLEEP getestet. Keine reale Rückfalluhr in der VM; Zustellung nach Menüschluss durch V3-Regression abgesichert. | | Mausereignisse in Zellenkoordinaten | Mapper-/Bounds-Tests, leere Verbraucher, KM/MK-Korpus und gemischte Eingaben. V4-Regressionen sichern EOF in modalen und modellosen Schleifen ab. | | Abschließende Liste der Zustellpunkte | DOEVENTS-Wert, SLEEP, vorbereitete und erst beim Warten eintreffende INPUT-Ereignisse getestet; V1–V3 geschlossen. | | Getrappte Tasten verlassen den Eingabestrom | ON/OFF/STOP × INKEY$/INPUT/LINE INPUT/INPUT$, mehrfaches STOP-Merken und Dialogrestpuffer getestet. | | Signal-Trap auf Betriebssystemsignalen | Beide Kennungen, Maskierung und ungültige Werte getestet. V1-Regression sichert Signalzustellung während blockierender Eingabe ab. | | Fokus, Tabreihenfolge und Access-Keys | Tab/Shift-Tab, BackTab-Mapper, Access-Keys und einfacher LostFocus→GotFocus-Lauf belegt. V2-Regressionen sichern Control-Argumente und verwandte Objektaufrufe ab. | | Menüsystem | Menüeigenschaften/-auswahl und Sperre an normalen Grenzen getestet. V3-Regression sichert Freigabe innerhalb von SLEEP ab. | | Zellenpuffer ohne Terminalabhängigkeit | Separater Workspace kompiliert FRM/VM und liefert KM; 16 Pakete im normalen Dependency-Graph, keines davon crossterm/ratatui/signal-hook. CLI schaltet das Feature ausdrücklich ein. | | Ereigniszustellung an Anweisungsgrenzen | Bestehende SUB-/GOSUB-/BYREF-/RESUME-Tests und Host ohne erlaubte Uhrabfragen grün. V2/V5-Regressionen sichern zulässige Handlerbeginn-Reihenfolge und klassische Priorität ab. | Erneut ausgeführt: - `cargo test --workspace`: **419 bestanden, 0 fehlgeschlagen, 1 ignoriert**. - `openspec validate ereigniszustellung-und-hostgrenzen --strict`: gültig. - Isolierter Einbetter mit CaptureHost: **KM**, Dependency-Prüfung erfolgreich. - Separate [Review-Proben](review-probes.rs): **6 bestanden, 0 fehlgeschlagen**. Die Kontrollprobe prüft Maus unmittelbar vor getrappter Taste. - Workspace-Ereignistests: **25 bestanden**, einschließlich Frist-Watchdog. - Keine bestehenden Sollausgaben neu aufgezeichnet oder geändert. Warnings-denied Clippy, Formatprüfungen und Compile-/VM-Benchmarks wurden nach der Behebung erneut erfolgreich ausgeführt; Zahlen siehe [verification.md](verification.md). Kein interaktiver Terminaltest und keine Windows-/Linux-Matrix. Die Proben speisen Ereignisse gezielt über Host ein und benötigen weder echte Signale noch reale Wartefristen. ## Review-Proben reproduzieren Im Repository-Wurzelverzeichnis ausführen. Das erzeugt ausschließlich einen separaten temporären Cargo-Treiber und referenziert den aktuellen Produktcode: ```sh python3 - <<'PY' from pathlib import Path import json, subprocess, tempfile root = Path.cwd() p = Path(tempfile.mkdtemp(prefix='tb-review-')) manifest = '[package]\nname="tb-review"\nversion="0.0.0"\nedition="2021"\n[workspace]\n' manifest += '[[test]]\nname="befunde"\npath=' + json.dumps(str(root / 'openspec/changes/archive/2026-09-05-ereigniszustellung-und-hostgrenzen/review-probes.rs')) + '\n[dependencies]\n' for name in ['tb-vm', 'tb-runtime', 'tb-ui', 'tb-frontend']: manifest += name + ' = { path = ' + json.dumps(str(root / 'crates' / name)) + ' }\n' (p / 'Cargo.toml').write_text(manifest) subprocess.run(['cargo', 'test', '--manifest-path', str(p / 'Cargo.toml'), '--test', 'befunde', '--', '--nocapture'], check=True, timeout=120) PY ``` Alle sechs Proben müssen auf dem korrigierten Stand bestehen. Ihre Erwartungen wurden auch in den regulären Workspace-Testlauf übernommen.