Files
dxfmakros/doc/TODO-plan-vf-interactive.md
T
s.ayadi 428f1ced70 [FEAT] VF-Linienzug aus Eingabedaten bauen (Stufe 1: Spec -> Journal -> Replay)
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>
2026-09-03 10:44:38 +02:00

38 KiB

TODO/Plan: VF-Linienzug ohne GUI/Konsole aufrufbar machen

Stand: 2026-09-02 · Status: Stufe 0 fertig (im CAD noch ungetestet) Herkunft: Planungslauf (Plan-Modus) vom 2026-09-02, hier eingecheckt zur Nachverfolgung.

Fortschritt

Schritt Beschreibung Status
P0 vfl-journal-reset im Dispatcher hochziehen erledigt
P0b member-Shadowing in vf-linienzug-modus2 erledigt
P1 vfl-meldung statt alert in den Bau-Pfaden erledigt
P2 *vfl-headless*: leere Replay-Queue wird zum Fehler erledigt
P3 Kleinkram (*vfl-meldungen*-Reset, vfl-view-refresh) erledigt
S1 Stufe 1: Lisp/vf_spec.lsp (Spec -> Journal -> Replay) Modus 1 fertig, im CAD ungetestet
S2 Stufe 2: echte Funktionstrennung (Schritte 0-11) offen
PY lib/vf_journal_export.py: Grammatik vervollstaendigen erledigt

Was Stufe 0 konkret gebracht hat

Neue Symbole in Lisp/vf_linienzug.lsp (Abschnitte "TEIL 0a-2" und "TEIL 0a-3"):

Symbol Zweck
*vfl-meldungen* / vfl-meldung Bau-Meldungen sammeln statt blockierend zu alerten (alert nur bei ssg-gui-p, sonst princ)
*vfl-headless* / vfl-headless-p Schalter "keine Live-Eingabe erlaubt"
vfl-headless-abbruch / -notausgang / -ort harter Abbruch mit Fundstelle bzw. Hook-Variante
*vfl-headless-fehler* Diagnose-Alist (was/glied/eingabe/ort)
*vfl-headless-antwort-fn* optionaler Hook fuer nicht vorhersagbare Rueckfragen

Eingebaut an den vier Eingabe-Engstellen (vfl-in-value, vfl-in-value-p, vfl-in-selection 2x, vfl-in-abstand 2x). vfl-journal-reset loescht Meldungen und Diagnose mit; vfl-view-refresh ueberspringt headless _PLAN/_ZOOM. tests/test_hundm05.lsp schaltet *vfl-headless* ein (Save/Restore in hundm05:stubs-an/-aus), zaehlt erreichte Live-Eingaben (*hundm05-prompts*) und schreibt prompts, headless_fehler, meldungen ins Ergebnis-JSON; tests/test_hundm05.py prueft alle drei.

Bereits abgesichert, ohne CAD lauffaehig: tests/test_vf_headless_statisch.py (10 Tests) haelt das Design gegen Verrottung - 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 in vfl-journal-reset und die P0-Reihenfolge im Dispatcher. Der Waechter wurde gegengeprobt: ein injizierter alert im Bau-Pfad wird erkannt, ein alert in einem Kommentar nicht.

CAD-Lauf 1 (2026-09-03): die erste Kette wurde headless gebaut (">>> VF chain inserted! <<<", kein Prompt, kein Dialog) - der Riegel und der Replay funktionieren also. Danach brach der Treiber ab:

[TEST_HUNDM05] FEHLER in der Kettenschleife:
  no function definition <ENTPREV>

entprev gibt es in AutoLISP nicht (nur entnext und entlast) - mein Fehler in hundm05:last-insert-prefix, der Suche nach dem fertigen VF_-Block. Erreicht wurde sie erst, weil entlast nach dem Bau nicht der Block ist (danach entstehen noch Beschriftungstexte). Behoben:

  • Suche laeuft vorwaerts (hundm05:suche-vorwaerts, letzter Treffer gewinnt), und zwar ab dem Zeichnungsstand VOR dem Bau (vor-ent, in hundm05:build-linienzug gemerkt). Das ist schnell und kann nicht den Block eines FRUEHEREN Baus liefern - deshalb dort bewusst kein entlast-Kurzschluss.
  • Dieselbe Falle in tests/test_mubea.lsp (mubea:last-insert-prefix) mitbehoben. Sie schlug dort nie zu, weil entlast bisher immer sofort traf; entprev war nur der nie erreichte Schleifenschritt.
  • Die Kettenschleife fangt jetzt je Kette (vl-catch-all-apply um hundm05:build-linienzug): ein Fehler NACH dem Bau nimmt nicht mehr die restlichen vier Ketten mit ("0 OK, 0 Fehler" ohne jede Auskunft).
  • Neuer Waechter test_keine_nicht_existierenden_funktionen in tests/test_vf_headless_statisch.py prueft alle .lsp in Lisp/ und tests/ gegen eine Liste erfundener Funktionen (entprev u.a.) - genau diese Fehlerklasse (falscher Name in einem selten erreichten Zweig) kostet sonst jedes Mal einen CAD-Lauf. Gegengeprobt: ein wieder eingebautes entprev wird gefunden, das Wort im Kommentar nicht.
  • vfl-meldung verkraftet jetzt txt = nil (fehlender i18n-Schluessel wuerde strcat genau dann abbrechen, wenn schon etwas schiefging).

Noch offen (braucht BricsCAD): TEST_HUNDM05 muss 5x "status": "executed" mit prompts 0 liefern, und eine interaktive Gegenprobe (FOERDERANLAGE -> Linienzug Modus 1, Doppelklick-Edit, SSG_DIM_SWITCH) muss unveraendert aussehen. Erst danach kann in tests/alltests.json das "disabled": true der hundm05-Zeile weg.

Bewusst nicht umgestellt: vfl-konvertiere-ent (Batch-2D/3D) laeuft weiter ohne *vfl-headless* - eine Live-Rueckfrage ist dort bisher gewolltes Verhalten. Kandidat fuer Stufe 1, wenn der Ergebnis-Record steht.

