Files
karim a6c2c04736 Doku: STATUS.md (Codebase-Analyse) + Kern-Docs an den Ist-Zustand angeglichen
Vollständige Bestandsaufnahme der Codebasis als neue STATUS.md (Kennzahlen,
Feature-Inventar, Mist-Liste: toter Code, verwaiste WASM-Crates,
Doku-Widersprüche). ARCHITECTURE.md/README.md/CONVENTIONS.md waren noch auf
dem Tag-1-Planungsstand (Electron/Three.js/OpenCascade/Zustand/HLR-Worker) und
beschrieben nicht mehr, was tatsächlich gebaut wurde (eigene Rust/WASM-Engines,
eigener Store, analytische Rust-Schnitt-Pipeline, Tauri auf macOS + Electron
auf Linux). ROADMAP.md und HANDOVER.md als historisch markiert (Hinweis-Box),
Inhalt unverändert.
2026-07-21 13:35:58 +02:00

20 KiB
Raw Permalink Blame History

STATUS — Codebase-Analyse

Stand: 2026-07-21 · Vollständige Bestandsaufnahme von Code + Dokumentation. Ersetzt NICHT ROADMAP.md/ARCHITECTURE.md (die wurden im gleichen Zug überarbeitet), sondern begründet die Überarbeitung mit Zahlen und Befunden. HANDOVER.md und PENDENZEN.md bleiben die laufenden Arbeitsprotokolle (nicht rückwirkend umgeschrieben).

0. TL;DR

„Dossier" (Arbeitstitel cad, Rhino-Vorbild DOSSIER) ist in 3 Wochen (erster Commit 2026-06-30, 362 Commits bis 2026-07-20) von einem Risiko-Spike zu einem funktionsreichen Desktop-CAD/BIM-Tool gewachsen: eigenes semantisches Gebäudemodell, zwei eigene Rust/WASM-Rendering-Engines („Nordstern"), ein Rhino-artiges Kommandosystem, IFC/DXF/PDF/STL/OBJ-Export, Swisstopo-Import, SIA-416-Flächen, Materialbibliothek (statisch + live von ambientCG), Layouts/ Plansätze, Ausschnitte, native Tauri-Fenster. ~125.000 Zeilen Code (TS+Rust, inkl. Tests), gebaut über viele autonome Agent-Sessions.

