OpenSpec-Review dokumentieren und ISAM-Vertragsabweichungen beheben

This commit is contained in:
2026-09-05 17:55:09 +02:00
parent 19804e0e2d
commit 57d6386a5a
61 changed files with 3087 additions and 86 deletions

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-09-05

View File

@@ -0,0 +1,37 @@
## Context
INPUT # liest stets eine ganze Zeile und ersetzt fehlende Felder durch leer. INPUT$ zählt Tastendrücke bzw. Dateibytes statt Zeichen. bi_cv prüft nur Mindestlänge. Zeitzone::ermitteln erfasst den Startzustand, versatz kann später still auf UTC fallen. Siehe proposal.md und die Delta-Specs.
## Goals / Non-Goals
**Goals:** Die vorhandenen Lese-/Konvertierungspfade mit erhaltener Position, klaren Fehlern und abfragbarem Zeitzustand korrigieren.
**Non-Goals:** Kein allgemeines CSV-Paket, keine Änderung der UTF-32-Recorddarstellung, kein Stellen der Betriebssystemuhr.
## Decisions
### D1 — Ein Lesefortschritt je Datei
Sequenzieller Dateiinput hält Feld-/Zeichenrest und Datei-/Decoderposition zusammen. INPUT # kann Felder derselben Zeile in mehreren Aufrufen lesen; fehlende geforderte Felder führen zu Fehler 62. LINE INPUT und INPUT$ müssen mit demselben logischen Fortschritt zusammenspielen, statt über getrennte Handles dieselben Bytes erneut zu lesen.
### D2 — Codepoints und Bytedarstellung trennen
INPUT$ zählt Unicode-Codepoints, behält den Rest einer erweiterten Tastenfolge und decodiert UTF-8 vor der Zeichenzählung. GET/PUT und MK/CV bleiben Byte-/UTF-32-Recordpfade; CV verlangt genau seine Zielbreite. Keine stillen Ersatzwerte für beschädigte Teilsequenzen.
### D3 — Fehler am Dateieinstieg zuordnen
Bei NotFound zwischen fehlendem Elternpfad und fehlender Datei unterscheiden; vorhandene allgemeine Fehlerabbildung wiederverwenden und die zusätzliche Pfadprüfung an den Dateisystemoperationen bündeln.
### D4 — Zonenzustand als kleiner lesbarer Vertrag
TIMEZONEKNOWN ohne Argument liefert INTEGER -1/0. Zeitwert und Status beruhen auf derselben jeweils gültigen Zonenermittlung; späterer Rückfall darf nicht beim Startzustand stehenbleiben. Rust-Einbetter können den Zustand weiter prüfen, CLI-Warnung bleibt ergänzend. Der Name ist die vorgeschlagene additive API dieses Changes und wird als TerminalBasic-Erweiterung dokumentiert.
## Risks / Trade-offs
- Gemischte INPUT-/INPUT$-/LINE INPUT-Aufrufe können Positionen verschieben → alle Übergänge auf derselben Datei und an CRLF/EOF testen.
- Strengere CV-Länge ändert bisher permissive Eingaben → ausdrücklich dokumentieren, Fehler 5 entspricht dem vorhandenen Spec-Vertrag.
- Zonenermittlung hängt vom System ab → Tests müssen Ermittlungsausfall und Wiederherstellung injizieren können, ohne die Rechnerzeitzone zu ändern.
## Migration Plan
Eigenständig; FREEFILE bleibt vollständig im ISAM-Change. TIMEZONEKNOWN ersetzt keine monotone Ereigniszeit und teilt deren Zustellpfad nicht. Bestehende Spec-/Codeverträge erst nach erfolgreicher Umsetzung synchronisieren und archivieren. Bis dahin bleiben alle Tasks offen. Änderungen als zusammenhängenden Commit je Change integrieren; bei Fehlschlag auf den vorherigen Code zurückgehen und neue Datenformatversionen nicht mit alten Lesern öffnen.