Kontext

VF_n-Ketten entstehen heute nur interaktiv: vf-linienzug-modus (Modus 1, freies Zeichnen), vf-linienzug-modus2 (Modus 2, Pfad + Zielhoehe) und vf-linienzug-modus3 (Modus 3, Vorwaerts-Nachbau, Legacy) fragen jeden Wert einzeln per getpoint/getstring/getint/getreal bzw. per DCL-Wizard ab. tests/testdata/object_data.md Abschnitt 3.3 fuehrt den Linienzug darum als "nicht scriptbar".

Ziel: eine Kette soll aus einem Stapel Eingabedaten plus einer Handvoll LISP-Funktionen gebaut werden koennen - ohne Dialog, ohne Konsolenfrage. Damit werden Regressionstests (siehe tests/test_hundm05.lsp, 5 echte Ketten aus data/polylines.dxf), Batch-Nachbauten und der 2D/3D-Umbau reproduzierbar, und die Bau-Logik wird pro Abschnitt einzeln aufrufbar.

Entscheidungen des Auftraggebers (fix):

  • Zweistufig: erst Daten-API (Spec -> Journal -> Replay), dann echte Trennung der Misch-Funktionen in Frage-Schale + reinen Bauteil.
  • Modus 1 + 2 vollstaendig, Modus 3 nur duenn gewrappt (ist als "wird umgebaut" markiert).
  • Eingabeformat: benannte LISP-Spec (Alist je Abschnitt) + JSON-Loader.
  • Fehlerverhalten: fail fast mit Ergebnis-Record, nichts raten, kein Dialog.

Zeilennummern in diesem Dokument beziehen sich auf den Stand bei der Planung (Lisp/vf_linienzug.lsp, Lisp/vf_core.lsp) und verschieben sich mit jeder Aenderung - im Zweifel per Funktionsname suchen.


Teil 1 - Befund: was ist heute schon headless moeglich?

Modus Headless heute? Mechanismus Blocker
1 (frei zeichnend, vf-linienzug-modus :3211) Ja, in der Praxis Journal-Replay: vfl-journal-replay-start :1545 fuellt *vfl-replay-queue*, alle vfl-in-*-Wrapper lesen zuerst daraus. Produktiv genutzt von vfl-edit-ent :4322, vfl-edit-glied :4190, vfl-konvertiere-ent :4292 und von tests/test_hundm05.lsp Alerts nicht abschaltbar (:3523, :3550, :3559, :3650, :3772); leere Queue faellt still auf Live-Eingabe zurueck (:1186-1191); Daten muessen in exakter Frage-Reihenfolge vorliegen
2 (Pfad + Zielhoehe, vf-linienzug-modus2 :5278) Ja, gleicher Mechanismus Marker "linienzug2", Replay-Einstieg vfl-edit-ent2 :4397 Pfad-Objekte (LINE/ARC) muessen in der Zeichnung liegen - das Journal speichert nur Handles (OBJS, handent :1060); keine STEP-Marker -> kein Sektions-Edit; Dispatcher vf_core.lsp:1139 ruft vfl-journal-reset NICHT (Journal des Vorlaufs wird als Praefix mitgeschrieben); Alerts :5418, :5650; lokale Variable member :5289/:5496 verdeckt die Builtin-Nutzung :5686/:5759
3 (Vorwaerts-Nachbau, vf-linienzug-modus3 :4806) Nein Alle Eingaben laufen zwar durch die vfl-in-*-Wrapper (im Prinzip replaybar), aber: kein vfl-journal-reset, kein vfl-journal-xdata-schreiben, kein Marker, *error*-Hook wickelt keine Teil-Geometrie (:4835-4844) bewusst so, Kommentar :4825-4827; fehlt: Reset + XDATA-Schreiben + Marker + Edit-Zweig

Modus-uebergreifende Blocker:

  • 40 alert-Aufrufe im Cluster, keiner durch ssg-gui-p gesichert; im Bau-Pfad erreichbar: :3523/:3550/:3559/:3650/:3772 (M1), :5418/:5650 (M2), :4901/:4921/:5029 (M3), :1067 (Replay: Handles fehlen), :123 (GF-Modul fehlt). Mehrere mit anschliessendem (exit).
  • (ssg-gui-aus) deckt nur zwei Stellen ab: vf_core.lsp:632 (vf-frage-element-winkel) und vf_linienzug.lsp:447 (vfl-wizard-mode-p -> alle vflw-*-Dialoge). Die Nicht-Wizard-DCLs (variofoerderer_basis, variofoerderer_winkel, gefaellestrecke, vfl_edit_modus, vfl_edit und die drei wiederverwendeten vflw_*-Edit-Dialoge :3962/:4000/:4044) bleiben modal.
  • Der Dispatcher selbst fragt: c:VarioFoerderer (vf_core.lsp:1073) holt Anlagentyp (getint :1108) und Untermodus (getint :1130) roh ab. Ein headless Aufruf muss darum immer direkt vf-linienzug-modus* aufrufen.
  • Rohe Eingaben ohne Journal in Nebenpfaden: vfl-praeambel-erfragen :4445, c:VF_SEKTION_RESTORE :4496, c:VFL_KS_DIAG :4622, c:Vario_Kette_Merge :6347.
  • ATTREQ/ATTDIA: ohne 0 fragt das (command "_.INSERT" ...) in den Einfuegeprimitiven nach Attributwerten - der wahrscheinlichste Haenger.

Namensfalle: die vfl3-*-Helfer (:5093-5276) gehoeren zu Modus 2, die vfl2-*-Helfer (:4703-4804) zu Modus 3.


Teil 2 - Invarianten

