Spaces:
Running
Running
|
Download STATUS.md from Bryan-HSLU/FP_POC: direct link, hf CLI and curl.
- Browser
- Download file 80.5 kB
-
https://huggingface.co/spaces/Bryan-HSLU/FP_POC/resolve/main/STATUS.md
- Command line
-
hf download hf://spaces/Bryan-HSLU/FP_POC/STATUS.md
-
curl -L -o STATUS.md https://huggingface.co/spaces/Bryan-HSLU/FP_POC/resolve/main/STATUS.md
80.5 kB
| # STATUS – wo stehen wir? | |
| > **Übergabe-Dokument zwischen Arbeits-Sessions.** Jede Session (Mensch oder | |
| > KI) aktualisiert dieses File nach jedem abgeschlossenen Schritt: Was ist | |
| > fertig, was ist in Arbeit, was ist als Nächstes dran, welche bewussten | |
| > Abweichungen gibt es. Meilenstein-Definitionen: Brain → | |
| > `vault/50_Umsetzung/Bauplan-Meilensteine.md`. | |
| **Stand: 2026-09-30** | |
| > ℹ️ Die Arbeiten 2026-07-16 bis 2026-08-04 (Farbwelt 16→33 Slugs, +28 Möbel | |
| > inkl. Vorfilter-Passung, L-Sofa 2D=3D, Viewer-Fixes, Kurator v3.3 mit | |
| > schlankem Repair und erkannten Abschneidungen) sind nicht als eigener | |
| > Abschnitt hier, sondern als Learning im Brain zusammengefasst: | |
| > `vault/10_Learnings/Learning-Kurator-v33-Katalog-Varianten-Tokenbudget.md` | |
| > (Details: Commits `3f3c1ea` … `85a71a3`). | |
| ### Scan ohne LiDAR: Video → MapAnything im Colab-Worker (2026-09-30, ADR-0016) | |
| Bryans Vorgabe: Scan **muss ohne LiDAR** gehen (USP). Recherche: keine Gratis- | |
| iOS-App exportiert ohne LiDAR Video + Posen (Stray Scanner nur LiDAR, | |
| NeRFCapture nur Einzelbilder) → AR-Posen-Pflicht aus ADR-0012 fällt. | |
| - **Neuer Standardweg** in `services/scan-worker`: normales Video → | |
| `frames` (Schärfe = Laplace-Varianz, zeitbasiert N Keyframes/s, Default 3, | |
| verwackelte < 35 % Median raus, max. 120) → **MapAnything** | |
| (`facebook/map-anything-apache`, Apache) → `rekonstruktion` (Hochachse aus | |
| Bild-oben aller Kameras, gedrehtes Video erkannt, Verfeinerung per | |
| Bodenebene im unteren Höhenband + SVD-Fit ≤ 10°, Boden → z = 0, Diagnose | |
| Raum-/Kamerahöhe) → optional Massstab aus bekannter Raumhöhe → | |
| `fuse_mit_farben` (2 cm) → PLY → SpatialLM. GPU-Speicherfehler → Wiederholung | |
| mit halb so vielen Frames. AR-Posen-Weg bleibt (`.zip` mit `poses.json`). | |
| - **SpatialLM in eigenem venv** (`FP_SPATIALLM_PYTHON`, pinnt torch 2.4.1), | |
| MapAnything im Colab-Python; GPU-Speicher dazwischen freigegeben. | |
| Notebook `colab_worker.ipynb` entsprechend (Setup, Regler, Filmtipps). | |
| - **Tests:** scan-worker 22 → 41 (Frame-Auswahl; synthetischer Raum in | |
| beliebig gedrehtem Weltsystem inkl. gedrehtem Video und 4° Handy-Kippung; | |
| Verdrahtung mit gestubbten GPU-Teilen inkl. Speicher-Rückfall). | |
| **Nicht getestet: echter Colab-Lauf** (Installation, T4-Speicher, Qualität). | |
| - **Als Nächstes:** Bryan startet Colab mit den alten R1-Videos (erster Lauf = | |
| Gate für Installation/Speicher) → R1 neu filmen (normale Kamera-App) + | |
| Restmasse → Messung gegen Ground Truth → Learning. Danach M7: Massstab- | |
| Bestätigung im Korrektur-Modus, Live-Weg als Job + Polling. | |
| ### Vercel-Eingang Phase 2 – erster Deploy grün (2026-09-29) | |
| - **Preview live** (Workflow «Deploy Vercel» Lauf #8, Branch | |
| `claude/keen-meitner-0qijkc`): Build 14 s, Upload 20.8 MB, Vercel-Projekt | |
| `bryan-125a/fp-poc`. Produktions-Domain ist **`fp-poc-seven.vercel.app`** | |
| (`fp-poc.vercel.app` war vergeben; in Vercel → Domains änderbar). | |
| - **Token-Odyssee** (Läufe #1–#7, «Could not retrieve Project Settings» bzw. | |
| «User not found (404)»): IDs waren korrekt, der Token nicht nutzbar. Gelöst | |
| mit neu erzeugtem persönlichem Token (Account Settings → Tokens, Scope «Full | |
| Account»). Dafür neuer Workflow-Schritt «Vercel-Konfiguration prüfen» | |
| (Leerraum, `prj_`/`team_`-Präfixe inkl. Vertauschung, Token-Länge, | |
| `project ls` im Team) – bleibt drin, spart beim nächsten Mal die Suche. | |
| - **Brain nachgeführt:** ADR-0015, Learning Vercel-Eingang, | |
| `POC-Demo-Architektur-HF`, Scan-Fahrplan («Job + Polling Pflicht»). | |
| - **Als Nächstes:** Bryan testet die Preview am Handy (Checkliste: Start/Weck- | |
| schirm, Bad/Wohnen/Küche + Vorschlag, Swipe-Fotos, Export, Scan-Bundle, | |
| Vergleich HF). Danach Branch → `main` = erster Produktions-Deploy (wartet auf | |
| `/api/health.build`). Offen: 27-MB-Upload durch den Rewrite + Kaltstart live. | |
| ### Vercel-Eingang Phase 1 – Fundament für zwei Frontends (2026-09-28) | |
| Ziel (mit Bryan besprochen, Variante «K5»): Frontend ZUSÄTZLICH auf Vercel | |
| (`fp-poc-seven.vercel.app`), `/api/*` per Rewrite an den HF-Space; der Space bleibt | |
| vollständige Referenz (Frontend + API wie bisher). Phase 1 = alles, was beide | |
| Eingänge brauchen – wirkt schon jetzt auf HF. Abwägung K1–K7 (Timeouts, | |
| 4.5-MB-Body, Kontingente, Nutzerreise): kommt als ADR-0015 ins Brain. | |
| - **Swipe-Bilder statisch** unter `/bilder/...` aus dem Build: Vite-Plugin | |
| `fpBilder()` (`vite.config.ts`) – Dev-Middleware mit Path-Traversal-Schutz, | |
| Build kopiert die 114 Fotos nach `dist/bilder/` (nur beim echten Build). | |
| `Stil.tsx` baut URLs über `bildUrl()` (segmentweise kodiert – Dateinamen mit | |
| Leerzeichen/Klammern). `/api/bilder` bleibt als Rückfall bestehen. | |
| - **Weck-Logik** (`backend.ts` + `api.ts`): HTML statt JSON (HF-Ladeseite eines | |
| schlafenden Space, auch mit Status 200; Proxy-Fehlerseite) oder Netzfehler → | |
| EIN gemeinsamer Weckvorgang (`/health`-Pings 2/3/5 s …, max. 3 min) → Anfrage | |
| genau einmal wiederholt (unbedenklich: alle Endpunkte ohne Server-Zustand). | |
| App zeigt Ladezustand-Variante `wecken` bzw. Fehlerkarte «Erneut versuchen»; | |
| der Hinweis «pnpm api starten» erscheint nur noch im Dev-Modus. | |
| - **Kurator-Gesamtdeadline** `FP_KURATOR_DEADLINE_S` (Default 90 s, `0` = aus) | |
| über alle LLM-Calls inkl. Repairs und 429-Backoff: unter 5 s Restzeit kein | |
| neuer Call, HTTP-Timeout auf Restzeit gekürzt, ein Backoff, der das Budget | |
| sprengen würde, bricht ab → ehrlicher (Teil-)Fallback + Marker | |
| `CURATOR_DEADLINE`. Die ungültige Antwort wird jetzt VOR dem Repair gesichert | |
| → die Platz-Rettung greift auch, wenn für den Repair keine Zeit mehr bleibt. | |
| Grund: Vercel-Rewrites warten max. 120 s aufs erste Byte. LLM-Eval-Workflow: | |
| Deadline aus (misst KI-Qualität unter Drosselung, nicht Fallbacks). | |
| - **API:** `Cache-Control: no-store` auf allen Antworten ausser `/bilder` | |
| (Middleware liest den Pfad VOR `call_next` – Starlette mutiert `root_path` im | |
| Mount); `/health` meldet additiv `build` (Git-SHA aus `BUILD_SHA`, schreibt | |
| `deploy-space.yml`; `git add -f`, weil die mitkopierte `.gitignore` sie sonst | |
| im Deploy verschluckt); `.webmanifest`-MIME in `space.py`. | |
| - **PWA:** `manifest.webmanifest` («FP POC», standalone, Theme #243D35), Icons | |
| 180/192/512/512-maskable aus dem Signet (deckend weiss, sonst füllt iOS | |
| schwarz), Meta-Tags in `index.html`. Bewusst KEIN Service Worker. | |
| - **Tests:** web 223→243, engines 434→454 (Deadline mit simulierter Uhr, | |
| Weck-Logik mit gemocktem fetch + Mutationstest). E2E-Smoke `space.py` lokal: | |
| Manifest/Icons/`/bilder`/`/api/bilder`/`/api/health` wie erwartet. | |
| - **Phase 2 (Code fertig, wartet auf Bryans Vercel-Projekt + Secrets):** | |
| `vercel.json` (Build aus dem Monorepo-Root, Output `apps/web/dist`, Rewrite | |
| `/api/*` → `bryan-hslu-fp-poc.hf.space/api/*`, Git-Deploys AUS) + | |
| `deploy-vercel.yml`: Produktion erst, wenn `/api/health.build` = Commit-SHA | |
| (max. 20 min, `cancel-in-progress` spart Actions-Minuten), Previews für | |
| andere Branches; gebaut per `vercel pull/build/deploy --prebuilt` auf dem | |
| Runner (CLI 60.1.3 gepinnt, gleiche Toolchain wie CI, Commit-Autor egal). | |
| Ohne Secrets übersprungen. Lokaler `vercel build` geprüft: nur statisch | |
| (22 MB, 114 Bilder, Icons, Manifest), KEINE Functions, Routing = | |
| filesystem → Rewrite. README «Deploy» + CLAUDE.md §11 nachgeführt. | |
| - **Als Nächstes:** Bryan legt Projekt `fp-poc` an + 3 Secrets → Preview-Test | |
| (27-MB-Upload durch den Rewrite, Kaltstart live, Handy-Durchgang auf beiden | |
| URLs) → Produktion; danach ADR-0015 + `POC-Demo-Architektur-HF` + | |
| Scan-Fahrplan «Schritt 5 = Polling Pflicht». | |
| ### LLM-Läufe real: Kurator antwortet echt – Groq-Debugging-Saga (2026-07-15) | |
| 6 Workflow-Läufe (`kurator-llm-eval.yml`, Secret FP_KURATOR_API_KEY) bis zur | |
| ersten vollständigen echten KI-Antwort. Fehlerkette (je Lauf diagnostiziert): | |
| 1. **413**: Call-A-Prompt zu gross (volle achsenTags-JSON je Kandidat) → | |
| v3.2 Prompt-Diät (Kompakt-Stil-Notation, Kandidaten-Budget, adaptive | |
| Kürzungs-Leiter, FP_KURATOR_MAX_PROMPT_TOKENS). | |
| 2. **413 trotz Diät**: Groq zählt Prompt + MAXIMALES Antwort-Fenster; ohne | |
| max_tokens wird das volle Kontextfenster angenommen → v3.2.1 max_tokens | |
| explizit (FP_KURATOR_MAX_ANTWORT_TOKENS) + 429-Backoff. | |
| 3. **400 json_validate_failed**: Qwen3 denkt DEFAULT laut, <think>-Präfix | |
| bricht response_format=json_object, der gescheiterte Call verbrennt das | |
| Minutenbudget → v3.2.2 reasoning_effort=none für Qwen3 (env-übersteuerbar). | |
| 4. **429**: Free-Tier TPM (Qwen 6k, Llama 12k) drosselt Serien → v3.2.3 | |
| Backoff 3×/30s + FP_EVAL_PAUSE_S zwischen Läufen. | |
| **Ergebnis (Llama-3.3-70b-versatile):** 3/9 Diagnose-Kombis mit VOLLER echter | |
| Antwort, alle 6 Plausibilitäts-Ampeln grün – z.B. wohnen×mittig ohne jeden | |
| Marker: Konzept (Eiche+Leinen, erdig), 4 Stühle zum Esstisch, Farben je Item, | |
| Boden parkett-eiche, Wände putz-warm + EINE Täfer-Akzentwand. Rest-Fallbacks | |
| nur noch 429 (Budget). 413/400 mit Llama komplett weg. | |
| **Empfehlung:** Space-Secret FP_KURATOR_MODEL auf llama-3.3-70b-versatile – | |
| Einzelnutzer-App (3 Calls/Plan) liegt locker im 12k-TPM-Budget. Qwen3-Pfad | |
| bleibt funktionsfähig (Thinking default aus). Offen: Eval-Gate-Vergleich fair | |
| machen (9 vs 45 Läufe), Norm-Korrektur-Rate erst mit mehr echten C-Calls | |
| aussagekräftig. | |
| ### Welle C – UI-Trio + Diagnose/LLM-Workflow + Norm-Verifikation (2026-07-14/15) | |
| - **UI-Trio:** Einzelwand-Materialwahl (`apps/web/src/wandauswahl.ts`, Panel- | |
| Wandliste 1-basiert angezeigt, 2D-Highlight, Norm weiterhin über | |
| `/flaechen/pruefen`) · **«3 Vorschläge»-Karten** in SchrittVorschlag | |
| (Mini-2D readonly + Kennzahlen; `/solve` `variantenDetails` → additiv | |
| `variantenPlaene` best-first) · **2D-Flächen-Layer** (Default AN, gleiche | |
| Auflösung wie 3D via `flaechen2d.ts`, Legende; AUS = alte Darstellung, | |
| testbelegt). Offen: Relations-Score in Karten roh/negativ → normalisieren. | |
| - **Merge-Erkenntnis C×D:** Begehbarkeits-Leiter in `varianten._waehle_begehbar` | |
| zentralisiert — der Karten-Kopf ist IMMER der gelieferte begehbare Plan | |
| (auch wenn nicht Score-Sieger), Rest best-first; Test präzisiert. Dabei | |
| `by_id`-NameError im Reduktions-Zweig gefixt (Folge des Parallel-Refactors). | |
| - **Diagnose-Harness** `scripts/kurator_diagnose.py` (ADR-0014): Raum×Profil- | |
| Matrix, echte Kurator-Antworten + 6 Plausibilitäts-Ampeln; Baseline 45/45 | |
| ohne ⚠️, byte-deterministisch. **LLM-Lauf:** Workflow | |
| `.github/workflows/kurator-llm-eval.yml` (Runner haben Netz zu api.groq.com, | |
| Remote-Sessions nicht; Thinking per Input `reasoning`) — **wartet auf | |
| Repo-Secret `FP_KURATOR_API_KEY`** (Klartext-Key als Input wird vom | |
| Secret-Scanning korrekt blockiert). | |
| - **Flächen-Normregeln verifiziert:** Küchen-Spritzzone 1.2→**1.5 m** | |
| (Fliesenspiegel-OK ~1.5 m ab Boden), Nasswand 2.0 m bestätigt (DIN 18534: | |
| ≥20 cm über Brausekopf), Rutschhemmung Ziel bfu GB2/B (erst mit Produkt- | |
| daten prüfbar). Quellen: Brain `Quellen-Flaechen-Normen`. | |
| ### Welle D – softScore bad/wohnen echt + Begehbarkeit hart am Planende (2026-07-15) | |
| Zwei Qualitätspunkte aus dem v3-Fund («softScore bad/wohnen immer 0.0») und dem | |
| circulation-Learning (Metrik vertrauenswürdig, Hürde war nur Hot-Path-Performance). | |
| - **softScore stil/relation echt befüllt (alle Raumtypen konsistent):** Muster | |
| des Küchen-Ergonomie-Patches – der Domänen-Solver schreibt NACH dem | |
| Interpreter-Lauf in die vorhandenen Felder; Interpreter/Schema/Goldens | |
| unberührt (Paritäts-Gesetz aus dem Weg). `stil` = mittlerer Stil-Score der | |
| platzierten Items (Wiederverwendung `kurator.stil_score`, kein Duplikat); | |
| `relation` = Anteil erfüllter relationaler/Anordnungs-Wünsche am fertigen | |
| Plan (gleiche Quelle `baue_rel_map` wie Platzierung + K-Scoring, binäre | |
| v0-Urteile `solver._relation_erfuellt`, ohne Wünsche vakuum-wahr 1.0); | |
| `ergonomie` bleibt Küchen-spezifisch (Arbeitsdreieck). Beispielwerte | |
| bad-sample seed 1 mit Profil: stil 0.14 · relation 1.0. | |
| - **Begehbarkeit hart am Planende (Weg «hart am Ende», nicht im Filter):** | |
| Messung: circulation kostet das 10–13-fache ALLER harten Regeln (~15 ms Bad / | |
| ~33 ms Wohnen vs. 1.4–2.6 ms) bei 22–47 Feasibility-Aufrufen je solve ⇒ hart | |
| im Filter wäre ~7–10× langsamer; zudem globale Grid-Eigenschaft, nicht | |
| inkrementell. Regel-JSON bleibt **soft** (Parität/Goldens byte-identisch); | |
| die Härte lebt in der Liefer-Schleife: `solver.solve_begehbar` (API-Pfad ohne | |
| Varianten) prüft den fertigen Report, bei Verletzung deterministischer | |
| Re-Solve mit reduzierter Auswahl (letztes P3-/Ergänzungs-Item ohne | |
| Anker-Pflicht, max. 3), danach VOLLER Plan mit sichtbarem Hinweis | |
| («BEGEHBARKEIT NICHT ERREICHT» im circulation-`ruleResult.hinweis` – | |
| constraintReport ist additionalProperties:false, darum kein neues Feld). | |
| K-Varianten (`loese_mit_varianten`): Leiter = nächstbeste BEGEHBARE Variante | |
| → Reduktions-Re-Solve → Hinweis; Massnahme additiv in | |
| `varianteInfo.begehbarkeit`, Rangfolge sonst byte-identisch (dokumentiert + | |
| getestet). Küche: letzte P3-Deko-Platzierung entfernen (max. 3) → Hinweis. | |
| - **Tests:** neues `test_begehbarkeit.py` (54 Tests): Property ⭐ «jeder | |
| gelieferte Plan begehbar ODER sichtbarer Hinweis» über bad/wohnen/kueche × | |
| Seeds + Varianten-Pfad, 0-❌-Invariante, Determinismus beider Leitern, | |
| echter unfixbarer Bestands-Engpass (Hinweis-Pfad), Reduktions-Mechanik, | |
| softScore-Diskriminierung/Defaults. `test_varianten`/`test_solve_endpoint` | |
| «best ≥ v0» präzisiert (gilt, ausser die dokumentierte Leiter greift). | |
| - **Wirkung (echter Evaluator, seeds 0–11):** bad-sample 8 direkt ok · 1 durch | |
| Reduktion · 3 Hinweis; wohnen-sample 6 · 1 · 5; Varianten-Pfad wohnen: alle | |
| Seeds begehbar (meist via «andere-variante»). Küche unverändert (knapp/ok). | |
| - **Bewusst offen:** Regel-`hinweis`-Text in `data/rules/basis.json` erwähnt | |
| noch «Hochstufung braucht Solver-Support» – Textupdate würde die 3 goldenen | |
| Paritäts-Fixtures anfassen (dort eingebettet), bewusst verschoben. Learning- | |
| Loop-Notiz ins Brain (Weg-1-Entscheid + Messzahlen) steht aus. | |
| ### Kurator v3.1 Welle A – Objekt-Ebenen + Anzahl + Thinking (2026-07-14, ADR-0014) | |
| Vorgabe: Brain `ADR-0014-objekt-ebenen-und-kurator-kontrolle` + `Objekt-Ebenen-Modell`. | |
| Eiserne Regel: jede neue KI-Freiheit ↔ deterministische Kontrolle. | |
| - **Schemas (additiv):** `katalog-item` bekommt `objektEbene` (haupt|ergaenzung), | |
| `ankerTyp`, `maxAnzahl` (1..6, Default 1). `kurator-vertrag` v0.6: Response | |
| `hauptObjekte` + `ergaenzungen[{itemId,anzahl}]` (beide optional); `auswahl` | |
| bleibt Pflicht + expandiert (jede itemId genau einmal). Codegen TS+Python neu. | |
| - **Daten:** alle 127 Katalog-Items getaggt (bad 11 haupt/29 erg · wohnen 12/28 | |
| · kueche 38/9). **2 neue Esszimmerstuhl-Items** (wohnen, P2, ergaenzung, | |
| ankerTyp esstisch, maxAnzahl 6, `near:esstisch:1.3`) – das 3D-Kit `stuhl` + | |
| 2D-Symbol existierten bereits (wiederverwendet, kein Duplikat). Neu | |
| `data/kurator/anzahl-leitplanken.json` (Instanz-Korridor je Raumtyp/Fläche). | |
| - **Kurator:** Call A zweistufig (`hauptObjekte` zuerst, dann `ergaenzungen` mit | |
| Anker+maxAnzahl je Slot; Anzahl-Leitplanke aus Daten gerendert). Harte | |
| Kontrollen `_validiere_ebenen`: Auswahl⊆Kandidaten · P1-Pflicht in haupt · | |
| anzahl 1..maxAnzahl · Anker-Haupt-Pflicht · Platz-Budget über alle Instanzen. | |
| WEICH: Korridor (1 Repair, dann Marker `CURATOR_ANZAHL_AUSSERHALB`). Baseline | |
| zweiphasig (haupt → verankerte Ergänzungen, Stühle det. bis 4, Korridor-Cap). | |
| Thinking: `FP_KURATOR_REASONING` (→ reasoning_effort + reasoning_format hidden, | |
| nur bei Env) + `FP_KURATOR_TEMP`. Alte Kataloge ohne `objektEbene` brechen nicht. | |
| - **Solver/API:** `solve()`/`loese_mit_varianten()` neuer `mengen`-Param | |
| (itemId→anzahl → n Placements, eindeutige IDs, `near:esstisch` je Instanz, | |
| Determinismus unberührt). `/solve` optionales `mengen`; Baseline-Pfad leitet | |
| es aus `ergaenzungen` ab (`mengen_aus_antwort`, kein Vertrags-Extra-Feld). | |
| Client: `mengenAusKurator` → /solve. K-Varianten reichen mengen durch. | |
| - **Eval:** Überlebensrate zählt jetzt Instanzen; neue Spalte «Anker-Erfüllung». | |
| Baseline-Report neu (0.84 Überleben / Anker 100 % / 0 ❌ in 45). | |
| - **Bewusste Abweichungen / offen:** (1) Korridore ggü. ADR-Beispiel etwas höher | |
| gewählt, weil Stühle jetzt als Instanzen zählen. (2) Stuhl-Distanz 1.3 m (0.8 m | |
| aus der ADR-Skizze kollidiert mit dem 1.4×1.2-Tisch). (3) **Doppelzählung | |
| Esstisch↔Stühle:** die Esstisch-Items heissen «(inkl. 4 Stühlen)» und Preis/2D | |
| deuten Stühle an – jetzt kommen zusätzlich echte Stuhl-Instanzen. Bewusst NICHT | |
| angefasst (Naming/Preis/Rendering = grösserer Eingriff) → Bryan-Entscheid, ob | |
| Esstisch entkoppeln (umbenennen/entpreisen) oder Stühle nur als eigene Instanzen. | |
| - Gates grün (lint/typecheck/test/schema-check); NICHT committet (Orchestrator). | |
| ### Kurator-Pipeline v3 – 5 Wellen (2026-07-13, ADR-0013) | |
| Vorgabe: Brain `Kurator-Pipeline-v3-Konzept` + `ADR-0013-kurator-pipeline-v3`. | |
| Eiserne Regel: jede neue KI-Freiheit ↔ neue deterministische Kontrolle. | |
| - **W1 Kohärenz/Norm:** Call A liefert zuerst `konzept` (Vertrag v0.4), Konzept | |
| → B+C; Stilprofil neu in B, Auswahl neu in C; **Platz-Budget hart** in | |
| `_validiere` (Daumenregel wie Baseline, Unsatisfiability-Guard); | |
| **Norm-Kontext aus `data/rules/flaechen.json` pro Raum gerendert** | |
| (`norm_kontext_flaechen`: konkrete Nasswand-Indizes; Norm-Prosa aus der | |
| Prompt-.md entfernt – eine Quelle); neu `kueche-wand-spritzzone` (1.2 m, | |
| zu-verifizieren); Relations-Ziel-Validierung; Few-Shots; temp 0.3 + seed. | |
| - **W2 Daten:** alle 125 Katalog-Items volle 8 Achsen + `farbVarianten` | |
| (16 farbSlug-Enum im Katalog-Schema); 3 falsch getaggte Wohnen-Bilder + | |
| Eckschrank-Copy-Paste-Tags korrigiert. | |
| - **W3 Farben (KI+UI):** Vertrag v0.5 `farben` (itemId→farbSlug, Cross-File- | |
| `$ref` aufs Katalog-Enum – Codegen löst auf, kein Duplikat; 2 Testdateien | |
| auf Registry-Validierung umgestellt); `placement.farbe` (Plan additiv); | |
| eigener Validierungsschritt + Repair + Bereinigung (CURATOR_FARBEN_BEREINIGT); | |
| Client `farben.ts` (MANUELL>KI>Default, Default = erste farbVariante); | |
| Farb-Picker am selektierten Objekt + Flächen-Material-Picker; manuelle | |
| Flächen laufen durch `POST /flaechen/pruefen` (Python bleibt Norm-Quelle). | |
| Bewusst: Wand-Material gilt für alle Wände (keine Einzelwand-Selektion). | |
| - **W4 Eval:** `kurator_eval.py` = 3 Räume × 3 Profile × 5 Seeds; Metriken | |
| Überlebensrate/Auslastung/Palette-Treffer/Norm-Korrektur-Rate/Invariante; | |
| deterministischer Report `services/engines/reports/kurator_eval.json`. | |
| **Baseline-Messlatte: 0.867 / 0.886 / 0.855, 0 ❌ in 45 Läufen.** LLM-Lauf | |
| mit FP_KURATOR_URL wiederholen → muss Baseline schlagen (Gate). | |
| - **W5 K-Varianten:** `varianten.py` (K=3 Sub-Seeds deterministisch, bestes | |
| lexikografisch: platziert → −knapp → Relations-/Stil-Score → Index); | |
| `/solve` Flag `varianten` (Default false), App nutzt true (Bad/Wohnen; | |
| Küche ausgenommen). **Fund:** `constraintReport.softScore` ist bei | |
| bad/wohnen immer 0.0 (nur Küche patcht ergonomie) → knapp-Zähler ist das | |
| echte Soft-Signal. Offen: LLM-Eval-Lauf; «3 Vorschläge zeigen» (UI-Bonus); | |
| Einzelwand-Material-Selektion. | |
| ### CI-Fix + 2D-Wand-Semantik + 3D-Polish + Ladebildschirme (2026-07-13) | |
| - **CI grün:** Prettier-Format der Codegen-Ausgabe gefixt; Merke: Gates immer | |
| mit den ROOT-Kommandos fahren (`pnpm lint/typecheck/test` deckt alle | |
| Workspaces — apps/web allein reicht nicht). | |
| - **2D-Wand-Semantik korrigiert:** `floor.polygon` = INNENKANTE (nutzbare | |
| Raumfläche, Solver-Realität) → Wand wächst jetzt nach AUSSEN | |
| (`aussenPolygon`, Gehrung aussen); Boden = volles Polygon. | |
| - **3D-Rendering-Polish:** prozedurale Environment (Lightformer-Softbox, | |
| offline/CSP-fest), ACES-Tonemapping, ContactShadows; Chrom echt spiegelnd, | |
| Glas reflektierend. Kein Post-Processing (bewusst schlank). | |
| - **Ladebildschirme:** FP-Logo + Puls + Fortschrittsbalken an allen 4 | |
| Wartepunkten (v.a. Vorschlag/Kurator mit 3 KI-Calls); Piktogramme +20–30%. | |
| ### Kurator-Pipeline v2 + Licht + individuelle Flächen (2026-07-12) | |
| - **Kurator v2 – 3 KI-Calls** (`kurator.py`, Vertrag v0.2 additiv): A Auswahl · | |
| B **Anordnung** (je Item wandIndex/relationen/prioritaet; Solver setzt sie | |
| WEICH um – Ranking, nie NoFeasiblePlacement wegen Wandwunsch) · C **Flächen** | |
| (materialSlug-Enum 10 Slugs als einzige Quelle, bereich voll/halbhoch/sockel, | |
| hoeheM, akzent). Jeder Call validiert + 1 Repair + **Teil-Fallback** | |
| (B→relationalRules, C→None). Prompts: `data/prompts/kurator-{rolle,anordnung, | |
| flaechen}.md`. Norm-Filter/Parität unangetastet → 0 ❌ bleibt beweisbar. | |
| - **Licht & Lampen** (Dressing): Platzierungsart `an_decke` (Schema-Enum | |
| additiv); Pendelleuchte (wohnen+kueche, über Esstisch/Arbeitsfläche), | |
| Tischleuchte (wohnen) – leuchten echt (Emissive + pointLight). Offener Punkt: | |
| glTF-Upgrade einer Leuchte braucht das Punktlicht noch (additiv nachrüstbar). | |
| - **3D-Flächen-Rendering**: Kurator-`flaechen` sichtbar – je Wand eigenes | |
| Material (raumhoch/halbhoch/Sockel, Akzentwand), Boden aus Slug; ohne | |
| `flaechen` exakt bisheriges stilabgeleitetes Verhalten. Offen: Zusammenspiel | |
| Kurator-Flächen vs. manuelle Oberflächen-Variante definieren; 2D zeigt die | |
| Flächen (bewusst) noch nicht. | |
| - HF: /plan macht jetzt bis zu 3 Groq-Calls → wenige Sekunden länger; Fallback- | |
| Marker je Call in der Begründung (`CURATOR_ANORDNUNG_FALLBACK` etc.). | |
| - **Flächen-Normkontrolle (Nachtrag):** `data/rules/flaechen.json` (deklarativ, | |
| getrennt vom Paritäts-Set) prüft jeden KI-Flächen-Output hart: Bad-Boden | |
| wasserfest, Nasswände ≥2.0 m wasserfest (Heuristik: Fixpunkte ≤0.5 m), | |
| Küchenboden abwaschbar. Ablauf: Regeln VORAB im Prompt → pruefe_flaechen → | |
| 1 Norm-Repair (`…NORMREPAIR`) → deterministische Korrektur | |
| (`…NORMKORREKTUR`). Vokabular +tapete-hell/+taefer-holz (Wohnräume: Putz/ | |
| Tapete/Täfer statt Fliesen). Richtwerte «zu-verifizieren» (SIA 271/DIN 18534). | |
| ### Katalog-Ausbau: 13 neue Möbeltypen (2026-07-12) | |
| - **26 neue Katalog-Items** (je 2 Stil-Varianten, alle P3): Bad waeschekorb/ | |
| badhocker/abfalleimer/midischrank · Wohnen pouf/vitrine/konsolentisch/ | |
| barwagen/recamiere · Küche barhocker/servierwagen/vorratsschrank/ | |
| weinkuehlschrank (elektro). relationalRules nutzen die neue Grammatik | |
| (group:sitzgruppe, against-wall, near, corner). | |
| - **Voll dargestellt:** 13 volumetrische 3D-Kits (`moebel3d.tsx`) + 13 | |
| 2D-Plan-Symbole (`symbole2d.ts`) + MATERIAL_FARBE. | |
| - **Baseline-Fix** (`kurator.py`): Rest-Slots nach priorityClass P1→P2→P3 statt | |
| alphabetisch (latenter Bug: P3-Deko konnte Kernmöbeln die Flächen-Daumenregel | |
| aufbrauchen). Solvability-Regression: alle 10 Raum-Fixtures × Seeds 0–5 → | |
| 0 ❌, kein NoFeasiblePlacement (kleine Räume lassen P3 erwartungsgemäss weg). | |
| - **Offen:** weitere Wunschlisten-Typen (z.B. Dusch-WC, Raumteiler, Kücheninsel | |
| als eigenes Möbel) bei Bedarf nach demselben Muster. | |
| ### 3D-Volumetrie + Scene-Dressing für ALLE Raumtypen komplett (2026-07-09) | |
| - **Modelle** in höherer Volumetrie (rundbox/lathe/torus + Glas/Chrom) für | |
| **Bad, Wohnen UND Küche** – alle `moebel3d`-Bauer klar erkennbar, nicht mehr | |
| schematisch; Ampel-/Solver-Logik unberührt, bbox-Invariante bleibt. | |
| - **Scene-Dresser** für alle drei Raumtypen: `data/dressing/{bad,wohnen,kueche}.json` | |
| + Kits in `dressing3d-kits.ts`, generischer Loader/Engine, „Deko"-Toggle. | |
| Sparsam, „frisch gebaut". Verändert Plan/`constraintReport`/LV NICHT (0 ❌). | |
| - **Offen/Backlog:** komplett neue Möbeltypen aus Bryans Wunschliste (Recamiere, | |
| Weinkühler, Doppelwaschtisch, Barwagen …) = eigener Schritt (Katalog+Regeln+ | |
| Solver). Deko-Sonderfall „an Gerätegriff hängen" bräuchte neue Platzierungsart. | |
| Echtes Spiegel-Chrom bräuchte Environment-Map. Bryans echte `.glb` ersetzen | |
| Platzhalter über `apps/web/public/assets/dressing/`. | |
| ### 3D-Modelle Bad – höhere Volumetrie (2026-07-09) | |
| - **Primitiv-System erweitert** (`apps/web/src/moebel3d.tsx`): neben box/zyl/kugel | |
| neu **`rundbox`** (RoundedBox), **`lathe`** (Rotationskörper), **`torus`** – | |
| plus Material-Rollen **`glas`** (echt transparent) und **`chrom`** (metallisch). | |
| Ampel-Farblogik unangetastet (Rolle steuert nur Oberflächen-Physik). | |
| - **Alle Bad-Objekte + 5 Deko-Kits** auf klar erkennbare, plastische Volumetrie | |
| gehoben (WC/Lavabo/Dusche als Flagship, dann Fan-out: Badewanne, Spiegel, | |
| Badmöbel, Hochschrank, Regal, Handtuchstange/-heizung, Urinal, Bidet, | |
| Badteppich, Wandleuchte, Pflanze; Deko: Seifenspender, Zahnputzbecher, | |
| gefaltete Handtücher, Tray, Pflanze). `dressing3d.tsx`-Renderer auf die neuen | |
| Primitive erweitert. bbox-Invariante (`passtInBbox`/`clampTeil`) bleibt. | |
| - **Offen:** Fan-out Wohnen/Küche-Modelle im gleichen Detailgrad; echtes | |
| Spiegel-Chrom bräuchte eine Environment-Map (aktuell mattes Metall). | |
| ### Scene Dressing – Bad-Durchstich (2026-07-09) | |
| - **Neue visuelle Deko-Ebene**, client-seitig & getrennt vom Plan (Konzept: | |
| Brain `vault/50_Umsetzung/Scene-Dressing-Konzept.md`). `sceneDressing()` in | |
| `apps/web/src/dressing.ts` (Seed/Anker/Stil/Klasse-B-Kollision), gerendert als | |
| `DressingLayer3D` mit **„Deko"-Toggle** im 3D-Viewer. Verändert | |
| `placements`/`constraintReport` NICHT → 0 ❌ unberührt (Regressions-Test). | |
| - **Ästhetik „frisch gebaut, nicht bewohnt":** 5 sparsame Bad-Objekte | |
| (Seifenspender, Zahnputzbecher, Tray, gefaltete Handtücher, Pflanze). | |
| - **Asset-Drop-in:** `apps/web/public/assets/dressing/<gltfRef>.glb` (README dort); | |
| `assetStatus:"modeled"`+`gltfRef` → ersetzt Platzhalter automatisch. Bryan | |
| modelliert + lädt hoch, Rest macht die App. | |
| - Bugfix: Ecken-Footprint (rotiert) stach durch die Wand → inkrementell nach | |
| innen rücken. Details: `vault/10_Learnings/Learning-Scene-Dressing-Bad-Durchstich.md`. | |
| - **Offen:** Fan-out Wohnen/Küche; Klasse C (`an_wand`) in Engine da, ungenutzt. | |
| ### Zuletzt (2026-07-08, diese Session) | |
| - **UI-Feinschliff:** Schein nach innen stärker & überall, mehr CI-Grün, | |
| Piktogramme überall grösser (`fp.css`/`theme.ts`/`Piktogramm.tsx` + Ansichten). | |
| - **Solver/Kurator «Stufe 1»:** reiche Anordnungs-Grammatik (`near`, | |
| `against-wall`, `corner`, `facing:<typ>`, `opposite:<typ>`, `group:<id>`, | |
| `pair-with:<itemId>`) als weiche Constraints in P2/P3 + **stil-abhängige | |
| Platzierung** (v0: Achse `raumgefuehl` → Wand-Nähe, kleines Gewicht). Harter | |
| Norm-Filter/Interpreter/Parität unangetastet → 0 ❌ bleibt beweisbar. Neu: | |
| `services/engines/src/fp_engines/relationen.py`; `solve()` um `style_profile` | |
| additiv erweitert; `kurator-rolle.md` lehrt die Grammatik; `wohnen.json` demo. | |
| **Offen (Kalibrierung):** welche Stilachsen welchen Platzierungs-Bias steuern → | |
| Brain-Learning `vault/10_Learnings/Learning-Solver-Stufe1-Anordnung-Stil.md`. | |
| - **2D-Grundriss CAD-Look:** Wand-Aussenkante liegt auf der Raumlinie, Stärke | |
| wächst nach innen, Gehrungs-Ecken (`innenPolygon`/`wandBaender` in `plan2d.ts`); | |
| Öffnungen sitzen im Band. | |
| - **Objekt-Panel erweitert:** `ObjektInfoPanel.tsx` – Kosten + Wechsel-Alternativen | |
| (Thumbnail = 2D-Symbol, Preis, Masse, Stil-Match). Produktfotos je Item fehlen | |
| noch (Asset-Pipeline-Thema) → Thumbnail als Austauschpunkt vorbereitet. | |
| - **(läuft)** mehr Beispielräume (`packages/shared/fixtures/artefakte/raummodell.*`). | |
| ## Meilensteine | |
| | M | Inhalt | Status | | |
| |---|---|---| | |
| | **M0** Repo-Setup | Monorepo-Gerüst, Pins, Setup-Scripts, CI, CLAUDE.md/README | 🟢 fertig | | |
| | **M1** Verträge & Regel-Kern | JSON-Schemas (7 Verträge) + Codegen + Regel-Interpreter TS & Python + Paritätstest | 🟢 fertig | | |
| | **M2** Scan-Spike | Eval-Notebook, Messung R1–R3 (parallel, blockiert nichts) | 🟡 gestartet | | |
| | **M3** Durchstich BAD ⭐ | Sample-Bad → Baseline → Solver P1–P3 → Viewer → Report → Mengen/KV-PDF | 🟢 DoD erfüllt | | |
| | **M4** Auswertung voll + Kurator | LV, Bauzeitenplan, Offert-Paket, DXF · Kurator + Mini-Eval · Stil-UI | 🟢 DoD erfüllt | | |
| | **M5** Durchstich WOHNEN | Sample-Wohnzimmer → Regelsatz/Katalog/Bilder wohnen → Solver mit freier Boden-Platzierung → LV/Bauzeit/Dokumente | 🟢 fertig | | |
| | **M6** Durchstich KÜCHE | Formwahl + lineare Baugruppe + API + Frontend; Grossraum über Zone geplant | 🟢 DoD erfüllt | | |
| | **M7** Scan-Integration (+AR) | Adapter · Space-Deploy · scan-worker · Upload/`/scan` · Korrektur-Modus fertig; offen: R1-Gate auf Colab (Schritt 5) | 🟡 gestartet | | |
| ## Was konkret existiert | |
| - **M0:** pnpm-Workspace (Node 22 LTS, pnpm gepinnt) · `apps/web` | |
| (React+Vite+TS, r3f-Smoke-Szene) · `services/engines` (uv, Python 3.12, | |
| FastAPI-Skeleton mit `/health`) · `packages/shared` (Schemas/Fixtures/ | |
| TS-Quellcode) · `data/`-Ordnerstruktur mit READMEs · Setup-Scripts | |
| (`scripts/setup.ps1` für Windows = Bryans Dev-System, `setup.sh` für CI) · | |
| GitHub-Actions-CI (Lint → Typecheck → Tests → Schema-Check) · `LICENSES.md`. | |
| - **M1:** 9 JSON-Schemas in `packages/shared/schemas/` (7 Verträge laut | |
| Schema-Spezifikation + Projekt-Hülle + Taxonomie) · Codegen beidseitig | |
| (`pnpm codegen` → TS-Typen + pydantic-v2-Modelle, generiert & eingecheckt) · | |
| **Regel-Interpreter doppelt** (`packages/shared/src/rules/` ↔ | |
| `services/engines/src/fp_engines/rules/`, Semantik-Doku im rules-README) · | |
| Stammdaten `data/rules/basis.json` + `bad.json` (Norm-Regelsatz-v0, | |
| Richtwerte «zu-verifizieren») + `data/taxonomy/stilachsen.json` (8 Achsen, | |
| ADR-0006) · goldene Fixtures (Sample-Bad 3.0×2.4 m, Plan ok/verletzt) + | |
| **Paritätstest grün** in vitest UND pytest · `POST /validate` liefert den | |
| `constraintReport` über die API (inkl. Fehler-Envelope). | |
| - **M2 (gestartet 2026-06-11):** `notebooks/scan-spike/` mit Colab-Notebook | |
| `spike_eval.ipynb` (P0–P5-Skelett: Frames+Gate, Tiefe DA-V2-Small, | |
| Grounding DINO; P1 Layout / P4 Spiegel als TODO bis zum ersten GPU-Lauf) · | |
| `capture_check.py` (lokaler Vorabcheck) · **R1-Testvideos von Bryan** | |
| (Bad, normal + weitwinkel) in `testdata/r1/` · Vorabcheck-Report mit | |
| **Aufnahme-Guideline v1** in `reports/r1-vorabcheck.md` (Befund: Material | |
| zu unscharf/texturarm für die Kette → R1 nach Guideline wiederholen; | |
| Weitwinkel ~3× besser) · **Ground Truth R1 erfasst** (Bryan 2026-06-11): | |
| L-förmig, 1.8×1.0 m mit Versatz 0.3 m (Nische 0.7×0.8 m), 1.56 m² → | |
| `ground-truth/r1.json` + reales Fixture | |
| `packages/shared/fixtures/artefakte/raummodell.r1-wc.json` (6 Wände, | |
| erster nicht-rechteckiger Grundriss). Offen: Raumhöhe, Türbreite, | |
| Objektmasse, Neuaufnahme nach Guideline. | |
| - **M2 (2026-06-14, getesteter Metrik-Kern):** `notebooks/scan-spike/` | |
| `eval_metrics.py` – **GPU-freier, abhängigkeitsfreier** Mess-Kern | |
| (Wandlängen-Fehler Median/Max, Fläche %, Rechtwinkligkeit, Objekt-Recall) + | |
| `gate()` (Go/Anpassen/Pivot aus den Spike-Schwellen). **`test_eval_metrics.py` | |
| grün** (5 Tests gegen R1-Ground-Truth: perfekte Schätzung = 0 Fehler, 1.56 m²/ | |
| 5.6 m reproduziert, 5-cm-Störung erkannt, Eckenzahl-Mismatch gemeldet, Recall). | |
| Notebook nutzt jetzt diesen Kern und kennt die **Ecken-Antippen-Variante** | |
| (`corners/<raum>.json`, Wandgenauigkeit GPU-frei). Die schweren ML-Schritte | |
| (Depth Anything V2, Grounding DINO, SAM2) brauchen GPU+Modell-Download → | |
| laufen auf **Colab (T4)**, nicht in dieser Umgebung (kein GPU, HF 403). | |
| - **M3 (2026-06-11):** kompletter End-to-End-Klickpfad: Raum wählen | |
| (Sample-Bad ODER echtes R1-WC) → «Plan vorschlagen» (Baseline-Kurator + | |
| Feasibility-first-Solver P1–P3, `data/catalog/bad.json`) → 3D-Viewer | |
| (r3f: Hülle + Box-Platzhalter, Auswahl, Pfeiltasten/«r» verschieben/ | |
| rotieren, sperren) mit **Live-Norm-Ampel** (TS-Interpreter, dieselben | |
| Regel-JSONs) → «Variante würfeln» (Seed) → Auswertung (Mengen + KV mit | |
| Bandbreite + Next-Steps) → **KV-PDF** (ReportLab, CI-Look). | |
| **Solver-Invariante ⭐ als Property-Test grün** (12 Seeds × 2 Räume, 0 ❌; | |
| Plan validiert gegen Plan-Schema; Determinismus + Varianten getestet). | |
| API: /samples/rooms · /catalog/{rt} · /rules/{rt} · /solve · /validate · | |
| /evaluate · /export/kv-pdf (Fehler-Envelope, 422 NO_FEASIBLE_PLACEMENT). | |
| - **M4 (2026-06-11, DoD erfüllt):** | |
| - **Dokumente:** LV (deklarativer Positionskatalog `data/positions/bad.json`, | |
| Trigger→Template, rückverfolgbar via herkunft) · Bauzeitenplan | |
| (Sequenz-DAG `data/sequence/bad.json` mit Trocknungs-Wartekanten) · | |
| Offertanfrage-Paket je Gewerk (ohne Preise + Rückgabeblatt) · DXF- | |
| Grundriss (ezdxf) · alles als API-Exporte (+PDF) und getestet. | |
| - **Kurator-Port** (`fp_engines/kurator.py`): Vorfilter → Prompt | |
| (`data/prompts/kurator-rolle.md`) → Validierung → Repair → Fallback; | |
| Ports baseline | llm-api/llm-local (FP_KURATOR_URL). **Mini-Eval** | |
| `scripts/kurator_eval.py`; **Gate-Stand: Baseline aktiv** (kein LLM | |
| konfiguriert – mit FP_KURATOR_URL erneut messen). | |
| - **Stil-UI:** 8 Sample-Bilder (SVG-Platzhalter) + Bild-Katalog | |
| `data/images/bad.json` · Swipe-Overlay + Preset-Klick · Smart Spider | |
| (SVG-Radar, Achsen aus /taxonomy) · POST /style/profile · Klickpfad | |
| Stil → /curate → /solve im Viewer verdrahtet (Begründung wird gezeigt). | |
| - **Alle MVP-Dokumente generierbar (DoD):** KV · Mengen · LV · | |
| Bauzeitenplan · Offertanfrage-Paket · Gewerke-Übersicht · Einkaufsliste · | |
| 2D-Plan (PDF **und** DXF) · 3D-Export (glTF 2.0, handgebauter Writer, | |
| deckungsgleich mit dem Box-Viewer) · Next-Steps (im KV). Im Viewer als | |
| «📄 Dokumente…»-Menü. **Eval-Gate entschieden: Baseline aktiv** (LLM darf | |
| sie per FP_KURATOR_URL herausfordern). | |
| - **Nicht code-seitig (bei Bryan):** Mini-Eval mit echtem LLM messen + | |
| Mensch-Rating; echte Bad-Fotos taggen (ersetzt SVG-Platzhalter). | |
| - **M5 (2026-06-12, Durchstich WOHNEN):** | |
| - **Sample-Raum:** `raummodell.wohnen-sample` (Wohnzimmer 4.5×3.6 m, 16.2 m², | |
| 4 massive Wände, Tür 0.9 m an kurzer Wand, Fenster als Öffnung, KEINE | |
| Fixpunkte = Trockenraum). In `/samples/rooms` automatisch eingehängt. | |
| - **Stammdaten wohnen:** `data/rules/wohnen.json` (host-binding Regal/ | |
| Wandbild, soft object-distance Sofa↔Couchtisch, hard clearance Esstisch | |
| ≥1.0 m + Sideboard ≥0.6 m; circulation bleibt Basis-Stub) · | |
| `data/catalog/wohnen.json` (28 Items: sofa/esstisch/tvmoebel P1, | |
| couchtisch/regal/sideboard/stehleuchte P2, teppich/pflanze/wandbild/ | |
| beistelltisch P3 – je 2–3 Stil-Varianten, Präfix `bbbbbbbb-…`) · | |
| `data/images/wohnen.json` + 8 SVG-Platzhalter (2 Presets) · | |
| `data/positions/wohnen.json` (Trockenraum-Gewerke: Maler Wände+Decke, | |
| Bodenleger, Elektro Leuchten-Anschluss, Möbel-/Wandmontage) · | |
| `data/sequence/wohnen.json` (Ausräumen → Maler[Trocknung] → Boden → | |
| Elektro → Montage → Endreinigung). | |
| - **Solver – freie Boden-Platzierung:** neu `_floor_candidates` (0.25-m- | |
| Raster über der Bodenpolygon-BBox, Yaw 0/90/180/270, nur mount=boden) + | |
| `_candidates` (Wand- ⊕ Boden-Kandidaten). Vorfilter/Caps unverändert | |
| (P2 300 / P3 200), neu Cap P1-Backtracking 400. Determinismus gewahrt | |
| (Kandidatenreihenfolge deterministisch vor dem seed-shuffle). Solve | |
| wohnen ~0.05–0.11 s, Testsuite 109 grün in ~12 s. | |
| - **Beweis freie Platzierung:** Property-Test + dedizierter Test (Couchtisch | |
| steht frei vor dem Sofa, Wandabstand >0.3 m). Alle Dokument-Exporte | |
| (LV/Bauzeit/KV/DXF/glTF/Plan-PDF) laufen für wohnen E2E. | |
| - **M6 Phase A (2026-06-12, Durchstich KÜCHE – Stammdaten/Zonen):** | |
| - **Sample-Räume:** `raummodell.kueche-sample` (geschlossene Küche 3.2×2.6 m, | |
| 4 massive Wände, Tür 0.9 m, Fenster, Fixpunkte wasser/abwasser/starkstrom/ | |
| elektro/lueftung an der Anschluss-Längswand) · `raummodell.grossraum-sample` | |
| (eine Hülle 7.0×4.5 m, `zones[]` = Küche 2.8×4.5 + Wohnen; Zonengrenze als | |
| `wall.kind:"offen"` mitten im Raum; Fixpunkte mit `zone`-Referenz an der | |
| massiven Stirnwand der Küchenzone). Beide automatisch in `/samples/rooms`. | |
| - **Stammdaten küche:** `data/rules/kueche.json` (connection spüle→wasser/ | |
| abwasser, kochfeld→starkstrom, GS→wasser/abwasser, kühlschrank→elektro je | |
| hard, dunstabzug→lueftung soft · object-distance kochfeld↔spüle 0.3 hard · | |
| clearance ≥1.0 m je Haupttyp · host-binding Hängeschrank/Dunstabzug an Wand) | |
| · `data/catalog/kueche.json` (37 Items, `normProfileVariante` ch55/eu60 für | |
| Korpusse+Geräte, Präfix `cccccccc-…`) · `data/images/kueche.json` + 8 SVG | |
| (2 Presets) · `data/positions/kueche.json` (Gewerke Küchenbauer/Sanitär/ | |
| Elektro/Lüftung/Maler/Bodenleger) · `data/sequence/kueche.json` (Demontage → | |
| Roh-Installation → Maler[Trocknung] → Boden → Küchenmontage → | |
| Fein-Installation → Endreinigung). | |
| - **Zonen-Ableitung:** `services/engines/src/fp_engines/zonen.py` – | |
| `zone_room(room, zone_id)` projiziert eine Zone auf ein eigenständiges, | |
| schema-valides Teilraum-Raummodell (floor=Zonen-Polygon via Shoelace, Wände | |
| auf die Zonenkanten geclippt: deckende Hüllenwand erbt kind massiv/offen, | |
| sonst synthetisch `virtuell`; Öffnungen + Offset umgehängt; nur Fixpunkte | |
| der Zone). Solver/Interpreter laufen unverändert darauf (nutzen nur | |
| `kind=="massiv"`). v0-Annahme: achsparallele Rechteck-Zonen. | |
| - **Tests:** `test_zonen.py` (Teilraum schema-valide, floor=Zonen-Polygon, | |
| nur Küchen-Fixpunkte, virtuelle Kante bei fehlender Hüllenwand, offene | |
| Zonengrenze nicht montierbar, massive Stirnwand erhalten, reine Funktion) · | |
| Schema-Check + beide Schema-Tests (TS+Py) um die 3 neuen Raum-Fixtures und | |
| die Regelsätze wohnen/kueche erweitert. Alles grün (Python 122, vitest 19). | |
| - **M6 Phase B (2026-06-12, Durchstich KÜCHE – Formwahl + Baugruppe):** | |
| - **Küchen-Solver** `services/engines/src/fp_engines/kueche.py`: | |
| - `formwahl(room, style_profile, norm_profile)` – Wandzüge (massiv, | |
| achsparallel) + Anschlusswand (Wasser/Abwasser-Fixpunkte am nächsten); | |
| Kandidaten-Formen nach Tabelle 1a hart gefiltert (I ≥2.4 m + Querbreite | |
| ≥1.6; Galley 2 parallel + Breite ≥2.4; L ≥1.8+≥1.2; U 3 Züge + Innenbreite | |
| ≥1.2; Insel Breite ≥3.4 UND Boden-Fixpunkt); Soft-Score | |
| 0.35·stil+0.30·ergo+0.20·arbeitsplatte+0.15·stauraum mit Stil→Form- | |
| Heuristik (`_FORM_STILZIEL` auf den Stilachsen). Rückgabe Top-3 DISTINKTE | |
| Formen (Begründung, Score, anchorWallIds, Nutzlänge). | |
| - `solve_kueche(...)` – lineare Baugruppe: Raster ch55/eu60, Slots ab | |
| Wandzug-Anfang (türfreies Teilstück), AMK-Füllung **P1** Spüle@Wasser → | |
| GS direkt daneben → Kochfeld ≥1 Slot Abstand + nahe Starkstrom → Kühl an | |
| Zeilenende → Dunstabzug als Wand-Placement über dem Kochfeld; **P2** | |
| Hochschrank an Enden, Unterschränke in Restslots, Hängeschrank-Ebene (nicht | |
| über Kochfeld, nicht vor Fenster), Füllstücke (0.05/0.15) ans Zeilenende; | |
| **P3** 1–2 Deko über `_floor_candidates`. Jede Platzierung gegen | |
| `_zulaessig` (evaluate_rules) – Solver-Invariante **verletzt==0** gewahrt, | |
| sonst `NoFeasiblePlacement`. `plan.assemblies` = eine kuechenzeile-UUID je | |
| Zeile, `meta.normProfile`. Stil-Auswahl reuse über `kurator._cos`. | |
| Regel-Interpreter **nicht angefasst** (Paritäts-Gesetz). Solve-Zeiten: | |
| geschlossene Küche ~0.09–0.12 s, Grossraum-Zone ~0.13 s (< 2 s). | |
| - **API:** `POST /kueche/formen` (Top-3) · `/solve` erweitert um | |
| `normProfile`/`form`/`zoneId`, Routing über `_effektiver_raum` (zoneId ODER | |
| Auto-Küchenzone im Grossraum → `zone_room`), Küchen-Pfad → `solve_kueche`; | |
| Response liefert zusätzlich `room` (effektiv geplanter Teilraum) für Viewer + | |
| Live-Ampel. Alle `/export/*` laufen für Küchen-Pläne (placements-basiert). | |
| - **Frontend:** Küchen-Erkennung (roomType kueche ODER Küchen-Zone); | |
| Normprofil-Toggle CH/EU, Formwahl-Karten (Name, Begründung, Score-Balken), | |
| Grossraum-Hinweis «geplant wird die Zone Küche»; Viewer + Ampel nutzen den | |
| von `/solve` zurückgegebenen effektiven Raum; «Variante würfeln» behält | |
| Form + Normprofil. Bad/Wohnen-Flows unverändert. | |
| - **Tests:** `test_kueche.py` (Formwahl: Insel ausgeschlossen, Anschlusswand | |
| in jeder Top-Form, Stil verschiebt Ranking · Baugruppe Property-Test | |
| {kueche, grossraum+zone}×{ch,eu}×6 Seeds = 0 ❌ + schema-valide + | |
| deterministisch · GS neben Spüle · Kochfeld↔Spüle ≥0.6 m · eine Assembly-ID | |
| je Zeile · Rasterpositionen · ch55/eu60-Varianten · Grossraum-Placements in | |
| Zone · Seed-Variation) + Endpoint-Tests (/kueche/formen, /solve kueche, | |
| /solve Grossraum-Zone, 1 Export-Smoke). **Gesamt: Python 163 grün (~9 s), | |
| vitest 19 grün, mypy/ruff sauber, Schema-Check 11 Files.** | |
| - **M3-Politur (2026-06-13, Verkehrsweg-Freiraumanalyse `circulation`):** | |
| Der seit M3 offene `circulation`-Stub ist jetzt ein **echter Evaluator** in | |
| BEIDEN Interpretern (1:1, ganzzahlige Raster/Erosion-Analyse: Bodenraster → | |
| freie Zellen → Manhattan-Distanztransform → Bottleneck via Union-Find über | |
| fallende Clearance-Schwellen; Anker = Türmünder, bei 1 Tür zusätzlich der | |
| offenste Punkt). **Marge = 2·Bottleneck − minWidth** (0.05-m-Raster). Die | |
| Live-Ampel und alle Reports zeigen jetzt ein Verkehrsweg-Urteil. | |
| - **Bewusst SOFT in v0** (Norm-Regelsatz lässt hard/soft offen): informiert, | |
| ohne die Solver-Invariante zu berühren. Der Solver ist noch nicht | |
| verkehrsweg-optimierend → seine Pläne zeigen oft eine **soft** | |
| circulation-Verletzung (bad knapp, wohnen/kueche verletzt) – ehrlich. | |
| - **Performance:** circulation läuft NICHT im Solver-Hot-Path – `_zulaessig` | |
| wertet dort per `nur_hart=True` nur harte Regeln (verhaltensneutral, da | |
| soft nie in `hard.summary` zählt); voller Report inkl. circulation nur 1×. | |
| - **Parität:** neuer goldener Fall `flur-circulation-verletzt` (Trennwand | |
| pincht Korridor) lockt den Verletzungs-Pfad TS↔Python; +4 Unit-Tests. | |
| - **Gesamt grün:** Python 171 (~20 s, 0.05-Raster), vitest 23, Parität | |
| beidseitig, mypy/ruff/Prettier/Schema sauber. | |
| - **M3-Politur (2026-06-13, 2D-Grundriss-Ansicht):** Neuer **Aufriss von oben** | |
| als SVG (`apps/web/src/Viewer2D.tsx`) – Header-Umschalter 3D↔2D, **2D ist | |
| Default** (normgerecht beurteilbar). Wände (massiv/offen), Öffnungen mit | |
| **Türschwenk**, Footprints **nach der Norm-Ampel eingefärbt** (verletzt/knapp/ | |
| ok/gesperrt), wandmontierte Objekte gestrichelt+transparent, klick-auswählbar, | |
| Legende. Geometrie-Kern `plan2d.ts` nutzt **`footprint()` aus @fp/shared/rules** | |
| → exakt deckungsgleich mit Solver/Interpreter/3D-Viewer (kein zweites | |
| Rotations-Mathe). **Test-Infra für `apps/web` neu aufgesetzt** (vitest 4.1.8): | |
| `plan2d.test.ts` (Transform/Footprint/Normale) + `Viewer2D.test.tsx` | |
| (Render-Smoke via renderToStaticMarkup). apps/web 8 Tests grün, Build ok. | |
| - **Drag&Drop (2026-06-13):** Footprints im 2D-Grundriss per Maus/Touch | |
| ziehen (unverriegelte Items), Live-Ampel rechnet sofort mit. Pointer→Welt | |
| über die SVG-CTM + `toWorld` (Umkehrung von `toScreen`, Roundtrip-Test). | |
| Pfeiltasten/«r»/sperren bleiben. | |
| - **«austauschen» (2026-06-13):** Im Auswahl-Panel das Item gegen eine | |
| Katalog-Alternative tauschen (gleicher Funktionstyp + gleiche | |
| normProfileVariante → Küchenzeile bleibt konsistent); Pose bleibt, Ampel | |
| rechnet die neuen Masse sofort durch. | |
| - **Verkehrsweg-aware Solver, Schritt 1 (2026-06-14, Tür-Korridor-Freihaltung):** | |
| Optionale (P2/P3) Objekte werden NICHT mehr in einen Tür-Zugangsstreifen | |
| (Türbreite × 0.9 m ins Rauminnere) platziert – reiner Geometrie-Filter in | |
| `solver.py` (`_tuer_korridore`/`_blockiert_korridor`), billig, paritätsneutral | |
| (kein Interpreter/Goldens, kein Grid im Hot-Path), P1 unberührt. **Effekt: Bad | |
| von knapp/verletzt auf circulation ok (+60 cm)** – genau «Korridor in P2/P3 | |
| freihalten». Test `test_tuer_korridor_frei_von_optionalen`. Suite 172 grün. | |
| - **Verkehrsweg-aware Solver, Schritt 2 (2026-06-14, Metrik-Fix Tür-Anker):** | |
| Die in Schritt 1 gefundene «Metrik-Fragilität» war der **Tür-Anker am Türmund** | |
| (1.5 Zellen) – dadurch war faktisch die fixe **Türbreite** der Engpass statt | |
| des durch Möbel beeinflussbaren Innenraum-Korridors. **Fix (1:1 TS & Python): | |
| Anker ~minWidth/2 HINTER die Tür** (ins Korridor-Innere). Der grosse Refactor | |
| (Chamfer/Wände-als-Hindernis) war NICHT nötig. **Effekt (echter Evaluator): | |
| wohnen −70 → ok +10, kueche −70 → knapp 0, bad bleibt ok +60, flur (echte | |
| Sperre) bleibt verletzt −30.** Goldens neu (Parität bit-identisch), 172 pytest | |
| + 23 vitest grün. Die Metrik urteilt jetzt sinnvoll & verteidigbar. | |
| - **hard-Hochstufung jetzt plausibel, aber bewusst noch soft:** Solverpläne | |
| sind jetzt circulation ok/knapp (kein verletzt in der Praxis). Hürde für hard | |
| ist nicht mehr die Metrik, sondern die **Hot-Path-Performance** (circulation | |
| ist teuer ~0.4 s/Auswertung; als hard liefe sie je Kandidat). Der billige | |
| Tür-Korridor-Filter (Schritt 1) verhindert die häufigsten Verletzungen schon | |
| ohne Grid – ein finaler Hard-Check + Keep-out könnte reichen. Mit Bryan | |
| abstimmen, ob/wann hard. Details: Brain `Learning-Circulation-Metrik-Fragilitaet`. | |
| - **Küchen-Politur (2026-06-14, Arbeitsdreieck als echter Score):** Der bisher | |
| fix auf 0.0 gesetzte `softScore.ergonomie` wird für Küchenpläne mit dem | |
| **gemessenen AMK-Arbeitsdreieck** (Spüle–Kochfeld–Kühlschrank) befüllt: drei | |
| Seitenlängen + Summe → Trapez-Score [0,1] (Seite ideal 1.2–2.7 m, Summe | |
| 4–8 m = effizient). Berechnet **nach** der Platzierung (`arbeitsdreieck()` in | |
| `kueche.py`) – **ohne Regel-Interpreter, Schema oder Goldens zu berühren**: das | |
| Feld existierte bereits im Plan-Schema, der Solver post-prozessiert nur den | |
| fertigen `constraintReport` (Paritäts-Gesetz unberührt, Invariante bleibt 0 ❌). | |
| `/solve` liefert für Küchen zusätzlich ein `arbeitsdreieck`-Detail (Seiten/ | |
| Summe/Bewertung); der Viewer zeigt es als Panel (effizient/akzeptabel/beengt/ | |
| weitläufig). Ehrliche Werte (echter Evaluator): Sample-Küche 3.2×2.6 m = | |
| **beengt** (0.26, Summe 2.2 m), Grossraum-Zone = **akzeptabel** (0.67, Summe | |
| 3.3 m) – differenziert nach Raumgrösse. `formwahl` (Pre-Placement-Ranking) | |
| bleibt bewusst beim Proxy (das echte Dreieck ist vor der Platzierung unbekannt). | |
| Suite: 187 pytest + 23 vitest + 8 apps/web-vitest grün, mypy/ruff/Prettier/ | |
| Schema sauber. Brain: Learning-Arbeitsdreieck-Ergonomie-Score. | |
| - **M7 Schritt 1 (2026-07-05, Scan-Vertrags-Naht):** Neues Paket | |
| `fp_engines/scan/` – **SpatialLM-Layout-Parser** (`spatiallm.py`, z-up- | |
| Textformat Wall/Door/Window/Bbox) + **Adapter** (`adapter.py`: z-up→y-up | |
| **ohne Spiegelung** (x,y,z)→(x,z,−y), Normierung auf min=0, mm-Rundung, | |
| Wand-Ketten→Boden-Polygon mit 2-cm-Toleranz, Öffnungen mit hostWall/offset/ | |
| sill, Objekt-Boxen mit needsReview, **deterministische uuid5-IDs**, ehrlicher | |
| `AdapterFehler` bei offener Hülle) + **Scan-Bundle-Posen v0** (`poses.py`: | |
| kanonisches `poses.json` – Meter/Sekunden/Quaternion xyzw + gravity; App- | |
| Exporte werden am Rand dorthin konvertiert). **Kernbeweis:** handgebautes | |
| R1-WC-Layout (`fixtures/scan/r1-wc.layout.txt`) ergibt nach dem Adapter | |
| **exakt** das Ground-Truth-Polygon von `raummodell.r1-wc.json` (1.56 m², | |
| 6 Wände). 11 neue Tests (Schema+pydantic-valide, Determinismus, Segment- | |
| Reihenfolge egal, Posen-Validierung). **Suite 198 grün**, mypy/ruff/Schema ok. | |
| Kontext: Brain ADR-0012 (Scan-Kette fix: AR-App-Aufnahme → known-pose Fusion | |
| → SpatialLM), Code-Fahrplan in `M2-M7-Scan-Pipeline-Fahrplan`. | |
| **Offen im Adapter-Umfeld:** Yaw-Vorzeichen + Winkel/Scale-Konvention gegen | |
| echte SpatialLM-Ausgabe verifizieren (R1-Lauf, Schritt 5); Konverter | |
| App-Export→poses.json, sobald Voxelio-/ARCore-Exportformat fixiert ist. | |
| ## Nächste Schritte (für die nächste Session) | |
| 1. **Scan-Code-Fahrplan (Brain: `M2-M7-Scan-Pipeline-Fahrplan`, von Bryan | |
| freigegeben 2026-07):** ✅ Schritt 1 Adapter fertig (s.o.) · ✅ **Schritt 2 | |
| Space-Deploy-Gerüst (2026-07-05):** `fp_engines/space.py` (EIN Origin: | |
| `/api` → Engines, `/` → gebautes Frontend – exakt die Dev-Proxy-Semantik, | |
| kein CORS) + `Dockerfile` (multi-stage Node-Build → Python/uv, Port 7860, | |
| User 1000) + `.dockerignore` + `deploy-space.yml` (pusht bei jedem | |
| main-Push einen frischen Einzel-Commit OHNE notebooks/.git – die 50 MB | |
| R1-Videos überschreiten HFs 10-MB-Grenze – mit HF-Frontmatter-README in | |
| den Space `Bryan-HSLU/FP_POC`; Secret `HF_TOKEN` liegt in GitHub). | |
| 2 neue Tests (test_space.py), Suite 200 grün, Smoke lokal ok (API + | |
| index.html). **Erster echter Space-Build läuft mit diesem Push** – | |
| Ergebnis auf huggingface.co/spaces/Bryan-HSLU/FP_POC prüfen; Groq-Secrets | |
| (`FP_KURATOR_URL/_MODEL/_API_KEY`) später in den Space-Settings setzen. | |
| · ✅ **Schritt 3 scan-worker (2026-07-05):** neues Paket | |
| `services/scan-worker` (eigenes uv-Projekt, Base-Dep nur numpy; gradio als | |
| Extra `worker`; torch/spatiallm/open3d NIE als Deps – nur Colab, NC!). | |
| **CPU-getesteter Geometrie-Kern:** `kamera.py` (OpenCV-Pinhole-unproject, | |
| Quaternion→Pose) · `fusion.py` (Voxel-Zentroid-Downsampling, deterministisch) | |
| · `ausrichtung.py` (z-up aus gravity via Rodrigues + `boden_ransac`-Fallback, | |
| Boden→z=0) · `skalierung.py` (Wandhöhen-Fallback; Posen metrisch ⇒ Skala 1) | |
| · `ply.py` (binary PLY XYZ+RGB = SpatialLM-Contract) · `pipeline.py` | |
| (Keyframe-Sampling = Laufzeit-Hebel, TiefenProvider injizierbar) · | |
| `worker.py` (Gradio-App, GPU-Teile guarded) · `notebooks/colab_worker.ipynb` | |
| (Starter: PAT-Clone, EINE Setup-Zelle mit Drive-Wheel-Cache-TODO, share-URL | |
| → manuell als `FP_SCAN_WORKER_URL` in den Space = Zeiger v0). | |
| **Kamera-Konvention festgezurrt** (poses.py-Docstring: OpenCV-Pinhole, | |
| T_wc; ARKit-Konverter = R·diag(1,−1,−1)). CI erweitert (lint/typecheck/ | |
| test + sync). **Suite: 200 engines + 22 scan-worker = 222 grün.** | |
| · ✅ **Schritt 5 vorbereitet (2026-07-06):** `_lauf_spatiallm` **verdrahtet** – | |
| ruft das offizielle SpatialLM-`inference.py` als Subprozess | |
| (`-p scene.ply -o layout.txt -m manycore-research/SpatialLM1.1-Qwen-0.5B`), | |
| dessen `to_language_string()`-Ausgabe = unser `layout.txt`-Vertrag (robust | |
| gegen SpatialLM-API-Änderungen, kein Nachbau der Vorverarbeitung). Repo-Pfad | |
| + Modell über `FP_SPATIALLM_DIR`/`FP_SPATIALLM_MODELL`. Notebook-Setup-Zelle | |
| klont SpatialLM, installiert den 1.1-Stack (Poetry + `poe install-sonata`) | |
| mit **flash-attn-Wheel-Cache auf Drive**. **Korrektur:** SpatialLM 1.1 nutzt | |
| **Sonata + flash-attn** als Backbone, **nicht** TorchSparse (das war nur 1.0) | |
| → Wheel-Cache zielt jetzt auf flash-attn. | |
| **Offen (= der eigentliche R1-Gate, Schritt 5):** erster echter Colab-Lauf – | |
| torch/CUDA-Pins an die Session anpassen (SpatialLM will 2.4.1/CUDA 12.4), | |
| Genauigkeit gegen R1 messen, Intrinsics aus AR-Metadaten statt Schätzung. | |
| Braucht Bryans AR-App-Aufnahmen (R1/R2/R3). | |
| · ✅ **Schritt 4 Upload-UI + `/scan` (2026-07-05):** `POST /scan` | |
| (multipart) nimmt ein **vorberechnetes Scan-Bundle** (`layout.txt` einzeln | |
| ODER `.zip` mit `layout.txt`/`poses.json`) → `_bundle_dateien` entpackt → | |
| `parse_layout` + `layout_to_raummodell` → schema-valides Raummodell + | |
| `warnungen` (needsReview-Objekte, fehlende Anschlüsse). `poses.json` wird, | |
| falls vorhanden, validiert (Warnung statt Abbruch). Fehler-Envelope: | |
| SCAN_INVALID (roomType/Layout kaputt) · SCAN_NO_LAYOUT (nur Video → Live-Weg | |
| folgt Schritt 5). Frontend: Header-Bedienung «📷 Scan laden» + Raumtyp-Select | |
| → `api.scan` (FormData) → Raum wird in die Liste gehängt und über | |
| `raumWaehlen` in den bestehenden Klickpfad eingespeist. **v0 = Vorberechnen** | |
| (Demo-Regel); Live-Weiterleitung an `FP_SCAN_WORKER_URL` bleibt Schritt-5- | |
| TODO. 6 neue Endpoint-Tests + Live-Smoke (R1-Layout → 1.56 m², 6 Wände, | |
| 2 Öffnungen). Suite: **206 engines + 22 scan-worker grün**, Frontend | |
| lint/typecheck/build sauber. | |
| · ✅ **3D-Objekte statt Box-Platzhalter (2026-07-05, Bryan-Wunsch):** | |
| `moebel3d.tsx` – alle 31 Katalog-funktionsTypen als Primitiv-Kompositionen | |
| (2–7 Teile; WC/Lavabo/Dusche mit Glaswänden/Sofa/Kochfeld …), Fallback = | |
| alte Box. **bbox-Treue als Test-Invariante** (`passtInBbox` über 5 Grössen): | |
| kein Primitiv verlässt w×d×h, Gruppen-Transform + Klick 1:1 wie vorher → | |
| Norm-Ampel-Farben/Logik unangetastet. Hinweis: glTF-Export bleibt bewusst | |
| Boxen (Viewer detaillierter als Export – POC-ok). | |
| · ✅ **Manueller Raum-Editor (2026-07-05, Bryan-Wunsch, Brain: | |
| Raum-Editor-Manuell):** dritte Erstellungsvariante «✏️ Raum erstellen» – | |
| `raumbau.ts` (pure, getestet: Rechteck/L-Form-Polygone, Shoelace, Öffnungs- | |
| Validierung, R1-L-Form = 6 Wände/1.56 m²) + `RaumEditor.tsx` (SVG-Draufsicht, | |
| Werkzeuge Tür/Fenster/Anschluss per Wand-Klick, Pflicht-Anschluss-Hinweis je | |
| Raumtyp, nutzt `plan2d`-Transform) → schema-konformes Raummodell | |
| (source manuell, `geometryConfirmed true` → keine Unsicherheits-Marge), | |
| geht wie Scan/Sample durch `raumWaehlen` in den Klickpfad. | |
| apps/web: 30 Tests grün, tsc/eslint/prettier/build sauber. | |
| · ✅ **Corporate-Identity-Theme (2026-07-05, Brain: Corporate-Identity):** | |
| `theme.ts` mit den 5 CI-Tokens (Dunkelgrün #243D35 primär, Orange #D6914F | |
| CTA, Off-White #F0F7F2 Grund, Dunkelblau, Salbeigrau) · Header-Wortmarke | |
| FUTURE (weiss) / PLANNING (orange, gesperrt) + Claim «Meet. Match. Build.» | |
| · alle alten Marken-Hexwerte in App/Stil/RaumEditor/Viewer2D/Viewer3D auf | |
| Tokens · **Ampel-/Statusfarben bewusst unangetastet** (verletzt/knapp/ | |
| gesperrt + P2/P3; P1 war schon CI-Grün, jetzt via Token + Klarstellungs- | |
| Kommentar) · CI-Fonts NICHT eingebettet (Lizenz offen lt. Brain, Kommentar | |
| im Code) · index.html-Titel mit Claim. | |
| · ✅ **Wizard-UI + Pitch-Grafikstil + Logos + Möbel-Materialfarben | |
| (2026-07-06, Bryan-Vorgaben aus CD-Sheet/Flyer/App-Mockups – Brain: | |
| Corporate-Identity §Layout- & Grafiksprache):** | |
| - **Schritt-für-Schritt-Wizard** statt alles auf einem Screen: 1 Projekt | |
| (Sample-Karten/Scan/Raum erstellen) → 2 Stil → 3 Vorschlag (Küche: | |
| Formwahl) → 4 Anpassen (Viewer/Ampel/würfeln) → 5 Auswertung & Export. | |
| Auto-Weiter nach Raumwahl und Plan; Badge-Navigation; keine Funktion | |
| entfernt (Checkliste im Commit). | |
| - **Pitch-Grafikstil als Tokens:** harter Schlagschatten OHNE Blur | |
| (8px 8px 0) + weisser Innen-Schein auf allen Karten; orange Pill-Buttons; | |
| dünne Versal-Titel; heller Verlauf-Grund (dunkler Flyer-Look = Marketing). | |
| - **Echte Logos:** `public/FP-Logo-horizontal.png` im hellen Header + | |
| Signet als Favicon (aus Brain-assets). | |
| - **Möbel-Materialfarben:** MATERIAL_FARBE je funktionsTyp (Keramik/Holz/ | |
| Salbei/Edelstahl/Terracotta/Grün) – greift NUR bei Ampel-Status ok; | |
| verletzt/knapp/gesperrt behalten Statusfarben (Ampel dominiert). Dafür | |
| Viewer3D jetzt mit statusById → **Norm-Ampel auch in 3D sichtbar**. | |
| apps/web 32 Tests grün, alle Gates sauber. CI-Fonts weiter bewusst nicht | |
| eingebettet (Lizenz offen). Bryan liefert eigene Piktogramme nach → | |
| gleicher Stil (inner glow + harter Schatten). | |
| · ✅ **Schritt 6 Scan-Korrektur-Modus (2026-07-06, Brain: ADR-0003 / | |
| M2-M7-Scan-Pipeline-Fahrplan):** nutzergeführte Korrektur gescannter Räume | |
| (~8.5 cm Unsicherheit, kein LiDAR). Reine Geometrie `korrektur.ts` (getestet, | |
| DOM-frei): `ecken` (eindeutige Ecken via Endpunkt-Matching mit Epsilon – | |
| Wand-Array NICHT umlauf-sortiert), `verschiebeEcke` (angrenzende Wände | |
| wandern mit), `snappe` (Achsen-Snap auf Nachbar-x/z < 7 cm → rechtwinklig = | |
| das Anti-8.5-cm-Werkzeug, dann 5-cm-Raster), `kettePolygon` (Umlauf schliessen | |
| analog `_kette` in adapter.py, offene Hülle = Fehler-Objekt statt Wurf → | |
| UI blockt «Übernehmen»), `wendeAn` (Öffnungs-offset-Clamp, Fixpunkt behält | |
| relatives t auf der Wandachse, Fläche/Polygon neu, Objekte | |
| bestätigt→needsReview:false / entfernt raus, geometryConfirmed→true, IDs | |
| stabil, 2-Dezimal-Rundung). UI `ScanKorrektur.tsx` (Muster RaumEditor): | |
| SVG-Draufsicht, Ecken als ziehbare Griffe (Pointer = Maus **und** Touch/ | |
| Antippen, live-Snap + Längen), Werkzeuge Tür/Fenster/Anschluss per Wand-Klick, | |
| Scan-Objekte als gestrichelte rotierte bbox (needsReview orange), rechte | |
| Spalte mit Scan-Warnungen + fehlenden Pflicht-Anschlüssen + Öffnungs-/ | |
| Anschluss-/Objekt-Listen, «Übernehmen» gesperrt bei Öffnungs-Fehler oder | |
| offener Hülle. App.tsx: `scanLaden` öffnet jetzt das Korrektur-Modal (State | |
| `korrektur`) statt direkt zu wählen; «Übernehmen» → korrigierter Raum in den | |
| Klickpfad, «Abbrechen» → Scan unkorrigiert (geometryConfirmed bleibt false); | |
| «📐 Korrigieren»-Knopf im Schritt «Projekt» für gescannte Räume | |
| (`meta.captureMethod === "ar"`, defensiv). 16 neue Tests (korrektur.test.ts, | |
| inkl. Schema-Validierung des korrigierten Raums). apps/web **52 Tests grün**, | |
| tsc/eslint/prettier/build sauber. | |
| · ✅ **Bild-Katalog aus Bryans Metadaten + echte Fotos (2026-07-06):** | |
| `data/images/{bad,wohnen,kueche}.json` von je 8 Platzhaltern auf **je 30 real | |
| getaggte Bilder** (aus Bryans ZIP-Metadaten generiert; alle 8 Achsen + reiche | |
| `attributTags` + Palette + Lizenz; schema-sauber, ungültiger `roomType:`-Tag | |
| entfernt). **Die echten PNG-Fotos hat Bryan direkt auf `main` hochgeladen** | |
| (`data/images/{roomType}/…png`, 90 Dateien ~2 MB) – bildRef ↔ Datei matcht | |
| 1:1 (0 fehlend). `BildKachel` zeigt als Fallback die Farbpalette, falls ein | |
| Foto mal fehlt. Tests robust: Bildzahl-Assert dynamisch, Preset-Test skippt | |
| (Bryans Bilder alle istPreset=false). Bryans neue detailliertere `moebel3d`- | |
| Objekte via `clampTeil`-Sicherheitsnetz bbox-treu gehalten (Norm-Ampel). | |
| · ✅ **Möbel-3D-Varianten-Bibliothek (2026-07-06, Brain: | |
| Moebel-3D-Varianten-Bibliothek):** neues optionales Katalog-Feld | |
| `modell3d` (Schema additiv + Codegen TS/pydantic) → Viewer-Lookup | |
| `modell3d → funktionsTyp-Standard → Box` via `bausatzSchluessel()`. | |
| 5 erste Varianten-Bausätze (wc-wandhaengend, lavabo-aufsatz, lavabo-doppel, | |
| sofa-l, dusche-eck) + 7 Katalog-Items zugeordnet. **Stil entscheidet die | |
| Variante** (Kurator-Score über achsenTags – Beleg: Profil warm/natürlich → | |
| Wc Klassik + Naturstein-Aufsatzbecken; Profil kühl/modern → wandhängendes | |
| Design-WC + Eckdusche). Erweitern = Katalog-Item mit achsenTags (+ optional | |
| neuer Bausatz), 3-Schritte-Anleitung im moebel3d-Docstring. Suite: Web 36 + | |
| engines 205/1 skip + scan-worker 22 grün. | |
| · ✅ **3D-Viewer: Türen/Fenster + stilgetriebene Oberflächen (2026-07-07, | |
| Bryan-Wunsch):** Wände jetzt aus massiven Segment-Quadern statt einer Voll-Box | |
| → Türen/Fenster sind **echte Löcher** (Vollsegmente + Sturz + Brüstung, ohne | |
| CSG). `raum3d.ts` (rein, getestet: `wandSegmente`/`clipZone`/`oeffnungsPose`) + | |
| `raum3d.tsx` (`Tuer3D` mit ~20°-Türblatt/Griff, `Fenster3D` mit getöntem Glas + | |
| Sprosse, `WandMitOeffnungen`, prozedurale CanvasTexture für Boden/Wand). Boden- | |
| & Wandoptik werden aus dem Stilprofil abgeleitet (`oberflaechen.ts`, rein/ | |
| deterministisch, **kein Schema-Eingriff** – Konvention wie `MATERIAL_FARBE`): | |
| Bad→Fliesen+Wandsockel 1.2 m, Wohnen→Parkett, Küche→Stein/Fliesen je | |
| Materialität; Achsen temperatur/helligkeit/materialitaet/farbigkeit steuern die | |
| Farbe (HSL-Herleitung). Ohne Stilprofil bleibt die heutige neutrale Optik; | |
| Türen/Fenster erscheinen immer. Abweichung dokumentiert: Wand-Fliesenzone per | |
| Höhen-Clip (2 gestapelte Zonen) statt CSG-Zonenschnitt – robust & dependency- | |
| frei. Suite: **Web +21 (raum3d 12 · oberflaechen 9)**, Gates lint/typecheck/ | |
| test(73)/build grün. | |
| · ✅ **3D-Viewer v2: Ansichts-Presets, Orbit+Begehung, 3D-Drag/Rotate, | |
| Ebenen, waehlbare Oberflaechen (2026-07-07, Bryan):** `Viewer3D.tsx` | |
| generalüberholt. **Ansichts-Presets** (Perspektive/Draufsicht/Front/Seite) | |
| als Leiste über dem Canvas – Kamera-Posen aus der Raum-BBox skaliert | |
| (`presetKamera`), OrbitControls-Ziel = Raumzentrum, Draufsicht mit winzigem | |
| z-Versatz gegen die Gimbal-Entartung. **Zwei Begehungsmodi**: 🌀 Orbit (wie | |
| bisher) und 🚶 Begehung = First-Person (Augenhöhe 1.6 m, WASD/Pfeile gehen, | |
| Drag umsehen, Doppeltipp = Schritt vorwärts – Maus **und** Touch, ohne | |
| PointerLock; **keine** Wandkollision, POC-bewusst). **Direkte Objekt- | |
| Interaktion wie im 2D**: gewähltes Möbel per Drag auf der y=0-Ebene | |
| verschieben (Raycast → 5-cm-Raster, `verschiebeNach`-Constraints), Doppelklick | |
| = +90° (`rotiereNach`); Klick öffnet weiterhin die Elementkarte. Nur in | |
| Schritt 4 (`interaktiv`), Vorschau read-only. **Ebenen-Toggles** Ampel | |
| (Statusfarben an/aus) + Wände (ausblendbar für freie Sicht von aussen). | |
| **Oberflächen als wählbare Objekte**: Klick auf Boden/Wand (kein Möbel | |
| getroffen) wählt die Fläche → Elementkarte-Ersatz «Oberfläche» in | |
| `SchrittAnpassen.tsx` mit 3 vordefinierten Boden-/Wandvarianten je Raumtyp | |
| (`variantenFuer`); die Wahl überschreibt lokal die stilabgeleitete Spez | |
| (`wendeVariantenAn`, **rein visuell, kein Schema-/API-Eingriff**) und **bleibt | |
| beim «Variante würfeln» erhalten** (eigener State, `loesen` fasst ihn nicht | |
| an; nur Raumwechsel setzt zurück). Reine Logik in `viewer3d-logik.ts` | |
| (getestet: BBox, Preset-Posen, Begehungs-Schrittvektor, Blickrichtung). Im | |
| Begehungsmodus ruhen die Möbel-Pfeiltasten (`viewer3dModus` in App, Konflikt | |
| vermeiden). Bewusst weggelassen: Wandkollision (POC), 3D-Labels/Beschriftungs- | |
| Ebene (der 3D-Viewer trägt keine Text-Labels), PointerLock (Drag-Look ist | |
| robuster + mobiltauglich). Suite: **Web +19 (viewer3d-logik 13 · oberflaechen | |
| +6) → 120**, Gates lint/typecheck/test/build grün. | |
| · ✅ **Viewer-Feinschliff (2026-07-07, Bryan):** (1) **3D-Bearbeitungsmodus | |
| entfernt** – Möbel werden im 3D NICHT mehr verschoben/gedreht (Drag/Rotate + | |
| DragEbene raus); 3D = reine Ansicht/Begehung, Klick wählt weiterhin aus | |
| (Produktkarte) und Flächen/Oberflächen bleiben wählbar. Bearbeiten läuft nur | |
| noch im 2D-Grundriss. (2) **2D-Planlook bei Ampel-aus**: ist die Ampel-Ebene | |
| aus, zeichnen die Objektsymbole mit schwarzem Stift (`FARBE_PLAN`) und | |
| **weisser Schraffur-Füllung** (SVG-`<pattern>` 45°), Boden wird reinweiss – | |
| Architektenplan-Optik; Ampel an = farbig wie bisher. (3) **Zurück zur | |
| Titelseite**: «Zurück» auf Schritt 1 führt zurück ins Startmenü | |
| (`setPhase("menue")`, Label «← Zur Startseite»); AppRahmen um `zurueckLabel` | |
| erweitert. Gates grün, 120 Tests. | |
| · ✅ **Space-Deploy entschlackt + HF-Build-Fix (2026-07-07, Bryan):** Der HF- | |
| Space bekam bei jedem Deploy ~233 MB Bilder (wahrscheinliche Build-Fehler- | |
| Ursache). Fotos `data/images` von **PNG 941×1672 (1.7–2.8 MB)** → **JPEG q82, | |
| max 1400px** (197 MB → 19 MB), `bildRef` in bad/kueche/wohnen.json auf `.jpg` | |
| (StaticFiles serviert weiter). 43 ungenutzte Piktogramm-Originale (35 MB, teils | |
| Umlaut-Dateinamen) entfernt – die App lädt nur die 25 ASCII-Registry-Kopien. | |
| Deploy-Bilder gesamt **233 → 37 MB**. Engines 205 + Web 120 Tests grün. | |
| · ✅ **2D Layer-System v2 + Wand-/Fenster-Look (2026-07-07, Bryan):** Die vier | |
| «Ebenen»-Checkboxen ersetzt durch ein **Layer-Panel** (`layer2d.ts`): 8 | |
| **Darstellungs-Layer** (Wände/Öffnungen/Objekte/Bounding-Boxen/**Platzbedarf**/ | |
| Beschriftung/Masse/Ampel, Defaults: Boxen/Platzbedarf/Masse aus) + **Objekt- | |
| Layer** (jedes Möbel einzeln ein-/ausblendbar, CAD-artig, `versteckteObjekte`). | |
| **Platzbedarf-Layer**: Clearance-Zonen aus den `type:"clearance"`-Regeln | |
| (`clearanceRect` in plan2d) als Bewegungsflächen vor den Objekten (halbtransp. | |
| + gestrichelt, Tooltip = `hinweis`). **Fenster jetzt IN der Wandstärke** (echte | |
| Aussparung via `wandLuecken`, Glas über volle Wandstärke) statt Linie obenauf; | |
| **Wand-Look nach Referenzbild** (helle graue Füllung `#d3d3d3` + dünne Kante). | |
| `rules` von App an Viewer2D durchgereicht; Planlook (Ampel aus) bleibt. | |
| +11 Tests (plan2d clearance/wandLuecken, layer2d) → **Web 131**, Gates grün. | |
| · ✅ **UI-Redesign Etappe A: Designsystem + App-Rahmen (2026-07-07, | |
| Bryan-Konzept):** Fundament, das die 5 Schritt-Ansichten (Etappe B) nur noch | |
| konsumieren. **Designsystem** – globales Stylesheet `apps/web/src/fp.css` | |
| (in `main.tsx` importiert): `:root`-Farbrollen als CSS-Variablen | |
| (`--fp-primary/-dark/-accent/-muted/-soft/-background/-text`), Typografie-Vars | |
| (`--fp-font-display/-body`, Schriftdateien BEWUSST nicht eingebettet – Lizenz | |
| offen), vereinheitlichter Kartenstil `.fp-card` (+ `.fp-card-flach` | |
| flach, `.fp-card-aktiv` oranger Rand) mit hartem Schlagschatten OHNE Blur | |
| (7px 7px 0) + Innenschein, `.fp-button` (Press/Hover-Animation + `:active` | |
| scale), `.fp-schritt-neu` (einmalige Einblendung), `.fp-piktogramm-puls`, | |
| Responsive-Helfer `.fp-two-column`/`.fp-drei-karten` (@media 820px) + reduce- | |
| motion. **Hintergrund reinweiss** (index.html body + `--fp-background`); | |
| Off-White nur für Sekundärflächen. `theme.ts` **v2** – Rückwärtskompatibel | |
| (THEME/karte/pill/titel/schlagschatten/innerGlow behalten, zeigen auf die | |
| neuen Werte) + neu `FP_VAR` (CSS-Var-Strings) & `CSS` (Klassennamen-Konstanten). | |
| **App-Rahmen** `AppRahmen.tsx` (Header Logo/Projektname/Menü-Platzhalter · | |
| Fortschrittsweg · Inhalt zentriert max-width 1400 · Footer Zurück/Weiter). | |
| **Fortschrittsweg** `Fortschrittsweg.tsx` (Kreis+Label+Linie, aktiv=orange / | |
| erledigt=grün+✓ / gesperrt=salbei, mobil scrollbar) auf getesteter Logik | |
| `fortschritt.ts` (`schrittZustand`, 6 neue Tests). **Piktogramm-System** | |
| `Piktogramm.tsx` – 25 Inline-SVGs + **Drop-in** (`<img /piktogramme/<name>.png>` | |
| → onError-Fallback aufs SVG; Ordner `public/piktogramme/` mit README). **Lade- | |
| zustände** `Ladezustand.tsx` (pulsierendes Piktogramm + 4 Presets stil/ | |
| vorschlag/scan/dokumente – Etappe B verdrahtet). App.tsx: nur Rahmen- | |
| Präsentation ersetzt (weisser Grund, alter Header/Stepper/Footer → AppRahmen), | |
| Schritt-Logik/State unangetastet. **Web 79 Tests grün**, lint/typecheck/build | |
| sauber. | |
| · ✅ **UI-Redesign Etappe B: die 5 Ansichten (2026-07-07, Bryan-Konzept):** | |
| Schritt-Inhalte aus App.tsx in eigene Komponenten gezogen – | |
| `SchrittProjekt.tsx` («WAS MÖCHTEST DU PLANEN?», 3 Raumtyp-Karten mit | |
| Piktogramm + Auswahlzustand, darunter die 3 Wege Beispiel/Scan/Manuell; | |
| Raumtyp-Vorwahl steuert Scan-Raumtyp + filtert Beispiele) · | |
| `SchrittStil.tsx` (bildzentriertes Bewerten inline statt Overlay, | |
| Fortschritt «n von m», Like/Dislike/Überspringen mit Piktogrammen, | |
| Stilprofil-Karte mit Kurzworten/Spider/Top-3-%-Balken via fp-two-column, | |
| «Dein Stilprofil wird genauer.» alle 5 Bewertungen) · `SchrittVorschlag.tsx` | |
| (Zustand A Auslöser inkl. Küche-Normprofil/Formwahl; Zustand B «DEIN | |
| RAUMVORSCHLAG IST BEREIT» mit 2D-Vorschau, Stilbegründung, Haupt- | |
| materialien, Variante/Seed, einfacher Normstatus; EINE orange Hauptaktion | |
| «Ansehen & anpassen») · `SchrittAnpassen.tsx` (fp-two-column: Viewer links, | |
| Elementkarte rechts mit Normstatus passt/knapp/anpassen als Text+Piktogramm, | |
| Tausch-Alternativen, Sperren; Hilfe-Karte ohne Auswahl) · | |
| `SchrittAuswertung.tsx` («DEIN PROJEKT»-Zusammenfassung mit Kosten-Spanne/ | |
| Gewerke-Zahl/Status + Dokument-Karten-Raster mit Piktogrammen, bestehende | |
| api.dokument-Downloads). Ladezustände (stil/vorschlag/scan/dokumente) | |
| verdrahtet. Logik/State/API unverändert in App.tsx. Hinweis: Etappe-B-Agent | |
| brach am Session-Limit ab – Splice-Reparatur (verwaistes </div>, TS-Narrowing | |
| Stil-Bild, Prettier) durch die Hauptsession. **Web 79 Tests grün**, | |
| lint/typecheck/build sauber. | |
| · ✅ **Stil-Schritt v2: Live-Profil pro Swipe, Swipe-Animation, | |
| Konvergenz-Stopp, Bildhöhe fix (2026-07-07, Bryan):** Swipe-Bild auf | |
| `min(46vh,420px)` begrenzt (kein Scrollen) · Stil-Analyse steht jetzt IMMER | |
| neben dem Bild (fp-two-column immer aktiv; Neutralzustand «Bewerte Bilder, | |
| dein Profil entsteht live.») und aktualisiert LIVE nach jeder Bewertung | |
| (neuer Prop `onZwischenProfil` → `api.styleProfile`, nur Profil-State, kein | |
| Schrittwechsel/Ladezustand; Balken re-animieren via `fp-schritt-neu`) · | |
| Swipe-Animation (Like gleitet rechts + oranger Akzent, Dislike links + | |
| dunkel, ~220 ms, reduce-motion respektiert, Überspringen ohne Animation) · | |
| Konvergenz-Stopp: neues getestetes Modul `stilkonvergenz.ts` | |
| (`istStabil(verlauf, minBewertungen=8, delta=0.06, fenster=2)`) stoppt das | |
| Bewerten sobald das Profil stabil ist («Weiter mit diesem Profil» / «Weiter | |
| verfeinern»), statt alle 30 Bilder zu erzwingen. Kleine, dokumentierte | |
| Abweichung: finales `onProfil` springt nun automatisch zu Schritt 3 | |
| (bestätigtes Profil → «weiter»). **Web 86 Tests grün** (79 + 7 neue), | |
| lint/typecheck/build sauber. | |
| · ✅ **2D-Viewer v2: Wandstärke, Objektsymbole, Ebenen, Messen, Drag&Rotate, | |
| Produkt-Panel (2026-07-07, Bryan):** Der 2D-Grundriss zeigt jetzt echte | |
| **Objektsymbole** (Architekten-Draufsicht) statt nur beschrifteter Boxen – | |
| neues reines Modul `symbole2d.ts`: je funktionsTyp eine Signatur (WC | |
| Schüssel+Spülkasten, Lavabo-Becken, Dusche Quadrat+Diagonale+Abfluss, | |
| Badewanne, Sofa Sitz/Rücken/Armlehnen, Ess-/Couchtisch, Bett Kissen+Decke, | |
| Regal/Sideboard/TV Tiefenlinien, Kochfeld 4 Kreise, Spüle Becken+Armatur, | |
| Kühlschrank Türlinie, Leuchten Kreis+Strahlen, Pflanze, Teppich gestrichelt, | |
| Schränke, …) – **alle 31 Katalog-funktionsTypen abgedeckt** (Test), Fallback = | |
| bisherige Box. Die Symbole nutzen die vorhandene Footprint-Transformation | |
| (Position/Yaw/bbox über `rotateY`+`toScreen`, deckungsgleich mit `footprint()`) | |
| und die **Ampel-/Materialfarbe** als Strichfarbe. **Wände mit echter | |
| `thickness`** als gefüllte Polygone (`wallQuad`, Fallback 0.1 m); Türen mit | |
| Aufschlag-Viertelkreis + Fenster als Doppellinie bleiben. **Ebenen-Leiste** | |
| (Beschriftung/Boxen/Masse/Ampel, Default alles an ausser Boxen). | |
| **Messwerkzeug** «📏 Messen» (zwei Klicks → Linie + Distanz in m, Snap auf | |
| Wand-Ecken < 15 cm, Escape/Moduswechsel löscht). **Direkte Interaktion**: | |
| gewähltes Objekt per Pointer-Drag verschieben (5-cm-Raster, bestehende | |
| `verschiebeNach`-Constraints) + **Rotations-Griff** (Drag rastet 15°, | |
| Doppelklick +90° via neues `rotiereNach`); Live-Ampel läuft wie beim Keyboard | |
| weiter. **Detail-Panel (Schritt 4)** erweitert: funktionsTyp, Prioritätsklassen- | |
| Badge, Materialfarbe-Punkt + Masse; Tausch-Alternativen als kleine Produkt- | |
| karten (Name + Farbpunkt + Masse) statt Select. Schritt 3 (Vorschau) bleibt | |
| read-only (`interaktiv=false`): Symbole/Wandstärke automatisch, keine | |
| Editier-Interaktion. Neue reine, getestete Geometrie in `plan2d.ts` | |
| (`wallQuad`, `distanz`, `wandEcken`, `naechsteEcke`, `yawAusZeiger`, `rasten`). | |
| App.tsx nur minimal angefasst (Props + `rotiereNach`); Keyboard-Steuerung | |
| unangetastet. **Web 101 Tests grün** (86 + 15 neue), lint/typecheck/build | |
| sauber. Bewusst weggelassen: typübergreifender Tausch (wie schon dokumentiert), | |
| Symbole als Fill (bewusst nur Strichkontur = Architektenlook, Ampel bleibt als | |
| Tint-Füllung + Rahmen lesbar). | |
| **Als Nächstes:** Presets optional kuratieren · ⚠️ 90 PNG (~180 MB) blähen | |
| Repo + Space-Deploy – ggf. Bildgrösse reduzieren/auslagern · | |
| Schritt 5 E2E gegen R1 auf Colab (braucht AR-App-Aufnahmen) · | |
| Bryans Piktogramme. Alt-Punkte unverändert offen: circulation | |
| auf `hard` hochstufen (Hot-Path-Performance, mit Bryan abstimmen); Küche | |
| post-POC: mehr Slot-Breiten (30/45/90), triangle-aware Slot-Optimierung. | |
| 2. **M2 Scan-Spike weiterführen:** Metrik-Kern + Ecken-Antippen-Pfad stehen & | |
| sind getestet (2026-06-14). **Offen – Bryan:** R1-Restmasse (Raumhöhe, | |
| Türbreite, Objektmasse) + Neuaufnahme nach Guideline + R2/R3; dann | |
| `spike_eval.ipynb` einmal auf **Colab (T4)** laufen lassen (GPU-Schritte gehen | |
| hier nicht). **Offen – Code:** P1 automatischer Layout-Fit (GPU) + P4 | |
| Spiegel/Glas-Maskierung; danach Gate-Entscheid → Learning ins Brain. | |
| 3. Goldens bewusst aktualisieren: `uv run python scripts/update_goldens.py` | |
| (aus `services/engines/`), nur zusammen mit Interpreter-Änderung committen. | |
| ## Bewusste Abweichungen / Engineering-Entscheide | |
| | Entscheid | Grund | Wo dokumentiert | | |
| |---|---|---| | |
| | Eigener Code proprietär (kein LICENSE-File) | Entscheid Bryan 2026-06-11 | README, CLAUDE.md | | |
| | `circulation` v0 **soft** statt hard (Norm-Regelsatz nennt hard) | Norm-Regelsatz lässt unter «Offene Fragen» hard/soft explizit offen; soft informiert ohne die Solver-Invariante zu brechen (Solver ist noch nicht verkehrsweg-aware). Hochstufung auf hard = bewusster Folgeschritt mit Solver-Support | rules/basis.json, rules-README, Learning | | |
| | `circulation`-Marge grob/konservativ (0.05-m-Raster, bbox-Blocker, Türmund-Pessimismus) | v0-Freiraumanalyse: ganzzahlig (paritätssicher), Manhattan-Distanztransform, achsparallele Bounding-Box je bodenstehendem Objekt; Türbreite cappt den Bottleneck. Tuning (Euklid, feiner, türbewusst) post-POC | interpreter.py/.ts (Docstring), Learning | | |
| | Kollision prüft vertikale Überlappung (Höhenintervalle) | Spiegel ÜBER Lavabo ist keine Kollision – nötig für P2-Wandobjekte | Interpreter beidseitig, Learning im Brain | | |
| | Editor: Drag&Drop nur im 2D-Grundriss (3D bleibt Pfeiltasten) | 2D hat eine eindeutige Screen→Welt-Umkehrung (toWorld); 3D-Drag bräuchte Raycasting – später | Viewer2D, plan2d.ts | | |
| | «austauschen» bietet nur gleichen Funktionstyp + gleiche normProfileVariante | hält Plan/Küchenzeile konsistent; typübergreifender Tausch (z.B. Dusche→Badewanne) wäre eine eigene Re-Solve-Logik – post-POC | App.tsx (alternativen) | | |
| | `door-swing` v0 als Rechteck (Breite×Radius) statt Viertelkreis | identische, einfache Geometrie in TS & Python; konservative Näherung | Code-Kommentar + Fixtures | | |
| | M5: Bett-Regel «Zugang ≥1 Längsseite» nicht umgesetzt → Wohnzimmer-Fokus | Mit den aktuellen Regel-Typen (clearance/object-distance/host-binding) nicht ausdrückbar; Schlafen-Spezifika (Bett, beidseitiger Zugang) auf später verschoben statt Interpreter zu ändern (Paritäts-Gesetz) | STATUS, wohnen.json | | |
| | M5: Esstisch inkl. Stühlen als EIN Footprint | POC-Vereinfachung – Stuhl-Einzelplatzierung wäre eigene Solver-Stufe; Footprint deckt Tisch + ausgezogene Stühle ab, clearance-Regel zusätzlich ≥1.0 m | catalog/wohnen.json (Item-Beschreibung) | | |
| | M5: relationalRules-Distanzen wohnen als Zentrum-zu-Zentrum kalibriert (z.B. `near:sofa:1.3` statt 0.45) | Der Solver-Relationsfilter misst Zentrumsabstand; bei grossen Ankern (Sofa 2.1×0.95) wäre der ergonomische Kantenabstand 0.40–0.45 m als Zentrumswert kollidierend. Die ergonomische Norm bleibt als **soft** object-distance-Regel (Kantenmass 0.40 m) erhalten | catalog/wohnen.json, rules/wohnen.json | | |
| | M6-A: Grossraum-Sample mit echter `wall.kind:"offen"`-Kante mitten im Raum (statt nur Zonen-Polygone) | Code verträgt innenliegende Segmente problemlos (kein Hüllen-Closure-Validator; Solver/Interpreter filtern auf `kind=="massiv"`). Die offene Kante modelliert die reale offene Zonengrenze explizit; `zone_room` clippt sie auf die Zonenkante und erhält `kind:"offen"`. Die synthetische `virtuell`-Erzeugung greift nur, wenn KEINE Hüllenwand die Zonenkante deckt (separat getestet) | grossraum-sample, zonen.py, test_zonen.py | | |
| | M6-A: GS↔Spüle-«maxDist»-Regel NICHT als `object-distance` umgesetzt | Der Regel-Interpreter kennt bei `object-distance` nur `minDist` (kein maxDist). «Geschirrspüler direkt neben Spüle» ist Baugruppen-/Slot-Logik → kommt in Phase B; Interpreter wird (Paritäts-Gesetz) nicht erweitert. Nähe bleibt v0 über `relationalRules:["near:spuele:0.9"]` am Katalog-Item | rules/kueche.json, catalog/kueche.json, STATUS | | |
| | M6-A: clearance je Küchen-Haupttyp (spuele/kochfeld/geschirrspueler/unterschrank) statt einer Sammelregel | `appliesTo` matcht auf `funktionsTyp`; eine Regel pro Typ ist die mit den bestehenden Regel-Typen ausdrückbare Form des «Gang vor Zeile ≥ 1.0 m». Echte Zeilen-/Gang-Geometrie (circulation) kommt mit Phase B | rules/kueche.json | | |
| | M6-B: Ecke bei L/U → **Eckschrank** (Politur 2026-06-14, behebt den früheren Totraum) | grid×grid-Eckquadrat am Wand-Stoss wird aus den Schenkel-Slots reserviert, ein Eckschrank (Karussell, ch55/eu60) gesetzt – VOR den Füllstücken, damit sie ihm ausweichen. Additiv (nur wenn zulässig), Invariante bleibt 0 ❌. L = 1 Ecke, U = 2 | kueche.py (`_eck_zonen`/`_platziere_eckschraenke`), catalog/kueche.json, test_kueche.py | | |
| | M6-B: Fenster blockieren Unterschränke NICHT, nur die Hängeschrank-Ebene meidet Fenster | Brüstungsfenster (sill ≥ 0.9 m) erlauben darunter eine Arbeitsfläche/Unterschrank; nur Hängeschränke dürfen nicht vor ein Fenster. Türen blockieren dagegen die ganze Zeile (Nutzlänge = türfreies Teilstück) | kueche.py (`_fuelle_haengeschraenke`, `_freies_teilstueck_intervall`) | | |
| | M6-B: Hängeschrank-Heuristik = Ebene über allen Unterschränken ausser Kochfeld | Über dem Kochfeld hängt der Dunstabzug; sonst wird jede freie Wandposition mit Hängeschrank belegt (vertikal getrennt von den Korpussen → keine Kollision dank Höhenintervall-Prüfung des Interpreters). Einfach + deckt den Stauraum-Score | kueche.py (`_fuelle_haengeschraenke`) | | |
| | M6-B: GS-«direkt neben Spüle» als Slot-Nachbarschaft (nicht als Regel) | Der Interpreter kennt kein `maxDist` bei object-distance (M6-A-Entscheid); die Baugruppe setzt den GS deterministisch in den Nachbarslot der Spüle. Damit ist die Forderung konstruktiv erfüllt, ohne den Interpreter zu ändern | kueche.py (`_platziere_geschirrspueler`) | | |
| | M6-B (Review-Fix): P1-Geräte sind Pflicht – fehlt Spüle/GS/Kochfeld/Kühlschrank → 422 NO_FEASIBLE_PLACEMENT (nur Dunstabzug best-effort, lueftung-connection ist soft) | Vorher entstand still ein Rumpf-Plan ohne Kühlschrank (constraintReport 0 ❌, aber fachlich unvollständig) – ehrliches Scheitern statt stiller Degradation | kueche.py (solve_kueche) | | |
| | M6-B (Review-Fix): Solver-Vorfilter toleriert Berührung (Überlappung ≤ 0.05 cm = halbe Rundungsquante) | Exakt anliegende Korpusse (Küchenzeile!) erzeugen Float-Krümel-Überlappungen ~1e-16; der Vorfilter war strenger als das Interpreter-Urteil (0.1-cm-Rundung) und verwarf gültige Slots – deshalb fehlte der Kühlschrank | solver.py (_schnell_unzulaessig, _BERUEHRUNGS_EPS) | | |
| | M6-B: `formwahl`-Score nutzt für Ergonomie weiterhin einen Proxy (echtes Dreieck erst NACH der Platzierung) | Formwahl läuft VOR der Platzierung → das echte Arbeitsdreieck ist dort unbekannt; der Proxy (kompakte I-Zeile, L/U-Bonus) ist richtungsrichtig. Das **gemessene** Dreieck füllt seit 2026-06-14 `softScore.ergonomie` des fertigen Plans (AMK-Trapez-Score, server-berechnet) – kein Eingriff in Interpreter/Schema/Goldens | kueche.py (`formwahl` Proxy · `arbeitsdreieck` Messung) | | |
| | M6-B: /solve-Response um `room` (effektiver Raum) erweitert | Response ist kein Schema-Vertrag (Plan-Schema bleibt unberührt). Der Grossraum-Fall braucht den abgeleiteten Teilraum für Viewer + Live-Ampel; additiv am pydantic-Response-Modell | api.py (`/solve`), App.tsx (`planRoom`) | | |
| ## Offene Fragen an Bryan | |
| - AR-Vorschau (Stretch) bestätigen → `vault/50_Umsetzung/AR-Vorschau-Konzept.md`. | |
| - Erste Katalog-Quelle für echte Items/Preise (POC-Fallback: Sample-Daten). | |
| - Spike-Testräume R1–R3 aufnehmen (sobald Eval-Notebook steht). | |