Files
DOSSIER-STANDALONE/PENDENZEN.md
T

137 lines
30 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# PENDENZEN — Aufgaben-Queue (Single Source of Truth)
> **Diese Datei ist die einzige verbindliche Aufgabenliste.** HANDOVER.md enthält nur
> noch Kontext/Konventionen/Environment/Zielmodelle — keinen Backlog mehr.
## Arbeitsprotokoll (ZWINGEND)
**Bearbeiter:**
1. **Zuerst diese Datei lesen**, dann `CONVENTIONS.md` + verlinkte Detailquellen des Items.
2. Oberstes nicht-blockiertes Item aus **🔧 In Arbeit** bzw. sonst **⏭️ Als Nächstes** nehmen, **fertig** machen, verifizieren (`npx tsc --noEmit` + `npx vitest run` + trace-scan), abhaken, eine Ergebniszeile nach **✅ Erledigt** schreiben (mit Commit-Hash, sobald committet).
3. **Rückfrage-Recht:** Bei Unklarheit/Design-Entscheid NICHT raten — Item mit `❓` markieren, kurze Frage darunter notieren, nächstes freies Item nehmen. Fragen sammeln sich unter **❓ Offene Rückfragen**.
4. **Kein Arbeitsschritt endet ohne aktualisierte Liste.** Status hier ist immer aktuell, sonst driftet es wieder.
5. Bearbeiter **committet nicht selbst** und delegiert Unteraufgaben nicht weiter.
**Planer** (mit dem Nutzer, kuratiert):
- Nimmt Nutzer-Feedback, pflegt daraus die Liste (rein/umpriorisieren/aufspalten). Führt selbst keine Queue-Items aus.
- Prüft **❓**-Zeilen mit dem Nutzer, wandelt sie in konkrete Items.
---
## ⛔ Blocker (zuerst klären)
- [x] ~~**Toolchain prüfen**~~**ERLEDIGT 2026-07-04 (macOS-Gerät):** `node`/`npm`/`cargo` (1.96.0)/`wasm-pack` (0.15.0) alle vorhanden. `npm install` + `npm approve-scripts esbuild wasm-pack …` (npm gated Install-Scripts → `allowScripts`-Block in `package.json`, ungetrackt gelassen), `rustup target add wasm32-unknown-unknown`, beide WASM-Engines gebaut, Frontend gebaut, **`npm run tauri:build` → Mac-App (`cad.app` + `cad_0.1.0_aarch64.dmg`, arm64) läuft.** Verifikations-Baseline grün: `tsc --noEmit` sauber, `vitest run` 230/230, `cargo test render3d` 56/56. **Kein Blocker mehr für Engine-Slices auf diesem Gerät.**
## 🔧 In Arbeit
- [ ] **kernel2d-Port nach Rust/WASM** (Plan: [PORT_PLAN.md](PORT_PLAN.md), Crate `src-tauri/kernel2d`, TS-Referenz bleibt `kernel2d.ts`, Differential-Harness `src/geometry/kernel2d.parity.test.ts`). Fortschritt:
- [x] Phase 1: Crate-Skelett + WASM-Fassade + `build:kernel2d``a78e7c7`
- [x] Phase 2: Primitive/Schnitt/Fläche/Kreis + Batch-Fassaden + Diff-Harness (Zufall+Golden) — `9e2c521`
- [x] Phase 3: Offset (Miter + 1e-9-Fallback) + Fillet — `c8ea2bf`
- [x] Phase 4: Trim/Split/Join (`trimPolyline`, `splitAtIntersections`, `joinChains` — Löwenanteil) — `28471c1`
- [x] Phase 5: `roomArea`-Flächen/`ceiling`/`stair`/`roomBoundary` portiert (vitest 263, 33 Parity) — `a608a59`. **Offen in Phase 5:** `opening` (mit Aufrufstellen-Änderung) — noch nicht portiert.
- [ ] Phase 6: TS-Fassade umstellen (alt → `kernel2d.legacy.ts`), Suite grün, `npm run build` + WASM sauber. **Achtung Laufzeit-Entscheid:** macht die Live-App synchron WASM-abhängig (Init + Per-Call-Marshalling) — heute nutzt die App KEINE WASM-Geometrie zur Laufzeit; vor Umstellung mit Nutzer klären.
- **Join-Durchstich verworfen (2026-07-05, gemessen):** `computeJoins` live auf WASM zu legen lohnt NICHT. Benchmark TS vs. WASM inkl. JSON-Marshalling (Median ms/Aufruf, 200 Iter): 6 W → TS 0.018/WASM 0.022 · 20 → 0.027/0.043 · 50 → 0.082/0.102 · 120 → 0.331/0.246 · 300 → 1.68/0.67. Crossover erst ~100+ Wände; realistische Plan-/Geschossmengen liegen darunter → TS schneller, und selbst 300 Wände sind mit TS 1,7 ms (nicht wahrnehmbar). Marshalling frisst den Rust-Vorteil, plus dauerhafte Rust↔TS-Paritätspflicht. **Fazit:** reines TS behalten; WASM für Joins nicht weiterverfolgen. WASM lohnt erst bei echten Rechen-Hotspots (Booleans/Tessellierung).
## ⚠️ Zu prüfen (evtl. schon erledigt / Status unklar)
- [x] ~~**Snap an Wand-Schichttrennlinien**~~**gelandet `339202b`** (`wallLayerBoundarySegments` in `src/tools/snapping.ts`), verifiziert vorhanden.
## ⏭️ Als Nächstes
- [ ] **Ribbon-UI + modulare Bars** (Nutzer-Vision 2026-07-05, bestätigt: Tab-Schema **2D·3D·BIM·Ansichten**). Voller Plan + datengetriebene Architektur: **[docs/design/ribbon-ui-plan.md](docs/design/ribbon-ui-plan.md)**. Ribbon-Oberleiste mit Tabs ersetzt die Werkzeug-Sidebar; datengetriebene Registry (RibbonItem = tool|command|action) ermöglicht auch eine **modulare Custom-Bar** (gleiche Items, vom Nutzer gewählt). Attribute bekommen volle Höhe, Objektinfo darunter gemergt; XYZ-Box oben rechts bleibt. **Phasen:** ~~(1) Gerüst + 2D/BIM-Tab~~ ✅ (`9d6e86d`), ~~(2) TopBar → Ansichten-Tab mergen~~ ✅ (`85011cb`), ~~(2b) Tabs in die TopBar-Zeile~~ ✅ (`456ebc8`), ~~(2c) OCS-Chrome (kleine Wortmarke + Quick-Access-Icons statt Burger, Zeile 26px)~~ ✅ (`4e3b074`), ~~(2d) Text + Ansichten auf eine Leiste, „Ansichten" als Standard-Tab zuerst~~ ✅ (`fe22cbf`), (3) **teilweise** ✅: Werkzeug-Sidebar aus Default-Layout raus + Attribute volle linke Höhe + Wandtyp-/Deckentyp-Picker ins Attribute-Panel verschoben (Nutzer-Entscheid), `LAYOUT_VERSION`→8; **offen:** Objektinfo unter Attribute mergen (großer Panel-Umbau, XYZ-Box-Platzierung — visuell iterieren), ~~(4) modulare Custom-Bar~~ ✅ (Tab „Eigene" + -Picker, localStorage-persistiert). **Offen:** 3D-Tab füllen (aktuell leer; ggf. 3D-spezifisch statt Doppelung mit Ansichten), Band-Höhe/Abstände + 26px-Zeile visuell im Tauri abnehmen, Dauer-Zoom-Anzeige (Statusleiste?) klären. ✅ Vorarbeit: Eigenschaften-Grid im OCS-Stil (`00733d8`), Kreis+Bogen-Werkzeuge (`e454eab`/`bd2b12b`). **Nächster Schritt: im Tauri visuell prüfen (Band-Höhe, Icons, Aktiv-Highlight), dann Phase 2/3.**
- [x] ~~**SPIKE — Bild-Texturen in `render3d`**~~**erledigt `0ca3b1d`** (verifiziert 2026-07-05): `RenderStyle::Textured` real, prozedurales 256×256-Schachbrett (kein Asset/`image`-Crate), UVs planar in Metern, Textur-Bind-Group group 1, `MESH_TEXTURED_WGSL` (gleiche Beleuchtung, Albedo aus `textureSample`), `spike3d` per `T` umschaltbar. Alt-Vertexpfad `[pos,normal,color]` bitgleich (Regressionstest). `cargo test` 58 grün (59 mit `--features render`, inkl. naga-Test); `spike3d`-Build sauber; keine neuen Deps, Default-Build unverändert. Auftrag: [SPIKE_TEXTUR_render3d.md](SPIKE_TEXTUR_render3d.md). **Lücken bis „richtig gutes" Texturing → siehe 3D-REST unten.**
## 📋 Backlog (Priorität grob absteigend)
- [x] ~~**Zeichenwerkzeuge ergänzen: Kreis + Bogen.**~~**komplett erledigt (2026-07-05):** beide Werkzeuge + Center-/Quadrant-Snaps + WebGL-Sichtbarkeitsfix (`2c8ad8f`). Details in den Unterpunkten:
- [x] ~~**Kreis-Toolbar** (trivial)~~**erledigt `e454eab` (2026-07-05):** `ToolId`+`"circle"`, Platzhalter `circleTool` (nicht floorOnly), `TOOL_COMMAND`+`TOOL_ORDER`, Kreis-Icon in `ToolsPanel`, i18n `tool.circle`/`tool.circle.hint`. tsc + Suite 331 grün. (Kreise rendern seit `4ac99d3` glatt als `<circle>`.)
- [x] ~~**Bogen-Werkzeug** (mittel)~~**erledigt (2026-07-05):** `arcCommand` in `src/commands/cmds/arc.ts` (3-Klick: Mittelpunkt → Start/Radius → Endwinkel, CCW; Vorschau via `arcPts`/`circlePts`), registriert in `registry.ts` (Alias `a`/`bogen`), `"arc"` als ToolId + Toolbar-Eintrag (Bogen-Icon) + i18n. tsc + Suite 331 grün. ✅ **Center-/Quadrant-Snaps ergänzt (2026-07-05):** `collectCircles` + Snap-Block in `snapping.ts` — Mittelpunkt + Quadranten (Kreis: alle 4; Bogen: nur im Spannbereich) unter der `center`-Einstellung, Bogen-Endpunkte unter `endpoint`; +3 Tests (Suite 334).
- [ ] **BAUTEILE aufs Rhino-Niveau heben (Treppe/Fenster/Tür).** Vergleich Rhino-Plugin ↔ TS + priorisierte Ansätze: **[RESEARCH_BAUTEILE_RHINO.md](RESEARCH_BAUTEILE_RHINO.md)**. ✅ **Gruppe A (2D, Items 16) komplett — verifiziert 2026-07-05:** (1) Treppe-Outline (`stairOutline`, gerade/L/Wendel, `generatePlan.ts:2186`), (2) Fenster-Brüstungslinie (`window-sill`, gepunktet, `sillHeight>0`, `:1810`), (3) Tür-Sturzlinien (`door-lintel` + `lintelLines` keine/innen/aussen/beide, gestrichelt, `:1711`), (4) Treppe-Referenz links/mitte/rechts, (5) Fenster-Flügel-Mittelpfosten, (6) Tür `wandoeffnung`. **Offen:** Gruppe B (2D mittel: Tür-Schwung am Rahmen, Treppen-Pfeil-Style `filled`, Fenster/Tür-Presets, `swing_invert`; Fenster-Anschlag-Striche) — Feinpolish. Gruppe C (3D: Rahmen/Blatt/Glas/Sims als Mesh — wartet auf Mesh-/B-Rep-Pipeline). **Der große Rest ist „Schnitt- vs. Ansichts-Darstellung" (eigenes Item unten).**
- [ ] **DWG/DXF-Import via `acadrust` (weiterbauen).** ✅ Spike `763a558`: `acadrust` 0.4 (MPL-2.0, pure Rust) **baut zu wasm32** (Crate `src-tauri/dwgimport`, 839 KB), parst DXF aus Byte-Buffer (`DxfReader::from_reader`+`Cursor`), headless getestet. **Offen:** (1) Entity→DOSSIER-Modell-Mapping (LINE/ARC/… → Wand/Öffnung — die eigentliche Domainarbeit, Wochen), (2) Datei-Upload-Glue im Browser (`<input type=file>`→Uint8Array→`parse_dxf_summary_json`, trivial), (3) DWG-binär (`DwgReader::from_reader` analog, aber R13R2018-Korrektheit unverifiziert), (4) WASM-Größe (nalgebra Haupttreiber). **Klarstellung:** der TS-DXF/DWG-Import (`parseDxf`/`parseDwg`/`dxfToDrawings`) + Upload-UI (`App.tsx`, `ImportDialog.tsx`) existieren längst und funktionieren — der acadrust-Weg wäre eine Rust-Neuimplementierung des Lesens (nur DWG-**Schreiben** ist eine echte Lücke). ✅ **2887794 (2026-07-05): Kurven-Abdeckungslücke geschlossen**`parseDxf` deckt jetzt ARC/CIRCLE/ELLIPSE (tesselliert zu Konturen, Winkel Radiant, voller Umlauf geschlossen) zusätzlich zu LINE/LWPOLYLINE/POLYLINE/MESH ab; 5 Tests, volle Suite 307 grün. ✅ **c481373 (2026-07-05): SPLINE + INSERT ergänzt**`parseDxf` wertet SPLINE als echte B-Spline (De Boor, Grad/Knoten; Fallback fitPoints/Kontrollpolygon) aus und expandiert INSERT-Block-Referenzen (2D-Transform Scale/Rotation/Basispunkt + MINSERT-Array + verschachtelte Blöcke, Tiefe ≤8) zu transformierten Konturen; Kontur-Dispatch in gemeinsamen `collectContours` refaktoriert; +7 Tests, volle Suite 314 grün. **Bekannte Grenzen:** rationale SPLINE-Gewichte ignoriert (dxf-parser liefert sie nicht); Block-interne MESH/3DFACE-Entities werden im 2D-Import nicht expandiert. ✅ **c29f27e (2026-07-05): HATCH ergänzt** — dxf-parser hat KEINEN HATCH-Handler (verwarf HATCH stumm); Lösung via `registerEntityHandler` + eigenem `HatchHandler` (sammelt rohe Gruppencodes) + testbarer `hatchContours`-Auswertung: Randpfade (Polyline-Pfade + Linien-/Bogen-Kanten, Bögen über vorhandene Tessellierung) → geschlossene Konturen mit `Contour.filled`; `contoursToDrawings` macht daraus gefüllte `polyline`-Drawing2D (fillColor-Default, restylebar). +6 Tests, Suite 320 grün. ✅ **05bc5aa (2026-07-05): HATCH-Ellipse/Spline-Kanten** ergänzt (Kantentyp 3/4 tesselliert; B-Spline-Sampling in `sampleBSpline` extrahiert). ✅ **4b93ac9 (2026-07-05): TEXT/MTEXT**`parseDxf` liefert `DxfImportResult.texts` (`ImportedText`: Position/Höhe-in-Metern/Winkel-Radiant; MTEXT-Formatcodes grob gesäubert); `textsToDrawings``{shape:"text"}`-Drawing2D; **Darstellung neu**: `addDrawing2D` emittiert ein schlankes `kind:"drawingText"`-Primitiv, PlanView rendert es rein per SVG (modellverankert, Rotation; GPU-Guard so, dass es in ALLEN Renderer-Modi im SVG bleibt); `toRenderScene` überspringt es; ImportDialog zählt/importiert Texte. +5 Tests, Suite 327 grün. **Bekannte Grenzen HATCH:** Bulges an Polyline-Rändern als Sehne; Insel-Loops = eigene Ringe (keine echten Löcher). **Bekannte Grenzen TEXT:** importierte Texte (pointerEvents:none) noch nicht per Canvas-Klick selektierbar; MTEXT-Feinformatierung flachgeklopft; Block-interne TEXT/MTEXT nicht expandiert. **Text im Tauri visuell abgenommen (Nutzer 2026-07-05)** — auch gedreht korrekt. ✅ **4ac99d3: CIRCLE/ARC als echte glatte Formen**`Contour.curve` trägt die wahre Kreis-/Bogen-Geometrie (pts bleiben für Kontext/3D); `contoursToDrawings` baut `{shape:"circle"|"arc"}`; neue Primitive `drawingCircle` (SVG `<circle>`) + `drawingArc` (SVG-Bogenpfad), `toRenderScene` tesselliert sie für den nativen Pfad; +4 Tests, Suite 331. Ellipse bleibt tesselliert (kein Ellipsen-Primitiv). **Weiter offen:** Entity→Wand-Semantik (die dicke Domainarbeit); DWG-Schreiben (einzige echte Export-Lücke).
- [ ] **STRATEGIE — „von BIM-Tool zu echtem CAD".** Direkt am Quellcode studierte Referenzen (OpenCADStudio/truck/acadrust) + Web-Import-Landkarte → konkrete, priorisierte Ansätze in **[RESEARCH_CAD_APPROACHES.md](RESEARCH_CAD_APPROACHES.md)**. Kern: (1) generisches Entity-Modell + Trait-Dispatch, (2) modeless Command-System (`StepInput`-Funnel + Kommandozeile), (3) DWG/DXF-Round-Trip via `acadrust` (MPL-2.0, pure Rust, WASM-tauglich), (4) volle Object-Snap-Schicht, (5) 3D-B-Rep später selektiv via `truck` (Apache-2.0, Geometrie-Crates WASM-fähig, Booleans/Fillets noch instabil). Der `kernel2d`-Rust/WASM-Kurs ist damit bestätigt. **Mit Nutzer priorisieren, welcher Ansatz zuerst.**
- [ ] **Schnitt- vs. Ansichts-Darstellung nach Schnitthöhe (BIM-Standard).** Kern-Idee (Nutzer): jedes Bauteil bekommt getrennt eine **Schnittlinie** (kräftig, z. B. 0.250.35 mm, + Schnitt-Poché) und eine **Ansichtslinie** (Haarlinie); WELCHE gilt, entscheidet die z-Ausdehnung des Bauteils vs. die **Schnitthöhe** des Grundrisses (Default ~1 m):
- Bauteil wird von der Schnittebene GESCHNITTEN → Schnittlinie + Schnitt-Poché (heutiges Wandverhalten).
- Bauteil liegt ganz UNTER der Ebene (z. B. 30-cm-Wand bei 1 m Schnitthöhe, Brüstung, Podest) → nur „von oben gesehen" = **Ansichtslinie/Haarlinie, KEINE Schnitt-Poché**. ← genau der vom Nutzer genannte Fall.
- Bauteil liegt ganz ÜBER der Ebene (Decke/Slab, Unterzug) → Ansicht, üblicherweise **gestrichelte** Überkopf-Haarlinie.
- **Passt konsistent zum bereits existierenden `viewHatchId` (Ansichts-Schraffur) vs. Schnitt-Schraffur** — die Linienstärke-Dualität (View-/Cut-Weight je Component) ist die natürliche Erweiterung derselben Logik.
- **Nicht nur cut/view, sondern cut / AUFSICHT / UNTERSICHT (Nutzer):** ein Bauteil sieht von oben anders aus als von unten. Der Grundriss (Blick nach unten) zeigt Bauteile UNTER der Ebene in **Aufsicht** (Oberseite); ein **Deckenspiegel/Reflected Ceiling Plan** (Blick nach oben) zeigt Bauteile ÜBER der Ebene in **Untersicht** (Unterseite — z. B. Kassettendecke, Leuchten). Also je Component potenziell **drei** Darstellungs-Slots (Schnitt / Aufsicht / Untersicht) × {Schraffur + Linienstärke}. Das heutige `viewHatchId` ist faktisch EIN View-Slot und vermischt Auf-/Untersicht; sauber wäre die Trennung. WELCHER Slot gilt, entscheidet die **Blickrichtung der Sicht** (Grundriss ↓ / Deckenspiegel ↑) UND die z-Lage relativ zur Schnittebene.
- **Verallgemeinert den Decken-Footprint-Clip** (`a2f6923`): „Decke unter Wand verdeckt" ist ein Spezialfall von „Ansichtsbauteil vs. schneidende/überdeckende Bauteile".
- Aufwand: mittelgroß, phasenweise machbar (1: z-Extent-vs-Schnitthöhe-Klassifikation cut/above/below; 2: Ansichtslinie-Weight je Component + Haarlinie/gestrichelt; 3: 30-cm-Wände & Slabs verdrahten). Nicht zu komplex im Konzept — es ist der reguläre CAD/BIM-Weg (ArchiCAD/Vectorworks/Revit). Mit Nutzer Detailgrade/Defaults festlegen.
- [x] ~~**Ebene-Schraffur editierbar**~~**gelandet `dcb6ed5`**: Kategorie-Dialog (`App.tsx`, `editor.hatch`-Feld) hat `<select>` auf `cat.hatch` + `HatchSwatch`-Vorschau. Verifiziert vorhanden.
- [ ] **GEO-BLOCK** (gemeinsame Dateien io/geoContext/swissTopo/terrain/ContextImportDialog/Viewport3D/siteSlice):
- Reale Höhen + **Projekt-MüM** (EG-Referenzhöhe): Terrain georeferenziert bei realem z relativ dazu, Gebäude auf Terrain drapiert (heute alles z=0).
- **Luftbild/SWISSIMAGE**-Orthofoto als Textur aufs Terrain-Mesh.
- Importierte Geo-Elemente auf **aktives Geschoss** (`viewSlice.activeLevelId`) + Gelände-Ebene.
- **Nordstern-Geo-Rendering:** importierte Meshes (heute nur three.js `importedMesh`/`terrainMesh`) auch in `projectToModel3d` einspeisen.
- **3D-Mesh-DXF/DWG-Import** (heute DXF nur 2D); Building-Draping; höhere DTM-Auflösung.
- [x] ~~**ResourceManager Bauteile-Tab** auf Master-Detail~~**bereits Master-Detail** (`ComponentsTab`/`ComponentDetail` in `src/ui/ResourceManager.tsx`, Liste links `res-md-list` / Detail rechts). Verifiziert vorhanden.
- [ ] **Einstellungs-Fenster (Rest):** Verdrahtung ist **da** (`viewSlice.snapColor`/`marqueeColor` → PlanView `SnapMarker`/Marquee, Defaults aus `theme/accents.ts`, Projekt-MüM-Feld `referenceElevationMasl`). **Offen bleibt nur:** Snap/Endpunkt-Default = ❓„aki" (s.u., derzeit Sora #5FA1C9) — reine Farbentscheidung des Nutzers.
- [ ] **Bildschraffur:** ambientCG/CGI-Colorfiles als Quelle (Material-Lib WIP — erst nach Freigabe); Bild-Filter Sättigung/Helligkeit/Kontrast/SW (`image.filters`).
- [ ] **E2b Schraffur-Kachel-Motiv** (MotifEditor für HatchStyle-Tile wiederverwenden).
- [x] ~~**Linienstile aufräumen**~~**erledigt (2026-07-05):** die drei funktional identischen 0.13-Volllinien (`thin`/`hatch-line`/`joint-massive` — alle weight 0.13, `dash:null`, gleiche Farbe) auf EINE kanonische „Volllinie 0.13" (`thin`) zusammengeführt; alle weight-only-Stile klar als „Volllinie X.XX" benannt; Schraffur-Referenzen (`hatch-line``thin`, inkl. `ResourceManager.patToHatches`) + Schichtfugen (`joint-massive``thin`) remappt; `hatch-dash` (einzige gestrichelte) bleibt. Ids stabil gelassen (geladene Projekte + interne Refs bleiben heil; Rendering-Gewichte unverändert). 7→5 Stile. tsc + Suite 331 grün.
- [ ] 2D-Plan z-Anordnen (Kombo-Schraffuren); Bild-Schraffur GL/DXF (heute Fallback).
- [ ] **AUDIT (DOSSIER-Studie):** A1 Override-Regel-Engine; A2→A3 View-Snapshots → Print-Layout-Blätter (PDF pro Blatt); A5 reichere Öffnungen; B1 Text-Werkzeug (+ Kreis-Tool → Shortcuts 1&3); A4 Tragwerk; B2 Object-Info numerisch. (A6 Bauteil-Schedule-CSV erledigt.) Belege in `/tmp/dossier-ref/rhino/*.py`.
- [ ] Elemente im Schnitt anwählbar; render3d 2D-Schraffur auf 3D-Flächen.
- [ ] **TEAMWORK — kollaboratives Bearbeiten (Supabase self-hosted).** Projekte auf einem self-hosted Supabase-Stack speichern; mehrere Nutzer bearbeiten dasselbe Projekt gleichzeitig. Kernkonzept: **pessimistisches Object-Locking** (wie Revit Worksharing / ArchiCAD Teamwork) — alle Objekte sind zunächst gesperrt; ein Nutzer *reserviert* die Elemente, die er bearbeiten möchte (exklusiver Schreibzugriff), und *gibt sie frei*, sobald er fertig ist. Freigabe → sofort für alle anderen sichtbar via Supabase Realtime (WebSocket-Kanal). Kein Merge-Konflikt nötig, weil niemals zwei Nutzer dasselbe Objekt gleichzeitig schreiben. Grobe Schichten:
- **Auth + Projekt-Liste:** Supabase Auth (Email/Magic-Link), Projektübersicht, Öffnen/Schliessen.
- **Lock-Service:** Tabelle `object_locks (project_id, object_id, user_id, locked_at)` mit Row-Level Security; `reserveObjects(ids[])` / `releaseObjects(ids[])` als Supabase-RPC; Optimistisches Check-in via DB-Constraint (doppelte Reserve → Fehler → UI-Feedback).
- **Realtime-Sync:** Supabase Realtime-Channel pro Projekt; bei Freigabe werden die veränderten Objekte (JSON-Patch oder ganzes Objekt-Payload, TBD) gepusht; lokaler Store merged incoming changes sofort.
- **Presence:** Wer ist online, wer hat welche Objekte reserviert (farbige User-Badges an reservierten Elementen im Plan).
- **Offline-Guard:** Beim Verbindungsabbruch Locks automatisch nach Timeout freigeben (DB-seitig: `locked_at + interval` prüfen).
- **Umfang/Granularität TBD mit Nutzer:** Object = Wand/Raum/Drawing2D-Element? Geschoss? Layer? Feinere Granularität = mehr Parallelarbeit, aber komplexeres UI.
- **Aufwand:** gross (24 Wochen echte Arbeit). Erst sinnvoll, wenn Kern-CAD-Features stabil. Mit Nutzer Granularität + Hosting-Setup klären bevor Implementierung startet.
### 3D-REST (engine-schwer, bewusst NICHT blind — mit Nutzer angehen)
- [ ] **Textur-/PBR-Pipeline** (Sampler/Bindings/UV in wgpu; dann `textured`-Style + `Component.texture3d`/Material echt rendern). ✅ **Erster Durchstich erledigt** (`0ca3b1d`, Schachbrett-Textur auf Wänden, group-1-Bind-Group, `MESH_TEXTURED_WGSL`, planare Meter-UVs). **Verbleibende Lücken bis „richtig gut" (Grobschätzung ~1829 PT):** Bild-Datei-Laden (`image`-Crate, PNG/JPG→GPU) ~12 · Material→Textur-Zuordnung (Wandtyp/Layer→Material→Textur-Set, Cache/Atlas oder Bind-Group je Material) ~35 · Normal-/Roughness-/Metallic-Maps + Cook-Torrance-BRDF + Tangentenraum ~58 · Mipmaps (Blit-Pass) + anisotropes Filtern ~12 · Web-Pfad (`web.rs`/WebGPU, Bild-Upload via ImageBitmap) ~34 · UI zum Zuweisen + Persistenz im Dokumentmodell ~58.
- [x] ~~**Wand-Schicht-Bänder in 3D** Option B~~**bereits umgesetzt** in `resolveWallBands(layered=true)` (`src/plan/toWalls3d.ts:236-241`): 3D-Viewer-Pfad liefert je Materiallage ein eigenes `WallBand` (Dicke + Component-Albedo + Normalen-Versatz), `pushSegment` emittiert jede Lage als eigene Voll-Box. `dominantLayerColor` ist nur noch Fallback für den Schnitt-Einkörper-Pfad (`layered=false`). Verifiziert per Code-Lesung.
- [ ] **Ortho-Ray-Picking** (aktuell perspektivischer Pick-Strahl; Front/Top/Side-Presets vor erster Navigation leicht ungenau).
- [ ] **3D-Griffe/Editieren** (Wand-Endpunkte im 3D ziehen etc. — bisher nur Auswahl + Panel-Edit).
## ❓ Offene Rückfragen (an den Nutzer)
- [x] ~~**„aki"** Snap/Endpunkt-Farbe~~**entschieden 2026-07-04: Sora #5FA1C9** als endgültiger Default festgeschrieben (`src/theme/accents.ts` `DEFAULT_SNAP_COLOR`, Doc aktualisiert). Frage geschlossen.
- [ ] Floating-ResourceManager „headless" = ganz ohne Titelleiste? (aktuell MIT)
- [ ] Geo-Block: Projekt-MüM zuerst oder Nordstern-Geo-Rendering?
- [ ] Verifizieren/klären: Isometrie „echte" orthographische Iso (teilw. durch Locked-Iso `cb8fae5` adressiert)? · TopBar-Detailgrad (zoom% ganz aus Footer)? · DOSSIER-Audit welche Features konkret übernommen?
---
## ✅ Erledigt (Verlauf, neueste oben)
_Nur jüngste Session; ältere Historie siehe `git log` und HANDOVER-Narrative._
- [x] 2026-07-05 **Ribbon Phase 4: modulare Custom-Bar** (Tab „Eigene") — datengetrieben auf der bestehenden Registry: neuer `custom`-Tab, `CustomBar` in `RibbonBar.tsx` rendert die vom Nutzer gewählten Items + einen „+ Hinzufügen"-Picker (Dropdown mit Häkchen, listet ALLE Werkzeuge/Befehle aus `ALL_RIBBON_ITEMS`, Klick = an/abwählen). `itemKey`/`itemFromKey` für stabile Persistenz; State in App (`customItems`) via localStorage (`dossier.ribbon.customItems`). Gleiche `RibbonButton`-Aktivierung wie normale Tabs (kein Sonderweg). tsc + Suite 334 grün.
- [x] 2026-07-05 **Ribbon Phase 3 (Teil): Werkzeug-Sidebar raus**`DEFAULT_LEFT_GROUPS` nur noch `attributes` (volle linke Höhe), `LAYOUT_VERSION` 7→8 (gespeicherte Layouts fallen auf neuen Default zurück → sichtbar). Wandtyp-/Deckentyp-Picker von `ToolsPanel` ins `AttributesPanel` verschoben (Nutzer-Entscheid „ins Attribute-Panel") — erscheint bei aktivem Wand-/Decken-Werkzeug (Sektion „Neues Bauteil", auch ohne Auswahl), Host-State unverändert. `ToolsPanel` bleibt registriert (per Fenster-Menü andockbar), `Dropdown`-Import dort entfernt. tsc + Suite 334 grün. **Offen:** Objektinfo unter Attribute mergen.
- [x] 2026-07-05 **Fix: gezeichnete/importierte Kreise+Bögen im WebGL unsichtbar** — der WebGL-Compiler (`glPlan/glPlanCompile.ts`, Default-Renderer) dispatchte `polygon`/`line`/`arc`, aber NICHT `drawingCircle`/`drawingArc` → seit `4ac99d3` (Kreise als echtes `drawingCircle`-Primitiv statt 64-Eck-Polygon) fielen sie im GL still raus (SVG-/WASM-Pfad hatten sie, GL nicht). Zweig ergänzt: bildschirm-adaptive Tessellierung wie beim `arc`-Primitiv (Kreis geschlossen + optionale Vollton-Füllung, Bogen a0..a1 offen). tsc + Suite 334 grün. **Nutzer-Report** („zeichne Kreis, bleibt nicht sichtbar").
- [x] 2026-07-05 **Textur-Spike verifiziert erledigt** (`0ca3b1d`) — bei der Backlog-Abarbeitung festgestellt, dass die render3d-Textur-Spike (`RenderStyle::Textured`, Schachbrett, planare Meter-UVs, `MESH_TEXTURED_WGSL` group 1, `spike3d`-`T`-Toggle) bereits vollständig umgesetzt + committet war; `cargo test` 58/59 grün, keine neuen Deps, Alt-Pfad bitgleich. „Als Nächstes"-Eintrag war veraltet → abgehakt; PBR-Restlückenliste (~1829 PT) in 3D-REST übernommen.
- [x] 2026-07-05 **Ribbon-Feinschliff (OCS-Zeile)** — Tabs in die TopBar-Zeile verlegt (`456ebc8`, eine Leiste Chrome+Tabs, Inhalt darunter; Tab-State in App); OCS-Chrome: kleine Wortmarke „dossier." + Quick-Access-Icons für ALLE Datei-/Export-Aktionen statt Burger-Menü, Zeile auf 26px (`4e3b074`); Text-/Font-Formatierung mit der Ansichts-/Zoom-Steuerung auf EINE Leiste gelegt, „Ansichten" als Standard-Tab zuerst + initial aktiv (`fe22cbf`). Alle tsc + 331 Tests grün. Visuelle Abnahme (26px, Icon-Sitz) noch offen.
- [x] 2026-07-05 **Ribbon Phase 2: TopBar → „Ansichten"-Tab gemergt** (`85011cb`, Nutzer-Entscheid „voll mergen") — die Ansichts-/Zoom-/Darstellungs-Cluster der TopBar (View-Grid+Kamera, Ebenen-/Zeichnungs-Kombis, Detailgrad, Massstab/Zoom, Darstellungsart) als `ViewRibbonTab` (in `TopBar.tsx`) in den Ansichten-Tab verschoben; App reicht sie als `viewsContent`-Node an `RibbonBar` (analog Layout-Menü). TopBar ist jetzt schmale globale Leiste (Marke/Ressourcen · Text · Datei/Export/Einstellungen · Fensterknöpfe). `TopBarProps` entsprechend verschlankt. Visuelle Feinabstimmung offen.
- [x] 2026-07-05 **Ribbon-UI Phase 1** (`9d6e86d`) — datengetriebene Tab-Leiste (`src/ui/ribbon/`: `ribbonItems.ts` Registry, `RibbonBar.tsx`, `CommandIcon.tsx`) unter der TopBar, additiv (Sidebar bleibt). Tabs 2D·3D·BIM·Ansichten; 2D=Zeichnen(select/line/polyline/rect/circle/arc)+Ändern(move/copy/mirror/offset/trim/join), BIM=Bauteile(wall/window/door/stair/ceiling/room); 3D/Ansichten noch leer. Ein Aktivierungs-Pfad: tool→`onSelectTool`, command→`onRunCommand`(engine.start); Aktiv-Highlight über `activeTool`/`engineView.commandName`. `ToolIcon` aus ToolsPanel exportiert (wiederverwendet).
- [x] 2026-07-05 **Attribut-Panel: ein Grid, volle Breite** (`ace0dc6`) — drei getrennte Grids zu EINEM durchgehenden Zwei-Spalten-Grid gemerged (Wertspalte über alle Sektionen bündig), Dropdown-Pills füllen die Wertspalte (fixe Breiten raus), doppeltes Eigen-Padding + zweiter „Attribute"-Titel entfernt. **Nutzer-Report.**
- [x] 2026-07-05 **Eigenschaften-Grid OCS-Stil** (`00733d8`) — `.attr-*` als klares Grid: Sektion-Balken, Zeilentrenner, füllende linksbündige Wertfelder (Texte/Zahlen/Dropdowns einheitlich). Erste Stufe der Ribbon-UI-Vision.
- [x] 2026-07-05 **Zoom-Scroll-Fix** (`077e774`) — Dokument-Overscroll/Rubberband gesperrt (`html,body,#root { overflow:hidden; overscroll-behavior:none }`); Viewport-Zoom zieht die UI nicht mehr mit (macOS). **Nutzer-Report.**
- [x] 2026-07-05 **Kreis- + Bogen-Werkzeug** (`e454eab`, `bd2b12b`) — Kreis-Toolbar (circleCommand gekoppelt) + neues `arcCommand` (3-Klick CCW), beide mit Toolbar-Icon/i18n; rendern glatt via `drawingCircle`/`drawingArc`.
- [x] 2026-07-05 **DXF-Import: Platzierungsoption** (`dd76ec8`) — ImportDialog fragt „relativ zum Nullpunkt" ODER „in die Mitte der aktuellen Ansicht"; `PlanViewHandle.viewCenterModel()` neu; `runImport` verschiebt den Gesamt-Umriss (bbox-Mitte → Ansichtsmitte). tsc + Suite 331 grün.
- [x] 2026-07-05 **Zeichnungen Copy/Paste über Geschosse** (`376aa67`) — Ctrl/Cmd+C kopiert gewählte Drawing2D tief; Ctrl/Cmd+V fügt Klone (neue IDs) auf dem AKTIVEN Geschoss ein und wählt sie. Für z. B. importiertes Mobiliar. Textfeld-Fokus bleibt natives Copy/Paste.
- [x] 2026-07-05 **Tauri Drag&Drop + Import-Dialog-Fix** (`c5b5ca6`, `45e19b7`) — `import`-Befehl als `autoRun` (Datei-Dialog öffnet synchron in der Geste, HMR-Falle via Config-Relaunch behoben); `dragDropEnabled:false` (Tauris natives Drag-Drop fing HTML-Drops ab). **Nutzer-bestätigt: Dialog + Text gehen.**
- [x] 2026-07-05 **Layout: Befehlszeile in Mitte-Spalte** (`c794fee`) — nur Viewport-breit, Docks gewinnen Höhe. **Nutzer-bestätigt „sieht clean aus".**
- [x] 2026-07-05 **Textur-Spike render3d** (`RenderStyle::Textured` real) — zweiter Vertex-Pfad `[pos,normal,uv]` aus dem Mesh abgeleitet (Alt-Pfad bitgleich, per Test belegt), prozedurales 256×256-Schachbrett (kein Asset/`image`-Crate), Textur-Bind-Group group 1, `MESH_TEXTURED_WGSL` (gleiche Beleuchtung, Albedo aus Sampler), Pipeline bitidentisch zur Haupt-Pipeline, `spike3d` per `T` umschaltbar. Verifiziert: cargo test 58/59 (inkl. naga-Test) grün, alle 4 Builds sauber. **Visuelle Fenster-Abnahme durch Nutzer bestanden 2026-07-05** (Schachbrett korrekt, `T`-Umschaltung ok). Erster Durchstich der Textur-/PBR-Pipeline; ehrliche Lückenliste im Bericht — `8556037`
- [x] 2026-07-04 **Grundriss: Decke drückt nicht mehr durch die Wände** — Decken-Umriss an Wand-Footprints (OBB) geclippt; Füllfläche strokelos, Umriss nur über unverdeckte Teilstücke (Überstände). Deckungsgleiche Decke ⇒ Umriss entfällt. vitest 230, tsc sauber — `a2f6923`
- [x] 2026-07-04 **T-Stoss-Putznaht entfernt** — L-Seitenlinie nur noch bei materialFREMDEM Nah-Putz; materialgleicher Putz verschmilzt nahtlos (Nutzer-Direktive „Naht entfernen"). TS+Rust synchron, 3 Tests gezogen, cargo 8/8 — `a5ebfa7`
- [x] 2026-07-04 **Snap-Farbe entschieden: Sora #5FA1C9** als endgültiger Default festgeschrieben (`DEFAULT_SNAP_COLOR`, Doc), „aki"-❓ geschlossen.
- [x] 2026-07-04 **Mac-Build via Tauri + Queue-Abgleich** — Toolchain auf macOS-Gerät verifiziert, `cad.app`/`cad_0.1.0_aarch64.dmg` gebaut & gestartet. Verifikations-Baseline grün (tsc/vitest 230/cargo 56). Queue-Reconciliation: Toolchain-Blocker, Snap-Slice (`339202b`), Ebene-Schraffur (`dcb6ed5`), Bauteile-Tab-Master-Detail, Einstellungs-Verdrahtung UND Wand-Schicht-Bänder 3D (Option B, `toWalls3d.ts`) waren allesamt **bereits gelandet**, aber in PENDENZEN noch als offen gelistet → abgehakt. (kein Code-Commit)
- [x] 2026-07-04 **Öffnungen als echte Boolean-Löcher** (+ Deckentrim-nur-3D) — Fenster/Türen = 1 Wandkörper mit rechteckigen `holes` (Rechteck-Gitter-Zerlegung + Laibungsquads), Segment-Boxen weg; Deckentrim nur noch im 3D-Pfad, Schnitt volle Höhe. Pflicht-Testfall versetzt-überlappende Fenster grün. cargo test 56, vitest 230, build:engine3d + tsc sauber — `1407c68`
- [x] 2026-07-04 **Joins Phase 1c** Durchgangswand am T-Stoss echt aufbrechen (spanCutouts) — `c5a344d`
- [x] 2026-07-04 **Locked-Iso-Fix** freie Kamera bleibt nach Ortho-Preset orthografisch — `cb8fae5`
- [x] 2026-07-04 **3D-Live-Schnittebene** mit schraffierten Schnittflächen — `03f0c40`
- [x] 2026-07-04 **Joins Phase 2** Merge-Regel im Schnitt (gleiche Komponente verschmilzt) — `82d354f`