# Invariante Sicherung
I1 Jeder fertige VF_n-Block traegt ein gueltiges SSG_VF_EDIT-Journal (Marker "linienzug"/"linienzug2") und bleibt per Doppelklick editier- und 2D/3D-konvertierbar Stufe 1 baut ueber die unveraenderte Modus-Funktion (schreibt :3867 selbst). Stufe 2: kein Bauteil beruehrt das Journal - im Frage-Pfad erzeugen es die vfl-in-*-Wrapper, im Daten-Pfad wird es einmal aus der Spec erzeugt und vor dem Bau gesetzt
I2 Kein Prompt, kein Dialog GUI aus + Wizard aus + zaehlende Eingabe-Stubs + *vfl-headless* (harter Fehler statt Frage)
I3 Nichts geraten Leere Queue = Fehler mit Fundstelle; jede abgewiesene Sektion erzeugt eine gesammelte Meldung; Spec-Validierung bricht vor dem ersten Insert ab
I4 Interaktives Verhalten unveraendert Jede Produktionsaenderung ist ein No-Op, solange *ssg-gui-aus* und *vfl-headless* nil sind

Teil 3 - Stufe 0: Vorarbeiten in der Produktion

Fuenf kleine Aenderungen, alle No-Ops im interaktiven Betrieb. Reihenfolge = Empfehlung; P0 und P1 sind eigenstaendige Bugfixes und koennen sofort raus.

P0 - vfl-journal-reset hochziehen (Lisp/vf_core.lsp:1139). Heute nur im Modus-1-Zweig. Folge: ein frischer Modus-2-Lauf erbt das Journal des Vorlaufs und schreibt es in die XDATA - ein spaeterer Doppelklick spielt Muell vor. Reset vor die cond ziehen. Reiner Bugfix (die Edit-Pfade laufen nie hier durch), behebt zugleich ein veraltetes *vfl-seg-glied-letzte*.

P0b - member-Shadowing in vf-linienzug-modus2: lokale Variable member (:5289, gesetzt :5496) gegen Builtin-Nutzung (:5686, :5759) im selben Scope. Lokale umbenennen (z.B. vf-run-member).

P1 - vfl-meldung statt alert in den Bau-Pfaden. Neuer Helfer neben vfl-journal-record (~:170): Text in *vfl-meldungen* sammeln, dbgmsg schreiben, dann alert (GUI an) oder princ (GUI aus). alert -> vfl-meldung an genau diesen Stellen: :123, :1067, :3523, :3550, :3559, :3650, :3772, :5418, :5650, :4901, :4921, :5029. Die reinen Interaktiv-Alerts (:3968, :4006, :4050, :4266, :4325, :4566, :4593) bleiben. Ohne P1 blockiert ein Alert den Lauf und der Text - die einzige Auskunft, welche Sektion abgewiesen wurde - ist verloren.

P2 - *vfl-headless*: leere Queue wird zum Fehler. Neuer Notausgang vfl-headless-notausgang (was) neben vfl-replay-pop (~:210): setzt *vfl-headless-fehler* samt Glied-Index und Eingabe-Nummer (aus vfl-steps-zaehlen :1612 und (length *vfl-journal*)), meldet und bricht ab. Optionaler Hook *vfl-headless-antwort-fn* darf einen Wert liefern (wird journalisiert und als Warnung protokolliert). Vier Einbaustellen, je ein neuer cond-Zweig vor der Live-Eingabe:

  • vfl-in-value :1185 und vfl-in-value-p :1196 - deckt vfl-in-point, -string, -real, -int, vfl-menu, vfl-menu-int, vfl-menu-winkel und die AS/ES-Winkelfrage ab (rund 90 % aller Eingaben)
  • vfl-in-selection :1055 (vor dem ssget :1069) und der fehlt > 0-Zweig :1066: unter headless abbrechen statt mit einer Teilauswahl weiterzubauen (aendert sonst still die Modus-2-Fragenzahl)
  • vfl-in-abstand :2113 (eigene Replay-Logik)

P3 - Kleinkram: *vfl-meldungen* in vfl-journal-reset :157 mitloeschen; vfl-view-refresh :2028 unter headless ueberspringen (_.PLAN/_.ZOOM vor jeder Laengeneingabe, im Batch nur Kosten).


Teil 4 - Stufe 1: Daten-API (Spec -> Journal -> Replay)

Neue Datei Lisp/vf_spec.lsp, geladen aus vf_core.lsp direkt nach vf_linienzug.lsp (:1062) - deckt beide Ladewege ab (MNL ueber VarioFoerderer.lsp und Lisp/ssg_load.lsp), also keine Aenderung an menu/SSG_LIB.mnl. Guarded Nachlade-load am Kopf fuers isolierte Testen (Muster ssg_ks_insert in vf_core.lsp:66).

4.1 Spec-Form

'(("version" . 1) ("modus" . 1) ("name" . "VF_LZ_01") ("dim" . "3D")
  ("start" ("punkt" 4912.0 1231.0 2100.0) ("hoehe" . 2154.0)
           ("as" . T) ("as-winkel" . "90") ("as-seite" . "links"))
  ("sektionen"
     (("glied" . "Linie-GF") ("dl" . 5500.0) ("hz" . 0.0)
      ("gefaelle" . "winkel") ("winkel" . 3.0) ("ende" . "nein"))
     (("glied" . "Horizontal-VF") ("dl" . 4566.7)
      ("gf-verteilung" . "einlauf") ("sep-vor" . nil) ("sep-nach" . nil)
      ("weiter" (("sub" . "vario-kurve") ("winkel" . 90)
                 ("seite" . "links") ("variante" . "aussen"))
                (("sub" . "horizontal") ("dl" . 250.0))
                (("sub" . "kettenende") ("es" . T) ("dl" . 6215.0)
                 ("hoehe" . 4500.0)))
      ("ende" ("es-winkel" . "90") ("es-seite" . "rechts")))))

Durchgaengig Domaenenwerte ("links", "winkel", "aussen", T/nil), keine Menue-Codes; rohe Codes ("1"/"2") werden als Durchreiche fuer zurueckgelesene Journale akzeptiert. Glied-Typen: GF-Bogen, Linie-GF, Linie-VF, Horizontal-VF, Linie, plus das automatische ES-Glied.

