Commit Graph

266 Commits

Author SHA1 Message Date
s.ayadi e91f1d00d0 [REFACTOR] Stufe 2: VF-Eingang/-Ausgang getrennt + Regressionsnetz fuer die Geometrie
Der CAD-Lauf belegt die Schritte 0-4 jetzt auch EMPIRISCH:
results/test_hundm05.dxf entstand nach dem Umbau, das Ergebnis-JSON von
11:18 davor - fuer alle 5 Ketten sind ALLE 37 Attribute identisch,
inklusive der reihenfolgeabhaengigen Komma-Listen L_VF_m, L_GF_m, GF_WINKEL
und ANTRIEBFAHRTRICHTUNG. TEST_VF_SPEC: 28 PASS / 0 FAIL.
results/test_linienzug.dxf zeigt eine vollstaendige Kette (AS+ES, Motor,
Umlenkung, 2 Vario-Kurven, 22 Bausteine, HOEHE_VON = HOEHE_BIS = 4500 bei
DELTA_H 0).

Schritt 5a/5b - vfl-vf-eingang-bauen und vfl-vf-ausgang-bauen: beide Bloecke
(GF1 + Einlauf-Separator + Umlenkstation bzw. Motorstation + GF2) enthalten
keine Frage und sind zusammenhaengend, der Umzug ist wortwoertlich
(Zeilenvergleich: 0 Zeilen entfernt, nur zwei Koepfe, zwei Aufrufe und zwei
"frame)" neu). Die Auswahl gf2-eff (ziel-gf2 im Kettenende-Modus, sonst
L_GF2-bau) bleibt BEWUSST an der Aufrufstelle - genau dort entsteht sonst
still die falsche GF2 hinter dem Motor. Der Separator-Zaehler und die
vfl-acc-*-Aufrufe bleiben an derselben Stelle in derselben Reihenfolge.

Regressionsnetz, damit die restlichen Schritte nicht blind gemacht werden
muessen:
- lib/dxf_vf_abbild.py (neu): liest eine Testzeichnung streamend und bildet
  je Kette Attribute, Bausteinzusammensetzung und Einfuegepunkt ab. Ketten
  werden ueber den EINFUEGEPUNKT der Spec zugeordnet, nicht ueber den
  Blocknamen - die VF-Nummer beginnt in jeder neuen Zeichnung wieder bei 1.
  ID und Bezeichnung sind aus dem Vergleich heraus (pro Zeichnung neu).
  --referenz vergleicht (Exit 1 bei Abweichung), --schreibe-referenz frischt
  die Referenz nach einem GEPRUEFTEN Lauf auf.
- tests/reference/hundm05_attribute.json (neu): die Referenz, erzeugt aus dem
  geprueften Lauf - also dem Stand, der attributgleich mit dem Zustand VOR
  dem Umbau ist.
- tests/test_vf_geometrie.py (neu, 8 Tests): vergleicht automatisch, mit
  einem eigenen Test nur fuer die Komma-Listen (das einzige, was eine
  vertauschte vfl-acc-*-Reihenfolge sichtbar macht) und einer Gegenprobe,
  dass eine verfaelschte Referenz auch erkannt wird.

Das faengt, was der Ergebnis-Record NICHT sieht: er sagt "executed, kein
Prompt, Journal aufgegangen", aber nichts darueber, ob dieselbe Geometrie
herauskam. Ablauf ab jetzt pro Schritt: umbauen -> TEST_HUNDM05 (save dxf)
-> pytest tests/test_vf_geometrie.py.

Offen bleiben 5c, 6, 8, 9, 10 (Schleifenrumpf der VF-Einheit, Daten-Executor,
Einheit-Abschluss, Kettenebene je Glied, vfl-spec-ausfuehren). Die vier
haengen zusammen: 6 und 10 brauchen den aufgeteilten Schleifenrumpf. Halb
umgebaut waere der Code schlechter dran als vor oder nach dem Umbau, darum
als ein Schritt mit CAD-Lauf davor und danach.

Verifiziert: 117 pytest-Tests gruen, vf_linienzug.lsp lint-sauber.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 14:10:56 +02:00
s.ayadi 02303ad7fc [REFACTOR] Stufe 2, Schritte 0-4: Frage-Schale und reinen Bauteil trennen
Alle Aenderungen sind verhaltensgleich: die Frage-Schalen behalten ihre
Namen, keine Aufrufstelle in Modus 1/2/3 wurde angefasst.