Die drei zentralen Vision-Dokumente (ARCHITECTURE.md, README.md, ROADMAP.md) stammen aus der allerersten Woche (Stand 28./29.6.) und beschreiben einen Plan, der in der Zwischenzeit an vielen Stellen überholt, anders gelöst oder längst umgesetzt wurde (z. B. HLR/OCCT→eigene Rust-Schnitt-Pipeline, „Booleans noch offen"→teilweise längst gelöst). Diese Doku-Drift war der Auslöser für diese Analyse; die Docs sind im gleichen Zug revidiert worden.

1. Kennzahlen

Code-Umfang

Bereich Dateien LOC (ohne Tests) Tests
src/ (TypeScript, gesamt) ~230 87.736 869 (Vitest, 71 Dateien) / 16.855 LOC
src-tauri/render3d („Nordstern" 3D) 14 10.246 97 #[test]
src-tauri/render2d (2D-WGSL-Renderer) 11 3.530 18 #[test]
src-tauri/kernel2d (Rust-Geometriekern, Paritätstest) 1 3.383 18 #[test]
src-tauri/geometry (Wand-Join-Mathe, unbenutzt) 1 1.057 8 #[test]
src-tauri/trucksolid (CSG/Extrusion, truck+csgrs) 2 758 15 #[test]
src-tauri/dwgimport (DXF-Parser-Spike, unbenutzt) 1 284 1 #[test]
src-tauri/src (Tauri-Host: Fenster, Dialoge, Lock) 4 1.044
Gesamt ~108.000 (ohne Tests) / ~125.000 (mit Tests) 869 Vitest + 157 Rust-Tests

Größte TS-Bereiche: plan/ (23.626 LOC — Plan-Ableitung + 3 Renderer), ui/ (12.897 LOC — App-Shell, ResourceManager, Ribbon), panels/ (9.538 LOC), model/ (7.043 LOC inkl. Tests), commands/ (6.973 LOC), io/ (5.299 LOC), state/ (5.297 LOC), geometry/ (5.559 LOC), viewport/ (5.165 LOC), export/ (4.280 LOC). src/App.tsx allein ist 7.130 Zeilen.

Tempo

362 Commits in 3 Wochen; Woche 27 (30.6.6.7.): 233 Commits, Woche 28: 126, danach starker Rückgang (Woche 30 bislang 3) — die Session-Dichte hat spürbar abgenommen, nicht das Projekt gestoppt (siehe PENDENZEN.md, weiterhin aktiv).

2. Architektur, wie sie WIRKLICH ist (nicht wie geplant)

2.1 Datenmodell — kein Element[]-Union, sondern typisierte Arrays

ARCHITECTURE.md (alt) plante eine diskriminierte Union Element = Wall | Door | Window | …. Tatsächlich hält Project (src/model/types.ts:2095) pro Bauteiltyp ein eigenes optionales Array: walls, ceilings?, roofs?, doors, openings? (Fenster/Türen gehostet in Wänden, kind:"window"|"door"), stairs?, rooms?, columns?, extrudedSolids?, drawings2d, context? (Importe/Terrain), plus die Bibliotheks-/Typtabellen (lineStyles, hatches, components, wallTypes, roofTypes?, doorTypes?, …) und die Dokument-Ebene (viewSnapshots?, layouts?, masterLayouts?, …). Der Typ-Alias Element (types.ts:1601) existiert zwar noch, wird aber nirgends verwendet (Element-Baum/Selektion arbeiten direkt auf den typisierten Arrays). Praktisch funktioniert das gut (jeder Bauteiltyp hat sein eigenes, spezifisches Interface), ist aber eine bewusste Abweichung vom ursprünglichen Uniform-Union-Plan.

2.2 State — kein Zustand/Redux/Immer, sondern ein Eigenbau

docs/design/state-architecture.md empfahl Zustand. Gebaut wurde stattdessen ein abhängigkeitsfreier Store auf useSyncExternalStore (src/state/store.ts, gleiches Muster wie src/i18n). createStore() komponiert Slice-Fabriken (projectSlice inkl. Undo/Redo, historySlice, selectionSlice, viewSlice, layoutSlice, siteSlice, notifySlice) über eine gemeinsame RootState. Funktioniert, aber: der geplante Folgeschritt „App.tsx wird dünne Shell, View-Routing nach src/views/, Kontextmenüs nach src/menus/" ist nicht passiert — src/views/ und src/menus/ existieren nicht, View-Umschaltung und Kontextmenü-Aufbau liegen weiterhin inline in App.tsx (7.130 Zeilen). Das ist der deutlichste Doku-vs-Code-Widerspruch im ganzen Repo (CONVENTIONS.md verlangt explizit das Gegenteil).

2.3 Rendering — drei 2D-Pfade, zwei 3D-Viewports

2D-Plan: es gibt tatsächlich drei koexistierende Renderer, nicht einen:

  1. PlanView.tsx (SVG) — Referenz-/Fallback-Pfad, bleibt IMMER im DOM für Hit-Testing/Grips, unabhängig davon was zeichnet.
  2. plan/glPlan/ — eigener TypeScript-WebGL2-Renderer (glPlanCompile/-Render/ -Shaders/-Hatch.ts).
  3. useWasmPlanRenderer.ts → Rust-render2d-Crate (WGSL, nativ via wgpu, Web via WebGPU/WebGL2-Fallback, inkl. echtem Text-Rendering via glyphon).

Beide GPU-Pfade fallen bei Initialisierungsfehler still auf SVG zurück.

3D: ebenfalls zwei Viewports: Viewport3D.tsx (three.js, „Free"-Stufe) und Wasm3DViewport.tsx (Rust/wgpu „Nordstern", editierbar, Default). Ein Settings-Schalter wählt die Engine.

2.4 Schnitt/Section — NICHT über HLR, sondern eigene Rust-Pipeline

src/section/hlr.ts + occt.ts (der ursprüngliche OpenCascade.js-HLR-Spike aus Phase 0) hat keinen einzigen Aufrufer mehr im gesamten src/ — toter Code. Der tatsächliche, funktionierende Live-Schnitt läuft über einen völlig anderen, analytischen Mechanismus: App.tsx (section3dCutId/section3dPlane) → Wasm3DViewport.tsx (section3d-Prop → setSectionPlane) → src-tauri/render3d/src/{section.rs, section_boolean.rs, section_fill.rs}. Die Rust-Seite nutzt aus, dass jedes Bauteil ein Prisma mit konstantem Querschnitt ist — eine Schnittebene liefert dadurch immer ein achsparalleles Rechteck, nie ein Trapez; section_boolean.rs ist ein 1:1-Port von toSection.ts::subtractDominantBands, damit 2D-Plan-Schnitt und 3D-Live-Schnitt exakt übereinstimmen. Kein Worker, kein Comlink (beides war geplant, keines existiert) — läuft synchron/GPU-seitig.

2.5 Öffnungen als Löcher — echt, aber kein Mesh-Boolean

Fenster/Türen schneiden echte achsparallele Rechteck-Löcher aus dem Wandkörper (plan/toWalls3d.ts RHole/subtractSpans, gespiegelt in render3d/{mesh.rs,section.rs}) — funktioniert, ist aber KEIN generisches Mesh-Boolean. Ein echtes CSG-Boolean existiert bereits (trucksolid::boolean_mesh, csgrs-basiert, 15 Rust-Tests) und wird von src/engine/truckSolid.ts für das Extrusions-Kommando genutzt — ist aber nicht an die Wand/Öffnungs-Pipeline angeschlossen (bestätigt: booleanMesh hat ausserhalb von truckSolid.ts keinen Aufrufer).

2.6 Rust-Workspace: sechs unabhängige Crates, nicht ein Workspace

src-tauri/Cargo.toml bindet nur den Tauri-Host (cad-tauri) als Workspace- Mitglied; render2d/render3d/geometry/kernel2d/trucksolid/dwgimport sind eigenständige Cargo-Packages, die dem Host nur optional (Features native2d/native3d, standardmässig AUS) als Path-Dependency zugespielt werden. Jedes Crate muss headless (cargo test) UND per wasm-pack --features web bauen, ohne den Tauri-Toolchain-Zwang zu erben — bewusst so geschnitten. Geteilte Abhängigkeiten: wgpu 29/naga 29 (render2d+render3d, versionsgekoppelt wegen glyphon 0.11), truck-modeling+csgrs(gepinnter Git-Rev)+nalgebra nur in trucksolid.

2.7 Zwei Desktop-Rahmen: Tauri (macOS) + Electron (Linux)

Die App läuft plattformabhängig in zwei verschiedenen nativen Rahmen — das ist Absicht, kein Wildwuchs, und hängt an WebGPU:

  • macOS → Tauri. WKWebView unterstützt WebGPU, das die render2d/render3d- WASM-Engines brauchen. src-tauri/tauri.conf.json (Identifier ch.dossier.cad, eigene Titelleiste, trafficLightPosition) + isTauriRuntime()-Gates an 6+ Stellen in App.tsx + vier eigene native Zusatzfenster (src/native/: Resources, Settings, DrawingLevels, LayerSettings, ContextImport).
  • Linux → Electron. Tauris Linux-Webview WebKitGTK unterstützt WebGPU nicht zuverlässig → dort läuft die App über eine Electron/Chromium-Shell (scripts/electron-main.cjs + electron-preload.cjs, gestartet via npm run electron). Der Kommentar in electron-main.cjs sagt es explizit: „Ersetzt WebKitGTK durch Chromium, damit WebGPU zuverlässig läuft."

Beide teilen sich dieselbe React-App und dieselbe randlose eigene Titelleiste; die Laufzeit erkennt den Host über window.__TAURI__ (Tauri) bzw. window.dossierWindow (Electron, per contextBridge injiziert). Die Fenstersteuerung (src/ui/WindowControls.tsx) ist an beide Wege angebunden. Kein Rust-Backend nötig auf dem Electron-Pfad — computeJoins hat einen TS-Fallback (src/compute/index.ts). Electron ist also kein totes Gleis, sondern der aktive Linux-Zielrahmen.

3. Feature-Inventar (was tatsächlich funktioniert)

Modell & Bauteile

  • Mehrschichtige Wände (WallType.layers[]) mit L-Eck-Gehrung UND Prioritäts-T-/X-Stössen (joinPriority am Component) — fertig, in 2D-Plan, 3D-Viewport UND 3D-Live-Schnitt konsistent (Rust-Port section_boolean.rs).
  • Parametrische Wände (ParametricWall: Grid/Modul/Sequenz/Referenzlinie/ bedingte Dicke) lösen sich zu konkreten Wall[] auf.
  • Decken (Slabs, ceilings?) mit Aussparungen, eigenem Typkatalog.
  • Türen/Fenster gehostet in Wänden, mit Rahmen/Zarge/Blockrahmen, Kämpfer, Oberlicht, Detailgrad grob/mittel/fein (2D UND 3D), Schwenkbogen; daneben existiert weiterhin ein älteres, separates Door[] neben Opening[] — laut PENDENZEN.md explizit als offene Doppelspur/Aufräum-Punkt vermerkt.
  • Treppen (gerade/L/Wendel), geschossübergreifend, 2D-Symbol mit Lauflinie/Pfeil.
  • Dächer (Flach/Pult/Sattel/Walm/Mansarde/Zelt) über Rechteck-Umriss, First/ Traufe/Grat im 2D-Plan.
  • Stützen (Column) mit Profilbibliothek (Quadrat/Rechteck/Rund/I/Rohr).
  • Räume (SIA-416: HNF/NNF/VF/FF/GF/AGF) mit automatischer Bilanz + CSV-Export, Raumstempel-Editor (Drag&Drop-Felder).
  • Extrudierte Volumenkörper (truck-Integration: konkave Profile, Verjüngung).
  • Kontext-Layer (Terrain-TIN, importierte Meshes, Konturen) — semantisch getrennt.

Zeichnen & Bedienung

  • Rhino-artiges Kommandosystem (commands/): getippte Koordinaten (5,3/r5,3/5<45), Tab-Feld-Zyklus für Präzisionseingabe (src/ui/CommandLine.tsx), Alias/Autocomplete, ~25 Kommandos (wall, ceiling, opening, stair, column, roof, room, line/polyline/rect/circle/arc, text, move/mirror/copy/offset/trim/join, extrude, import, terrain, measure, Schnittlinie, Georef).
  • Snapping (Endpunkt/Mitte/Schnittpunkt/Lot/Raster/Ortho), Grips, Array, Trim/Split/Join, 2D-Booleans (Union/Subtract/Intersect via polygon-clipping).
  • Messwerkzeug (Polygonzug, Länge + Fläche).
  • Rich-Text-Annotationen (Bold/Kursiv/Hoch-/Tiefstellung).

Darstellung / Ressourcen

  • Resource Manager: Line/Hatch/Component-Manager, Wand-/Decken-/Tür-/Fenster-/ Treppen-/Dach-Typeditoren — als eigenständiges natives Fenster (nicht als Dock-Panel).
  • Materialbibliothek: 13 fest gebündelte PBR-Starter (ambientCG, lokale Texturen) plus Live-Suche der kompletten ambientCG-Bibliothek (Auflösung 1K/2K/4K, on-demand Download+Entpacken via jszip, Proxy wegen CORS) — heute bereinigt (siehe Commit-Historie dieser Session).
  • Regelbasierte Overrides (Bedingung → Farbe/Strichstärke/Schraffur/Sichtbarkeit).
  • Detailgrad grob/mittel/fein je Bauteil + Dokument-Override.
  • Hell-/Dunkel-Theme, Akzentfarben.

Pläne / Output

  • Ausschnitte (View-Snapshots: Kamera, Massstab, Detailgrad, Sichtbarkeiten, Override-Preset) in Ordnerstruktur.
  • Layout-Blätter (Plansätze): Papierformat/-grösse, mehrere Viewports pro Blatt, Masterlayout-Vererbung (Titelblock), Ordnerstruktur, freie 2D-Annotationen.
  • Vektor-Export: PDF (Einzelblatt UND Mehrseiten pro Ordner, layoutPdf.ts::buildFolderPdf), DXF, IFC4 (mit echten Fenster-/Tür-Löchern, deterministischen GUIDs), STL, OBJ, CSV-Bauteil-Schedule (volles Element-Set).
  • Kamera-Presets (Kardinal + Iso), Norden-Rotation.

Import / Kontext

  • DXF (Konturen), DWG (@mlightcad/libredwg-web, WASM), .lin/.pat.
  • Swisstopo: swissBUILDINGS3D (radiusgenau zugeschnitten, nicht die ganze STAC-Kachel), swissALTI3D, SWISSIMAGE-Orthofoto-Draping, LV95↔WGS84, Georeferenzierung über EINEN Vermessungspunkt (E/N/H, geoAnchor).
  • OSM/Overpass-Kontextimport (7 Kategorien).
  • Terrain-Mesh-Generator.

Desktop-Integration (Tauri)

  • Eigene randlose Fenster mit nativer Titelleiste (macOS-Ampel-Position).
  • Native Speichern/Öffnen-Dialoge (plugin-fs/plugin-dialog), eigenes .obp-Projektdateiformat.
  • OS-Level-Exklusiv-Lock gegen Doppelöffnen desselben Projekts (fs4-Crate).
  • Vier eigenständige native Zusatzfenster (Resources, Settings, DrawingLevels, LayerSettings, ContextImport) statt Overlay/Modal.
  • Native macOS-Menüleiste.
  • i18n de/en durchgängig, eigener t()-Mechanismus (kein i18next).

4. Mist-Liste — Befunde, Doku-Widersprüche, offene Fäden

4.1 Verwaiste WASM-Crates (gebaut, aber nirgends importiert)

  • src-tauri/geometry (1.057 LOC, 8 Tests) → pkgGeometrynull Importstellen in src/. Wand-Join-Mathe existiert redundant als TS (src/model/joins.ts) UND als Rust-Port, aber nur die TS-Version läuft.

  • src-tauri/dwgimport (284 LOC) → pkgDwgImportnull Importstellen; DWG-Import läuft stattdessen über @mlightcad/libredwg-web (npm-Paket).

  • src-tauri/kernel2d (3.383 LOC, 18 Tests) → pkgKernel2d — wird nur von einem Paritätstest (kernel2d.parity.test.ts) konsumiert, nicht produktiv. Die TS-Version src/geometry/kernel2d.ts (886 Zeilen) ist die tatsächlich laufende Implementierung. Laut PENDENZEN.md bewusst so belassen: ein Join-Benchmark zeigte WASM unter ~100 Wänden langsamer als die naive TS-Routine. Kein Bug, aber die drei Crates zusammen sind ~4.700 Zeilen Rust (+44 Tests), die aktuell nichts zur Laufzeit beitragen ausser einem Korrektheits-Cross-Check für kernel2d.

    Empfehlung: entweder (a) geometry- und dwgimport-Crate + ihre build:*-Scripts entfernen (kein Nutzen, nur Wartungslast), oder (b) explizit als „Referenzimplementierung/Zukunftsoption" in ARCHITECTURE.md dokumentieren, damit niemand sie für aktiv hält.

4.2 Toter Code

  • src/section/hlr.ts + occt.ts + occt-wasm.d.ts (473 LOC) — OCCT-WASM- HLR-Spike aus Phase 0, keine Aufrufer mehr. Ersetzt durch die analytische Rust-Schnitt-Pipeline (§2.4). opencascade.js bleibt als npm-Dependency bestehen, obwohl nur noch dieser tote Code sie importiert.
  • src/export/planToPrintSvg.ts — Kommentar im Code selbst sagt „ERSETZT durch sceneToPrintSvg.ts", ist aber noch im Baum.
  • Element-Typalias (src/model/types.ts:1601) — definiert, nirgends benutzt.

4.3 Das grösste Doku-vs-Code-Problem: App.tsx

CONVENTIONS.md verlangt seit Tag 1 „App.tsx bleibt dünner Shell, keine Geschäftslogik". docs/design/state-architecture.md plante explizit die Extraktion nach src/views/ (View-Routing) und src/menus/ (Kontextmenü-Aufbau). Beide Ordner existieren nicht. App.tsx ist mit 7.130 Zeilen die grösste Einzeldatei des Projekts und enthält weiterhin View-Umschaltung und Kontextmenü-Konstruktion inline. Das ist der genaue „God-Component"-Zustand, den die Doku von Anfang an vermeiden wollte.

4.4 Bekannte Doppelspur: Door[] vs. Opening[]

Project führt sowohl ein älteres doors: Door[] als auch das neuere, allgemeinere openings?: Opening[] (kind:"door"|"window"). Laut PENDENZEN.md ist das erkannt und als Aufräum-Punkt vorgemerkt, aber nicht konsolidiert.

4.5 Doku-Widersprüche (README/ARCHITECTURE/CONVENTIONS vs. Realität)

Dokument Behauptung Realität
README.md Shell = Electron, Tauri „ausrangiert" Falsch andersrum gedacht: beide sind aktiv — Tauri auf macOS (WKWebView+WebGPU), Electron auf Linux (WebKitGTK kann kein WebGPU); siehe §2.7
README.md „HLR noch nicht ans UI verdrahtet, Views sind Stubs" Der OCCT-HLR-Pfad stimmt (tot), aber Schnitte/Ansichten funktionieren real über eine andere, eigene Rust-Pipeline
README.md „Prioritäts-T-/X-Stösse … Risiko #1" unter „bewusst offen" Seit 7.7. erledigt, inkl. Rust-Port
README.md „PDF-Export ist noch single-sheet" layoutPdf.ts::buildFolderPdf erzeugt echte Mehrseiten-PDFs pro Ordner
README.md Engine-Liste nennt nur render2d/render3d Es gibt 6 Rust-Crates (+kernel2d/geometry/trucksolid/dwgimport)
CONVENTIONS.md Struktur-Ziel src/views/, src/menus/ Existieren nicht; Logik liegt in App.tsx
CONVENTIONS.md Dev-Port 5173 Tatsächlich 5187 (vite.config.ts, tauri.conf.json)
ARCHITECTURE.md Ziel-Struktur store/, sheets/, workers/geometry.worker.ts (Comlink) Tatsächlich state/, panels/layoutModel.ts; kein Worker/Comlink irgendwo im Projekt
ARCHITECTURE.md HLR „im Web Worker (Comlink)" Kein Comlink im Projekt; Schnitt läuft synchron GPU-seitig in Rust
HANDOVER.md Neuester Block: „Stand 2026-07-09" Jüngster Commit + PENDENZEN.md sind vom 17.20.7. — 8+ Tage/mehrere Sessions veraltet

4.6 Codequalität — besser als der Tempo vermuten lässt

Trotz 3 Wochen / 362 Commits über viele autonome Sessions: keine FIXME/HACK/ XXX-Marker im ganzen Projekt; nur 2 TODOs (beide bekannt/harmlos: Geländer in Viewport3D.tsx:2649, Kanten-Tiefe in toSection.ts:1093); eslint-disable fast ausschliesslich react-hooks/exhaustive-deps (bewusst); keine _v2/_old/_backup-Dateileichen. Die eigentliche Aufgabenliste lebt diszipliniert in PENDENZEN.md statt in Code-Kommentaren verstreut — gesünder als der Durchschnitt für dieses Bau-Tempo.

4.7 Genuine offene Punkte (Auszug aus PENDENZEN.md, Details dort)

  • Geo-Block: Layer-Zuordnung für importierte Gebäude/Terrain, reale Höhen + Projekt-müM-Draping, SWISSIMAGE-Draping.
  • 3D-Feinschliff: Fensterrahmen-Ecken bei „fein" überlappen (kein Gehrungs- Union), Dach-First/Grat hat unverschmolzene Dreiecke, unerklärte Vertikalstreifen auf oberen Wandflächen (undiagnostiziert).
  • truck-Boolean nicht an die Wand/Öffnungs-Pipeline angeschlossen (Scope- Entscheid mit Nutzer ausstehend).
  • Feld-Controller (Tab-Zyklus) fehlt für Body-Move und für 3D-Griffe generell (nur 2D-Einzelpunkt-Drag hat ihn); 3D-Griff-Drag hat gar kein Snapping.
  • make2D-Kommando (3D→flacher 2D-Plan mit Füllungen) ungebaut.
  • Ribbon-3D-Tab leer; einige Punkte visuell noch nicht in Tauri abgenommen (u. a. Materialfarben-Textur-Array, Schraffur-Schnittfüllung — laut PENDENZEN als „[~] implementiert, aber unverifiziert" markiert).
  • DWG/DXF-Domänen-Mapping (Entitäten → Wände/Öffnungen) unbegonnen; DWG-Schreiben fehlt (Lesen über libredwg-web vorhanden).
  • Teamwork/Kollaboration (Supabase) bewusst nicht begonnen, gilt als späte Phase.

5. Vergleich: Tag-1-Vision vs. heute

Vision (28./29.6.) Heute
Three.js als einziger 3D-Renderer, OpenCascade.js für Booleans/HLR Eigene Rust/WASM-Engines („Nordstern") für 2D+3D; three.js nur noch „Free"-Fallback; OCCT-Pfad tot
Ein Element[]-Union Typisierte Arrays pro Bauteiltyp auf Project
Zustand-Store Eigener useSyncExternalStore-Store
Web Worker + Comlink für HLR Synchrone, analytische Rust-GPU-Schnitt-Pipeline
„Booleans: Entscheidung in Phase 0" Trucksolid/csgrs-CSG existiert, ist getestet, aber nicht an Wände angeschlossen
web-ifc für IFC Eigener IFC4-Writer (exportIfc.ts)
Phase 25 grösstenteils „Backlog" Treppen, Dächer, Stützen, SIA-416, Swisstopo, OSM, Kamera-Presets, Layouts, Ausschnitte, Terrain — alles bereits gebaut

Kurz: die Prinzipien (ein Modell, viele Ableitungen; Darstellung erst beim Rendern; keine Cache-Stale-Bugs) haben gehalten und wurden korrekt umgesetzt. Die konkreten Technologie-Entscheidungen sind fast durchgängig anders gelaufen als geplant — meist zugunsten einer eigenen, schnelleren Rust/WASM- Lösung statt einer Drittbibliothek.