View File

@@ -0,0 +1,29 @@
## Why
Die Laufzeit verwirft INPUT-Felder, liest INPUT$ mit falscher Zeichenzählung und weicht bei CV-Längen sowie Dateifehlern ab. Zusätzlich fehlt die spezifizierte BASIC-Abfrage des Zeitzonenrückfalls (F14F17/F19). Siehe [Review vom 05.09.2026](../../../docs/reviews/2026-09-05-openspec-code-review.md).
## What Changes
- INPUT # als fortlaufenden Feldleser mit korrektem EOF-Verhalten führen.
- INPUT$ für Unicode-Codepoints und Teilfolgen von Sondertasten auf exakt n Zeichen begrenzen.
- Exakte CV-Argumentbreiten und Datei-/Pfadfehler 53/76 sicherstellen.
- Die verlangte Zonenzustandsabfrage als parameterlose INTEGER-Funktion TIMEZONEKNOWN konkretisieren: -1 bei ermittelter Zone, 0 beim UTC-Rückfall.
## Capabilities
### New Capabilities
Keine neuen Capability-Pfade.
### Modified Capabilities
- `datei-eio`: Fortlaufende Eingabefelder, exakte Record-Konvertierungsbreite und präzise Pfadfehler.
- `textbildschirm`: INPUT$ zählt genau n Codepoints in Terminal- und Dateieingabe.
- `konsolen-basisbibliothek`: Programmseitige Zonenzustandsabfrage und sichtbarer Rückfall auch nach dem Start.
- `sprach-frontend`: Signatur der konkretisierten Zonenzustandsfunktion.
## Impact
tb-runtime Datei-/Builtin-/Zeitmodule, tb-vm INPUT-Pfad, Frontend-Builtin/HIR-Zuordnung, Inventar und Eingabe-/Zeitzonen-Korpus. TIMEZONEKNOWN ist eine additive Konkretisierung des bestehenden Solls, keine Behauptung historischer BASIC-Kompatibilität.
Eigenständig; FREEFILE bleibt vollständig im ISAM-Change. TIMEZONEKNOWN ersetzt keine monotone Ereigniszeit und teilt deren Zustellpfad nicht.

View File