Schritt 0 - vfl-ziel-report: der Soll-Ist-Vergleich am Kettenende stand
zweimal WORTGLEICH in vfl-vf-einheit-abschluss (einmal fuer "Kettenende ohne
ES", einmal "mit ES"); die Faelle unterscheiden sich nur darin, wann sie
melden, nicht was.

Schritt 1 - Winkelwahl aufgeteilt: vfl-winkel-gueltige (Kandidaten filtern)
und vfl-winkel-nach-index (Kandidat waehlen) sind rein; die Frage-Schale
vfl-waehle-winkel setzt sie zusammen. Neuer Vorgabe-Kanal
*vfl-winkel-idx-vorgabe*: ist er gesetzt, wird nicht gefragt. Kanal statt
Parameter, weil vfl-waehle-winkel aus vier Solvern gerufen wird
(vfl-vf-winkel, vfl-vf-entscheidung, vfl-body-zerlegung,
vfl-segment-entscheidung) - ein Parameter wuerde vier Signaturen und alle
deren Aufrufer aendern. Default nil, also heute ohne Wirkung.

Schritt 2 - vfl-es-masse-setzen: reines Globals-Setzen (ES-Winkel merken +
vf-set-es-masse) aus vfl-frage-es-seite gezogen. *vfl-es-winkel* wird LAZY
von den Blocknamen-Bauern gelesen und muss vor dem ersten ES-Insert stehen.

Schritt 3 - vfl-hor-koerper-bauen: die drei Fragen (Separator vor/nach,
Endpunkt) haengen an keinem berechneten Wert und stehen jetzt alle vor dem
Bau. Journal-Reihenfolge UND Entity-Reihenfolge bleiben identisch; nur
interaktiv erscheint der auf_3-Uebergangsblock erst nach den drei Fragen
statt zwischen Frage 1 und 2. Die dL-Subtraktionskette wurde Zeile fuer Zeile
uebernommen - jeder Schritt ist mit (max *vfk-restlaenge-min-clamp* ...)
geklammert, also nicht kommutativ, und der auf_3-Insert sitzt bewusst
zwischen Subtraktion 1 und 2 (sein Fussabdruck wird GEMESSEN). Nachweis:
Zeilenvergleich alt/neu, dieselben 15 geometrie-relevanten Zeilen in
derselben Reihenfolge.

Schritt 4 - vfl-body-abschluss-bauen: hier laesst sich NICHT alles vorab
fragen (vfl-neue-linie-messen braucht den Frame nach vfl-nach-3grad, die
Hoehenvorschlaege brauchen dL und die Kettenhoehe). Die Schale macht darum
3-Grad-Abschluss -> messen -> Vorschlaege -> Zielhoehe fragen, der reine Teil
beginnt bei der Zerlegung. Nachweis: Multiset-Vergleich der Zeilen, ausser
Kopf, Klammer und Aufruf ist keine Zeile veraendert.

Schritt 7 (Assertion-Teil) - vsp-journal-diff in Lisp/vf_spec.lsp: stellt das
aus der Spec erzeugte Journal Token fuer Token gegen das beim Bau neu
aufgezeichnete. Schaerfster Desync-Detektor - offene Queue-Werte und die
Glied-Folge zeigen nur grobe Abweichungen, ein einzelner Wert, der an der
falschen Stelle verbraucht wird, kann beide passieren lassen und trotzdem
andere Geometrie erzeugen. Neues Record-Feld journal_diff, neuer Test
test_journal_token_gleich.

Zwei bewusste Abweichungen von der Planung (begruendet in
doc/TODO-plan-vf-interactive.md, Abschnitt "Umsetzungsstand Stufe 2"):
vfl-hor-koerper-bauen behaelt ziel-modus als eigenen Parameter neben
ende-code (ende-code darf nil sein, die Separator-Subtraktionen haengen aber
allein am Ziel-Modus); vfl-body-abschluss-bauen braucht letzt-hz und
es-gewuenscht nicht.

Offen: Schritte 5, 6, 8, 9, 10. Das sind die, bei denen die Reihenfolge
selbst Geometrie ist - der Fahrplan verlangt nach jedem einen CAD-Lauf
(TEST_HUNDM05 + TEST_VF_SPEC + TEST_LINIENZUG), nach den Geometrie-Schritten
zusaetzlich DXF-Diff und Sivas-Export-Vergleich. Ohne Lauf zwischen den
Schritten waere ein Fehler nicht mehr einem Schritt zuzuordnen. Sie bringen
keine neue Faehigkeit: der Bau aus Daten laeuft seit Stufe 1 und ist mit
VF_SPEC_BAU belegt (5 OK, 0 Fehler).

Verifiziert: 109 pytest-Tests gruen, beide .lsp lint-sauber, kein neuer
alert/get*/ssget im Bau-Pfad (statischer Waechter).

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 12:14:27 +02:00
s.ayadi 21684101f9 [FIX] Eindeutige IDs und korrekte ZUORDNUNG der verpackten Separatoren
Beim CSV-Export von Mubea trugen Gefaellestrecke/VF/Kreisel und die aus
ihnen erzeugten Separator-Kopien dieselbe ID (26 Dubletten 0001-0026), und
die ZUORDNUNG der Separatoren zeigte auf den falschen Carrier.

ssg-id-check-all: neue Phase 0 ermittelt das globale Maximum der bereits
vergebenen IDs, BEVOR die erste neue ID vergeben wird (ausgelagert nach
ssg-id-max-in-ss, das auch ssg-id-max nutzt). Bisher wurde max-id erst
waehrend Phase 1 mitgezogen (Start 0); da (ssget "X" ...) in BricsCAD die
zuletzt erzeugten Entities zuerst liefert, standen die noch ID-losen
Separator-Kopien ganz vorne und bekamen 0001, 0002, ... - genau die IDs der
weiter hinten liegenden Wrapper-Bloecke. Phase 2 konnte das nicht heilen,
weil frisch vergebene IDs nicht in id-map landen.

ssg-collect-nested-inserts: fuehrt Position, Z-Drehung und Skalierung jetzt
ueber alle Verschachtelungsebenen mit (Records statt nackter Entity-Namen).
Vorher gab die Rekursion Entities tieferer Ebenen mit ihrer ROH-Position aus
der Zwischen-Blockdefinition zurueck - zwei Separatoren an derselben lokalen
Stelle in zwei verschieden platzierten Zwischenbloecken landeten dadurch auf
exakt derselben Weltposition.

csv:sep-proxies-erzeugen: die Kopie steht jetzt exakt auf Position/Drehung/
Skalierung ihres verpackten Vorbilds; der kosmetische Versatz von 500 mm ist
weg (er kippte Separatoren am Kettenende in die Boundingbox des Nachbar-
Carriers). Der vla-InsertBlock-Aufruf ist gekapselt, damit ein Sonderfall
nur diese eine Kopie ausfallen laesst statt den ganzen Export abzubrechen.

csv:sep-proxies-zuordnung-setzen (neu, laeuft NACH ssg-id-check-all, da ein
frisch gebauter Wrapper vorher keine ID hat): fuer einen VERPACKTEN Separator
ist der Carrier bekannt - es ist der Wrapper, in dem er steckt. ZUORDNUNG
wird daher auf die Wrapper-ID gesetzt (Separator in VF 0010 -> ZUORDNUNG
0010) und ueber *cs-sep-fix-by-handle* festgenagelt: cs-zuordnung-lauf
uebernimmt sie unveraendert statt sie geometrisch neu zu raten, und
csv:block-to-json reicht sie als "zuordnung_fix" an export_csv.py durch.
Ohne das ueberschrieb compute_sensor_zuordnung (Prioritaet GF > Foerderer >
Kreiselhaelfte) den bekannten Wert - in der Mubea-Zeichnung landeten 26 in
VF/GF verpackte Separatoren so bei einer Kreiselhaelfte.

export_csv.py: respektiert "zuordnung_fix" und ersetzt eine vorhandene
ZUORDNUNG nicht mehr durch "nicht zugeordnet" - nur ein echter Treffer
ueberschreibt, wie im Docstring von compute_sensor_zuordnung beschrieben.

tests/test_export_ids.py (neu): prueft je tests/output/*_export.csv, dass
jede TeileId hoechstens einmal vorkommt und jede Sensor-Zuordnung auf eine
existierende TeileId zeigt. Gegen die fehlerhafte Mubea-CSV schlaegt der
Test mit allen 26 Dubletten an.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-09-03 11:38:18 +02:00
s.ayadi 5902343352 [CHANGE] Nur noch EIN Test baut die HundM-Geometrie: Spec wird TEST_HUNDM05
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>
2026-09-03 11:11:12 +02:00
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
s.ayadi ba01455d52 [FEAT] VF-Linienzug ohne GUI/Konsole baubar (Stufe 0) + hundm05-Testfall
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>
2026-09-03 10:14:31 +02:00
s.ayadi e2f038465b [FEAT] Verpackte Separator_SP-Sensoren in VF_n/GF_n/KREISEL_n vor Export erfassen
Separator_SP_2D/_3D-Sensorsymbole, die beim Zusammenbau der Compound-Bloecke
(VF_n/GF_n/KREISEL_n) als Sub-INSERT in deren Blockdefinition verpackt
wurden, waren fuer (ssget "X" ...) unsichtbar und blieben daher ohne eigene
ID und ohne Zeile im Export-JSON. csv:sep-proxies-erzeugen (export.lsp)
sucht solche verpackten Symbole jetzt vor jedem EXPORTCSV/EXPORTSIVAS ueber
den neuen rekursiven Helfer ssg-collect-nested-inserts (ssg_core.lsp) und
legt fuer jeden Fund eine echte, temporaere Kopie an seiner Weltposition an
(silent ueber vla-InsertBlock statt command-line INSERT). Diese Kopie
durchlaeuft ID-Vergabe/Export unveraendert ueber die bestehenden Funktionen
und wird danach wieder entfernt (csv:sep-proxies-loeschen).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-02 10:03:00 +02:00
s.ayadi 04a12e5981 [FIX] VF-Linienzug: Abbruch beim Editieren brach den VF-Block auf
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>
2026-09-01 15:15:16 +02:00
m.stangl 1d19121679 [FEAT] VF-Linienzug Modus 2+3: Segment-Gruppen-Dialoge + Highlight
Modus 2 (Pfad+Zielhoehe) und Modus 3 (Vorwaerts-Nachbau) fassen die je
Segment unmittelbar aufeinanderfolgenden Fragen (Typ + ggf. Neigung/
Vario-Winkel/Variante) in EINEM Wizard-DCL-Dialog zusammen - analog zu
Modus 1. Der Dialogkopf zeigt "Segment i/n ..."; das aktuelle Pfad-Segment
(LINE/ARC) wird vorher per redraw-Highlight in der Zeichnung hervorgehoben.

- Neue DCL-Dialoge: vflw_seg_linie_m2, vflw_seg_linie_m3, vflw_seg_bogen
- Neue Helfer: vflw-seg-*-impl (fuellen *vflw-pending*), vfl-seg-highlight,
  vfl-seg-kopf
- Modus 3 zusaetzlich: Kettenstart- und AS-Element-Gruppen-Dialog; AS-Winkel
  jetzt pending-aware ueber vfl-in-value
- Bogen-Dialog: vario-erlaubt-Flag (Modus 3 nur im offenen VF-Lauf), sonst
  wuerde die unkonsumierte Variante-Antwort ins naechste Segment lecken

Alles hinter (vfl-wizard-aktiv) - bei GUI-aus (Tests) faellt alles
unveraendert auf Konsole/Replay zurueck.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-31 16:45:25 +02:00
m.stangl ddb5dfa0f5 WINKEL_AS und WINKEL_ES hinzugefügt 2026-08-31 13:53:41 +02:00
m.stangl 2147f817fc [FEAT] VF-Linienzug: 2D/3D-Batch-Umschaltung implementiert
Bisher schaltete SSG_DIM_ALL_2D/3D die Linienzug-Foerderer nicht um
("gar nichts passiert"). Ursache: kein Dim-XDATA am VF_n-Block und
kein Konverter fuer die Marker "linienzug"/"linienzug2".

- Phase A: vfl-block-erstellen schreibt jetzt SSG_DIM-XDATA (deckt
  Modus 1/2/3 + Abbruch-Sicherung in einem Zug ab).
- Phase B: neuer nicht-interaktiver Konverter vfl-konvertiere-ent
  (stummer Journal-Replay mit *ssg-ils-dim*-Override, vl-catch-all
  abgesichert).
- Phase C: ssg-dim-alle-umwandeln dispatcht VF_-Bloecke nach Marker
  (Standard/Etage -> vf-konvertiere-ent, Linienzug -> vfl-konvertiere-ent,
  Altbestand -> skip); Fehlversuche zaehlen als skip.
- Phase D: Doppelklick-Edit (vfl-edit-ent/-ent2) baut dimensionstreu
  in der Bestandsblock-Dimension neu auf.

Phase 0 (VFL_KS_DIAG-Pruefung der 2D-KS) + Verifikation stehen noch aus
(nur in BricsCAD moeglich).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-30 09:00:58 +02:00
m.stangl 64e8ebf6e1 [REFACTOR] VF-Linienzug: GF-Abhaengigkeitscheck der 3 Modi zusammengefuehrt
Der Block 'Gefaellestrecke-Modul geladen? + init-bibliothek falls noetig' war
in vf-linienzug-modus/-modus2/-modus3 wortwoertlich (bis auf den Alert-Text-
Key) dreifach vorhanden. Neue Hilfsfunktion vfl-gf-abhaengigkeit-sicherstellen
(alert-key) ersetzt alle drei Stellen; die modusspezifischen Alert-Texte
(Modus 1 ausfuehrlicher als 2/3) bleiben als Parameter erhalten, keine
Verhaltensaenderung.

Hintergrund: Analyse der beiden verbliebenen Punkt-4-Baustellen (siehe vorige
Session) ergab, dass der Journal-Serialisierer (String+JSON) KEIN Duplikat ist
(JSON ist reine Diagnose-Einbahnstrasse fuers .dbg-Log, kein Parser zurueck)
und das Modi-1/2/3-Praeludium bewusst NICHT weiter vereinheitlicht werden
sollte (die Abbruch-Handler-Aktivierung unterscheidet sich gewollt pro Modus -
Risiko > Nutzen). Dieser 3x identische GF-Check war der einzige echte Rest.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-30 08:34:08 +02:00
m.stangl 493967c06d [FIX] ssg_ks_insert: itoa auf Float-Winkel in Statusmeldung crasht
insert-inclined-scaled-block/insert-rotated-block-with-ks riefen (itoa
winkel) fuer die Statusmeldung auf. Seit *vfk-gefaelle-winkel* (3.0,
Float) statt rohem Integer-Literal 3 verwendet wird, brach das mit
"bad argument type <3.0>; expected <INTEGER>" ab - sichtbar beim
Etage-VF-Bau (Mubea-Testfall), der danach folgende Elemente (u.a.
Gefaellestrecken) nicht mehr baute. Fix: (itoa (fix winkel)).
2026-08-29 17:10:40 +02:00
m.stangl 41eea7fc01 [REFACTOR] VF-Cluster: Magic-Numbers auf *vfk-*-Konstanten umgestellt
vf_core/vf_standard/vf_etage/vf_linienzug referenzieren jetzt durchgaengig
die zentralen *vfk-*-Konstanten aus vf_konstanten.lsp statt rohe Winkel-/
Laengen-/Toleranz-Literale (3.0 Grad, 500/300mm Stationen/Separatoren,
1000/800mm Mindestlaengen, AS/ES-Fallback-Versaetze, Text-/Label-Masse).
Bereits ueber ssg-cfg-or config-gefuehrte Werte bleiben unangetastet
(Config bleibt dort die aktive Quelle). vf_etage-Bogenwinkel-Inkonsistenz
(fest verdrahtete Liste ohne Bezug zu *vfk-bogen-winkel*) behoben.
vf_konstanten.lsp-Kommentare auf den neuen, aktiven Status aktualisiert.
2026-08-29 17:10:05 +02:00
m.stangl bf0237666b [REFACTOR] VF-Linienzug: AS/ES-Winkel-Wertemenge zentral aus *vfk-as-es-winkel*
Die gueltige AS/ES-Winkel-Menge ("30"/"90") stand als Literal doppelt im
Glied-Schema. Jetzt einmalig als *vfk-as-es-winkel* in vf_konstanten.lsp,
Schema referenziert sie (mit Fallback in vf_linienzug).

BEWUSST bei STRING geblieben (nicht INT): AS/ES ist echt 2-wertig (keine
60-Grad-Bloecke), das Journal fuehrt AS/ES-Winkel als STR - eine Umstellung auf
INT haette Journal-Format + Alt-Block-Editier-Kompatibilitaet beruehrt (2
Cluster) fuer reine Konsistenz. Zentrale Konstante beseitigt die Streuung ohne
dieses Risiko (Entscheidung mit Nutzer abgestimmt).

Die index-basierten Dialog-Mappings (if gwinkel "1" -> "30"/"90") bleiben,
da sie an feste 2-Options-DCL-Layouts gebunden sind (keine Listen-Lookups).

Paren-Balance geprueft.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 12:51:09 +02:00
m.stangl 3a0caadbb5 [REFACTOR] VF-Linienzug: GF-Bogen/Vario-Kurve-Winkel zentral aus *vfk-gf-bogen-winkel*
Statt das '(30 60 90)-Literal an ~12 Stellen in vf_linienzug zu wiederholen
(Schema, schema-feld-pruefen, Live-Menue GF-Bogen + Vario-Kurve, Slice-Reader,
beide Edit-Dialoge), verweisen jetzt alle auf die EINMALIGE zentrale Definition
*vfk-gf-bogen-winkel* in vf_konstanten.lsp (war dort schon vorhanden, wurde aber
nirgends genutzt).

Kein Config-Eintrag (bewusst nicht in component_defaults.json): die Winkel sind
an die vorhandenen DWG-Bloecke gebunden, eine Config waere nur halb verdrahtet.
vf_konstanten ist zentrale Quelle; vf_linienzug hat einen Fallback, falls die
Datei nicht geladen wurde. Werte unveraendert (30/60/90), Journal/Blocknamen
kompatibel.

Paren-Balance geprueft.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 10:32:42 +02:00
m.stangl 089fbb8eed [REFACTOR] VF-Linienzug: Vario-Kurven-Winkelliste (90 60 30) -> (30 60 90)
Vereinheitlicht die Anzeige-Reihenfolge der Vario-Kurven-Winkel auf 30/60/90
(wie GF-Bogen). Betroffen: Glied-Schema, schema-feld-pruefen, Wizard-Gruppen-
dialog (vflw-gruppe-variokurve-impl), Live-Menue (vfl-insert-vario-kurve),
Edit-Dialog (vfl-glied-vario-dialog) und Slice-Reader (vfl-vario-slice-werte).

Labels, winkel-werte-Liste und Default-Index (jetzt Position 2 = 90) ueberall
konsistent geflippt. Reine Anzeige-Aenderung: das Journal speichert ohnehin den
ECHTEN Winkelwert (30/60/90), Blocknamen (Vario_Kurve_*_<itoa winkel>_TEF_*)
unveraendert -> bestehende Linienzug-Bloecke bleiben kompatibel
(vfl-winkel-normieren validiert ordnungsunabhaengig gegen die Menge).

Paren-Balance geprueft.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 10:21:19 +02:00
m.stangl 1e7a4d8620 [REFACTOR] VF: L_GF/L_VF-Solve aus Winkelberechnung zentralisiert (vf-winkel-solve)
Der L_GF/L_VF-Solve-Block (aus A/B-Restbudget) war in berechne-alle-winkel
(Standard) und berechne-winkel-etage byte-identisch. Als vf-winkel-solve
(winkel richtung A B sinα cosEff sinEff sin3 cos3) -> (winkel L_GF L_VF gueltig)
nach vf_core gezogen; beide Winkelberechnungen nutzen ihn jetzt.

Bewusst NICHT vereinheitlicht: die A/B-Berechnung (Etage hat zusaetzliche
2*schraeg-/2*gef-/2*feste-Terme, Standard nutzt feste-hz) und die Ergebnis-
tabelle (unterschiedliche Message-Keys/Arg-Form) - beides birgt Geometrie-/
Ausgaberisiko fuer geringen Zeilengewinn. Der identische, geometrie-kritische
Solve ist der wertvolle Teil.

test_foerderer.py (Winkel-Set, Monotonie, L_GF/L_VF>0) validiert das direkt.
Paren-Balance geprueft.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 10:17:40 +02:00
m.stangl d00e1a600b [REFACTOR] VF: Standard/Etage-Dialog-Ablauf vereint (vf-dialog-ablauf)
vfs-standard-dialog-ablauf/-berechnen-einfuegen und vfe-etage-dialog-ablauf/
-berechnen-einfuegen waren strukturell 1:1-Kopien (~200 Zeilen), Unterschiede
nur: Berechnungs-/Einfuege-Funktion, XDATA-Marker, horizontale Zwischenstrecke.

Neu in vf_core:
- vf-registry-berechne-fn/-einfuege-fn: Registry-Accessoren (berechne-fn/
  einfuege-fn kommen ohnehin aus *vf-typ-registry* pro Typ)
- vf-dialog-berechnen-einfuegen (typ ... horizontal-p): gemeinsamer Ablauf,
  horizontal-p T=Standard (mit Zwischenstrecke), nil=Etage
- vf-dialog-ablauf (typ vf-nummer horizontal-p): gemeinsame Neuanlage

Die vfs-*/vfe-*-Namen bleiben als duenne Wrapper (Doppelklick-Edit-Dispatch +
Gefaellestrecke-Aufruf vfs-standard-dialog-berechnen-einfuegen unveraendert,
gleiche Arity/Rueckgabe). XDATA-Schreiben identisch (vfs-xdata-schreiben war
schon (vf-edit-xdata-schreiben ent "standard" hz)).

-45 Zeilen netto, eine gemeinsame Implementierung. Paren-Balance geprueft.
Beruehrt Bau -> BricsCAD-Test Standard+Etage (Neuanlage + Doppelklick-Edit).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 10:14:21 +02:00
m.stangl 71ead0ee38 [FIX] ssg_load.lsp: ssg_ks_insert vor VarioFoerderer/Gefaellestrecke laden
Der Headless-Loader ssg_load.lsp (von den .scr-Testskripten genutzt) lud die
neue ssg_ks_insert.lsp nicht - dadurch waeren insert-block-by-ks & Co. beim
Laden ueber ssg_load undefiniert (nur der guarded Nachlade-Load in vf_core/
Gefaellestrecke haette gegriffen). Jetzt explizit in korrekter Reihenfolge
(nach ssg_core/-layer, vor KreiselInsert/VarioFoerderer/Gefaellestrecke).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 09:52:57 +02:00
m.stangl 3d5ae9a879 [FIX] vf-frage-element-winkel: GUI-Aus-Schalter respektieren
vf-frage-element-winkel (AS/ES-Winkel 30/90) pruefte *vfl-wizard-mode* direkt
und oeffnete den vflw-wahl-Dialog auch bei abgeschalteter GUI - dadurch kam im
automatischen TEST_LINIENZUG trotz (ssg-gui-aus) die AS-Element-Winkel-Abfrage
als Dialog hoch. Jetzt zusaetzlich (ssg-gui-p)-Guard wie in vfl-wizard-mode-p:
bei GUI-aus faellt die Abfrage auf getstring (Mock-Queue im Test).

War die letzte ungeguardete Wizard-Dialog-Eintrittsstelle.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 09:51:19 +02:00
m.stangl 8f133f69b0 [TEST] Globaler GUI-Aus-Schalter fuer automatische Testlaeufe
Der VF-Linienzug-Wizard (*vfl-wizard-mode* Default T) oeffnete beim
automatischen Replay-Test DCL-Dialoge und blockierte den Lauf.

- ssg_core.lsp: globaler Schalter *ssg-gui-aus* + ssg-gui-p/-aus/-an
- vf_linienzug.lsp: neue vfl-wizard-mode-p (Wizard nur wenn *vfl-wizard-mode*
  UND GUI nicht abgeschaltet); ersetzt die direkten *vfl-wizard-mode*-Checks in
  vfl-in-string/-real/-int, vfl-winkel-live und vfl-wizard-aktiv (deckt damit
  auch alle vflw-gruppe-*-Dialoge ab). Bei GUI-aus fallen die Eingaben auf den
  getstring/getint/getreal-Pfad, den die Testrunner per Mock/Replay bedienen.
- test_linienzug.lsp: (ssg-gui-aus) vor dem Replay, (ssg-gui-an) danach (immer).
- test_run_all.lsp: GUI aus um den gesamten Batch, danach wieder an.

Alle Guards ueber atoms-family, damit aeltere Ladezustaende unveraendert
funktionieren. Paren-Balance geprueft.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 09:39:30 +02:00
m.stangl 80804a321a [REFACTOR] KS-Extraktion + Einfuegeprimitiven zentral in ssg_ks_insert.lsp
Neun Funktionen waren doppelt gepflegt in vf_core.lsp (unbedingt) UND
Gefaellestrecke.lsp (geguardet 'Fallback wenn vf_core nicht geladen'). Da
vf_core im MNL immer nach Gefaellestrecke laedt, gewann bisher stillschweigend
die vf_core-Version - die Gefaellestrecke-Kopien waren de facto tot und wichen
leicht ab. Jetzt EINE Quelle:

  ssg_ks_insert.lsp: vec-length, ks-line-axis, ks-normalize-name, ks-relativize,
  ks-absolutize, ensure-block-loaded, extract-ks-from-block[-raw],
  insert-block-by-ks, insert-inclined-scaled-block, insert-rotated-block-with-ks

- Kanonische vf_core-Variante uebernommen (inkl. Null-Check, ssg-ils-block-auf-ebene,
  hz-Guard, Statusmeldungen). Gefaellestrecke erhaelt dadurch dieselbe Behandlung
  wie im MNL-Fluss ohnehin schon aktiv.
- Cache vereinheitlicht auf *ks-cache* (guarded init im Shared-File);
  *gf-ks-cache* entfaellt.
- MNL laedt ssg_ks_insert als Core-Modul VOR Gefaellestrecke/VarioFoerderer.
- vf_core + Gefaellestrecke: guarded Nachlade-Load fuer isoliertes Test/Dev-Laden.

Paren-Balance geprueft; jede der 9 Funktionen jetzt genau 1x definiert.
Beruehrt Block-Platzierung -> BricsCAD-Test Standard/Etage/Linienzug/Gefaelle
(2D+3D) noetig.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 08:37:35 +02:00
m.stangl 6cf54f646b [REFACTOR] VF: KS-Extraktion in init-Bibliotheken ueber vf-element-masse
Der Block 'Temp-Objekt einfuegen -> extract-ks-from-block -> KS_EIN/KS_AUS ->
(dx dy dz)-Diff -> Temp loeschen' stand in init-bibliothek 4x (AS/ES/Bogen
auf/ab) und in init-bibliothek-etage 4x (AS30/ES30/Gefaellebogen l/r).

