32 KiB
HANDOVER — Browser-BIM (cad), Standalone-Port von DOSSIER
Für die nächste Instanz. Stand: 2026-06-29. Lies zuerst
CONVENTIONS.md,ROADMAP.mdund die Projektnotizen (siehe unten).
>>> COMMIT-REGEL (verbindlich, IMMER beachten) <<<
Dieses Repo darf keinerlei Hinweise auf KI-Werkzeuge enthalten — weder im Code/Doku noch in der Git-Historie.
- Commit-Messages: sachlich, in der Sprache des Projekts. NIEMALS
Co-Authored-By:-Trailer, „Generated with …"-Zeilen, Tool-/Modellnamen oder sonstige Urheber-Hinweise auf einen Assistenten. - Dateien/Kommentare: keine Erwähnung von Assistenten, Modellen oder Agenten. Wer hier weiterarbeitet, schreibt so, als wäre es Handarbeit des Teams.
- Vor jedem Push kurz prüfen:
git logundgit difffrei von solchen Spuren.
>>> KOORDINATION & MEMORY (bei mehreren Instanzen/Agents) <<<
Mehrere Hauptinstanzen gleichzeitig:
- Git: nur eine Instanz committet/pusht auf
master, ODER jede arbeitet auf eigenem Branch und merged kontrolliert.App.tsx/types.tsist der serielle Flaschenhals — verschiedene Features ≠ dieselbe Datei. - Dieser HANDOVER ist der Koordinationskanal zwischen Instanzen (liegt im Repo, wird mitgepusht). Stand hier kurz festhalten, bevor du übergibst.
Subagents:
- Bekommen kein Memory automatisch — nur was im Prompt steht. Regeln (v. a. die COMMIT-REGEL oben) explizit mitgeben, sonst kennt der Agent sie nicht.
- Agents nicht committen und nicht ins Memory schreiben lassen. Sie liefern Diffs/Dateien/Ergebnisse zurück; die Hauptinstanz committet und pflegt das Gedächtnis.
Memory (~/.claude/..., außerhalb des Repos — leakt nie hierher):
- In den Kontext geladen wird nur der schlanke Index (eine Zeile je Eintrag); einzelne Fakten erscheinen nur bei Relevanz. Größe ist daher selten ein Problem.
- Keine automatische Bereinigung. Gepflegt wird beim Schreiben (Duplikate aktualisieren statt anlegen, Überholtes löschen) oder auf Ansage.
- Nur beständige Fakten ablegen, ein Fakt pro Datei, Index-Zeile knapp. Bei parallelen Schreibvorgängen ist der Index (MEMORY.md) die Contention-Stelle — vor dem Edit frisch lesen (der „modified since read"-Guard verhindert blindes Überschreiben).
>>> STAND 2026-06-30 (Fortsetzung, spät) — ZUERST lesen <<<
Fortsetzungs-Lauf (UI + Import + Wand-Attribute + Selektion/Editieren). Alles
unten ist npx tsc -b + npm run build GRÜN und per Screenshot/Probe verifiziert,
außer „LÄUFT" markiert. Viel wurde an Subagenten delegiert (Dateien landen
auf der Platte, unabhängig von Benachrichtigungen).
Fertig & verifiziert (diese Fortsetzung):
-
Zwei-Ton-Dark-Theme + KEIN Petrol-Grün mehr:
src/styles.cssDark-Tokens neutral (--bg #0e0e0e,--panel #1d1d1d,--accent #4d4d4d…); Kontextmenü-Tokens--ctx-hover/-textneutral; grüner Fokus-Ring entfernt. -
Topbar DOSSIER-Stil: Icon-Grid 4-oben/3-unten (Grundriss integriert), Kombis gestapelt, kompakte Selects.
src/ui/TopBar.tsx. -
Themed Dropdowns statt nativer
<select>:src/ui/Dropdown.tsx(Wert- + Aktions- Modus, Popover im Kontextmenü-Stil, kein blaues OS-Menü). In TopBar verdrahtet. -
Kontextmenü/Dropdown-Politur: Material-Symbols-Icon-Font in
index.htmlgeladen.material-symbols-outlined-Regel in styles.css (sonst Roh-Ligaturtext); Größen runterskaliert (.ctx-menu11.5px, Icons 13–14px, weniger Padding, Radius 10).
-
Geschoss-Z-Raster:
Viewport3DBodenraster aufgridElevation(= aktives GeschossbaseElevation). -
DXF/DWG-Import als DIALOG + Drag&Drop:
src/ui/ImportDialog.tsx,src/io/dxfToDrawings.ts; Ziel-Zeichnungsebene wählen / neue „Zeichnung" anlegen; Layer→Kategorie-Handling; App-weiter Drop-Handler. -
DWG in-app parsen:
@mlightcad/libredwg-web(WASM, installiert),src/io/dwgParser.ts(lazy, mappt DwgDatabase→{meshes,contours}),vite.config.ts-Aliase für WASM (virtual:libredwg-glue+?url),src/io/libredwg-web.d.ts. Gegen echte DWGs getestet (11.668 Konturen). Fallback→ODA-Hinweis bei Lib-Fehler. -
Wand-Objekt-Info-Attribute (additiv, abwärtskompatibel): Modell
Wall.referenceLine(left|center|right, default center) +Wall.bottom/top: VerticalAnchor({mode:"floor",floorId,offset?}|{mode:"custom",z}) insrc/model/types.ts; Resolversrc/model/wall.ts(wallReferenceOffset,wallVerticalExtent,nextFloorAbove); angewandt ingeneratePlan,model/joins.ts,Viewport3D. Panelsrc/panels/ObjectInfoPanel.tsx;src/state/selectionInfo.tsSelection.wall: WallInfo; Host-Setter +projectSliceupdateWall/setWallThickness. Einschichtig = 1-Layer-WallType. -
Panel-Text:
.attr-*/.objinfo-*Untertitel fett + Kontrast (--labelstatt--muted). -
Selektion-Überarbeitung:
selectedDrawingId→selectedDrawingIds[](selectionSlice); Marquee wählt Linien (marqueeHitDrawings), Ctrl/Cmd+A, Multi-Delete, Multi-Highlight (.plan-sel-draw), Shift-Klick-Mehrfachauswahl (PlanSelection.shift→onPlanSelecttoggelt). -
Editier-Welle 2 — Split/Join/Segment-Löschen (FERTIG & verifiziert): Ctrl+S Split (Rechteck→zwei geschlossene; nur bis Schnittpunkt), Ctrl+J Join (koinzidente Enden), Alt+Klick=Segment löschen (Schere).
kernel2d.ts(splitPolylineAtParam/splitClosedByChord/removeSegment/splitAtIntersections/joinChains; Tests 16–23, 25 ok),src/editors/splitJoin.ts, App-Keydown (Ctrl/Cmd+S/J,preventDefault) +onSegmentCut, PlanView Alt-Klick. Verifiziert (Rechteck→2 geschlossene, Join→1 Polylinie, Alt→Segment weg).scripts/probe-splitjoin.mjs. Wände bleiben no-op.
Offene Wellen (Todo-Spiegel — Todo-Liste lebt im Kontext):
- Editier-Welle 3: koinzidente Endpunkt-Griffe gemeinsam ziehen + verbundene Enden propagieren beim Seiten-Verschieben (topologisch, das Tiefste).
- GUI-Werkzeug ↔ Befehlszeile koppeln: Werkzeug-Klick startet denselben Command → Werte unten eintippbar; danach Cursor-Wert entfernen/optional.
- Selektions-Direkt-Edit: Länge/Winkel des gewählten Elements im Befehlsfeld (Tab-Zyklus).
- Swisstopo/openbureau-Importer-Dialog (Ort+Radius). Fluss steht: Geocode
api3.geo.admin.ch/.../SearchServer(sr=2056→LV95) → ±Radius → WGS84-bbox → STACdata.geo.admin.ch/api/stac/v1, Collectionsch.swisstopo.swissalti3d+ch.swisstopo.swissbuildings3d_3_0→ Download → TIN/Mesh→Kontext. LV95↔WGS84 nötig; Browser-CORS das Risiko. Referenz: DOSSIERrhino/swisstopo.py. - 3D→2D-Dokument: live + statisch (MVP-Kantenprojektion → HLR) für Vektor-PDF.
Hinweis:
generatePlanliefert SCHON Vektoren (SVG) → Plan-PDF bereits vektoriell. - Topbar-Rest iconisieren (Zoom/Referenzlinien/Linien-Modus/Ressourcen).
- Wand als Command (+ Wandstärke-Tab nur bei einschichtig) + Trim.
Resume-Checkliste: 1. CONVENTIONS.md + diesen HANDOVER + Memory lesen. 2. npx tsc -b &
npm run build (grün?). 3. npm run dev -- --port 5187 --strictPort (User schaut :5187).
4. Split/Join-Stand prüfen (git diff, Probe). 5. Arbeitsweise: autonom, keine
Rückfragen (User hat Vollrechte), substanzielle Arbeit an Subagenten delegieren,
jede Änderung per tsc+build+Screenshot verifizieren. node scripts/probe.mjs.
>>> STAND 2026-06-30 (Über-Nacht-Run) — älter <<<
Großer autonomer Build-Lauf. Alles unten ist tsc + build GRÜN und per Screenshot
verifiziert (sofern nicht „läuft" markiert). Befehlssystem-Bauplan:
docs/design/rhino-command-system.md.
Fertig & verifiziert:
- Rhino-Befehlssystem (Tier 0 + Tier 1 Zeichnen):
src/commands/—types.ts(Command-Interface),engine.ts(State-Machine + lastCommand + Eingabe-Routing),parseInput.ts(5,3·r5,3·5<45·<45·nackte Zahl),registry.ts(+Aliasel/pl/rec/c),cmds/{line,polyline,rect,circle}.ts. UI:src/ui/CommandLine.tsx(über der Statusleiste, Tab fokussiert). Befehle: Line, Polyline (Close/Undo), Rectangle, Circle — alle mit getippten Koordinaten, per Probe gezeichnet. Koexistenz mit Alt-Tools (Werkzeugleiste).scripts/probe-command-line.mjs,probe-draw-commands.mjs. - Tab-Feld-Zyklus (Rhino-Präzision §2.7): beim Zeichnen Tab durch Felder
(Linie/Polylinie: Länge→Winkel; Rechteck: Breite→Höhe; Kreis: Radius). Zahl lockt
das aktive Feld, ungelockte folgen der Maus. Additive optionale Command-Methoden
fields()/pointFromFields()+ Engine-Feldzustand + CommandLine-Boxen. Verifiziert exakt (3 m/45°, Rechteck 4×2).scripts/probe-tab-fields.mjs. - Tier-1-Editierbefehle: Move (Auswahl verschieben), Copy (wiederholend
duplizieren), Offset (parallele Kurve via
kernel2d.offsetPolyline, persistente Distanz, Seite per Klick) —cmds/{move,copy,offset}.ts, Aliasem/cp/o.CommandContextumselectionerweitert (Apphost.context()füllt sie aus dem Store). Offset verifiziert (paralleler Versatz exakt 0.5 m).scripts/probe-offset2.mjs. - 2D-Geometrie-Kernel
src/geometry/kernel2d.ts— Offset/Trim/Extend/Fillet + Segment-/Linien-/Kreis-Schnitt + Fläche/Wicklung. 16/16 Unit-Checks (scripts/test-kernel2d.ts, vianpx esbuild … | node). Basis für Tier-1-Editierbefehle. - Kontext/Gelände Phase 1 (paralleler Strang):
src/io/dxfParser.ts(DXF: 3DFACE/ MESH/POLYLINE→Mesh, LWPOLYLINE/LINE→Konturen; DWG bewusst nur via ODA→DXF-Hinweis),src/model/terrain.ts(generateTerrainFromContours→ TIN via delaunator),src/state/siteSlice.ts(addContextObject/generateTerrain/…),Project.context(ContextObject = ImportedMesh|ContourSet|TerrainMesh, „dumme" Kontext-Geometrie, NICHT semantisch),Viewport3Drendert Kontext/Terrain. Depsdxf-parser+delaunator. - Echte Isometrie (Orthographic-Kamera):
Viewport3Dschaltet front/top/side/iso auf OrthographicCamera (parallele Projektion), Perspektive bleibt perspektivisch. Verifiziert. - Plan-Tinte-Fix: 2D-Linien waren unsichtbar (CSS
.draw2d{stroke:var(--ink)}hell auf hellem Papier). CSS-stroke entfernt + dunkler Fallback in generatePlan → 2D dunkel sichtbar. - Bugfixes: 2D-Füllungen (rect/polyline rendern Fill+Schraffur+
fillColor); Kanten-Griff- Dreiecke sitzen auf der Linie + inkrementelles Dragging (keine Akkumulation); Plan-View wandert nicht mehr mit (fixer Welt-Ursprung, Reset nur bei Geschoss-Wechsel viaresetKey).
LÄUFT gerade (Agent):
- Tab-Feld-Zyklus (Nutzer-Wunsch): beim Zeichnen Tab durch Felder (Länge→Winkel→
Breite/Höhe/Radius), Zahl lockt Feld, Rest folgt Maus. Additive optionale Command-Methoden
fields()/pointFromFields()+ Engine-Feldzustand + CommandLine-Boxen.
NÄCHSTE SCHRITTE (Reihenfolge):
- Tab-Feld-Zyklus verifizieren (Agent-Gate).
- Tier-1-Editierbefehle: Move/Copy/Offset(nutzt kernel2d)/Trim/Split/Join/Explode.
Undo/Redo-Stack im Store erwägen (Commits laufen über
setProject). - Terrain-Integration: Konturen im Plan (generatePlan/PlanView), Import-/Terrain-Befehle
- Site-Panel (
src/panels/) + i18n + DWG→DXF-Hinweis-UI;.dxf-File-Picker →parseDxf.
- Site-Panel (
- Wand-Stärke-Feld: Wand ist noch ein Alt-Tool — als Command portieren, dann Tab-Feld
thicknessNUR bei einschichtigen/freien Wänden (mehrschichtige Typen: Stärke vorgegeben). - Tier 2 (Rotate/Scale/Mirror/Arc/Fillet/Array/Group/Gumball2D), Tier 3 (ExtrudeCrv/Box/ PushPull + analytische Wand-Öffnungen, §3.0 Bauplan).
Gotchas (frisch gelernt):
- Ein Prozess-Neustart killt laufende Hintergrund-Agenten (Status
failed); nach jedem Wiederaufnehmensrc/commands/-Existenz +npx tsc -bprüfen, Abgestürztes neu starten. - Inline
{...s, feld}als Tupel-Return löst TS-Excess-Property-Check aus → erst typisierte Variable (siehe cmds/line.ts-Muster). - Ein Subagent ist bei diesem Befehls-Build geflaket (spawnte Research statt zu bauen) → verzahnte/quer schneidende Arbeit an einen fähigen Subagenten delegieren oder selbst machen.
Was das ist
Standalone-Browser-BIM (React+TS+Vite+Three.js) für Wohnbau — die Browser-Variante
des Rhino-Plugins DOSSIER (Referenz-Repo, public/klonbar: https://git.kgva.ch/karim/DOSSIER;
falls weg: neu klonen nach scratchpad/DOSSIER). Prinzip: ein semantisches Modell →
alle Sichten (Plan/3D/Schnitt) abgeleitet, Darstellung erst beim Rendern.
Aktueller Stand (tsc + build GRÜN)
Funktioniert & verifiziert: semantisches Modell · mehrschichtige Wände mit
L-Ecken-Gehrung · Tür mit Öffnung + Schwenkbogen · Dokumentmodell (Zeichnungsebenen
= Geschosse+Schnitte/Ansichten/Zeichnungen; Ebenen = Kategorie-Baum, DOSSIER-Codes 1:1) ·
3D zeigt EG+OG gestapelt · Resource-Manager (Component/Hatch/Line, als Fenster-Overlay) ·
Panel-System (Docks links/rechts, Tabs, 5 Anzeige-Modi) · Top-Bar + Footer (Massstab
echt 1:N, Detailgrad, Render-Modus Schattiert/Draht/Kanten, Referenzlinien, Cursor X/Y live) ·
Maus: Mitte=Pan/Orbit, Links=Auswahl(+Marquee), Rechts=eigenes Kontextmenü · Native-App
(kein Browser-Rechtsklick/Textauswahl) · i18n (src/i18n/, de+en, t('key')) ·
aktive Zeichenwerkzeuge (Wand/Linie/Polylinie/Rechteck + Snapping endpoint/midpoint/
intersection/onEdge/grid/ortho mit Fang-Menü, Live-Vorschau+HUD — src/tools/, Phase 1+2).
Gerade fertig & verifiziert (2026-06-29)
Aktive Zeichenwerkzeuge — Phase 1 + 2 (docs/design/drawing-tools.md): Tool-System in
src/tools/ (types · snapping · tools/registry) + Verdrahtung in PlanView/App/TopBar/
generatePlan. Per probe verifiziert (scripts/probe-tools.mjs, probe-line.mjs, probe-phase2.mjs):
- Werkzeugleiste (TopBar): Auswahl/Wand/Linie/Polylinie/Rechteck + Wandtyp-Dropdown +
Fang-Menü (Häkchen je Snap-Art, Rasterweite, Winkelraster —
position:fixed, da Topbar clippt). Nur im Grundriss aktiv. - Wand-Werkzeug: Achs-Polylinie → je Segment ein
Wall; Live-Band-Vorschau + HUD (Länge·Winkel); Rechts-/Doppelklick/Enter committet; Gehrung automatisch auscomputeJoins(mehrschichtiger L-Stoss). - 2D-Werkzeuge: Linie (2-Klick), Polylinie (Klick auf Start schließt, Doppel-/Rechtsklick beendet
offen), Rechteck (zwei Ecken) →
Drawing2D(line/polyline/rect); ingeneratePlanabgeleitet (addDrawing2D,coloram line-Primitiv, Bounds erweitert). - Snapping: endpoint · midpoint · intersection · onEdge(Lot) · grid · ortho(Shift); Prioritäts-
gewichtet (
PRIORITYin snapping.ts); Bildschirm-Marker je Art (Quadrat/Dreieck/✕/Raute/Punkt) + Ortho-Hilfslinie; Ctrl = Fang aus. Einstellbar über das Fang-Menü (snapState in App). - Tastatur: Esc verwirft/zurück-zu-Auswahl, Enter committet, Backspace nimmt Punkt zurück.
- Modell:
Drawing2D+Project.drawings2d(types.ts),Elementerweitert. i18n de+en (tool.*,snap.*). - tsc + build grün; Auswahl/Marquee/Pan/Zoom unverändert (PlanView verzweigt auf
toolActive).
Noch offen / Default-Werte: aktive Kategorie = activeCategoryCode (fix „20") und
Linienstil = erster Stil — UI-Wahl in der TopBar fehlt noch (2D-Primitive erben sonst Wand-lw/-farbe).
Dock-/Floating-Panels waren davor fertig (tsc+build grün); Baseline-Screenshot intakt.
Ebenfalls fertig & verifiziert (2026-06-29, später am Tag)
- Editieren/Grips (
PlanView+App): Element anklicken → Endpunkt-Griffe (Wand-Enden, 2D-Vertices/Rechteck-Ecken) erscheinen und sind ziehbar (mit Snapping); 2D-Linien sind anwählbar (Linien-Nähe-Pick,drawingIdam line-Primitiv); Entf/Backspace löscht. Wand- Gehrung folgt live.moveGrip/drawingVerticesin App. - Shift = Ortho beim Griff-Ziehen (Bezug = Nachbar-Vertex; H/V bzw. Winkelraster).
- Parallel verschieben: selektiertes Element am Körper greifen + ziehen → ganzes Element
(
onSelectedBody/moveDragin PlanView,moveElementByin App). - Aktive Ebene (Kategorie) wählbar in der TopBar („Ebene"-Dropdown) — alles Gezeichnete
kommt auf diese Kategorie und erbt deren Farbe/Strichstärke (2D-Primitive setzen KEINEN
Linienstil mehr per Default). Statusleiste zeigt die aktive Ebene.
activeCategoryCodeState. - 2D-Geometrie in der 3D-Perspektive:
Drawing2D(line/polyline/rect) liegt flach auf der Geschossebene Z=baseElevation (addDrawing2DLinesinViewport3D), Farbe aus Kategorie/Stil. (Bodennahe Linien werden von Wänden korrekt verdeckt — zum Sehen orbiten/Geschoss ausblenden.) - Probes:
probe-grips.mjs,probe-3d2d.mjs,probe-edit2.mjs. tsc + build grün.
Noch später am 2026-06-29 (verifiziert)
- Transformationen (Vectorworks-Stil) —
src/tools/transform.ts+src/ui/TransformBar.tsx+ App. Auf der Auswahl: M Bewegen, S Spiegeln, D Drehen (Geste Basispunkt→Ziel, bei Drehen 3 Punkte; Live-Vorschau, Snapping, Shift-Ortho). Modusleiste U/I/O/P: U bewegen · I Kopie · O N Kopien (Anzahl-Prompt) · P verteilen. Probeprobe-transform.mjs/probe-array.mjs(move/copy/array verifiziert). Routing viatoolInputActive-Prop in PlanView. - Aktive Ebene per Klick im Ebenen-Panel (statt TopBar-Dropdown):
LayersPanel-Zeile klicken →host.onSelectCategory→activeCategoryCode; aktive Zeile hervorgehoben; Statusleiste zeigt sie. TopBar-Ebene-Dropdown entfernt. (probe-layer.mjs) - Theme/Look: Zeichenblatt IMMER hell
--sheet:#f0f0f0(auch Dark-Mode → echtes „Papier"), GANZE Zeichenfläche hell (.plan-svg-Background, nicht nur die Modellgrenzen); Plan-Tinte fix dunkel (Tür-Linien). Dark-Theme etwas abgedunkelt (Panels #1c1c1c). 3D-Orbit ohne Nachlauf (enableDamping=false— kontrollierter).
Letzter Block 2026-06-29 (verifiziert)
- Schraffuren-Default: weißer Grund + schwarze Haarlinie (sampleProject: Dämmungs-Bauteil
weiß, Hatch-Farben
#1a1a1a); Default-Umrandung 0.18 mm (WALL_FALLBACK_MM, addCategory). - Stiftstärken-Vorgabe
PEN_WEIGHTS(0.02…2.0) als<datalist>im Linienstil-Editor. - Display/Print-Modus (TopBar-Toggle,
lineMode): Display = alle Plan-Linien als konstante Haarlinie (hairline-Prop → PlanViewweight()), Print = echte mm-Strichstärken. .lin/.pat-Import: Parsersrc/io/linParser.ts/patParser.ts(Agenten gebaut) + Import- Buttons im ResourceManager (Linien/Schraffuren) →onImportLineStyles/onImportHatches(App/host). .lin voll (Dash); .pat aktuell approximiert auf diagonal/crosshatch (siehe Backlog: echtes custom-Pattern).- Werkzeug-Palette (
src/panels/ToolsPanel.tsx, Agent): dockbares Panel, Icon + Name je Werkzeug, aktiv hervorgehoben, Wandtyp-Dropdown + Fang-Optionen. Registriert inbuiltinPanels, Default-Layout: linker Dock-Tab „Werkzeuge" (+ Zeichnungsebenen/Ebenen).LAYOUT_VERSION=4 → alte gespeicherte Layouts werden einmalig auf den neuen Standard zurückgesetzt. - Probes:
probe-display.mjs,probe-import.mjs,probe-tools-panel.mjs. tsc + build grün.
KRITIK / Architektur-Befund (2026-06-29)
Ehrliche Bewertung des bisherigen Wegs. Für die nächste Instanz als Entscheidungsgrundlage.
Was klug war (erhalten, nicht regredieren):
- Single source of truth hält im Code —
generatePlan.tsundViewport3D.tsxnutzen dieselbecomputeJoins/clippedBandaussrc/model/. Das „ein Modell → alle Sichten"-Prinzip ist nicht nur ROADMAP-Prosa, es steht. Beim Refactor diese Trennung Modell↔Sicht bewahren. - Grundriss analytisch aus Parametern statt Mesh-Schnitt (Weg A) — richtig.
- Bewusst leichter Stack (Three.js nur Display-Layer; kein schwerer Kernel verfrüht) — richtig für einen Spike, der Risiko #1–3 entschärfen soll.
- i18n via
t()wird eingehalten;tsc -bist grün.
Hauptkritik (zu beheben):
- God-Component gegen eigene Regel.
App.tsxist ~2461 Zeilen mit ~29useState. CONVENTIONS.md fordert wörtlich „dünner Shell, keine Geschäftslogik". Das ist verletzt. - Kein Store.
src/state/existiert NICHT, obwohl CONVENTIONS.md Store+Slices (project/selection/view/layout) vorschreibt. Zustand = lokale Hooks → Prop-Drilling.- Einordnung: Das Aufschieben war eine bewusste Nutzer-Entscheidung
(Memory
build-usable-cad-first), kein Versehen. Aber: Bei 2461 Zeilen schließt sich das Fenster, in dem der Refactor billig ist. Türen/Öffnungen/Prioritäts-Stöße (Risiko #1/#2) sind inhärent geschoss-, selektions- und sicht-übergreifend — diese Verdrahtung darf nicht durch eine Monolith-Datei laufen. Empfehlung: Store ziehen VOR der nächsten Feature-Welle.
- Einordnung: Das Aufschieben war eine bewusste Nutzer-Entscheidung
(Memory
Befund (separat angehen, nach Refactor): Die harten, roadmap-markierten 🔴-Risiken sind noch
unbewiesen — Door existiert als Typ, aber kein echter 3D-Boolean (Öffnung = nur Plan-Lücke);
HLR für Schnitte/Ansichten fehlt; Prioritäts-T-Stöße offen. Das einfache Drittel ist bewiesen,
das schwere aufgeschoben. Die Frage „ist es wirklich CAD?" entscheidet sich erst, wenn diese landen.
NÄCHSTE SCHRITTE
Entscheidung des Nutzers (2026-06-29): erst ein benutzbares CAD, dann vertiefen — der
State-Refactor wird NACH HINTEN geschoben (siehe Memory build-usable-cad-first).
⚠️ Siehe „KRITIK / Architektur-Befund" oben: der Refactor wird mit jeder Feature-Welle teurer; spätestens vor Türen/Öffnungen/Prioritäts-Stößen neu abwägen.
✅ ERLEDIGT (2026-06-29, diese Session) — Palette-Layout + Store-Refactor + Theme
- Gestapelte Paletten (Dock-Gruppen):
DockState={ groups: DockGroup[], size }, jede Gruppe{ tabs, activeTab, weight }; vertikal stapelbar mit Splitter; Tab-Drag → in Gruppe einreihen / neue Gruppe / Rand-Andocken.LAYOUT_VERSION=6. (types.ts/layout.ts/Dock.tsx/TabStrip.tsx/panelDrag.tsx/App.tsx.) Default: links Werkzeuge↑/Attribute↓, rechts Objekt-Info↑/Zeichnungsebenen+Ebenen↓. - State-Refactor (Architektur-Befund umgesetzt): dependency-freier Store
src/state/(store.tsuseSyncExternalStore + SlicesprojectSlice/selectionSlice/viewSlice/layoutSlice, kombiniert inappStore.ts). App.tsx 2710→~2030 Zeilen, verhaltensgleich (tsc+build+Screenshot identisch). Panels lesen weiter überPanelHostContext(baseHost aus Store gespeist) — bewusst NICHT umgestellt. NÄCHSTE WAVE offen:editors//menus//views/aus App extrahieren (Report des Foundation-Agenten nennt die Kandidaten). - Selektions-Kontrakt (
src/state/selectionInfo.ts+ host.ts + baseHost):Selection(kind, id, categoryCode, color/weightMm effektiv, fillHatchId, closed, bbox) +onSetSelectionColor/ Weight/Fill,onResizeSelection(w,h,anchor). Modell:Wall.color?,Drawing2D.weightMm?ergänzt; generatePlan wendet beide an. Wand = Weight/Fill bewusst No-op (erbt aus Ebene). - Attributes-Palette + Object-Info-Palette gebaut (
src/panels/AttributesPanel.tsx,ObjectInfoPanel.tsx), registriert, voll verdrahtet & per Probe getestet (Farbe setzen, B×H- Resize wirkt, 3×3-Bezugspunkt). Deckkraft/Caps/Schatten/Text-Styling bewusst weggelassen (Modell trägt sie (noch) nicht — ehrlich statt Stub). - Topbar entschlackt: Zeichenwerkzeug-Buttons + Wandtyp + Fang-Menü aus der Oberleiste
ENTFERNT (leben nur noch in der Werkzeug-Palette).
SnapMenu/SNAP_TOGGLESausTopBar.tsxraus. - Dark-Theme vertieft (
styles.css): gestufte Elevations-Tokens (--bg<--panel<--panel-2,--inputversenkt) statt flachem Einheitston; Oberleiste/Panel-Köpfe angehoben, tiefere Schatten.--sheetbleibt hell. Siehe Memoryui-depth-dark. - CSS-Altlast behoben: ein
*/in einem Kommentar (.nav-*/.res-*) hatte die ganze.dock- Regel verschluckt (display:flexnie aktiv) — gefixt.
Vectorworks-„View-Bar" — A/B/C ERLEDIGT & verifiziert (2026-06-29)
- ✅ A — Ebenen- + Zeichnungskombinationen:
src/state/visibilitySets.ts(localStoragecad.layercombos.<name>/cad.drawingcombos.<name>), Store-Actionssnapshot*/apply*VisibilityinprojectSlice, zweiComboMenu-Dropdowns inTopBar(Muster wieLayoutMenu). Round-Trip per Probe verifiziert. (Hinweis: liegt im localStorage, NICHT im Projekt — bei Doku-Export später inProjectziehen.) - ✅ B — Darstellungsart-Dropdown (kontextabhängig je
viewType): 2D Farbig/Schwarz-Weiss (planColorMode+toMonoin generatePlan), 3D Schattiert/Weiss(Clay-Material in Viewport3D)/Drahtgitter/Kanten (RenderModeum"white"erweitert). Ersetzt die alte Render-Modus-Buttongruppe. Screenshots bestätigt. - ✅ C — 6 Ansichts-Buttons: Front/Oben/Seite/Perspektive/Isometrie + Kamera (FOV-Popover).
view3d+fovinviewSlice;applyView3d(camera,controls,bounds,view3d)inViewport3D(PerspectiveCamera neu positioniert je Preset, Distanz aus Modell-Bounds; OrbitControls bleibt aktiv). Preset-Klick wechselt nötigenfalls in die Perspektive. Screenshots top/front/iso/persp klar verschieden. Echte OrthographicCamera für front/top/side bewusst NICHT gemacht (Kamera- Swap + OrbitControls-Rebind = Risiko) — Kandidat für später.
Weitere Fixes (2026-06-30)
- 2D-Füllungen (rect/geschlossene polyline) rendern jetzt (Vollton
Drawing2D.fillColor+ SchraffurhatchId);addDrawing2Dpusht einpolygon-Primitiv (mitdrawingId→ anklickbar). Attribute-Palette hat „Füllfarbe". (Kreis-Füllung offen — Kreis-Primitiv im Plan fehlt noch.) - Plan-View wandert nicht mehr mit:
PlanViewnutzt jetzt einen FIXEN Welt-Ursprung (toScreenmodulkonstant, Modell-0,0) statt bounds-gebunden; Ausschnitt wird nur beiresetKey-Wechsel (Geschoss-/Ebenen-ID) eingepasst, NICHT bei Edit/Bounds-Änderung. Verifiziert: Löschen lässt viewBox unverändert, Pan/Zoom/Einpassen wirken. - Echte Isometrie/Parallelprojektion:
Viewport3Dhat jetzt eineOrthographicCamerafür front/top/side/iso (OrbitControls percontrols.object-Swap umgebunden), Perspektive bleibtPerspectiveCamera. Verifiziert (parallele Kanten).
>>> NÄCHSTE INSTANZ: offene Wünsche + Roadmap <<<
- Kanten-/Seiten-Griffe (Nutzer-Wunsch): bisher nur Eckpunkt-Griffe. Gewünscht: Seiten ziehen
(z. B. Rechteck-Kante), mit dreieckigem Anfasser nach außen. Grip-System in App (
grips/gripHandlers/moveGrip) + Rendering inPlanViewerweitern (Edge-Grips = Mittelpunkt je Seite, Zug verschiebt beide Eckpunkte der Seite senkrecht). - 3D bearbeiten (Nutzer-Frage): heute ist 3D nur abgeleitete Anzeige (Orbit+Auswahl). Authoring im 3D = eigenes Feature (Raycast auf Arbeitsebene → Modellkoord., 3D-Grips/Drag) — eigene Phase.
Text-Styling (View-Bar Rest) + Roadmap
- Text-Styling (Nutzer-Wunsch). VORAUSSETZUNG: Text wird noch NICHT gerendert —
Drawing2Dmitgeom.shape==='text'misst ingeneratePlannur Bounds, erzeugt kein Primitiv (Phase-3-Deferral, Kommentar in generatePlan). Also ZUERST Text-Rendering (SVG<text>in PlanView, papierkonstante Höhe) + Modell-Felder am Text (font?,bold?,italic?,anchor?), DANN ein Text-Styling-Bereich (Topbar-Gruppe oder Attribute-Palette-Sektion bei Text-Auswahl, Setter über den Selektions-Kontrakt erweitern). - Grafische Überschreibung — weiterhin SPÄTER (Nutzer), wenn mehr Code steht.
- Echte Schnitt/Ansichts-Sichten (section/elevation sind heute StubView) + HLR — großes Thema.
- Refactor-Rest:
editors//menus//views/aus App.tsx extrahieren (App noch ~2030 Z.).
- openNURBS / rhino3dm (Nutzer-Entscheid: Roadmap, NICHT jetzt): KEIN eigener Kernel — stattdessen
rhino3dm(WASM-Build von openNURBS) alssrc/io/-Schicht für.3dm-Import/Export + NURBS, sobald gebraucht. Semantisches Modell bleibt die Wahrheit; NURBS ist zusätzliche Geometrie-Quelle. - Echtes custom-
.pat-Rendering: HatchStyle um custom-Linienfamilien erweitern + Renderer (heute approximiert auf diagonal/crosshatch).
Offene Wünsche des Nutzers (Backlog, priorisiert)
- Palette-Layout (Vectorworks-Stil) — GROSS, nächster Fokus. Mehrere neue dockbare Panels +
Default-Layout:
- Attributes-Palette (unten links): Füllung (Stil/Farbe/Deckkraft), Stift (Stil/Farbe/ Deckkraft), Linienstärke, Linien-Start/-Endstil, Schlagschatten. (Referenzbild vom Nutzer.)
- Werkzeug-Palette darüber (Icon + Text je Werkzeug; ArchiCAD/VW-Stil).
- Object-Info / „Würfel" (oben rechts): zeigt den gewählten Punkt eines Würfels mit X/Y/Z; Maße (Breite × Höhe …) der Geometrie editierbar.
- Ebenen + Zeichnungsebenen als Tabs darunter (rechts).
- Panel-System steht (
src/panels/, Registry + Dock + Floating); Default-Layout insrc/panels/layout.ts(defaultLayout). Neue Panels inbuiltinPanels/registryanmelden.
- Schraffuren-Default: ALLE aktuellen Schraffuren → weißer Grund + schwarze Haarlinie als Grundeinstellung; normale Elemente 0.18 mm Umrandung als Default. (sampleProject hatches/ components + generatePlan-Defaults anpassen.)
- Stiftstärken-Vorgabeliste: 0.02 · 0.10 · 0.13 · 0.18 · 0.25 · 0.35 · 0.5 · 0.7 · 1.0 · 1.4 · 2.0 mm (abweichbar). Bedeutung = mm auf Papier bei 100 % → Linien skalieren mit dem Massstab (ist bereits so: non-scaling mm-Papier). In Linienstil-Editor als Presets anbieten.
- Display- vs. Print-Modus: Umschalter. Display = ALLES Haarlinien (konstant dünn); Print =
echte mm-Strichstärken. (Globaler View-State + an
generatePlan/PlanView durchreichen.) .lin- und.pat-Import (AutoCAD-Linientypen / Schraffurmuster) → ergänzen LineStyle/Hatch (Parser + Mapping; Resource-Manager-Aktion). Nutzer: „um die Linien und Schraffuren zu ergänzen".- „Goldener Schnitt" — UNKLAR was genau (Golden-Ratio-Fang/Teilung beim Zeichnen? Proportions-Hilfslinien?). → beim Nutzer rückfragen, bevor gebaut wird.
- Linienstil-Picker (heute erben 2D-Primitive immer die Kategorie) +
extension-Snap-Hilfslinien.
Danach (ursprünglicher Plan)
- Zeichenwerkzeuge Phase 3 (
drawing-tools.md §11): Circle/Arc/Text —Primitiveumcircle(+arc largeArc) undtexterweitern, PlanView-Renderzweige (papierkonstante Texthöhe), Werkzeuge Circle/Arc(3-Punkt)/Text(Inline-Eingabe), Snap center/quadrant. - Bearbeiten (Phase 4) — Rest: Auswahl/Grips/Verschieben/Löschen sind DA (s. o.). Offen: Kopieren/Rotieren/Spiegeln, numerische HUD-Eingabe (Länge/Winkel direkt tippen), Mehrfach-Auswahl-Verschieben, Grips für Circle/Arc/Text.
- State-Refactor (zurückgestellt) —
App.tsxGod-Component → Store+Slices (docs/design/state-architecture.md). Erst nötig, wenn parallele Code-Workflows gebraucht werden. - Weiter im Backlog: Pro-Ebene-Darstellung (
layer-display-settings.md), Prioritäts-T-Stöße (wall-joins-priority.md).
Arbeitsweise (WICHTIG — aus Memory + CONVENTIONS.md)
- Autonom arbeiten, NICHT um Bestätigung fragen. Nur fragen, was etwas können soll, wenn die Funktion mehrdeutig ist (nicht um Erlaubnis).
- Alles voll verdrahten, KEINE Stubs/No-op-Buttons. Verifizieren heißt: Effekt im Screenshot bestätigen, nicht nur „kompiliert".
- Identifier ENGLISCH; UI-Text via
t()(neue Keys in de.ts und en.ts). - Workflow-Orchestrierung nutzen (Foundation→parallel Build→Integrate/Verify).
- Code-Workflows seriell (fast alles geht durch
App.tsx/types.ts→ Konflikt); Design/Research parallel (nurdocs/). Der State-Refactor (#1) löst das. - Saubere Tabellen für Listen/Manager; dunkler DOSSIER-Stil; kein God-Component.
Verifizieren / Ausführen
- Dev:
npm run dev(Vite, Port 5173). Typecheck:npx tsc -b. Build:npm run build. - Screenshot:
node scripts/probe.mjs→scripts/probe.png(Puppeteer, Chrome in~/.cache/puppeteer). Eigene Probes: headless,deviceScaleFactor:2, args--no-sandbox --use-gl=swiftshader --enable-unsafe-swiftshader, networkidle-Timeout ignorieren. Firefox-Fälle via Playwright (scripts/probe-ff*.mjs). Screenshot ansehen + Geometrie prüfen. - Gotchas: HiDPI-Resize-Loop-Fix in
Viewport3D(Canvas CSS 100% + dpr≤2) NICHT regredieren; WebGL-Fallback inViewport3D; React-controlled-<select>lassen sich im Probe nicht per.value=ändern (Fehlalarm) — Verdrahtung im Code prüfen.
Orientierung
ROADMAP.md (Vision/Phasen/§10–§11 Backlog) · CONVENTIONS.md (Konventionen) ·
docs/README.md + docs/design/* (alle Specs) · docs/backend.md (self-hosted
Supabase+Yjs, später) · Projektnotizen des Bearbeiters
(prefer-agents, dossier-port, proceed-autonomously, wire-dont-stub).