@@ -0,0 +1,84 @@
## MODIFIED Requirements
### Requirement: Sequenzielle Datenübertragung
`PRINT #` SHALL wie `PRINT` formatieren (Druckzonen, Zahlendarstellung mit
Vorzeichenspalte), `WRITE #` SHALL Elemente komma-getrennt mit Strings in
Anführungszeichen schreiben. `INPUT #` SHALL komma-getrennte Felder lesen
und dabei Anführungszeichen auswerten, `LINE INPUT #` die ganze Zeile ohne
Zeilenende. `EOF` SHALL das Erreichen des Dateiendes melden; Lesen über das
Dateiende hinaus MUST Laufzeitfehler 62 „Input past end of file" auslösen.
INPUT # SHALL nicht konsumierte Felder einer Zeile für spätere Aufrufe bewahren und bei Bedarf über Zeilen hinweg weiterlesen. Fehlende geforderte Felder am Dateiende MUST Fehler 62 auslösen statt als leere Ersatzwerte zu gelten.
#### Scenario: WRITE # und INPUT # sind gegenläufig
- **WHEN** `WRITE #1, "a,b", 5` geschrieben und die Zeile mit `INPUT #1, s$, n` gelesen wird
- **THEN** enthält `s$` den Text `a,b` und `n` den Wert 5
#### Scenario: Lesen über das Dateiende
- **WHEN** `INPUT #1, x` nach dem letzten Datensatz ausgeführt wird
- **THEN** tritt Laufzeitfehler 62 auf
#### Scenario: Felder über zwei Aufrufe
- **WHEN** WRITE #1, "a", "b" geschrieben und nach Wiederöffnung zweimal INPUT #1 mit je einer Stringvariablen ausgeführt wird
- **THEN** liefern die Aufrufe a und b
#### Scenario: Zu wenige Felder
- **WHEN** nur ein Feld vorhanden ist und INPUT #1 zwei Felder verlangt
- **THEN** tritt Fehler 62 auf
### Requirement: Record-Konvertierungsfunktionen
Die Bibliothek SHALL die Konvertierungsfunktionen für Recordpuffer
bereitstellen: `MKI$`, `MKL$`, `MKS$`, `MKD$` und `MKC$` wandeln einen
numerischen Wert in seine Byte-Darstellung als String, `CVI`, `CVL`,
`CVS`, `CVD` und `CVC` wandeln zurück. Jedes Paar MUST gegenläufig sein.
Ein Argument, dessen Länge nicht zur Zielbreite passt, MUST
Laufzeitfehler 5 „Illegal function call" auslösen. `MKSMBF$`, `MKDMBF$`,
`CVSMBF` und `CVDMBF` SHALL dieselbe Rolle für das
Microsoft-Binärformat älterer BASIC-Versionen erfüllen; ist dieses
Format ein deklariertes Non-Feature, MUST die Ablehnung namentlich
erfolgen und in der Sprachreferenz unter „Abweichungen" stehen.
Die Argumentlänge der CV-Funktionen SHALL exakt ihrer Zielbreite entsprechen, nicht nur einer Mindestbreite.
#### Scenario: MK und CV sind gegenläufig
- **WHEN** `CVL(MKL$(123456))` ausgewertet wird
- **THEN** ist das Ergebnis 123456
#### Scenario: Falsche Argumentlänge
- **WHEN** `CVI("x")` mit einem ein Zeichen langen String ausgewertet wird
- **THEN** tritt Laufzeitfehler 5 auf
#### Scenario: Zu langes CVI-Argument
- **WHEN** CVI("abc") ausgewertet wird
- **THEN** tritt Laufzeitfehler 5 auf
### Requirement: Dateisystem-Anweisungen mit plattformübergreifender Pfadsemantik
`KILL`, `NAME … AS`, `FILES`, `CHDIR`, `CHDRIVE`, `MKDIR`, `RMDIR`,
`CURDIR$`, `DIR$` sowie `SHELL` als Anweisung **und** als Funktion SHALL
verfügbar sein. `CURDIR$` SHALL das aktuelle Verzeichnis liefern, `DIR$`
den ersten bzw. — bei leerem Argument — den nächsten Treffer eines
Suchmusters und den leeren String, wenn keiner mehr folgt. Die
`SHELL`-Funktion SHALL den Beendigungsstatus des aufgerufenen Prozesses
liefern. `CHDRIVE` SHALL auf Plattformen ohne Laufwerksbuchstaben
namentlich abgewiesen oder als Non-Feature dokumentiert werden. Pfade SHALL sowohl `\` als auch `/` als Trennzeichen
akzeptieren und auf die Konvention der laufenden Plattform abgebildet
werden; Laufwerksbuchstaben SHALL auf Nicht-Windows-Plattformen als
gewöhnlicher Namensbestandteil behandelt oder mit benannter Ablehnung
abgewiesen werden. Fehlende Dateien MUST Fehler 53 auslösen, fehlende
Pfade Fehler 76 „Path not found".
#### Scenario: Rückwärts-Schrägstrich auf Unix
- **WHEN** `OPEN "unter\d.txt" FOR OUTPUT AS #1` auf einer Unix-Plattform ausgeführt wird
- **THEN** entsteht die Datei `d.txt` im Verzeichnis `unter`
#### Scenario: Verzeichnis durchlaufen
- **WHEN** `DIR$("*.txt")` und danach `DIR$("")` wiederholt ausgewertet werden
- **THEN** liefern sie nacheinander alle passenden Namen und zuletzt den leeren String
#### Scenario: Fehlender Pfad
- **WHEN** `MKDIR` in einem nicht existierenden Elternverzeichnis aufgerufen wird
- **THEN** tritt Laufzeitfehler 76 auf
#### Scenario: OPEN mit fehlendem Elternpfad
- **WHEN** OPEN FOR INPUT einen Dateinamen in einem nicht vorhandenen Elternverzeichnis verwendet
- **THEN** tritt Fehler 76 auf; fehlt nur die Datei in einem vorhandenen Verzeichnis, tritt Fehler 53 auf