vf-element-masse (vf_core) kapselt exakt diese Sequenz bereits - init nutzt sie
jetzt statt eigener Kopien. Bogen-Tabellen-Eintraege via (cons w m) == altes
(list w dx dy dz), get-bogen-mass (cdr item) unveraendert. Etage-Fallbacks +
Block-vs-KS-Warnungen erhalten. Gemessene Bloecke identisch (_rechts bei Etage,
_links bei Standard).

-120 Zeilen netto. Paren-Balance geprueft.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 07:59:08 +02:00
m.stangl aa71d463cb [REFACTOR] Rz(hz)*Ry(vert)-Rotationsmatrix zentralisiert (ssg-rot-matrix-zy)
Die 4x4-Matrix Rz(hz)*Ry(vert) stand woertlich 11x: vf_core (2x), vf_etage (4x),
Gefaellestrecke (4x), TEFInsert (1x). Neuer dependency-freier Helper
ssg-rot-matrix-zy in ssg_core.lsp (immer zuerst geladen), damit alle drei
Cluster ihn ohne Cross-Modul-Kopplung teilen.

- vf-rot-matrix bleibt als duenner Alias in vf_core (VF-Aufrufstellen unveraendert)
- Reine 2D-Rz-Matrizen (insert-block-by-ks, nur horizontal) bleiben unangetastet
  (andere Form, kein Vertikalanteil)