Die variable VF-Einheit (heute bewusst nicht im Schema, Kommentar :260-292) wird als ("weiter" ...)-Liste modelliert, immer terminiert mit motorstation oder kettenende; Sub-Typen horizontal, vario-kurve, auf-ab.

Drei Fallen, die der Uebersetzer besitzen muss:

  1. Menue-Code haengt am Frame: nur die erste Sektion laeuft ohne Frame (4 Optionen :3396), alle spaeteren mit (5 Optionen :3378). Also Linie-GF = "1" in Sektion 1, "2" ab Sektion 2 usw.; GF-Bogen in Sektion 1 = Validierungsfehler (nicht angeboten).
  2. hz genau einmal: vfl-in-abstand journalisiert die Richtung nur bei hz-vorgabe = nil (:2130) - das ist ausschliesslich das erste Segment der Kette. hz an spaeterer Stelle verschiebt die ganze Queue -> harter Fehler; hz fehlt in Sektion 1 -> harter Fehler.
  3. gf-verteilung ist zwischen den Modi invertiert: Modus 1 :3118 ("1" = haelfte), Modus 2 :5729 ("2" = haelfte). Code-Tabelle pro Modus.

Nicht vorhersagbar bleibt die Winkelwahl (vfl-waehle-winkel :1656 fragt nur, wenn mehrere Kandidaten gueltig sind - abhaengig von der real gemessenen Restlaenge). Loesung: optionales Feld ("winkel-idx" . n); fehlt es und der Lauf braucht es, greift P2 mit einer Fehlermeldung, die Sektion und Eingabe-Nummer nennt. Kein Raten (I3).

4.2 Uebersetzer

vfl-spec-pruefen (nur Fehlerliste, fragt und baut nie) und vfl-spec->journal / -m2 / -m3 (Vorwaerts-Journal). Rueckgabe-Alist (("journal" . ...) ("fehler" . ...) ("warnungen" . ...)).

Wiederverwendung statt Neubau - diese Bausteine existieren schon: vfl-schema-slice-bauen :326, vfl-schema-feld-pruefen :303 (mit den erlaubten Werten aus *vfl-glied-schema* :243, *vfk-gf-bogen-winkel*, *vfk-as-es-winkel*), vfl-gf-bogen-slice-bauen :3941, vfl-es-slice-bauen :4093, vfl-vario-slice-bauen :4110, vfl-journal-list->string :1258. Neu sind nur Linie-GF/Linie-VF/Horizontal-VF/Linie und der VF-Fluss.

Wichtig: vfl-schema-slice-bauen loggt Schemaverstoesse und schreibt den Wert trotzdem ("Sicherung geht vor", :324) - richtig fuer den Recovery-Pfad, falsch hier. Darum prueft vfl-spec-* mit vfl-schema-feld-pruefen selbst vorab und ruft die Slice-Bauer erst mit sauberen Werten. vfl-schema-slice-bauen bleibt unangetastet.

Emitter-Regel fuer den VF-Fluss (macht den Uebersetzer trivial): die ist-Endpunkt-Antwort wird zwar an zwei Stellen gestellt (Schleifenkopf :2560 und innerhalb vfl-baue-horizontal-koerper im Ziel-Modus :2308, von dort als vor-antwort zurueckgegeben), landet in der flachen Queue aber immer an derselben linearen Position - direkt nach den Werten des Vorgaenger-Knotens. Also je Knoten: STR ende-code ("1" Motor / "3" Kettenende / sonst "2"), bei "2" zusaetzlich STR naechstes-vf plus die Nutzlast des Sub-Typs.

4.3 Headless-Rahmen und Ergebnis-Record

(vfl-headless-an opt) / (vfl-headless-aus)      ; Save/Restore, MUSS immer laufen
(vfl-bau-aus-spec spec opt)                     ; -> Ergebnis-Record
(vfl-bau-aus-spec-liste specs opt) / (vfl-bau-aus-json datei opt)
(vfl-result->json rec) / (vfl-results-schreiben recs datei)
(c:VF_SPEC_BAU)                                 ; Datei aus DXFM_VF_SPEC, fragt nichts

vfl-headless-an: *vfl-headless* T, *vfl-wizard-mode* nil, (ssg-gui-aus), zaehlende Stubs fuer vfl-getpoint/getstring/getint/getreal/getkword/ alert/new_dialog (jeder erhoeht *vfl-spec-prompts* und liefert nil), ssg-start mit OSMODE/ATTREQ/ATTDIA = 0, init-bibliothek falls noetig. ssget/entsel bewusst NICHT stubben - vf-next-number (vf_core.lsp:322) braucht (ssget "X" ...); die eine Bau-Pfad-ssget sitzt in vfl-in-selection und ist ueber P2 abgedeckt.

Pro Kette: validieren (Fehler -> Status "spec-fehler", nichts gebaut) -> *ssg-ils-dim* je Kette neu setzen (der Abbruch-Handler :3286 nullt es) -> lastEnt merken -> vfl-journal-reset + vfl-journal-replay-start -> *error* sichern, (vl-catch-all-apply 'vf-linienzug-modus '()), *error* zurueck (genau die Klammer aus hundm05:build-linienzug) -> Record aus den Globals sammeln -> aufraeumen.

Bewusster Kompromiss (wie beim Batch-Konverter vfl-konvertiere-ent :4292): weil gefangen wird, laeuft der *error*-Handler der Modus-Funktion nicht, die Teil-Geometrie wird also nicht zu einem Block gewickelt. Option ("bei-fehler" . "behalten"|"loeschen") entscheidet, ob sie stehenbleibt (per c:VF_SEKTION_RESTORE rettbar, weil vfl-segment-xdata-sichern :3855 pro Iteration schon SSG_VF_EDIT_SEG/_PRE geschrieben hat) oder ab lastEnt weggeraeumt wird.

