Files
TerminalBasic/openspec/changes/archive/2026-09-05-forms-zustand-und-bedienung/review.md

189 lines
11 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: forms-zustand-und-bedienung
Abnahme vom 05.09.2026, umgesetzt auf Basis von `644a862`.
Nach erfolgreicher Verifikation am selben Tag synchronisiert und archiviert. **V1, V2 und V3 sind behoben. Keine
offenen Befunde im Change.** Beide Delta-Requirements, alle acht Szenarien,
die ergänzten Abnahmetasks und D1D3 wurden erneut gegen Code und Tests geprüft.
| Dimension | Ergebnis |
| --- | --- |
| Vollständigkeit | 7/7 Tasks vollständig umgesetzt; beide Delta-Requirements mit allen acht Szenarien abgedeckt. Task 4.2 einschließlich Mindestmaßen und verwandten Zeichenpfaden erfüllt. |
| Korrektheit | 428 Workspace-Tests und alle vier Review-Proben bestanden. Keine kritischen Befunde, Warnungen oder offenen Verbesserungsvorschläge. |
| Kohärenz | D1D3 umgesetzt. Die stabile Sortierung erhält die Auswahl; Simple-ComboBox und ListBox verwenden denselben Listenrenderer. |
## V3 — behoben; historischer Befund vor der Korrektur
Die folgenden Beobachtungen gelten für den vorherigen Stand. Die Korrektur
und ihre erweiterten Nachweise stehen im nächsten Abschnitt.
### V3 (ursprünglich mittel): Listenrenderer überschreitet zulässige Mindestmaße
**Reproduktion:** Sichtbare Simple-ComboBox mit Width = 1, Height = 5,
Left = 2, Top = 2 in einem ausreichend großen Formular. Gegenüber dem
Bildschirm mit ausgeblendetem Control werden auch die Zellen in Spalte 4,
Zeilen 47 überschrieben; die einzige erlaubte Controlspalte ist Spalte 3.
Eine ListBox mit Width = 1 hat denselben horizontalen Überlauf. Bei einer
ListBox mit Width = 6, Height = 1 wird zusätzlich die vollständige Zeile
unterhalb des Controls gezeichnet. Benachbarte Inhalte können dadurch
überschrieben werden.
**Ursache:** [list_lines](../../../../crates/tb-ui/src/forms.rs#L2047) verwendet
`box_lines`, das Breite und Höhe auf mindestens 2 erhöht. Für Width < 3
kehrt der Listenrenderer ohne Begrenzung zurück; im ListBox-Pfad fehlt
auch eine abschließende Höhenbegrenzung. `write_at` begrenzt ausschließlich
auf den Bildschirm. [Width und Height](../../../../crates/tb-frontend/src/forms.rs#L202)
lassen ausdrücklich den Wert 1 zu.
**Vertrag:** Task 4.2 verlangt die Prüfung von Kürzung und Größenbegrenzung
für die Simple-ComboBox. Der neue gemeinsame Renderer übernimmt die bereits
vorhandene Mindestmaß-Lücke auch für die nun dargestellte Simple-Liste.
Die bestehenden Regressionen prüfen Breite 6 und kleine Combo-Höhen,
aber weder Breite 1 noch die ListBox-Höhe 1.
**Behebung:** Die gemeinsame Listenausgabe auf die tatsächlich angeforderte
Breite und Höhe begrenzen. Mindestbreite 1 für beide Klassen und Mindesthöhe 1
für ListBox durch Bildschirmprüfungen absichern; normale Maße beibehalten.
**Nachweis:** `listen_bleiben_auch_bei_minimalmassen_im_controlrechteck` in
[review-probes.rs](review-probes.rs) prüft den tatsächlichen Bildschirm vor
und nach Einblenden des Controls. Die Kontrollfälle ComboBox 15×5 und
ListBox 6×4 bleiben innerhalb ihrer Grenzen; die drei Mindestmaßfälle
schlugen vor der Behebung fehl und bestehen jetzt mit unveränderten Erwartungen.
## Behebung und Regressionen
- **V1:** Gemeinsame Sortierung für Laufzeit- und initiale Property-Zugriffe.
Sortierung ohne Beachtung der Groß-/Kleinschreibung; ursprüngliche Indizes
erhalten die Auswahl auch zwischen gleichen Texten. Regressionen prüfen
beide Klassen, alle ComboBox-Stile, Basis-/Arrayindex 0 und dynamische
Arrayelemente, wiederholtes Sortieren sowie anschließendes Einfügen/Entfernen.
Der Formular-Korpus prüft jetzt das Einschalten von Sorted nach dem Befüllen
mit unveränderter Sollausgabe.
- **V2:** Simple verwendet den bestehenden Listenrenderer samt Rahmen und
Auswahlmarkierung. Der Bildschirmtest prüft tatsächliche Einträge, Auswahl,
Entfernen und erhaltenen Eingabetext. V3 ergänzt die Mindestmaßabnahme.
- **V3:** `list_lines` begrenzt sämtliche Rahmenzeilen auf die angeforderte
Breite und Höhe, auch vor dem frühen Rücksprung für schmale Controls.
Alle Aufrufer (ListBox, Simple-ComboBox, DirListBox und FileListBox)
verwenden diese Korrektur. Die gemeinsame Textkürzung zählt dieselben
Zellenbreiten wie TextScreen und behandelt Steuerzeichen als Leerzeichen.
`TextScreen::print_line` verwendet den vorhandenen Zellenschreibpfad ohne
Umbruch oder Scrollen; `write_at` nutzt ihn für Forms-Ausgaben.
Das normale BASIC-PRINT behält Umbruch und Scrollen.
Die zusätzliche Regression
`listenrenderer_haelt_zellgrenzen_auch_an_bildschirmraendern_ein` vergleicht
alle Bildschirmzellen außerhalb des jeweiligen Controlrechtecks einschließlich
Farben und Unicode-Fortsetzungsmarkierung. **3.360 Kombinationen bestehen:**
ListBox, Combo-Stile 0/1/2, DirListBox, FileListBox und DriveListBox;
Basis- und dynamische Arrayelemente; Breiten 1/2/3/6/15/254 und Höhen
1/2/3/5/254; vier Positionen einschließlich rechtem/unterem Bildschirmrand
und vollständig außerhalb; leere und gefüllte Listen mit langen Texten,
breiten Unicode-Zeichen und CR/LF. Vor der Korrektur schlug dieser Test
bereits bei einer ListBox 1×1 fehl.
`ui_zeile_bleibt_am_rand_ohne_umbruch_oder_scrollen` prüft zusätzlich
vollständig passende und nicht passende breite Zeichen, Farben, CR/LF
sowie den rechten/unteren Rand und einen eigenen VIEW-PRINT-Bereich.
Bestehende Zeichenbild-, Auswahl-, Timer-, VM- und Korpustests bestehen
unverändert in ihren Erwartungen.
## Ursprüngliche Befunde — historischer Stand vor der Behebung
Die folgenden Ist-Beobachtungen dokumentieren den fehlgeschlagenen Review.
Beide Befunde sind durch die Nachweise oben geschlossen.
### V1: Nachträgliches Sorted lässt den Listeninhalt unsortiert
**Reproduktion:** In ListBox oder ComboBox zuerst `b`, dann `a` hinzufügen,
Eintrag 0 (`b`) auswählen, anschließend `Sorted = -1` setzen und `c`
hinzufügen. **Ist:** `List = [b, a, c]`, ListIndex = 0.
**Soll:** sortierte Liste `[a, b, c]` mit weiterhin ausgewähltem `b`, Index 1.
Der [Property-Setter](../../../../crates/tb-ui/src/forms.rs#L430) speichert
SORTED ohne Sortierung des vorhandenen Inhalts. [ADDITEM](../../../../crates/tb-ui/src/forms.rs#L1025)
verwendet anschließend `partition_point`, das bereits sortierte Daten
voraussetzt. Der Fehler tritt bei beiden Klassen auf.
**Vertrag:** Delta „Steuerelemente mit Listeninhalt“, Sortierung bei
Sorted = 1 und Konsistenz von List/ListIndex/Text; Task 1.1.
Die Tests setzen Sorted ausschließlich vor dem Befüllen und decken den
zulässigen Wechsel an einer gefüllten Liste nicht ab.
**Behebung:** Beim Einschalten der Sortierung vorhandene Einträge sortieren
und die Auswahl ihrem bisherigen Eintrag zuordnen; anschließend Einfügen
und Entfernen weiterhin konsistent halten. Regression für beide Klassen,
einschließlich der Auswahl, ergänzen.
### V2: ComboBox.Style 1 zeichnet keine Listeneinträge
**Reproduktion:** Sichtbare ComboBox mit Style = 1, Width = 15, Height = 5,
Text = `frei`; ADDITEM `apfel` und `birne`. **Ist:** Der Bildschirm zeigt
`frei` und einen leeren eingerahmten Listenbereich. **Soll:** Die beiden
Einträge erscheinen in diesem ausreichend großen Bereich.
Der [Renderer](../../../../crates/tb-ui/src/forms.rs#L2184) hängt für Style 1
nur `box_lines` mit leerem Inhalt an. Er liest die vorhandenen Listeneinträge
für diesen Bereich nicht. Die Probe prüft zuerst, dass das Control über den
Text `frei` tatsächlich sichtbar ist, und danach die beiden Listeneinträge.
**Vertrag:** Delta „Steuerelemente mit Listeninhalt“ verlangt die Darstellung
aller drei ComboBox-Stile; die [Forms-Referenz](../../../../docs/forms-referenz.md#L180)
zeigt für Simple einen sichtbaren Listeneintrag. Task 1.1 verlangt die Prüfung
aller Stile. Der bestehende Stiltest prüft nur Zeilenzahl und Präfix;
die neuen Auswahltests prüfen nur die oberste Zeile.
**Behebung:** Den vorhandenen Listeninhalt samt Auswahl im Simple-Bereich
darstellen und dessen Inhalt mit einem Bildschirmtest absichern. Die bereits
festgelegten Zeichenformen beibehalten.
Beide Lücken bestanden bereits vor diesem Change. Es handelt sich um
verbleibende Abweichungen im übernommenen Listen-Requirement, nicht um neu
eingeführte Regressionen. Die Korrekturen wurden nach diesem Review umgesetzt.
## Szenarioabdeckung und positive Nachweise
| Delta-Szenario | Nachweis |
| --- | --- |
| Element hinzufügen | Bestehender Sorted-Listentest und neue Auswahlmatrix: a/b, ListCount und List(i). Nachträgliches Einschalten einschließlich stabiler Auswahl durch V1-Regressionen abgesichert. |
| Keine Auswahl | ListIndex 1 bei leerer Liste und nach Entfernen der Auswahl. |
| Auswahl ausdrücklich aufheben | Modellmatrix für ListBox und ComboBox-Stile 0/1/2; Formular-Korpus. |
| Eintrag vor Auswahl einfügen | Sortierte/unsortierte Modellmatrix prüft Indexverschiebung und erhaltenen Text. |
| Timer feuert im Abstand | Zwei Ereignisse nach 250 ms aktiver Zeit, mehrere Timer und Arrayelemente, identische Wiederholung. |
| Interval 0 schaltet ab | Modelltest, Arrayindex-0-Reset und Änderung im VM-Handler. |
| Späte Aktivierung | VM: direkte Property, Control-Parameter und Enabled; Aktivierung bei 1000, still bei 1099, einmal bei 1100 ms. Zusätzliche erfolgreiche Probe für spät geladenes Timer-Arrayelement. |
| Abschalten verwirft anstehende Ereignisse | Interval/Enabled-Reset, Array-Entladen und Handlerwechsel mit altem Rückstau. |
Erneut ausgeführt:
- `cargo test --workspace`: **428 bestanden, 0 fehlgeschlagen, 1 ignoriert**.
Ignoriert bleibt der Generator für Sollausgaben; keine Golden Files geändert.
- `openspec validate forms-zustand-und-bedienung --strict`: gültig.
- `git diff --check`: erfolgreich.
- [Zusätzliche Review-Proben](review-probes.rs): **4 bestanden, 0 fehlgeschlagen**.
`cargo clippy -p tb-ui -p tb-vm -p tb-runtime --all-targets --all-features -- -D warnings`
und `cargo fmt --all -- --check` wurden nach der Behebung erfolgreich ausgeführt. Kein interaktiver Terminal-/VBDOS-Vergleich und
keine Windows-/Linux-Matrix. Die Darstellungsprobe prüft den echten Zellenpuffer
ohne Terminal; Timerprüfungen verwenden ausschließlich virtuelle Hostzeit.
## Review-Proben reproduzieren
Im Repository-Wurzelverzeichnis ausführen; erzeugt einen separaten temporären
Cargo-Treiber. Auf dem korrigierten Stand bestehen alle vier Proben.
```sh
python3 - <<'PY'
from pathlib import Path
import json, subprocess, tempfile
root = Path.cwd()
p = Path(tempfile.mkdtemp(prefix='tb-forms-review-'))
manifest = '[package]\nname="tb-forms-review"\nversion="0.0.0"\nedition="2021"\n[workspace]\n'
manifest += '[[test]]\nname="probes"\npath=' + json.dumps(str(root / 'openspec/changes/archive/2026-09-05-forms-zustand-und-bedienung/review-probes.rs')) + '\n[dependencies]\n'
for name in ['tb-ui', 'tb-vm', 'tb-runtime', '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'), '--offline', '--test', 'probes', '--', '--nocapture'], check=True, timeout=120)
PY
```