Werte identisch - reine Extraktion. Paren-Balance geprueft.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 07:55:00 +02:00
m.stangl 012c5da7f9 [REFACTOR] VF: 10-Feld-Eingabe-Entpackblock zentralisiert
Der identische (setq deltaL (nth 0 eingabe) ...)-Block mit 10 Feldern stand 4x
(vf_standard: vfs-standard-dialog-ablauf + c:VARIOFOERDERER_EDIT, vf_etage:
vfe-etage-dialog-ablauf + vfe-edit-ent).

Neu in vf_core.lsp: *vf-basis-eingabe-felder* (zentrale Feldreihenfolge) +
vf-basis-eingabe-entpacken (set 'sym wert auf die dyn.-skopten Aufrufer-Locals).
Alle 4 Aufrufer deklarieren die 10 Namen weiterhin in ihrer /-Liste.

Reines Refactoring, identisches Verhalten. Paren-Balance geprueft.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 07:39:39 +02:00
m.stangl 1e50a9388f [REFACTOR] VF-Linienzug: vfl-in-* Wrapper auf gemeinsames Skelett reduziert
vfl-in-point/-string/-real/-int teilten exakt dasselbe 3-Zweig-Muster
(Replay-Queue -> Pending-Queue -> Live-Eingabe -> Journal). Skelett jetzt
EINMAL in vfl-in-value; die vier Wrapper liefern nur noch livefn + kind.

- vfl-in-value: unveraendertes Default-Skelett (v non-nil = gueltig)
- vfl-in-value-p: Variante mit explizitem Gueltig-Praedikat, fuer vfl-in-string
  ("" ist ein gueltiger String -> striktes STR-Praedikat, Verhalten identisch)
- vfl-in-selection bleibt eigenstaendig (OBJS/Handle-Sonderlogik)

Signaturen + Journal-Format unveraendert, alle 63 Aufrufstellen bleiben gueltig.
Dynamic scoping: livefn-Lambdas sehen prompt/base/*vfl-wizard-mode* etc. ueber
den aktiven Wrapper-Frame. ~40 Zeilen weniger. Paren-Balance geprueft.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 07:37:07 +02:00
m.stangl 9f5b30709a [REFACTOR] VF: Core-Pfad-Ermittlung zentralisiert (ssg-lisp-verzeichnis/-datei-pfad)
Der 3-stufige Lisp-Pfad-cond (DXFM_LISP -> *ssg-lisp-pfad* -> nil) war 6-fach
dupliziert. Neuer Helper ssg-lisp-verzeichnis/ssg-lisp-datei-pfad in ssg_core.lsp.

- vf_core.lsp (Submodul-Loader): nutzt Helper direkt (ssg_core hier geladen)
- vf_standard/vf_etage/vf_konstanten/VarioFoerderer: Helper mit Inline-Fallback
  (atoms-family-Guard), falls ssg_core beim isolierten Einzel-Laden fehlt
- vf_core.lsp ssg_core-Bootstrap (Z.40): bleibt inline (laedt ssg_core erst)

Reines Refactoring, identisches Verhalten. Paren-Balance geprueft.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-29 07:33:20 +02:00
m.stangl c36d2774bf [CHANGE] VF-Linienzug: Winkel-Standardisierung + Glied-Schema + Vario-Kurve editierbar
Winkel im Linienzug durchgaengig als echter Wert (30/60/90) statt Auswahl-
Index (1/2/3) journalisiert - behebt den Bug, bei dem ein verrutschter
String-Wert zum falschen Bogen fuehrte (vfl-menu-winkel/-winkel-live/
-winkel-normieren, GF-Bogen und Vario-Kurve).

Zentrales Glied-Schema (*vfl-glied-schema*) als single source of truth fuer
AS/ES/GF-Bogen/Vario-Kurve: generisches bauen/lesen/validieren, benanntes
Debug-Log (GF-Bogen.winkel = 90 statt roher [INT]-Zeilen). VF-Einheit ueber
Sub-Step-Referenz (*vfl-vf-substeps*) benannt geloggt, ohne sie in ein starres
Feld-Schema zu zwingen.

Vario-Kurve als eigenes Sub-Glied editierbar (eigener STEP-Marker wie ES):
vfl-vario-slice-bauen/-werte/-splicen, vfl-glied-vario-dialog, Dispatcher-Zweig,
Label. Schwanz-erhaltender Splice (vfl-vario-slice-splicen), da die Vario-Kurve
mitten in der VF-Einheit steht und ihr Slice nachfolgende VF-Antworten enthaelt
- naiver Splice haette diese verworfen (adversarial verifiziert). Uebrige
VF-Sub-Segmente bleiben bewusst nur ueber Sektions-Ruecksprung editierbar.

Neuer Unittest tests/test_vfl_schema.lsp (TEST_VFL_SCHEMA, in alltests.json):
Roundtrip + Validierung + Vario-Schwanz-Splice ohne Geometrie.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-28 23:12:30 +02:00
s.hensch df2b4f1709 [CHANGE] Attribute für ILS Blöcke korrigiert - Artikelnummern für 30 Grad ES AS Elemente hinzugefügt, ZUORDNUNG als Attribut nur bei Scanner und Separator, ID als Attribut für alle Blöcke hinzugefügt 2026-08-28 10:10:19 +02:00
m.stangl 43896a28f5 VF-Linienzug: Einzelsegment-Bearbeitung (GF-Bogen) + punktfreies Journal
Doppelklick auf einen Linienzug-VF_n-Block bietet jetzt zwei Modi
(neuer Dialog vfl_edit_modus.dcl / vfl-dlg-modus): auf eine Sektion
zuruecksetzen (bisheriges Verhalten) ODER die Eigenschaften EINES
einzelnen Glieds aendern (vfl-edit-glied). Fuer GF-Boegen laesst sich
Winkel (30/60/90) und Seite (links/rechts) direkt aendern; das Glied
wird per vfl-journal-splice im Ketten-Journal ersetzt und die komplette
Kette 1:1 neu aufgebaut.

Damit die nachfolgenden Glieder nach einer Bogen-Aenderung korrekt neu
verketten, speichert das Journal fuer Linien-Segmente jetzt nur noch die
relative Distanz (deltaL, neuer Journal-Kind "DL") statt eines absoluten
Punkts - nur der Kettenstartpunkt bleibt ein echter Punkt. Richtung wird
ohnehin vom Vorgaenger-Frame geerbt (nur das erste Segment journalisiert
zusaetzlich die gesnappte Richtung). vfl-in-abstand ersetzt die
punktbasierte Messung in vfl-neue-linie-messen; vfl-kettenanfang-baustein
rechnet die AS-Restlaenge rein skalar (kein pick-punkt mehr).

Wichtige Korrekturen:
- vfl-entry->string/-entry kannten den DL-Kind nicht (wurde als NIL
  serialisiert -> Distanzverlust beim erneuten Lesen)
- vfl-in-abstand journalisiert jetzt in BEIDEN Zweigen (Replay UND Live),
  wie die anderen vfl-in-*-Wrapper - sonst gingen die DL-Werte replizierter
  Glieder beim erneuten Speichern verloren (2. Edit stuerzte ab)

Diagnose: komplettes Journal wird beim Erzeugen (XDATA-JOURNAL-JSON) und
zu Beginn eines Replays (REPLAY-QUEUE-JSON) als JSON in die Debug-Datei
geschrieben (No-Op ohne aktiven Debug-Schalter).

dcl/vfl_edit.dcl: Popup breiter (edit_width/list_width), damit lange
Sektionstexte nicht abgeschnitten werden.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-27 17:51:41 +02:00
m.stangl 308d49fc96 VF-Linienzug: baubare Hoehen-Vorschlaege (Ab/Auf) statt unveraenderter Ist-Hoehe, negative Restlaenge nach AS-Element abgefangen
- Hoehe-Prompt/Wizard-Dialog schlagen jetzt zwei tatsaechlich baubare
  Zielhoehen vor (Ab/Auf) statt der unveraenderten Kettenhoehe, die bei
  direkter Uebernahme immer als deltaH=0 abgelehnt wurde (Linie-GF,
  Linie-VF, automatische Linie, VF-Kette fortsetzen, Kettenende-Abschluss)
- Nach dem AS-Element-Einfuegen kann die real gemessene Restlaenge negativ
  werden (Klickpunkt zu nah); Linie-GF und automatische Linie pruefen das
  jetzt und brechen sauber ab statt eine entartete GF-Strecke zu bauen
- Debug-Log (Modus 1) protokolliert jetzt Erfolg/Misserfolg der
  Geometrieerzeugung inkl. der verwendeten Werte
- Neue Lisp/vf_konstanten.lsp: zentrale, dokumentierte Sammlung aller
  Laengen-/Winkel-Magic-Numbers aus dem VarioFoerderer-Cluster als
  Nachschlagewerk (Module selbst noch unveraendert)

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-27 13:27:25 +02:00
m.stangl 9fdc1b8bdd VF-Linienzug: Wizard-Gruppendialoge waehrend Journal-Replay unterdrueckt
Beim Editieren einer bestehenden VF_n-Kette (VARIOFOERDERER_EDIT) feuerten
die Wizard-DCL-Gruppendialoge (vflw-gruppe-*-impl) weiterhin, obwohl der
Ablauf gerade aus dem gespeicherten Journal repliziert wurde - sie waren nur
an *vfl-wizard-mode* gebunden, nicht an den Replay-Status. Ihre Antworten
landeten in *vflw-pending*, wurden dort aber nie konsumiert (die vfl-in-*-
Wrapper pruefen die Replay-Queue zuerst) und blieben liegen. Sobald die
Replay-Queue leer war und auf Live-Eingabe umgeschaltet wurde, laseen die
Wrapper diese laengst veralteten, falsch typisierten Werte statt neu zu
fragen - z.B. landete eine Menue-Antwort ("1") in vfl-in-point und liess
vfl-neue-linie-messen mit "bad argument type <1> ; expected <CONS>" abstuerzen.

Neue Hilfsfunktion vfl-wizard-aktiv prueft zusaetzlich *vfl-replay-queue*
und ersetzt an allen 15 Aufrufstellen die reine *vfl-wizard-mode*-Abfrage.
Als Absicherung leeren vfl-journal-reset und vfl-journal-replay-start jetzt
zusaetzlich *vflw-pending*.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-27 12:12:58 +02:00
m.stangl f92c80d82a VF-Linienzug: Modus 2 loggen, Debug-Default auf AN, GF-Hoehenvorschlag-Bug behoben
Debug-Logging (Schalter vfl-modus1/2/3) ist jetzt standardmaessig AN statt
AUS, damit nicht vor jeder Session manuell eingeschaltet werden muss. Modus 2
(vf-linienzug-modus2) war bisher nicht instrumentiert - Session-Open/Close
und *error*-Handling analog Modus 1/3 ergaenzt; da Modus 2 durchgehend die
vfl-in-*-Wrapper nutzt, wird das Eingabe-Logging automatisch ueber den
vorhandenen vfl-journal-record-Hook mitgezogen.

Bugfix: Der Hoehen-Vorschlag im GF-Zielhoehe-Dialog (Wizard + Konsole) war
schlicht die unveraenderte Ist-Hoehe der Kette. Direkt uebernommen ergab das
deltaH=0, was als "Auf" statt "Ab" gewertet und immer mit "kann nicht
steigen" abgelehnt wurde - der Default war also nie baubar. Neue Hilfs-
funktion vfl-gf-hoehe-vorschlag rundet auf volle mm ab und zieht bei
bereits ganzzahligen Werten zusaetzlich 1mm ab, damit der Vorschlag
garantiert unterhalb der Ist-Hoehe liegt.

Ausserdem: unnoetige Anfuehrungszeichen aus den zugehoerigen Fehlermeldungen
(de/en) entfernt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-27 11:25:47 +02:00
m.stangl 4238509e7d Debug-Logging fuer VF-Linienzug Modus 1 und Modus 3
Zentrale Debug-Schalter-Sammlung (*dbg-schalter*, Default AUS) in
ssg_dbg.lsp: dbg-schalter-on/-off/-p/-open/-liste. dbg*-Aufrufe bleiben
dauerhaft im Code, ohne im Normalbetrieb .dbg-Dateien zu erzeugen.

Modus 1 (vf-linienzug-modus): Session-Logging ueber Schalter
"vfl-modus1" nach DXFM_LOG/vfl_modus1.dbg. Da alle interaktiven
Eingaben bereits ueber die gemeinsamen vfl-in-point/-string/-real/
-int/-value/-selection-Wrapper laufen, reicht eine einzige
Instrumentierung in vfl-journal-record/-mark/-steplabel, um jede
Frage/Antwort automatisch mitzuloggen.

Modus 3 (vf-linienzug-modus3): auf dieselben vfl-in-*-Wrapper
umgestellt (vorher rohe getstring/getreal/getint/ssget) - profitiert
dadurch vom selben automatischen Logging (Schalter "vfl-modus3",
DXFM_LOG/vfl_modus3.dbg). Kein Journal-Replay/XDATA wie bei Modus 1/2,
nur das Logging wurde uebernommen. Fix nebenbei: Dialog-Kopfzeile
"Hoehe (Z) des Endpunkts [%1]" zeigte den Platzhalter woertlich statt
des Vorschlagswerts (ssg-text statt ssg-textf).

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-27 10:59:10 +02:00
m.stangl e3dbaceb24 Wizard mit Oberflächenstückwerk für den Mode 3 für den VF gebaut 2026-08-26 11:33:19 +02:00
m.stangl d7cb17f53f vf_*.lsp: verbleibende deutsche Meldungen auf ssg-text/ssg-textf umgestellt
Betrifft VarioFoerderer-Kern, Standard-/Etage-Aufbau und Linienzug (inkl.
altem Vorwaerts-Nachbau-Modus und Vario_Kette_Merge-Diagnose). Neue Keys in
lang/de_DE.json und lang/en_GB.json ergaenzt.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 23:34:32 +02:00
m.stangl 82ce795b53 Linienzug: Abbruch wickelt Teil-Geometrie statt sie zu loeschen; Editieren per DCL-Dialog
Abbruch (ESC) im Linienzug-Baumodus loescht die bereits eingefuegte
Geometrie nicht mehr, sondern wickelt sie wie ein fertiger Bau zu einem
VF_n-Block und schreibt das volle Eingabe-Journal als XDATA drauf
(vfl-modus-abbruch-sichern, ersetzt das bisherige Loesch-Rollback). Die
Teil-Kette bleibt damit stehen und ist sofort per Doppelklick weiter
editierbar/fortsetzbar - unabhaengig davon, ob der Abbruch beim frischen
Bauen oder mitten in einem Editier-Neuaufbau passiert. Der bisherige
Menuepunkt "Letzten Abbruch fortsetzen" (Session-Variable) entfaellt
dadurch ersatzlos.

vfl-edit-ent (Doppelklick-Editieren) fragt die Sektion, auf die
zurueckgesetzt werden soll, jetzt per neuem DCL-Dialog ab
(dcl/vfl_edit.dcl, vfl-dlg-position: Combobox 1..N + OK/Abbrechen) statt
per Text-Prompt. Vorbelegung auf die letzte Sektion, damit Doppelklick +
sofort OK einen abgebrochenen Bau nahtlos fortsetzt.

Die *error*-Handler-Installation wandert vor den allerersten Prompt
(vorher: nach Startpunkt/AS-Frage), damit ein ESC in diesem Fenster nicht
mehr auf den ungeschuetzten vorherigen Handler faellt. Das Wickeln im
Abbruch-Pfad ist per vl-catch-all-apply abgesichert, da vfl-block-erstellen
intern einen BKS-Wechsel per (command "_.UCS" ...) macht.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-08-25 22:06:17 +02:00
m.stangl 236808f4dc Varioförderer Aufbau enthält jetzt einen Historien Stack. Beim Abbruch können alle Elemente wiederhergestellt werden und dann einfach weiter gebaut. 2026-08-25 16:09:22 +02:00
m.stangl f5d0e57132 Meldung der unkorrekten Zuordnungen von Separatoren 2026-08-25 11:31:51 +02:00
s.ayadi c3f0d2717d Merge origin/master: Sensor-Zuordnung + Connections zusammenfuehren
Konflikt in lang/de_DE.json und lang/en_GB.json aufgeloest: beide Seiten
haben nur Schluessel ergaenzt (con-*/cmd-connection-* hier, sens-* aus
origin). Beide Saetze uebernommen, Einrueckung von origin (2 Leerzeichen)
beibehalten, tro-edit-fb mit UID-Anzeige uebernommen.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-24 12:13:09 +02:00
s.ayadi 7242e815f8 HundM05-Testfall und DXF-Analyse-Skripte
- 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>
2026-08-24 12:10:58 +02:00
m.stangl fe3adc7e59 Separatoren zaehlen: nur platzierte Symbole, interne Kettenglieder nicht
Der intern in der GF/VF-Kette gezeichnete 300-mm-Block
Staustrecke_Separator_SP ist ein Foerder-/Uebergabestueck, kein
eigenstaendiger Separator. Er wurde bisher als Separator mitgezaehlt
(ANZAHL_SEPARATOR = intern + platzierte Symbole), wodurch eine GF mit
einem darauf gelegten S-LP-Symbol faelschlich 2 statt 1 ergab.