Ergebnis-Record: Feldreihenfolge von hundm05:result-json beibehalten (test_id, kind, status, dimension, block_name, block_handle, insert_point, actual_attributes), dazu eingaben_gesamt, eingaben_offen, sektionen_soll/sektionen_ist, glieder, prompts, warnungen, fehler_sektion, fehler_text, ziel_abweichung, journal. Status: executed | warnung | desync | abbruch | spec-fehler.

Drei unabhaengige Desync-Detektoren (eine geometrisch abgewiesene Sektion wirft keinen Fehler, sie verbraucht nur weniger Eintraege): offene Queue-Werte, Vergleich der erzeugten STEP-Labels (*vfl-journal*) gegen die Glied-Folge der Spec (nennt die erste abweichende Sektion), und die gesammelten Meldungen aus P1.

4.4 Modus 2 und Modus 3

Modus 2: Spec traegt ("pfad-handles" ...) (Entity-Handles der LINE/ARC-Trasse) plus ("segmente" ...) in Pfadreihenfolge. Vor dem Bau wird die Segmentzahl gegen die aufgeloesten Handles geprueft und bei Fehlbestand abgebrochen - die Fragenzahl kommt aus gf-sortiere-objekte/gf-analysiere-kette auf der realen Geometrie. Eine Gerade direkt nach einer Vario-Kurve wird nicht gefragt (:5449); der Uebersetzer leitet das selbst ab.

Modus 3: nur vfl-bau-aus-spec mit Modus-3-Uebersetzer. Dokumentierte Einschraenkung: I1 gilt nicht (kein Journal-XDATA, also kein Doppelklick-Edit, keine 2D/3D-Konvertierung). Die volle Nachruestung braeuchte vier gekoppelte Eingriffe (Reset, XDATA-Schreiben, Marker "linienzug3" in der Whitelist :1340, vfl-edit-ent3) in dem Modus, der laut Code ohnehin ersetzt wird - darum bewusst zurueckgestellt.

4.5 JSON-Form

