doc/VarioFoerderer_Linienzug_Prinzipien.md ist bewusst nicht versioniert
(siehe ce00233). Die drei Stellen, die von dort die Begruendung geholt
haben, tragen sie jetzt selbst: warum quer und dZ null sein MUESSEN und
laengs abweichen DARF - naemlich weil beides zugleich geometrisch nicht
geht und der Hauptstrang gerade bleiben soll.
Ein Verweis auf eine Datei, die im Repo fehlt, kostet den naechsten Leser
mehr Zeit als die zwei Zeilen Text.
Nicht angefasst: die aelteren Verweise in vf_linienzug.lsp (Abschnitt 14,
14.1) und vf_standard.lsp - sie stammen nicht aus dieser Arbeit und
zeigen auf Inhalte, die hier niemand kennt.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Neu: TEST_LINIENZUG_MODUS2 spielt zwei echte Laeufe DERSELBEN Strecke ab -
einmal mit der 90-Grad-Ecke als Vario-Kurve (waagerecht, mit flacher Zone),
einmal als GF-Bogen (geneigt, ohne flache Zone). Beide muessen quer zur
ES-KS_AUS-Achse ~0 und dZ ~0 erreichen; laengs darf um die Ausladung des
ES-Elements abweichen (Leitsatz, doc/VarioFoerderer_Linienzug_Prinzipien.md
Abschnitt 0). Gemessen am 2026-10-27: beide 0.2 mm quer, dZ 0.
Das Paar ist Absicht. Die beiden Varianten laufen durch VERSCHIEDENE Zweige,
und erst ihr Vergleich hat die Fehler dieser Woche sichtbar gemacht - der
ES-Fussabdruck wurde vom falschen Segment abgezogen, was sich nur in der
GF-Bogen-Variante zeigte (878 mm). Einen der beiden zu loeschen nimmt dem
Test seinen Wert.
Anders als die Modus-1-Faelle braucht Modus 2 KEINE Mocks und KEINEN
gezeichneten Pfad: sein Journal traegt einen SEGS-Eintrag mit der kompletten
Segment-Essenz, ist also von den Original-Objekten unabhaengig. Der Test
spielt daher das echte, mit lib/vf_journal_export.py aus der Zeichnung
gelesene Journal ab. Jeder Eintrag fuehrt seine Art mit (PT/STR/REAL/SEGS),
womit die Verschiebe-Anfaelligkeit des Mock-Replays entfaellt.
Dazu: vf-linienzug-modus2 legt die gemessene Abweichung in
*vfl-m2-abweichung* ab (laengs quer dz). Sonst muesste ein Test sie aus der
Konsolenausgabe zurueckparsen.
Ausserdem behoben: beide Modus-1-Testskripte brachen mit
"bad argument type <\"5\"> expected <CONS> at [cdr]" ab. Commit fb56794
(Rueckwaerts-Bau) hat eine Frage VOR die AS-Praeambel gesetzt. Fuer Journale
ist sie abwaertskompatibel, fuer die MOCK-Skripte nicht: der Mock beantwortet
jede getstring-Abfrage aus der Queue, eine fehlende Antwort verschiebt also
alles Folgende um eine Position. Beide Dateien haben den Eintrag jetzt, mit
Begruendung im Kommentar.
Menue: Tests -> Foerderer-Linienzug ruft den neuen Fall mit auf. Die
kompilierte SSG_LIB.cui ist bewusst NICHT mit committet - ihre Aenderung
besteht groesstenteils aus fremden Eintraegen und verschobenen UIDs;
BricsCAD erzeugt sie beim naechsten _MENULOAD neu aus der .mnu.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
- TEST_LINIENZUG: seit 1cc163d/cccd362 fragt Modus 1 nach der AS-Seite die
optionale Zufuehrungsachse ab. Der Test mockt get* direkt (keine
Replay-Queue), die neue Punktfrage verschluckte die naechste Antwort und
der Lauf desynchronisierte (FEHLER, 21 Schritte offen). Neuer Schritt-Typ
"point_none" (getpoint -> nil) und in beiden Linienzug-Testdaten nach
der AS-Seite eingetragen.
- test_hundm05.py: Zusatzobjekt-Ergebnisse filterten nur kind "kreisel" -
Separatoren/Scanner/BTMT (kind "sensor") fehlten, test_je_objekt_ein_
ergebnis schlug faelschlich fehl.
- SSG_RUN_ALL_TESTS: #VF/#GF/#Kreisel/#Eckrad_LetzteNr vor jedem Test auf 0.
Der Lauf bleibt im Namensraum des Startdokuments, die Zaehler liefen
sonst ueber alle Tests weiter (VF_5/Kreisel12 in frischer Zeichnung) und
machten jeden Referenz-Diff von der Testreihenfolge abhaengig.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Neuer Separator auf Kreisel_TestSystem_07 Bahn L vor der Weiche zu
Kreisel_TestSystem_08 (aus results/export.csv, Separator 0022). Ohne ihn
steuert niemand den Uebergang 7 -> 8, im TRO-Fluss von sps_skel war der
Ausgang vom Eingang aus nicht erreichbar.
- Separator auf Kreisel_TestSystem_08 Bahn R lag auf z=0 statt 2000
(Export: Hoehe 0).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- x-Werte der Kreisel 2-9 auf exakte Beruehrung korrigiert (Kreisel 1 fest,
Abweichung in der Zeichnung bis 5.5 mm); alle 8 Weichenpaare beruehren sich
- Separatoren und BTMT-Beladung mit ihrem Kreisel verschoben
- Hinweis im Testkopf: erneuter Lauf von dxf_anlage_export.py macht die
Korrektur rueckgaengig
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Lisp/vf_core.lsp: fuenf eigene Menue-Wrapper (LinienzugVarioFoerdererManuell/-Zielhoehe/-Stueckweise, QcLinieMitGf/-UForm) ersetzen den alten interaktiven Modus-Dialog; vfc-dialog-linienzug-modus-waehlen entfaellt.
dcl/vf_linienzug_wizard.dcl + Lisp/vf_linienzug.lsp: "Neue Linie BIS Kettenende" ist kein Radio mehr, sondern eigener Button "OK und Abschliessen" neben "Ok Weiter"; GF-Optionen stehen vor VF-Optionen.
Menue (SSG_LIB.mnu/.cui), lang/*.json, doc/kommandos.md, doc/lisp_methods.md, doc/faq.md nachgezogen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- vfl-journal-reset-lauf ans Funktionsanfang verschoben (Modus 1/2/3,
Lisp/vf_linienzug.lsp): stand bisher nach der Startpunkt/Hoehe/AS-
Praeambel und loeschte diese beim Reset selbst wieder - Journal begann
mit dem ersten STEP-Marker statt PT, betraf jede Kette.
- Spec-Grammatik erweitert (Lisp/vf_spec.lsp, lib/vf_linienzug_grammatik.py,
lib/vf_spec_export.py): "auf-ab" bei bereits flach ankommender Kette
(Richtungswahl statt Zielhoehe) und neue Linie-GF-Fragereihenfolge
(Kettenende direkt nach laenge_modus, inkl. vorgezogenem ES). Tests in
tests/test_vf_spec.lsp/.py angepasst.
- lib/vf_linienzug_grammatik.py: _linie("kettenende_ziel") erwartete
faelschlich ein hz-REAL nach der Distanz - der reale Bauablauf
(vfl-body-abschluss) leitet die Richtung dort aus dem Frame ab und
fragt sie nie. Fuehrte zu einem Token-Desync beim Dekodieren echter
Kettenende-Journale.
- tests/testdata/hundm05.json (VF_hundm05_LZ_01): 5 ueberfluessige
hz-Felder entfernt. vsp-linie injiziert bei JEDEM vorhandenen hz-Feld
einen Richtungs-Token, unabhaengig vom tatsaechlichen Bauablauf - die
Felder desyncten den Replay und liessen die Kette stumm mit der
falschen (verkuerzten) Geometrie fertig bauen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Lisp (vf_linienzug.lsp/vf_spec.lsp):
- vsp-eingang-hoehe unterstuetzt jetzt "auto" (NIL-Token statt REAL) -
bewusst keine Zahl vorgeben, der Bauablauf berechnet seinen eigenen
Vorschlag, wie bei leerer Konsoleneingabe
- vfl-journal-reset-lauf: internes Reset innerhalb von vf-linienzug-modus/
-modus2 loescht *vfl-replay-queue*/*vflw-pending* nicht mehr mit (Bug:
REPLAY-getriebener Bau (vsp-bau-aus-spec) brach mitten in der Kette ab,
weil eine noch unverbrauchte Queue verworfen wurde)
Python-Gegenstueck nachgezogen (lib/vf_linienzug_grammatik.py,
lib/vf_spec_export.py, lib/vf_journal_export.py):
- NIL-Token-Unterstuetzung fuer eingang_hoehe="auto" im gemeinsamen
Parser-Kern, im Schreiber (SpecSchreiber) und in der Protokoll-Annotation
- gf_verteilung ist im Schreiber jetzt an der Feldpraesenz in der Spec
festgemacht statt an einem Grammatik-Flag (selbstbeschreibend, deckt
Specs mit und ohne diese Frage ab, ohne dass der Aufrufer die Grammatik
kennen muss)
- Rundlauf-Pruefung (main(), test_verlustfrei) toleriert jetzt die bekannte,
schon dokumentierte Erweiterung um drei neue Linie-GF-Pflichtfragen
(ist_teilfolge statt exakter Gleichheit)
- test_gleiche_journale_wie_protokoll: alle 5 Ketten in hundm05.json weichen
inzwischen vom Rohprotokoll ab (Kette 1 bewusst wegen eingang_hoehe,
Ketten 2-5 schon laenger wegen Handkorrektur gegen echte DXF-Positionen)
- expliziter Skip mit Begruendung statt leerem Loop
tests/testdata/hundm05.json:
- mm-Werte (dl, Start-/Stuetzpunkte, Koordinaten der Nachtrag-Objekte) auf
eine Nachkommastelle gerundet
- nicht abgefragte Kopf-Metadaten entfernt (beschreibung, sivas_id,
sivas_bezeichnung, planquadrat, block, dxf_handle) - nur quelle bleibt
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
vf-linienzug-modus fragt bei einem mit "Horizontal-VF" eroeffneten
Kettenanfang eine Ziel-Hoehe fuer den GF1-Einlauf ab (vfl-prompt-hoehe-
eingang-gf1) und laesst dort die GF-Verteilungsfrage weg (fest "alles am
Einlauf") - vsp-journal/vsp-vf-einheit kannten das noch nicht. Ausserdem
werden ES-Winkel/-Seite beim kettenende-sub jetzt an der richtigen
Journal-Position (inkl. eigenem STEP-Marker) emittiert.
tests/testdata/hundm05.json: VF_hundm05_LZ_02..05 (die vier baugleichen
Schleifen, Block VF_1) aus tests/testdata/linienzug_tests.json neu
abgeleitet, mit den realen Startkoordinaten aus results/test_hundM05.dxf
statt der alten "sub":"auf-ab"-Behelfsloesung. VF_hundm05_LZ_01 und alle
Kreisel-/Separator-/Scanner-/BTMT-Objekte unveraendert.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Lisp/vf_standard.lsp: berechne-alle-winkel um Parameter schon-flach
erweitert (Fussabdruck-Korrektur, wenn ein Frame flach statt bei 3 Grad
ankommt) - vf_linienzug.lsp rief die Funktion bereits mit diesem 5.
Argument auf, dieser Commit fehlte im letzten Commit und liess den
Zwischenstand mit Argumentzahl-Mismatch zurueck. tests/test_foerderer.lsp
und tests/test_mubea.lsp ziehen dieselbe Signatur nach (inkl.
berechne-horizontale-mitte, das schon-flach bereits erwartete).
tests/testdata/linienzug_tests*.json aktualisiert passend zum echten
Bau-Ablauf. menu/SSG_LIB.mnu/.cui: TEST_LINIENZUG_STUFE2 im Testmenue
ergaenzt.
Lisp/vf_spec.lsp + lib/vf_spec_export.py: *vsp-menu-start* auf die aktuelle
6-Optionen-Kettenanfang-Zuordnung umgestellt (vorher noch 4 Optionen) -
vsp-journal replayt gegen den LEBENDEN vf-linienzug-modus. Python-Tabelle
bewusst NICHT umgestellt (dekodiert eine eingefrorene Alt-Aufzeichnung).
TEST_HUNDM05 schlaegt trotzdem weiterhin fehl (separates, ungeloestes
Problem - siehe naechster Absatz).
Bekannter offener Fehler: TEST_HUNDM05 baut nach wie vor nicht korrekt -
der Menu-Code-Fix allein reicht nicht. Root Cause nicht abschliessend
geklaert, Uebergabe an Kollegen fuer Logik-Review vorgesehen.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Auf der neuen Kollegen-Architektur (Stufe 0-2: Spec/Journal/Replay-System
in vf_spec.lsp, Frage-Schale/Bauteil-Trennung) neu aufgebaut, nachdem der
urspruengliche Stand (Commit e76e24e) auf einer aelteren Basis beruhte und
per Rebase-Analyse als eigenstaendige, unabhaengige Erweiterung erkannt
wurde (der Kollege hat nichts entfernt - diese Features existierten vorher
nur lokal uncommitted).
Drei Erweiterungen fuer "Neue Linie: GF" in vf-linienzug-modus:
- Separator VOR/NACH direkt vor bzw. nach der Gefaellestrecke einfuegbar.
- Aeussere Vorwahl "Wie soll die Laenge bestimmt werden?": Endpunkt waehlen
(bisheriges Verhalten) oder Zielhoehe zuerst festlegen (Winkel wird
daraus berechnet).
- Dritte Option "Steigende GF" (Sonderfall, 0 bis 3 Grad): erlaubt eine GF,
die statt zu fallen steigt. Neuer Helfer vfl-bogen-uebergang erkennt
anhand der tatsaechlichen Frame-Neigung, ob 0/1/2 Uebergangsboegen
(Vario_Bogen_auf_3/ab_3) noetig sind, und baut sie automatisch - im
Normalfall (fallend->fallend) ein No-Op.
Lisp/vf_spec.lsp (Kollegen-Spec/Headless-Bau-System) um die drei neuen
Felder (laenge_modus/sep_vor/sep_nach/steigend_modus) erweitert, mit
Defaults, die alte Specs unveraendert lassen - haelt die "Spec-Pfad ==
interaktiver Pfad"-Invariante seines Systems (TEST_HUNDM05/VF_SPEC_BAU)
intakt. tests/test_vf_spec.lsp entsprechend mit neuen Testfaellen ergaenzt.
Neuer Regressionstest TEST_LINIENZUG_STUFE2 (linienzug_tests_stufe2.json)
sowie Anleitung doc/vf_linienzug_modus1_anleitung.md aus dem urspruenglichen
Commit uebernommen; die Gefaelle-Hoehe/Winkel-Optionsreihenfolge im
Testdatensatz an die jetzt geltende (Kollegen-)Konvention angepasst.
Offen (bewusst zurueckgestellt): lib/vf_spec_export.py (Python-Vorwaerts-
Emitter, Pendant zu vf_spec.lsp) noch nicht nachgezogen - siehe Folge-Commit.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
TEST_HUNDM05 baute bisher keine BTMT-Beladung/SC_Entladung-Stationen,
weil hundm05.json anders als mubea.json nie Eintraege dafuer hatte -
dadurch fehlten sie im CSV-Export der Testanlage. Koordinaten/Rotation
aus dem Insertpoint/K1-KOS-String der realen Referenz-CSV
(hundmM05_1.csv) dekodiert und als "block"-Eintraege ergaenzt; der
bestehende generische _.INSERT-Pfad in hundm05:bau-sensor baut sie ohne
weitere Code-Aenderung. Kommentare/Doku (test_hundm05.lsp,
object_data.md Abschnitt 5) an die jetzt nicht mehr auf Separator/
Scanner beschraenkte Nutzung angepasst.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
9 reale Separator/Scanner-Koordinaten aus der Anlage in hundm05.json
ergaenzt. hundm05:bau-zusatzobjekte (test_hundm05.lsp) baute bisher nur
Kreisel-Zusatzobjekte - neue hundm05:bau-sensor-Funktion (analog zu
mubea:build-separator-one in test_mubea.lsp) faengt jetzt auch
"block"-Eintraege (Separator/Scanner) ab und fuegt sie per _.INSERT ein.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
ILS_EINGANG_INSERT/ILS_AUSGANG_INSERT (Menue SPS > Connections) setzen
das Eingang-/Ausgang-Symbol automatisch lotrecht ueber eine gewaehlte
BTMT-Beladung/-Entladung-Instanz statt per freiem Einfuegepunkt.
Blockdateien Eingang_2D/3D.dwg und Ausgang_2D/3D.dwg ins Flach-Schema
von data/ils kopiert (Quellen in data/ils/2D|3D bleiben unangetastet).
Mubea-Testdaten um ein Eingang-Symbol ueber der Beladung und je ein
Ausgang-Symbol ueber beiden Entladungen erweitert.
Zusaetzlich: BTMT-Drehung im CSV-Export (export_csv.py) auf ganze
Grad gerundet (90/180/... statt z.B. 90.4078), da Kommastellen dort
keine Bedeutung haben.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Erwartete Drehung fuer den Separator in Kreisel_rechts korrigiert
(entdeckt beim Nachverfolgen der Separator-Rotation im GF-Export).
gf.dxf/test.dxf sind Testzeichnungen aus der Fehlersuche.
tests/testdata/hundm05.json enthaelt jetzt neben den 5 Spec-Ketten auch
andere Objekte der Anlage - erkennbar am Feld "function", im Format der
jeweiligen Einzel-Testdaten (ein Kreisel also wie in kreisel_tests.json).
Damit beschreibt EINE Datei die ganze Anlage.
- tests/test_hundm05.lsp: hundm05:bau-zusatzobjekte sammelt alle Objekte mit
"function" und baut sie; hundm05:bau-kreisel ruft kreisel-insert-script
(wie tests/test_kreisel.lsp) und liefert einen Ergebnis-Record in derselben
Form wie die Ketten. Eigener ssg-start-Rahmen mit ATTREQ/ATTDIA 0, weil
vsp-bau-datei seinen schon geschlossen hat und (command "_.INSERT" ...)
sonst nach Attributwerten fragt. Je Objekt gefangen, damit ein Fehler die
restlichen nicht mitnimmt.
- Lisp/vf_spec.lsp: "kind" ist jetzt ein Record-Feld (Default "linienzug")
statt eines Literals in vsp-result-json - so schreibt vsp-results-schreiben
beide Objektarten in EINE Ergebnisdatei.
- lib/vf_spec_export.py: Objekte der Ziel-Datei, die keine Kette beschreiben,
werden beim Neuschreiben unveraendert ans Dateiende uebernommen. Ohne das
waere jeder von Hand ergaenzte Eintrag beim naechsten Generatorlauf weg -
die Datei ist erzeugt UND handgepflegt. spec_aus_flachen_objekten
ueberspringt sie jetzt statt zu werfen, genau wie vsp-gruppieren in LISP.
- tests/test_hundm05.py: die Ketten-Tests filtern auf kind "linienzug"
(Records ohne das Feld stammen aus aelteren Laeufen und waren nur Ketten);
neue Klasse TestZusatzobjekte prueft Status, expect_block_prefix,
expect_hoehe (Attribut HOEHE), expect_kreiselart (KREISELART) und den
Einfuegepunkt - dieselben Erwartungsfelder wie tests/test_kreisel.py.
- tests/test_vf_spec.py: neuer Test, dass die Zusatzobjekte die
Ketten-Zerlegung nicht beeinflussen - auch nicht, wenn sie mitten zwischen
den Sektionen stehen (der eingetragene Kreisel stand zunaechst inmitten
der Sub-Knoten von Kette 5; nach dem Regenerieren steht er am Dateiende).
Verifiziert: 118 pytest-Tests gruen, Spec-Regenerierung uebernimmt das
Zusatzobjekt (58 Objekte), beide .lsp lint-sauber. Die Kreisel-Tests warten
auf den naechsten TEST_HUNDM05-Lauf.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Nach dem gruenen VF_SPEC_BAU-Lauf bauten zwei Tests dieselben 5 Ketten. Der
Spec-Pfad ist jetzt der routinemaessige Bau-Test, der Aufzeichnungs-Pfad der
abgeschaltete Regressionstest fuer das Journal-Format.
Umbenennungen:
- tests/testdata/vf_spec_hundm05.json -> tests/testdata/hundm05.json
Die Spec ist das Eingabeformat und die Datei, in der weitere Ketten der
Anlage nachgetragen werden. spec_ids jetzt VF_hundm05_LZ_* (wie im
Aufzeichnungs-Protokoll), damit sich die Ergebnisse beider Laeufe paaren
lassen.
- tests/testdata/hundm05.json -> tests/testdata/hm_recformat.json
tests/test_hundm05.lsp -> tests/test_hm_recformat.lsp (TEST_HM_RECFORMAT,
Praefix hmrec:, Export hm_recformat:export-results)
tests/test_hundm05.py -> tests/test_hm_recformat.py
In alltests.json auf "disabled": true.
Neu: tests/test_hundm05.lsp (TEST_HUNDM05) baut die Spec - OHNE eigene
Bau-Logik, es ruft vsp-bau-datei aus Lisp/vf_spec.lsp. Damit gibt es genau
einen Code-Pfad, der aus einer Spec Geometrie erzeugt; c:VF_SPEC_BAU nutzt
denselben. tests/test_hundm05.py prueft das Ergebnis (die 9 Tests, die
vorher in test_vf_spec.py standen); test_vf_spec.py ist jetzt reiner
Uebersetzer-Test ohne CAD.
Warum das Aufzeichnungsformat bleibt (Details in
doc/TODO-plan-vf-interactive.md Abschnitt 4.7):
- hm_recformat.json ist die EINZIGE eingecheckte Kopie der Originaldaten
(data/polylines.dxf ist mit 124 MB per .gitignore ausgeschlossen). Die Spec
ist daraus abgeleitet; ohne die Aufzeichnung faellt die rechte Seite des
Rundlauf-Beweises weg.
- Es prueft eine ANDERE Invariante: das Journal kommt roh aus der XDATA einer
Kundenzeichnung. TEST_HM_RECFORMAT ist damit der einzige Test dafuer, dass
ein BESTEHENDER VF_n-Block weiter abspielbar ist - also dass
Doppelklick-Edit und 2D/3D-Konvertierung an Altbestand funktionieren. Ein
spec-gebautes Journal kann das nicht zeigen, es kommt aus dem Uebersetzer.
- Es dokumentiert die Frage-Reihenfolge (kommentar je Eintrag); die Spec
verbirgt den Dialog, das ist ihr Zweck.
Weitere Anpassungen:
- Ergebnisdatei heisst nach der Spec-Datei (<basisname>_results.json), damit
Befehl und Testrunner in dieselbe Datei schreiben. Verzeichnis: tests/output
(Override DXFM_VF_SPEC_OUT); NICHT DXFM_RESULTS - das sind die Sivas-/
CSV-Exporte, dort landete die Datei ausserhalb des Testbaums.
- Neu *vsp-dim-override* fuer TEST_HUNDM05_2D/_3D: wird je Kette angewandt,
weil der Abbruch-Handler in vf-linienzug-modus *ssg-ils-dim* zurueck setzt.
- Das Anlagenkuerzel der test_id in lib/vf_journal_export.py kam aus dem
Namen der Ziel-JSON. Nach der Umbenennung haette eine Regenerierung die ids
stillschweigend auf VF_hm_recformat_LZ_* geaendert und die Paarung der
beiden Laeufe zerlegt - jetzt feste Konstante TEST_ID_ANLAGE.
- conftest: hundm05_* Fixtures -> hmrec_* (die Spec-Fixtures stehen in
tests/test_hundm05.py).
Verifiziert: 98 pytest-Tests gruen (die 9 Ergebnis-Tests warten auf einen
neuen TEST_HUNDM05-Lauf), alle .lsp lint-sauber, Spec-Regenerierung
idempotent, TEST_VF_SPEC in BricsCAD 28 PASS / 0 FAIL.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Stufe 1 des Fahrplans in doc/TODO-plan-vf-interactive.md, fertig fuer
Modus 1. Eine SPEC beschreibt eine Kette in Domaenenwerten ("links",
"winkel", "aussen", ja/nein) statt in Menue-Codes; vsp-journal uebersetzt sie
in ein Eingabe-Journal, vsp-bau-aus-spec spielt es per
vfl-journal-replay-start durch den UNVERAENDERTEN vf-linienzug-modus. Der
fertige Block traegt damit dasselbe SSG_VF_EDIT-Journal wie eine handgebaute
Kette und bleibt per Doppelklick editier- und 2D/3D-konvertierbar - kein
Journal-Konsument muss etwas von Specs wissen.
CAD-Lauf VF_SPEC_BAU: 5 OK, 0 Fehler. Je Kette status "executed",
prompts 0 (keine Live-Eingabe erreicht), eingaben_offen 0, keine
Spec-Fehler, keine Bau-Meldungen, glieder_ist == glieder_soll,
Einfuegepunkt gleich dem Kettenstart der Spec.
Neu:
- Lisp/vf_spec.lsp: Code-Tabellen, Emitter vsp-journal, Validierung
vsp-pruefen, flacher JSON-Loader, Headless-Rahmen vsp-headless-an/-aus,
Ergebnis-Record, vsp-bau-aus-spec/-liste, c:VF_SPEC_BAU. Von vf_core.lsp
NACH vf_linienzug.lsp geladen - damit sind beide Ladewege abgedeckt (Menue
und der .scr-Loader), das MNL bleibt unveraendert.
- lib/vf_spec_export.py: derselbe Emitter in Python PLUS die Umkehrung
(spec_aus_journal), erzeugt die Spec-Testdaten.
- tests/testdata/vf_spec_hundm05.json: die 5 echten Ketten als Spec,
erzeugt statt handgeschrieben.
- tests/test_vf_spec.lsp (C:TEST_VF_SPEC, in alltests.json): 7 Faelle je
Glied-Typ, 7 Validierungsfaelle, Gruppieren, und die 5 echten Ketten gegen
ihr aufgezeichnetes Journal.
- tests/test_vf_spec.py: 36 Tests (Rundlauf, Spec-Daten, Validierung,
Erwartungswert-Abgleich, Ergebnisse von VF_SPEC_BAU).
Drei Regeln, die der Uebersetzer besitzen muss - jede wuerde sonst die ganze
Replay-Queue verschieben:
- Der Menue-Code haengt am Frame: erste Sektion 4 Optionen (kein GF-Bogen,
es gibt noch keine Richtung), jede spaetere 5.
- hz steht genau EINMAL im Journal, beim ersten Segment (vfl-in-abstand
journalisiert die Richtung nur bei freier Richtungswahl).
- Nur ein HORIZONTALER Erstkoerper einer VF-Einheit stellt die Separator-/
Endpunktfragen vorab (winkel1=0 laeuft durch vfl-baue-horizontal-koerper);
ein gewinkelter wird ohne jede Frage gebaut.
Wie die Richtigkeit belegt ist - drei Implementierungen derselben Grammatik,
die einander pruefen:
- Rundlauf gegen echte Daten: journal_aus_spec(spec_aus_journal(tok)) == tok
fuer alle 5 HundM-Ketten, tokenweise numerisch verglichen. Damit ist
bewiesen, dass die Spec das Journal verlustfrei abbildet.
- Der Weg, den LISP nimmt (flaches JSON -> Spec -> Journal), ergibt separat
geprueft dieselben Journale wie das aufgezeichnete Protokoll.
- Der unabhaengige Dekoder aus lib/vf_journal_export.py verdaut alle 7
synthetischen Emitter-Ausgaben restlos, auch die zwei Zweige, die in den
echten Daten fehlen (Linie-VF, gewinkelter Erstkoerper).
- Die Erwartungswerte im LISP-Test kommen aus dem geprueften Python-Emitter;
TestLispErwartungen liest sie zurueck und vergleicht erneut. Ohne das
koennte ein Uebertragungsfehler einen falschen Erwartungswert
festschreiben und der CAD-Lauf waere gruen, obwohl der Emitter falsch
liegt.
Abweichungen von der Planung (Begruendungen in doc/TODO-plan-vf-interactive.md
Abschnitt 4.6): vsp-pruefen ruft den Emitter statt eine zweite Regelmenge zu
pflegen; das vollstaendige Journal steht nicht im Record (statt dessen
glieder_soll/glieder_ist als Desync-Detektor); Zusatzfeld segment_typ am
Glied "Linie", weil dort vfl-segment-entscheidung selbst zwischen GF und VF
waehlt; vf_ende-Werte "automatisch"/"zielpunkt-ohne-es" fuer die Faelle ohne
Frage; Praefix vsp- statt vfs- (das gehoert vf_standard.lsp).
Zusaetzlich:
- tests/test_vf_headless_statisch.py prueft jetzt auch, dass
Lisp/vf_spec.lsp UEBERHAUPT keine Eingabe-/Dialogfunktion aufruft - beim
Daten-Pfad ist die Null die Vorgabe.
- tests/testdata/mubea.json: die drei einzeln eingefuegten S-LP-Separatoren
entfernt (Fortsetzung von 699744e - die Separatoren stecken jetzt in den
Staustreckenbloecken).
Noch offen: die Uebersetzer fuer Modus 2 und 3. Modus 2 braucht laut
Fahrplan erst 2-3 echte "linienzug2"-Journale als Referenz -
tests/testdata/hundm05.json enthaelt ausschliesslich Modus-1-Ketten.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Ziel: eine VF_n-Kette soll aus einem Stapel Eingabedaten gebaut werden
koennen - ohne Dialog, ohne Konsolenfrage. Fahrplan und Begruendungen in
doc/TODO-plan-vf-interactive.md. Alle Aenderungen sind No-Ops, solange
*ssg-gui-aus* und *vfl-headless* nil sind.
Produktion (Lisp/vf_linienzug.lsp, Lisp/vf_core.lsp):
- vfl-journal-reset im Dispatcher VOR die Modus-cond gezogen. Bisher nur im
Modus-1-Zweig: ein frischer Modus-2-Lauf erbte das Journal des Vorlaufs und
schrieb es in die XDATA, ein spaeterer Doppelklick spielte fremde Eingaben
vor.
- Lokale Variable "member" in vf-linienzug-modus2 umbenannt. Sie verdeckte im
selben Scope das Builtin member, das weiter unten gebraucht wird - jedes
Kletterer-Segment waere in "bad function" gelaufen.
- Neu vfl-meldung: sammelt den Text nach *vfl-meldungen* + dbgmsg und zeigt
ihn nur bei erlaubter GUI modal, sonst per princ. Die 12 Bau-Pfad-alerts
darauf umgestellt; ein Alert blockierte sonst jeden Batch-Lauf, und sein
Text ist die einzige Auskunft, WELCHE Sektion abgewiesen wurde. Die reinen
Interaktiv-Alerts (fehlendes DCL, "nicht editierbar", "kein Journal")
bleiben alert.
- Neu *vfl-headless* (+ vfl-headless-p/-abbruch/-notausgang/-ort, Diagnose
*vfl-headless-fehler*, optionaler Antwort-Hook *vfl-headless-antwort-fn*):
eine erschoepfte Replay-Queue ist damit ein harter Abbruch MIT Fundstelle
(Art der Eingabe, Glied- und Eingabe-Nummer) statt eines stillen Rueckfalls
auf Live-Eingabe. Eingebaut in vfl-in-value, vfl-in-value-p,
vfl-in-selection und vfl-in-abstand.
- vfl-journal-reset loescht Meldungen und Diagnose mit (gehoeren zum Lauf);
vfl-view-refresh ueberspringt headless _PLAN/_ZOOM.
Testfall HundM05 (5 echte Ketten aus data/polylines.dxf):
- tests/testdata/hundm05.json neu erzeugt aus den XDATA-Journalen der
VF_n-Bloecke (lib/vf_journal_export.py) - flach, weil ssg-load-json
zeilenweise liest. Die drei kopierten Ketten bekommen ihren echten
Einfuegepunkt, nicht das veraltete HOEHE_VON-Attribut.
- tests/test_hundm05.lsp arbeitet jetzt per Journal-Replay statt mit
Eingabe-Mocks: ein echtes Journal fuehrt die geerbte Fahrtrichtung nicht mit
(vfl-in-abstand journalisiert hz nur beim ersten Segment), ein Mock kann sie
also nicht kennen. Schaltet *vfl-headless* ein und schreibt prompts,
headless_fehler und meldungen ins Ergebnis-JSON.
- Kettenschleife fangt je Kette: ein Fehler NACH dem Bau nimmt nicht mehr die
restlichen Ketten mit.
- entprev gibt es in AutoLISP nicht (nur entnext/entlast) - die Suche nach dem
fertigen Block laeuft vorwaerts ab dem Zeichnungsstand vor dem Bau. Dieselbe
Falle in tests/test_mubea.lsp mitbehoben; sie schlug dort nie zu, weil
entlast immer sofort traf.
Absicherung ohne CAD:
- tests/test_vf_headless_statisch.py: eingechecktes Inventar aller
alert/get*/ssget/new_dialog-Fundstellen je Funktion (ein neues getreal in
einer Bau-Funktion faellt auf, auch wenn sein Zweig im Test nie erreicht
wird), Praesenz des Riegels in allen vier Wrappern, Diagnose-Reset und die
Reset-Reihenfolge im Dispatcher. Dazu ein Waechter gegen erfundene
AutoLISP-Funktionen (entprev u.a.) - diese Fehlerklasse kostet sonst jedes
Mal einen CAD-Lauf.
- tests/test_hundm05.py prueft zusaetzlich prompts == 0, keine
Headless-Abbrueche und keine Bau-Meldungen.
tests/alltests.json: hundm05-Zeile laedt VarioFoerderer (nicht KreiselInsert)
und bleibt bis zu einem gruenen CAD-Lauf abgeschaltet.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Grundlage fuer reproduzierbare Nachbau-Testfaelle aus echten Projekt-
zeichnungen (HundM05).
- lib/vf_journal_export.py (neu): liest die Eingabe-Journale der VF_n-Bloecke
aus der XDATA (App SSG_VF_EDIT, Marker "linienzug") und schreibt sie als
Frage-Antwort-Protokoll im Schema von tests/testdata/linienzug_tests.json -
Gegenstueck zu vfl-entry->string, ohne ezdxf (reine Gruppencode-Lesung).
Optional --csv fuer Strecken-ID und Erwartungswerte je Kette.
- lib/extract_polylines.py (neu): LWPOLYLINE-Objekte als JSON, inkl.
OCS->Welt-Umrechnung fuer gekippte Ebenen (Handles, Segment-/Gesamtlaengen).
- lib/dxf_scan_components.py: erkennt jetzt zusaetzlich, ob ein Block ein
2D-Schema oder ein 3D-Modell ist (TYPEN_3D, ist_3d_block/darstellung_von) -
eine Anlagenzeichnung enthaelt beides. Dazu Sensor-Erfassung,
Zwillings-Zusammenfuehrung und Hoehenschaetzung aus der Umgebung.
- lib/dxf_abbild.py: gibt die erkannte Darstellung je Element mit aus.
- tests/test_vf_journal_grammatik.py (neu): prueft den Journal-Dekoder gegen
handgebaute Journale - ohne CAD und ohne die grosse DXF. Deckt die zwei
Zweige ab, die in den echten Ketten nicht vorkommen: Glied "Linie-VF" und
eine VF-Einheit mit gewinkeltem Erstkoerper (dort fragt vfl-vf-einheit
KEINE Separator-/Endpunkt-Fragen vorab, anders als beim horizontalen).
- data/polylines.md, tests/testdata/hundm05_linienzug_polylines.json:
ausgewertete Streckenzuege der Quellzeichnung.
- .gitignore: die Quellzeichnungen selbst (data/polylines.dxf 124 MB,
data/polylines.dwg, tests/HM5.dwg) bleiben draussen - eingecheckt ist die
Auswertung, nicht die Zeichnung.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Die interaktiven Editier-Pfade riefen den Neuaufbau ueber
vl-catch-all-apply auf. Der alte Block ist dort per entdel schon
entfernt, und der Catch faengt einen Abbruch (ESC -> (exit)) VOR
*error* ab - der Abbruch-Wickler vfl-modus-abbruch-sichern kam damit
nie zum Zug. Ergebnis: die komplette Kette blieb als lose Einzelteile
ohne VF_n-Block liegen und war nicht mehr per Doppelklick editierbar.
- vfl-edit-ent (Sektions-Zweig) und vfl-edit-ent2 rufen
vf-linienzug-modus/-modus2 jetzt DIREKT auf. Nur der
nicht-interaktive Batch-Konverter vfl-konvertiere-ent behaelt den
Catch (die Batch-Schleife muss weiterlaufen) und meldet den
betroffenen Block statt still zu scheitern.
- Beide Abbruch-Handler setzen *ssg-ils-dim* zurueck. Das tat bisher
nur der Aufrufer, der nach einem Abbruch nicht mehr erreicht wird -
der Dim-Override blieb fuer die restliche Sitzung stehen.
Wiederherstellung aus der Zeichnung (Sektions-XDATA):
- vfl-segment-xdata-sichern schrieb nur die Slice des LETZTEN Glieds
einer Schleifen-Iteration. Eine VF-Einheit mit eingebetteten
Vario-Kurven verlor dadurch ihre eigenen Eingaben. Jetzt wird der
komplette Journal-Abschnitt der Iteration geschrieben, indiziert mit
dem ersten Glied-Index darin (neu: vfl-journal-ab-glied,
vfl-steps-zaehlen). Ein Glied ohne Geometrie verbraucht seinen
Abschnitt nicht mehr - er wandert in den naechsten Record, der
Entities bekommt.
- Neue XDATA-App SSG_VF_EDIT_PRE haelt die Praeambel (Startpunkt,
Starthoehe, AS ja/nein + Winkel/Seite) auf den Entities der ersten
Iteration. Ohne sie fehlte der Kopf des Journals in jeder Sektion.
- Neuer Befehl VF_SEKTION_RESTORE: Auswahl der losen Geometrie ->
Sektionen lueckenlos ab Glied 1 zusammensetzen -> stummer Replay ->
interaktiv weiterbauen. Die alte Geometrie wird erst NACH
erfolgreichem Neuaufbau geloescht, ein Abbruch laesst sie samt XDATA
stehen (Versuch wiederholbar). Altbestand ohne Praeambel-XDATA wird
danach gefragt.
Die .dbg-Dateien bleiben reine Ausgabe und werden von keinem Befehl
gelesen - Wiederherstellungs-Daten gehoeren in die XDATA der Zeichnung.
tests/testdata/vfl_journal_hm05_abbruch.json: Journal der Session vom
2026-08-31 (9 Glieder), gegen das die Slice-/Join-Logik geprueft wurde.
Reine Daten, wird von keinem Befehl gelesen.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
- lib/dxf_scan_components.py: erkennt ILS-/Omniflo-Komponenten in fremden
Projektzeichnungen und schreibt sie im Testdaten-JSON-Schema aus
- lib/dxf_abbild.py: getreue Abbildung der Bauteile einer Fremdzeichnung
(Attribute, Weltkoordinaten, Unterkomponenten) ohne Interpretation
- tests/test_hundm05.{lsp,py}, testdata/hundm05.json, conftest-Fixtures und
alltests.json-Eintrag fuer den Kreisel-Abschnitt aus ST500592_05.dxf
- menu: TEST_HUNDM05 im Testmenue, Connection_Insert/Edit in SSG_LIB.cui
- Doku: hartkodierte Pfade durch (getenv "DXFMAKRO") ersetzt
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>