count_sep_scan.lsp: ANZAHL_SEPARATOR zaehlt jetzt nur noch die platzierten
Separator_SP/S-LP-Symbole (newP = nsep). Schnelltest cs-zuordnung-noetig-p
entsprechend auf reine Symbolzahl je Carrier umgestellt. Die interne
Zaehlung (cs-count-nested, *intern-separator-pattern*, internSep) entfaellt.

Gefaellestrecke.lsp: GF-Bau setzt ANZAHL_SEPARATOR beim Erstellen mit 0 vor
(interne Kettenseparatoren zaehlen nicht) - die echte Anzahl fuellt der
Export aus den platzierten Symbolen. Label "Sep=N" entfernt (waere sonst
immer 0 bzw. widerspraeche dem Export). n-bogen-gf/gf-make-label
entsprechend bereinigt.

Hinweis: tests/reference/gefaellestrecke_tests_export.csv (Anzahl_Separator=1
ohne platzierte Symbole) wird dadurch stale -> per TEST_EXPORT_ALL in
BricsCAD neu erzeugen.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-21 17:02:10 +02:00
m.stangl 9341d4c5c2 Sensor-Zuordnung: billiger Schnelltest vor teurem Lauf
cs-zuordnung-noetig-p prueft ohne jede Boundingbox (nur Attribute lesen +
interne Ketten-Separatoren aus der Blockdefinition zaehlen), ob der teure
cs-zuordnung-lauf (Boundingbox+Regen je Carrier und Sensor) ueberhaupt
noetig ist. Voller Lauf nur bei leeren ZUORDNUNG-Eintraegen oder wenn die
Summe ANZAHL_SCANNER/ANZAHL_SEPARATOR ueber alle Carrier nicht zur Anzahl
der Scanner-/Separator-Symbole (+ interne Ketten-Separatoren) passt.
Sonst wird uebersprungen (neue Meldung sens-skip).