ssg-load-json/ssg-parse-json-array (ssg_core.lsp:1146/1167) liest zeilenweise und flach: jedes { beginnt ein Objekt, Verschachtelung ist unmoeglich, Zahlen-Arrays muessen in einer Zeile stehen. Also dieselbe Form wie tests/testdata/hundm05.json: ein Kopf-Objekt (spec_id) plus flache Sektions-Objekte (glied), Sub-Objekte (sub) und Abschluss (ende), gruppiert wie hundm05:gruppiere. Wahrheitswerte als 1/0 (ssg-cfg-parse-value kennt kein true/false). Ein nr-Feld pro Sektion macht handgeschriebene Dateien selbstpruefend.

4.6 Umsetzungsstand Stufe 1 (2026-09-03)

Fertig fuer Modus 1. Was entstanden ist:

Datei Inhalt
Lisp/vf_spec.lsp Code-Tabellen, Emitter vsp-journal, Validierung vsp-pruefen, flacher JSON-Loader vsp-json-laden/vsp-gruppieren, Headless-Rahmen vsp-headless-an/-aus, Ergebnis-Record, vsp-bau-aus-spec/-liste, c:VF_SPEC_BAU
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 (57 flache Objekte), erzeugt statt handgeschrieben
tests/test_vf_spec.lsp C:TEST_VF_SPEC: 7 handgebaute Faelle je Glied-Typ, 7 Validierungsfaelle, Gruppieren, und die 5 echten Ketten gegen ihr aufgezeichnetes Journal
tests/test_vf_spec.py 27 Tests ohne CAD + 10 fuer die VF_SPEC_BAU-Ergebnisse

Abweichungen von der Planung, jeweils mit Grund:

  1. vsp-pruefen ruft den Emitter statt eine zweite Regelmenge zu pflegen. Zwei getrennte Regelwerke laufen auseinander; der Emitter validiert ohnehin jedes Feld, das er anfasst.
  2. Das vollstaendige Journal steht NICHT im Ergebnis-Record. Es ist schon in der Spec und in der XDATA des gebauten Blocks - eine dritte Kopie waere nur Ballast. Statt dessen glieder_soll und glieder_ist: das ist der Desync-Detektor, der auch dann greift, wenn die Queue zufaellig aufgeht.
  3. Zusatzfeld segment_typ am Glied Linie: dort waehlt vfl-segment-entscheidung selbst zwischen reiner Gefaellestrecke und VF-Einheit. Am Journal ist es erkennbar (VF-Einheit beginnt mit der GF-Verteilungsfrage), aus der Spec allein nicht - und Geometrie zu raten verstoesst gegen I3.
  4. vf_ende-Werte automatisch und zielpunkt-ohne-es neben ja-mit-es/nein: in beiden Faellen stellt vfl-vf-einheit-abschluss KEINE Frage (Glied Linie bzw. Kettenende am Zielpunkt ohne ES-Wunsch). Ohne diese Werte waere die Tokenzahl nicht bestimmbar.
  5. Praefix vsp-, nicht vfl-: vfs- ist schon von vf_standard.lsp belegt, und die Spec-Ebene ist bewusst von vf_linienzug.lsp getrennt (einseitige Abhaengigkeit).

Wie die Richtigkeit belegt ist - drei Implementierungen derselben Grammatik, die einander pruefen:

  • Rundlauf gegen echte Daten: fuer alle 5 HundM-Ketten gilt journal_aus_spec(spec_aus_journal(tok)) == tok, tokenweise numerisch verglichen. Damit ist bewiesen, dass die Spec das Journal verlustfrei abbildet - sonst waere ein spec-gebauter Nachbau eine andere Kette.
  • Der Weg, den LISP nimmt, ist separat geprueft: flaches JSON -> Spec -> Journal ergibt dieselben Journale wie das aufgezeichnete Protokoll.
  • Der unabhaengige Dekoder (lib/vf_journal_export.py, gegen die echten Ketten verifiziert) 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 sind nicht von Hand abgeleitet: sie kommen aus dem geprueften Python-Emitter, und TestLispErwartungen in tests/test_vf_spec.py liest sie aus tests/test_vf_spec.lsp zurueck und vergleicht sie erneut. Sonst koennte ein Uebertragungsfehler einen falschen Erwartungswert festschreiben und der CAD-Lauf waere gruen, obwohl der Emitter falsch liegt. Gegengeprobt: eine verfaelschte Zahl im LISP-Test wird erkannt.

CAD-Lauf VF_SPEC_BAU (2026-09-03): 5 OK, 0 Fehler. Alle 5 Ketten aus der Spec gebaut, je Kette status: executed, prompts: 0 (keine Live-Eingabe erreicht - der positive Beweis), eingaben_offen: 0, spec_fehler: [], meldungen: [], glieder_ist == glieder_soll, Einfuegepunkt gleich dem Kettenstart der Spec. Damit ist der Daten-Pfad in der Praxis belegt; die 9 Ergebnis-Tests in tests/test_vf_spec.py laufen gruen gegen diesen Lauf.

Zwei Nacharbeiten aus dem Lauf:

  • Die Ergebnisdatei landete in results/, weil c:VF_SPEC_BAU DXFM_RESULTS bevorzugte. Das ist das Verzeichnis der Sivas-/CSV-Exporte; Testergebnisse gehoeren nach tests/output (Konvention test_run_all.lsp, von den pytest-Fixtures gelesen, per .gitignore ausgeschlossen). Default jetzt tests/output, Override ueber DXFM_VF_SPEC_OUT. Die Fixture prueft beide Orte, damit ein alter Lauf nicht stumm uebersprungen wird.
  • TEST_VF_SPEC ist ein Testbefehl und muss vorher geladen werden: (load (strcat (getenv "DXFMAKRO") "/tests/test_vf_spec.lsp")) - oder ueber SSG_RUN_ALL_TESTS, wo vf_spec inzwischen in alltests.json steht.

Noch offen in Stufe 1: die Uebersetzer fuer Modus 2 (pfad-handles + Segmentliste, Abschnitt 4.4) und Modus 3 sind NICHT gebaut - Modus 2 braucht laut Reihenfolge (Punkt 11) erst 2-3 echte "linienzug2"-Journale als Referenz, und tests/testdata/hundm05.json enthaelt ausschliesslich Modus-1-Ketten. Ebenfalls offen: der CAD-Lauf TEST_VF_SPEC (Uebersetzer, ohne Zeichnung) und VF_SPEC_BAU (baut die 5 Ketten aus der Spec; danach prueft tests/test_vf_spec.py das Ergebnis gegen tests/output/hundm05_results.json - Attribut fuer Attribut, das ist der Beweis "Spec-Pfad == Journal-Pfad" auf Geometrie-Ebene).


Teil 5 - Stufe 2: echte Funktionstrennung

Konvention: reiner Bauteil bekommt Suffix -bauen (Geometrie aus Parametern) bzw. -setzen (nur Globals); die Frage-Schale behaelt den bestehenden Namen - dadurch aendert sich keine einzige Aufrufstelle in Modus 1/2/3.

heute gemischt reiner Bauteil (neu)
vfl-baue-horizontal-koerper :2270 vfl-hor-koerper-bauen (frame hz dL sep-vor sep-nach ende-code gf2-laenge)
vfl-body-abschluss :2409 vfl-body-abschluss-bauen (frame letzt-hz p-umlenk dL hz-neu hoehe-ziel es-gewuenscht)
vfl-vf-einheit :2497 vfl-vf-eingang-bauen / vfl-vf-sub-bauen / vfl-vf-ausgang-bauen / vfl-vf-einheit-bauen (frame vf-spec)
vfl-vf-einheit-abschluss :3112 vfl-vf-abschluss-bauen (...) + vfl-ziel-report (frame)
vfl-frage-es-seite :2956 vfl-es-masse-setzen (es-winkel es-seite)
vfl-waehle-winkel :1656 vfl-winkel-gueltige + vfl-winkel-nach-index

ende-code ersetzt das Flag ziel-modus; der Bauteil gibt dann immer nur frame zurueck (die Doppelrueckgabe (frame ist-ende-antwort) existiert nur, um die Antwort nach oben zu geben).

Die Winkelfrage sitzt im Solver, nicht in einer Schale. vfl-body-zerlegung :2357 (also nicht rein, anders als zunaechst angenommen), vfl-vf-winkel :1692, vfl-vf-entscheidung :1707 und vfl-segment-entscheidung :1972 rufen alle vfl-waehle-winkel. Ein Parameter wuerde vier Signaturen und alle Aufrufer aendern; stattdessen der Kanal, den die Datei schon fuer vfl-menu nutzt (:1118, dynamisch gebundene *vflw-menu-*): *vfl-winkel-idx-vorgabe*.

"Alles fragen, dann alles bauen" ist unmoeglich - und das ist der zentrale Punkt: vfl-neue-linie-messen braucht (car frame), die Hoehenvorschlaege brauchen (caddr (car frame)), und die dL-Reservierung braucht den gemessenen auf_3-Fussabdruck. Deshalb behaelt der interaktive Treiber seine while-Schleife, fragt aber pro Runde einen Knoten und baut ihn sofort ueber denselben reinen Knoten-Bauteil; der Daten-Treiber ist dieselbe Kette mit foreach statt while.

Knotenform: die rohen Antworten in Frage-Reihenfolge (nil = nicht gefragt) plus die abgeleiteten Bauwerte. Dann ist der Serializer ein dummer Flattener. Dazu gehoert das Feld dl-verworfen: vfl-in-abstand journalisiert bedingungslos (:2129), abgewiesene 25-m-Eingaben (:2165) stehen also im Journal - ohne dieses Feld ist Journal -> Spec verlustbehaftet und jeder Round-Trip-Test scheitert an einer solchen Kette.

Journal-Invariante im Daten-Pfad: die Spec erzeugt das Journal einmal (vfl-spec->journal), es wird vor dem Bau gesetzt, kein Bauteil ruehrt es an. Als Dauerbeweis eine dbgmsg-Assertion dort, wo beide Erzeuger sich treffen - in vf-linienzug-modus unmittelbar vor vfl-journal-xdata-schreiben (:3867) das aus der Spec serialisierte Journal gegen (vfl-journal->string) stellen. Ohne offene .dbg-Datei kostet das nichts, mit Logging beweist es die Treue bei jedem Bau.

Reihenfolge (billig/risikoarm zuerst)

  1. vfl-ziel-report aus den zwei byte-identischen Bloecken :3150/:3176 ziehen
  2. Winkelwahl (vfl-winkel-gueltige/-nach-index + *vfl-winkel-idx-vorgabe*)
  3. ES/AS-Masse (vfl-es-masse-setzen)
  4. vfl-hor-koerper-bauen
  5. vfl-body-abschluss-bauen
  6. VF-Einheit: Eingang/Sub/Ausgang + Schleifenrumpf
  7. Daten-Executor fuer die VF-Einheit
  8. Spec + Serializer + Assertion - dieser Schritt ist die Invariante, vorher nichts ausliefern
  9. Einheit-Abschluss
  10. Kettenebene, ein Glied-Zweig pro Commit: GF-Bogen -> ES -> Horizontal-VF -> Linie-GF -> Linie-VF -> Linie
  11. vfl-spec-ausfuehren (Daten-Pfad ohne Replay-Umweg)
  12. Modus 2 - erst wenn 2-3 echte "linienzug2"-Journale als Referenz vorliegen (tests/testdata/hundm05.json enthaelt ausschliesslich Modus-1- Ketten); sonst zurueckstellen

Wo Geometrie still kippen kann

  • Die dL-Subtraktionskette in vfl-baue-horizontal-koerper (:2280, :2293, :2301, :2319/:2323): jeder Schritt mit (max *vfk-restlaenge-min-clamp* ...) geklammert, also reihenfolgeabhaengig, und der auf_3-Insert sitzt zwischen Subtraktion 1 und 2 (Fussabdruck gemessen, nicht geschaetzt). Der Bauteil ist der heutige Rumpf ohne die drei vfl-menu-Bloecke und ohne jede Umsortierung. Die drei Fragen duerfen nach vorn in die Schale (keine haengt an pt/dL), die Subtraktionen nicht.
  • vfl-nach-3grad :2415/:2643 darf von Schale und Bauteil gerufen werden - es ist idempotent (:2236 prueft vfl-frame-flach-p).
  • ein-dx/ein-dz-Nullen (:2588-2593) wandert vom Aufrufer in den Bauteil und aendert damit das Budget in berechne-alle-winkel, also Geometrie. Nur der "ES nein"-Pfad fuehrt dort durch.
  • ziel-gf2 vs. L_GF2-bau im Ausgang (:2706): geht es verloren, entsteht still die falsche GF2 hinter dem Motor.
  • Die vfl-acc-*-Aufrufe muessen an derselben Stelle in derselben Reihenfolge bleiben, sonst vertauschen sich die Komma-Listen L_VF_m/L_GF_m/GF_WINKEL
    • in der Zeichnung unsichtbar, im Sivas-Export falsch.
  • *vfl-as-winkel*/*vfl-es-winkel* werden lazy von den Blocknamen-Bauern gelesen (:111/:112) - spaeter gesetzt als heute heisst falscher Block.
  • Im Daten-Pfad muss hz eines Fortsetzungsknotens "vom Frame erben" (nil) bedeuten, nie ein gespeicherter Absolutwert: vfl-insert-vario-kurve-block snappt den gemessenen Wert neu (:2838-2841), ein Absolutwert laesst die Kette driften.
  • Die aus-dx/ein-dx-Save/Restore-Fenster (:1693, :2362, :5125, :5236) sind heute nie verschachtelt; zwei ineinander und das innere Restore ueberschreibt das aeussere Save.

Ausdruecklich nicht anfassen

vf-linienzug-modus3 + alle vfl2-*; die vfl-in-*-Wrapper und vfl-menu*; vfl-entry->string und das XDATA-Layout/die Marker; alle Journal-Konsumenten (brauchen sie Aenderungen, ist die Invariante gebrochen - das ist der Lackmustest); die reinen vfs-*/berechne-* in vf_standard.lsp (via *vf-typ-registry* mit Standard/Etage geteilt); die vflw-*-Wizard-Schicht und die DCLs; das Buendeln der *vfl-acc-* zu einem Record; der Abbruch-/*error*-Pfad.


Teil 6 - Nebenarbeit: Python-Grammatik vervollstaendigen

lib/vf_journal_export.py enthaelt die Journal-Grammatik schon als Recursive-Descent-Parser (Journal.dekodiere), inklusive vorantwort- Mechanik, bedingtem Winkel-INT und der erster_dl/REAL hz-Regel - aber unvollstaendig: Linie-VF fehlt im Dispatch (lauf, sonst raise) und vf_einheit ruft horizontal_koerper() unbedingt als ersten Koerper (nur fuer Horizontal-VF richtig, falsch bei gewinkeltem Erstkoerper). Die 5 HundM-Ketten dekodieren nur, weil ihre Daten diesen Fall nicht enthalten. Beide Luecken zusammen mit dem LISP-Serializer schliessen: dann pruefen zwei unabhaengige Implementierungen der gleichen Grammatik einander.

Erledigt (2026-09-02): Linie-VF ist im Dispatch (glied_linie_vf: DL, Zielhoehe, optionale Winkelwahl, dann VF-Einheit), und vf_einheit bekommt erster_horizontal - das spiegelt die winkel1-Verzweigung in vfl-vf-einheit: nur der horizontale Erstkoerper laeuft durch vfl-baue-horizontal-koerper und fragt Separator vor/nach + Endpunkt vorab, ein gewinkelter wird ohne Frage gebaut. glied_linie_kettenende uebergibt False (fuer typ="VF" liefert vfl-segment-entscheidung immer einen Winkel

0).

Abgesichert von tests/test_vf_journal_grammatik.py (9 Tests, ohne CAD und ohne die 118-MB-DXF: Journale stehen als Token-Listen im Test). Gegenprobe gemacht: mit dem alten erster_horizontal-Verhalten scheitert die Linie-VF- Tokenfolge (Token 11: STR erwartet, STEP:ES gefunden), der Fix ist also tragend. tests/testdata/hundm05.json bleibt nach der Regenerierung byte-identisch - die 5 echten Ketten enthalten keinen der beiden Faelle.

Offen bleibt der Gegenpart: der LISP-Serializer (vfl-spec->journal, Stufe 1). Erst mit ihm pruefen zwei unabhaengige Implementierungen einander.


Verifikation

Stufe 0 (nach P0-P3, interaktiv unveraendert):

  • TEST_HUNDM05 in BricsCAD: 5 Ketten, alle "status": "executed", eingaben_offen 0 - beweist, dass Replay und Journal-XDATA unveraendert sind.
  • python -m pytest tests/test_hundm05.py -q (Daten-Checks laufen ohne CAD).
  • Interaktive Gegenprobe: FOERDERANLAGE -> Linienzug Modus 1 mit Wizard, eine kurze Kette bauen, Doppelklick-Edit, danach SSG_DIM_SWITCH - Alert- Texte und Dialoge muessen identisch aussehen.

Stufe 1:

  • Neu tests/test_vf_spec.lsp (C:TEST_VF_SPEC, Muster test_vfl_schema.lsp mit tvs-eq/tvs-truthy/tvs-nil, in alltests.json ohne "save"): Uebersetzer-Unit-Tests ohne Zeichnung - je Glied-Typ das erwartete flache Journal, die Menue-Code-Tabelle, die hz-Regel, die invertierte gf-verteilung, Validierungsfehler. Der entscheidende Test: tests/testdata/linienzug_tests.json (eine vollstaendig kommentierte Kette mit Linie-VF, Horizontal-VF, zwei Vario-Kurven, Option-3-Kettenende und ES-Glied) in eine Spec uebersetzen und pruefen, dass vfl-spec->journal dieselbe Liste liefert.
  • Neu tests/test_vf_spec_bau.lsp (C:TEST_VF_SPEC_BAU, "save": "dxf"): die 5 HundM-Ketten als Spec (tests/testdata/vf_spec_hundm05.json) bauen und das Ergebnis gegen tests/output/hundm05_results.json stellen - Attribut fuer Attribut, Einfuegepunkt fuer Einfuegepunkt. Das beweist Spec -> Journal -> Bau == aufgezeichnetes Journal -> Bau.
  • Neu tests/test_vf_spec.py + Fixtures in conftest.py (Muster der bestehenden hundm05_*-Fixtures mit pytest.skip): pro Kette status executed, eingaben_offen 0, sektionen_soll == sektionen_ist, glieder == Spec-Glied-Folge, warnungen leer, prompts == 0.
  • "Kein Prompt, kein Dialog" in vier Schichten: statischer Waechter (pytest ohne CAD, vergleicht die Fundstellen von alert/get*/ssget/ new_dialog gegen eine eingecheckte Liste - haelt das Design gegen Verrottung), zaehlende Stubs (prompts im Record als positiver Beweis), Schalterzustand (*ssg-gui-aus* T, *vfl-wizard-mode* nil mit Save/Restore in einer vl-catch-all-apply-Klammer), und ein tests/test_vf_spec.scr-Lauf (Muster test_unit.scr) mit Sentinel in der letzten Zeile: fehlt der Sentinel im Log, hat doch ein Prompt geoeffnet.