View File

@@ -0,0 +1,23 @@
## MODIFIED Requirements
### Requirement: Zonenermittlung mit Rückfallebene
Die Laufzeit SHALL die Zeitzone des Rechners über die
Betriebssystemeinstellung bestimmen. Lässt sie sich nicht ermitteln,
SHALL UTC gelten und das Programm ohne Fehler weiterlaufen. Ob die
Rückfallebene greift, MUST für ein Programm erkennbar sein und in
docs/sprachreferenz.md beschrieben stehen; ein stiller Wechsel auf UTC
MUST NOT vorkommen.
Die parameterlose INTEGER-Funktion TIMEZONEKNOWN SHALL -1 für eine ermittelte Systemzone und 0 für den UTC-Rückfall liefern. Auch eine nach Programmstart scheiternde Zonenermittlung SHALL diesen Zustand sichtbar ändern; die Abfrage SHALL keine Zeitzone oder Systemuhr verstellen.
#### Scenario: Zone nicht ermittelbar
- **WHEN** die Zeitzone des Rechners nicht bestimmt werden kann
- **THEN** rechnen die Zeitfunktionen in UTC und das Programm läuft ohne Fehler weiter
#### Scenario: Rückfallebene ist erkennbar
- **WHEN** ein Programm den Zonenzustand abfragt
- **THEN** unterscheidet die Antwort erkennbar zwischen ermittelter Zone und Rückfall auf UTC
#### Scenario: Rückfall nach Programmstart
- **WHEN** zunächst eine Zone ermittelt wurde, eine spätere Ermittlung aber scheitert
- **THEN** verwenden die Zeitfunktionen UTC und TIMEZONEKNOWN liefert 0

View File

@@ -0,0 +1,27 @@
## MODIFIED Requirements
### Requirement: Jedes dokumentierte Element besitzt eine Signatur
Die Semantik SHALL für jedes im Sprachinventar geführte Element eine
Signatur besitzen (Argumentanzahl und -typen) — auch für Elemente, deren
Laufzeitverhalten noch aussteht. Ein im Inventar geführtes Element MUST
NOT als unbekannter Bezeichner oder mit einem generischen Syntaxfehler
abgewiesen werden; die Diagnose bzw. der Laufzeitfehler MUST es
namentlich nennen (Guiding Principle). Das gilt insbesondere für die
Gruppen, die bisher gar keine Signatur haben: die finanzmathematischen
Funktionen, die Record-Konvertierungsfunktionen (`MK…$`/`CV…`), die
Dateisystem-Funktionen `CURDIR$`, `DIR$`, `CHDRIVE`, sowie `LPOS`,
`STACK`, `SYSTEM`, `ERDEV`/`ERDEV$` und `SetFormatCC`.
Die TerminalBasic-Erweiterung TIMEZONEKNOWN SHALL als parameterlose INTEGER-Funktion eine Signatur besitzen und im Inventar mit ihrer tatsächlichen Umsetzung geführt sein.
#### Scenario: Element ohne Laufzeitverhalten wird namentlich abgewiesen
- **WHEN** ein Modul eine im Inventar als `offen` geführte Funktion verwendet
- **THEN** nennt die Ablehnung deren Namen und nicht „unbekannter Bezeichner"
#### Scenario: Argumentprüfung ohne Laufzeitverhalten
- **WHEN** ein Modul `MKL$()` ohne Argument enthält
- **THEN** meldet die Semantik eine Argumentanzahl-Diagnose, die `MKL$` nennt
#### Scenario: Signatur der Zonenzustandsabfrage
- **WHEN** PRINT TIMEZONEKNOWN übersetzt wird
- **THEN** entsteht eine INTEGER-Funktionsabfrage; TIMEZONEKNOWN(1) wird mit benannter Argumentanzahl-Diagnose abgewiesen