csv:run-export ruft die Zuordnung jetzt nur noch bei Bedarf auf. Der
interaktive Befehl ZAEHLE_SEP_SCAN rechnet weiterhin immer komplett neu
(deckt auch den Fall ab, dass ein Sensor ohne Summenaenderung von einem
Carrier zu einem anderen verschoben wurde).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-21 15:54:47 +02:00
m.stangl edfba75801 Sensor-Zuordnung: Separator/Scanner je Kreisel/Strecke zaehlen vor Export
count_sep_scan.lsp neu als wiederverwendbare Engine (cs-zuordnung-lauf),
die automatisch vor jedem CSV-/Sivas-Export laeuft (export.lsp,
csv:run-export). Zaehlt Separator_SP/Scanner je Carrier (Kreisel/Eckrad,
VF_*, GF_*) ueber die gemeinsamen cfg/export.cfg-Muster und schreibt
ANZAHL_SEPARATOR/ANZAHL_SCANNER, so dass die Summe zur Szene passt.

Scanner ausserhalb jeder Carrier-Boundingbox ohne ZUORDNUNG werden per
Abstand dem naechsten Kreisel/Strecke zugeschlagen (ZUORDNUNG = Carrier-ID).
Ist der Abstand zum zweitnaechsten Kandidaten fast gleich (<= strittig_diff_mm,
neu in cfg/export.cfg [Sensorzuordnung]), gilt die Zuordnung als strittig:
Konsolenausgabe der ergaenzten Scanner + JSON-"warnung"-Feld mit den IDs der
strittigen Kandidaten (csv:block-to-json), das export_csv.py in der Spalte
"Warnungen" ausgibt.

