# 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 D1–D3 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 | D1–D3 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 4–7 ü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 ```