# Verifikation: projektmodule-und-kompilat

Geprüft am 05.09.2026: Arbeitsbaum auf Basis von `58b1f62`, alle sieben
Delta-Requirements mit 21 Szenarien, Tasks, D1–D4, Implementierung und
Abnahmenachweis. **Sechs offene Befunde; der Change ist nicht abnahmebereit.**
Die vorherige Aussage vollständiger Umsetzung wird durch diese Verifikation
korrigiert. Der Produktcode wurde bei diesem Review nicht verändert.

| Dimension | Ergebnis |
| --- | --- |
| Vollständigkeit | 7/7 Tasks sind angehakt und alle sieben Requirements haben Implementierungspfade. Die Befunde widerlegen jedoch die vollständige Erfüllung insbesondere von 1.1, 1.2 und 2.2; Checkboxen allein sind kein Abnahmenachweis. |
| Korrektheit | 437 bestehende Workspace-Tests bestanden; zusätzliche unabhängige Review-Proben: 1 bestanden, 6 fehlgeschlagen. Vier Kernfunktionslücken (CRITICAL), zwei weitere Vertragsabweichungen (WARNING). |
| Kohärenz | D4 und die FRM-Grundpfade von D3 sind umgesetzt. Quellorte und Modulkontexte gehen in weiteren Absenkungs-/Importpfaden verloren; der gemeinsame Objektraum berücksichtigt `$FORM` nicht vollständig. |

## CRITICAL — vor Archivierung beheben

### V1 — Quellorte und Breakpoints fehlen an Zweig- und Schleifengrenzen

**Priorität: hoch.** Delta „Zeilentabelle für Fehlerortung“ und
„Unterbrechbare step()-Ausführung“, D1, Tasks 1.1/2.2.

Die Fehlerortung funktioniert bei einfachen Anweisungen, nicht jedoch bei
weiteren ausführbaren Teilen zusammengesetzter Anweisungen:

| Probe | Erwartet | Beobachtet |
| --- | --- | --- |
| `IF 0 THEN` / `PRINT 1` / `ELSEIF 1/0 THEN` | Fehler 11 in Zeile 3 | Zeile 1 |
| `SELECT CASE 1` / `CASE 1/0` | Fehler 11 in Zeile 2 | Zeile 1 |
| `FOR i%=32767 TO 32767` / `PRINT 1` / `NEXT` | Überlauf beim NEXT in Zeile 3 | Zeile 2 |
| `DO` / `PRINT 1` / `LOOP UNTIL 1/0` | Fehler 11 in Zeile 3 | Zeile 2 |
| ELSEIF-Bedingung aus `cond.bi:1` | Include-Datei `cond.bi` | `main.bas:1:1` |
| Breakpoint auf ELSEIF in Zeile 3 | Halt vor Bedingung | Programm endet ohne Halt |