Menue: ZAEHLE_SEP_SCAN-Vorlauf vor EXPORTSIVAS entfernt (laeuft jetzt
automatisch im Export); interaktiver Befehl bleibt erhalten.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-08-21 15:37:50 +02:00
s.ayadi e91608d7cc Add Connections to SSG_LIB, reusing the TRO mechanisms
A connection is a CONNECTION_ARROW block sitting at the midpoint of an arrow
between two TRO markers. It stores the relationship as attributes rather than by
position:

    TRO11  ---------->  TRO14
    UID 0062            UID 0065

Same architecture as the TRO feature, nothing new introduced:

  Blockname CONNECTION_*  ->  c:CONNECTION_EDIT (Lisp/Connection_Edit.lsp)
                          ->  dcl/connection_edit.dcl

The double-click and EATTEDIT hooks already route every INSERT through
SSG_BLOCKEDIT, so this is one more branch in that dispatcher - placed before the
TRO branch since both come from the same annotation run and the patterns must not
overlap. DCL path from DXFM_DCL, ssg-start/ssg-end, ssg-attrib-read and
ssg-attrib-set-on, all text via ssg-text/ssg-textf with 16 new keys in both
language files. Loading is lazy: not preloaded in the MNL, pulled by the menu
macros and the dispatcher with (ssg-ensure "Connection_Edit"), with a fallback to
native EATTEDIT if the module is missing.