View File

@@ -0,0 +1,26 @@
## MODIFIED Requirements
### Requirement: Tastatureingabe ohne Zeilenmodell
`INKEY$` SHALL ohne zu blockieren die nächste anstehende Taste liefern:
den leeren String bei leerem Puffer, ein Zeichen bei einer
Zeichentaste, eine zwei Zeichen lange Folge mit führendem Nullzeichen bei
einer Sondertaste. `INPUT$(n [, #dateinummer])` SHALL genau `n` Zeichen
lesen und dabei blockieren, ohne sie am Bildschirm zu wiederholen.
INPUT$ SHALL n Unicode-Codepoints liefern. Nicht verbrauchte Zeichen einer Sondertastenfolge und noch nicht gelesene Dateizeichen SHALL für Folgeaufrufe erhalten bleiben. Dateieingabe SHALL UTF-8 vor der Zeichenzählung decodieren.
#### Scenario: INKEY$ bei leerem Tastaturpuffer
- **WHEN** `INKEY$` ohne anstehende Taste ausgewertet wird
- **THEN** liefert es den leeren String und blockiert nicht
#### Scenario: Sondertaste als zwei Zeichen
- **WHEN** F1 gedrückt wurde und `INKEY$` ausgewertet wird
- **THEN** hat das Ergebnis die Länge 2 und beginnt mit dem Nullzeichen
#### Scenario: Sondertastenfolge in zwei Reads
- **WHEN** F1 ansteht und zweimal INPUT$(1) ausgeführt wird
- **THEN** liefert der erste Aufruf das Nullzeichen und der zweite den Scancode, jeweils genau ein Zeichen
#### Scenario: Unicode aus Datei
- **WHEN** eine UTF-8-Datei mit ä beginnt und INPUT$(1,#1) aufgerufen wird
- **THEN** liefert der Aufruf ä ohne Ersatzzeichen

View File

@@ -0,0 +1,14 @@
## 1. Eingabe und Recordfunktionen
- [ ] 1.1 Fortlaufenden INPUT-#-Lesefortschritt implementieren; verifizieren mit zwei Einzelreads nach WRITE zweier Felder, mehreren Zeilen, Quotes/Kommas und Fehler 62 bei zu wenigen Feldern.
- [ ] 1.2 INPUT$ auf exakt n Codepoints führen und Reste erhalten; verifizieren mit F1 und zwei INPUT$(1)-Aufrufen, UTF-8 ä/Emoji aus Datei, gemischten Lesearten und EOF.
- [ ] 1.3 CV-Zielbreiten exakt prüfen; verifizieren mit allen fünf MK/CV-Paaren und jeweils zu kurzen/passenden/zu langen Argumenten.
- [ ] 1.4 Datei-/Elternpfadfehler unterscheiden; verifizieren mit fehlender Datei in vorhandenem Verzeichnis, fehlendem Elternpfad und bestehenden erfolgreichen Dateisystemfällen.
## 2. Zonenzustand
- [ ] 2.1 TIMEZONEKNOWN durch Frontend, HIR, Dispatch und Inventar ergänzen und dynamischen Rückfall sichtbar halten; verifizieren mit ermittelter Zone, UTC-Rückfall, späterem Ausfall/Wiederherstellung und unverändertem DATE$/TIME$/NOW/TIMER-Versatz.
## 3. Abnahme
- [ ] 3.1 Sprach-/Bibliotheksreferenz und Eingabe-/Zonenkorpus ergänzen; verifizieren mit cargo test --workspace, unveränderten vorhandenen Snapshots und openspec validate laufzeit-eingabe-und-systemstatus --strict.