Files
TerminalBasic/openspec/changes/archive/2026-09-05-ereigniszustellung-und-hostgrenzen/review.md

192 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 V1V5-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; V1V3 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.