Stufe 2: nach jedem Schritt TEST_HUNDM05 + TEST_VF_SPEC + TEST_LINIENZUG; nach den Geometrie-Schritten (3, 4, 5, 9) zusaetzlich DXF-Diff Frage-Pfad gegen Daten-Pfad ueber lib/dxf_abbild.py, und Sivas-Export-Vergleich (EXPORTSIVAS) wegen der Reihenfolge in L_VF_m/L_GF_m.


Getroffene Entscheidungen (aenderbar)

  1. Modus-2-Pfadobjekte: die Spec traegt die Entity-Handles. Damit bleibt I1 exakt und es braucht keinen neuen Marker. Alternative waere ein Marker "linienzug2s" plus Zweig in vfl-edit-ent2 - erweitert das Markerschema fuer jeden Leser, daher nicht gewaehlt.
  2. Segment-XDATA im Daten-Pfad: bleibt erhalten (Paritaet mit dem interaktiven Pfad), damit c:VF_SEKTION_RESTORE auch bei spec-gebauten Ketten greift. In Stufe 1 automatisch (Bau laeuft durch die Modus-Funktion); in Stufe 2 braucht der Executor denselben Per-Glied-Hook.
  3. Modus 3: nur Wrapper, kein Journal-XDATA (zurueckgestellt).
  4. vf_spec.lsp als neue Datei statt Anbau an vf_linienzug.lsp (schon ~6500 Zeilen, groesste Datei im Repo); Abhaengigkeit ist einseitig.

Betroffene Dateien

  • Lisp/vf_linienzug.lsp - P1/P2/P3-Hooks (:123, :157, :1055, :1066, :1185, :1196, :2028, :2113, :3523, :3550, :3559, :3650, :3772, :5418, :5650) und die ganze Stufe 2
  • Lisp/vf_spec.lsp - neu: Spec, Uebersetzer, Headless-Rahmen, Record
  • Lisp/vf_core.lsp - P0 (:1139), Ladezeile nach :1062
  • lib/vf_journal_export.py - Grammatik vervollstaendigen (Linie-VF, erster Koerper)
  • tests/test_hundm05.lsp - Prototyp zum Verallgemeinern (hundm05:gruppiere, -eintrag->journal, -result-json, -stubs-an/-aus, -queue-rest)
  • tests/testdata/linienzug_tests.json - fixiert den VF-Fluss im Unit-Test
  • tests/testdata/hundm05.json + tests/output/hundm05_results.json - Referenz fuer die Aequivalenz von Spec-Pfad und Journal-Pfad