**Ursache:** [ELSEIF-Absenkung](../../../../crates/tb-frontend/src/sema.rs#L1937)
und [CASE-Absenkung](../../../../crates/tb-frontend/src/sema.rs#L2914) verwenden
den Quellort des äußeren Statements. NEXT-/LOOP-Positionen werden nicht
vollständig durch AST/HIR bis zur auszuführenden Grenze getragen. Der
[FOR-Codegenerator](../../../../crates/tb-vm/src/codegen.rs#L737) dokumentiert
selbst die bisherige Verschiebung einer genauen NEXT-Zuordnung auf Phase 5;
das widerspricht der hier übernommenen vollständigen Quellortanforderung.

**Korrektur:** Physische Positionen aller ausführbaren Zweig-/Schleifenteile
bereits beim Parsen erhalten und passende Source-/Stmt-Grenzen ausgeben.
Nicht nur Fehlermeldungen umbenennen: Breakpoints, Einzelschritt und RESUME
müssen dieselbe richtige Zuordnung verwenden. Numerische ERL-Labels separat
lassen. Probe `v1_zweige_und_schleifen_behalten_eigene_quellorte`.

### V2 — Deklarationsimport verändert Typkontext und Abhängigkeitsreihenfolge

**Priorität: hoch.** Projektpipeline und vollständige Prozedursignaturen,
D2, Tasks 1.2/2.1.

Drei zulässige Mehrmodulkonstellationen werden abgewiesen:

- MAIN ruft `Doppelt(3)` auf; LIB enthält `DEFINT A-Z` und
  `FUNCTION Doppelt(x)`. Erwartete Ausgabe 6, tatsächlich
  `Parameter type mismatch: MAIN!DOPPELT`.
- MAIN enthält `CONST A=3` und verwendet B; LIB enthält `CONST A=3` und
  `CONST B=A+1`. Erwartet B=4, tatsächlich `LIB.bas:2:1: Invalid constant`.
- Beide Module enthalten denselben TYPE Inner. LIB definiert anschließend
  TYPE Outer mit einem Feld `i AS Inner`; MAIN verwendet Outer.
  Erwartet korrektes Layout und Feldausgabe 3, tatsächlich `Type not defined`
  an der gültigen Outer-Definition sowie Folgefehler für Feldzugriffe.

**Ursache:** [import_declarations](../../../../crates/tb-vm/src/project.rs#L103)
kopiert rohe Signatur-ASTs ohne den DEFtype-Kontext des definierenden Moduls.
Fremde CONST-/TYPE-Knoten werden [vor sämtliche lokalen Deklarationen
gehängt](../../../../crates/tb-vm/src/project.rs#L158). Dadurch fehlen ihnen zu
diesem Zeitpunkt lokal vorhandene Abhängigkeiten. Die Fehlerposition in LIB
ist hier irreführend: Die dortige Originalreihenfolge ist gültig.

**Korrektur:** Exportierte Signaturen und Konstanten im Ursprungskontext
auflösen; abhängige Typdefinitionen mit erhaltenen Identitäten und gültiger
Abhängigkeitsreihenfolge verbinden. Lokale Definitionen und echte Duplikate
nicht wieder durch Text-Deduplizierung verstecken. Probe
`v2_importierte_deklarationen_behalten_kontext_und_abhaengigkeiten`.

### V3 — `$FORM`-Module teilen versehentlich dasselbe Formularobjekt

**Priorität: hoch.** Delta „Objektzugriffe in Grammatik und Semantik“
einschließlich `$FORM`, getrennte Formulare, D2/D3, Task 1.2.

A.bas und B.bas enthalten jeweils `'$FORM`. A setzt `Caption="a"`, ruft eine
SUB aus B auf, die dort `Caption="b"` setzt, und liest anschließend die
eigene Caption. **Erwartet: a. Beobachtet: b.** Das verknüpfte Objektverzeichnis
enthält nur SCREEN und A. Auch `B.Caption` aus A wird als unbekanntes Objekt
abgewiesen. Der Fehler besteht nach TBC-Rundlauf fort.

**Ursache:** [lower_with_forms](../../../../crates/tb-frontend/src/sema.rs#L404)
erweitert pro Modul eine lokale Katalogkopie um das jeweilige `$FORM`-Objekt.
Der Linker übernimmt [nur die Objekte des ersten Moduls](../../../../crates/tb-vm/src/project.rs#L188)
und versetzt die Objektoperanden weiterer Module nicht. Deren Form-ID zeigt
anschließend auf A.

**Korrektur:** Sämtliche FRM- und `$FORM`-Formulare vor der modulweisen
Semantik in einen gemeinsamen Katalog mit stabilen IDs aufnehmen oder die
Objekt-/Ereignisreferenzen beim Linken vollständig versetzen. Zugriffe,
Form_Load-Bindungen und gegenseitige Formreferenzen für beide Quellarten
prüfen. Probe `v3_form_metabefehle_erzeugen_getrennte_formularobjekte`.

### V4 — COMMON verliert Variablenidentität und initialisiert Arrays mehrfach

**Priorität: hoch.** Designrisiko SHARED/COMMON, D2, Task 1.2 und Erhalt der
bestehenden COMMON-Sprachsemantik.

- Bereits ein Modul mit `COMMON SHARED c%, c$` wird mit
  `COMMON type mismatch: C` abgewiesen. Die beiden durch Typ-Suffixe
  verschiedenen Variablen dürfen nebeneinander existieren.
- MAIN und LIB deklarieren dasselbe `COMMON SHARED a%(2)`. MAIN soll
  `a%(1)=7` setzen und LIB den gemeinsamen Wert 7 ausgeben. Stattdessen
  entsteht vor dem Nutzcode `LIB.bas:1:1: Runtime error 10: Duplicate definition`.

**Ursache:** Die [COMMON-Zuordnung](../../../../crates/tb-vm/src/project.rs#L270)
verwendet nur Block und untypisierten Basisnamen. Arrays haben zusätzlich
nur `TypeInit::Empty` als Slotvorbelegung; Elementtyp und Form gehen in der
Vergleichsprüfung verloren. Der Slot wird zwar zusammengeführt, aber
[beide DIM-Initialisierungen](../../../../crates/tb-vm/src/project.rs#L381)
werden ausgeführt.

**Korrektur:** Vollständige Variablenidentität und Arrayvertrag beim Binden
berücksichtigen. Kompatible gemeinsame Arrays einmal initialisieren;
inkompatible Deklarationen vor der Ausführung am ursprünglichen Quellort
ablehnen. Probe `v4_common_behaelt_typidentitaet_und_initialisiert_arrays_einmal`.

## WARNING — weitere Vertragsabweichungen

### V5 — LOAD/UNLOAD umgehen die explizite Containerauflösung

**Priorität: mittel.** Formularnamensraum und expliziter Containerzugriff,
D2, Task 1.2.

Bei zwei Formularen mit jeweils Text1 als Control-Array werden
`LOAD Form2!Text1(3)` und `UNLOAD Form2!Text1(3)` mit
`Unknown object 'FORM2!TEXT1'` abgewiesen. Property-Zugriffe und die Übergabe
desselben qualifizierten Controls an einen CONTROL-Parameter funktionieren.

**Ursache:** Der [LOAD-/UNLOAD-Pfad](../../../../crates/tb-frontend/src/sema.rs#L3370)
übergibt den gesamten Bang-Pfad an `find_object`; die bereits vorhandene
containerbezogene Auflösung wird hier nicht verwendet.

**Korrektur:** LOAD/UNLOAD über dieselbe Objekt-/Containerauflösung wie
Property- und Referenzzugriffe führen; gleichnamige Arrays beider Formulare
und dynamische Instanzen gemeinsam prüfen. Probe
`v5_load_und_unload_loesen_den_expliziten_container_auf`.

### V6 — Linkerdiagnosen verlieren Datei, Zeile und Spalte

**Priorität: mittel.** Delta „Diagnostik mit Vorbild-Meldungen“, D1, Task 1.1.

MAIN deklariert `SUB F(x%)`, LIB implementiert `SUB F(x$)`. Die Ablehnung ist
richtig, die Meldung jedoch `0:0: Parameter type mismatch: MAIN!F` ohne Datei.
Das ist eine quellbezogene Diagnose, kein Fehler ohne zuordenbare Quelle.

**Ursache:** [diagnostic](../../../../crates/tb-vm/src/project.rs#L17) erzeugt
`file=None` und `SourcePos::default()`. [Linkfehler](../../../../crates/tb-vm/src/project.rs#L66)
werden erst nach `locate_diagnostics` in dieses Format umgewandelt. Dasselbe
Problem betrifft COMMON-Konflikte und weitere symbolbezogene Linkfehler.

**Korrektur:** Ursprung der betroffenen Deklaration bzw. Aufrufstelle mit
in die Linker-Symbolinformationen übernehmen und strukturierte Diagnosen
mit tatsächlicher SourcePos zurückgeben. Keine pauschale Ersatzposition
1:1 eintragen. Probe `v6_linkerdiagnose_nennt_den_urspruenglichen_dateiort`.

## Szenarioabdeckung und positive Nachweise

Alle 21 vorhandenen Delta-Szenarien wurden abgeglichen. Die einfachen
Originalbeispiele besitzen Implementierungs- und Testnachweise; die oben
reproduzierten Randpfade widersprechen den umfassenderen Requirements.

| Requirement / Szenarien | Ergebnis |
| --- | --- |
| Monomorpher Opcode-Satz: gemischter Ausdruck, aufgelöste Namen | Vorhandene Codegen-/HIR-Tests bestanden. Alle 152 Opcodes samt Operandentypen und Encodingbreiten stimmen mit der Dokumentation überein. |
| TBC: Roundtrip, unbekannte Version, Formularwerte | CLI-/VM-Projekttests bestanden: bytegleicher Rundlauf, hello/world aus Designarrays 0/2 nach Entfernen sämtlicher BAS-/FRM-/MAK-/BI-Quellen, Ablehnung alter/höherer Versionen. V2/V3 begrenzen dennoch das vollständige Projektmodell. |
| Quellorte: Fehlerzeile, Bibliotheksfehler | `lib.bas:2` und verschachtelte Include-Fehler bestehen. Unabhängig zusätzlich Fehler in physischer Zeile 42 geprüft. V1 zeigt fehlende Zweig-/Schleifenorte. |
| Benannte Objekte: Lesen/Schreiben, keine Standardeigenschaft, Wertebereich, getrennte Controls | Bestehende Semantik-/VM-/Modelltests und neuer Zwei-FRM-Test bestanden; Check1.Value=3 bleibt Fehler 5. V3 betrifft weitere Formularquellen, V5 die weiteren qualifizierten Zugriffspfade. |
| Diagnosen: Position, Include-Diagnose | Lexer-/Parser-/Semantikpfad trägt Originalpositionen. V6 betrifft die anschließende Linkerphase. |
| Objektgrammatik/-semantik: unbekanntes Objekt/Eigenschaft, Typkonflikt, TYPEOF, gleiche Controls | Bestehende Tests bestanden. V3/V5 verletzen den allgemeinen Modul-/Containervertrag trotz grüner Property-Beispiele. |
| Unterbrechung: Breakpoint, Inspektion, gleiche Zeile in zwei Modulen | Unabhängige Probe: MAIN passiert Zeile 10, LIB hält in Zeile 10; qualifizierte Array-/UDT-Inspektion liefert 7/8; Einzelschritt meldet Spalte 5; ERR/ERL bleiben 6/200. V1 lässt Breakpoints an ELSEIF aus. |

Erneut ausgeführt:

- `cargo test --workspace`: **437 bestanden, 0 fehlgeschlagen, 1 ignoriert**.
  Golden-Generator nicht ausgeführt, keine Sollausgaben geändert.
- [Review-Proben](review-probes.rs): **1 bestanden, 6 fehlgeschlagen**.
  Jede fehlgeschlagene Probe entspricht einem der sechs Befunde; mehrere
  verwandte Reproduktionen werden innerhalb einer Probe gesammelt.
- Zusätzlich zeitlich begrenzte CLI-Proben für die Befunde; temporäre
  Quellverzeichnisse anschließend entfernt.
- `cargo bench -p tb-vm --bench compile`: 508 Zeilen **0,54 ms**, 49.760 Zeilen
  in 20 verbundenen Modulen **67 ms**; beide Budgets erfüllt.
- Dokumentation: **152/152 Opcodes**, Operanden-/Gesamtbreiten und **9/9
  Containerabschnitte** gegen den aktuellen Code abgeglichen.
- `cargo fmt --all -- --check`, `openspec validate projektmodule-und-kompilat --strict`
  und `git diff --check`: bestanden.
- Clippy nicht nochmals ausgeführt: keine Produktcodeänderung seit dem
  erfolgreichen Clippy-Lauf der Implementierungsabnahme. Kein neuer
  interaktiver Originalsystemvergleich und keine Windows-/Linux-Testmatrix.

## Review-Proben reproduzieren

Im Repository-Wurzelverzeichnis ausführen. Der temporäre Treiber hält die
noch roten Vertragsproben außerhalb der normalen Workspace-Suite; ihre
Erwartungen beschreiben das Sollverhalten. Exit-Code ist bis zur Behebung 101.

```sh
python3 - <<'PY'
from pathlib import Path
import json, subprocess, tempfile, os
root = Path.cwd()
with tempfile.TemporaryDirectory(prefix='tb-project-review-') as folder:
    p = Path(folder)
    manifest = '[package]\nname="tb-project-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-projektmodule-und-kompilat/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)
    result = subprocess.run(['cargo', 'test', '--manifest-path', str(p / 'Cargo.toml'), '--offline', '--test', 'probes', '--', '--nocapture'], env={**os.environ, 'CARGO_TARGET_DIR': str(root / 'target/review-projektmodule')}, timeout=120)
    raise SystemExit(result.returncode)
PY
```

**Abnahmeentscheidung:** V1–V4 vor Archivierung beheben; V5/V6 ebenfalls in
die vollständige Umsetzung aufnehmen. Keine zusätzlichen Stilvorschläge.