CONNECTION_INSERT picks two TRO markers and draws the connection; the new
internal number comes from ssg-id-max/ssg-id-format, so it stays inside the
SSG_LIB number space. It refuses when the block definition is absent - the shape
comes from tro_annotate.py, this command does not invent one.

Menu: SSG_LIB > Connections with Verbindung einfuegen, Verbindung bearbeiten and
Bearbeiten (Auto), plus an entry in the POP501 edit context menu.

On the internal id: the markers keep their visible ID (TRO11) untouched - the
existing TRO_INSERT/tro-naechste-id read it and the request was explicit about
not changing it. The permanent unique number therefore lives in a separate
attribute UID, in the same four-digit space as ssg_id and the CSV TeileId.
Putting it into ID was tried and reverted: IDSCHECK treats ID as numeric and
would have overwritten TRO11 with a number while correcting duplicates.
Connections reference the UIDs, so the relationship survives a renamed or moved
marker.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-19 15:09:10 +02:00
s.hensch 49652b2744 [ADD] ILS Zusatzmodule Einfügefunktion und 3D Modelle implementiert 2026-08-04 11:23:40 +02:00
m.stangl 046d34c4aa Etage: Batch-2D/3D-Umschaltung + Nachruest-Befehl fuer Bestandsbloecke
vf-konvertiere-ent waehlt die Einfuege-Funktion jetzt per XDATA-Typ aus der Registry (standard/etage) statt fest variofoerderer-einfuegen -> SSG_DIM_SWITCH schaltet auch Etage-Bloecke um.

Neuer Befehl VARIOFOERDERER_NACHRUESTEN (Alias VF_NACHRUESTEN, + Menueeintrag): markiert bestehende, vor der Marker-Einfuehrung gebaute VF_n-Bloecke nachtraeglich mit SSG_VF_EDIT (Typ aus Attributen erkannt, Baurichtung hz abgefragt) - danach editier- und dim-umschaltbar. Schreibt nur XDATA, keine Geometrieaenderung.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-08-03 16:36:00 +02:00
m.stangl 7f42ac2701 Etagenförderer auch editierbar gemacht. 2026-08-03 16:25:44 +02:00
s.ayadi 9c7dda8a37 Add TRO_INSERT command to hand-place new TRO markers
Lets the TRO menu insert a fresh TRO_SYM_<Typ> marker (point + type +
auto-suggested TROnn id) by reusing a block definition tro_annotate.py
already created, instead of only editing markers it placed.
2026-08-03 15:56:13 +02:00