# Phase 14: Audit- und Implementierungsplan für die Revit-CSV-Anbindung ## Status Phase 14.0 ist abgeschlossen und freigegeben. Dieses Dokument beschreibt den gegen den aktuellen Code geprüften Zielzuschnitt. Phase 14.1 ist abgeschlossen. Phase 14.2 hat mit den externen Domänenverträgen, Identitätsregeln und dem additiven Persistenzschema begonnen; eine bestätigte Importübernahme existiert noch nicht. Fachliche Quelle bleibt [Revit-CSV-Integration – Anforderungen und Implementierungsanweisung](revit-csv-integration-requirements.md). Dieses Dokument konkretisiert dafür Namen, Modulgrenzen, Persistenz und die Reihenfolge kleiner Arbeitspakete. ## Ergebnis des Bestandsaudits ### Beibehalten - Das Circuit-First-Modell bleibt unverändert: Ein `Circuit` besitzt null bis viele `CircuitDeviceRow`-Datensätze. - `ProjectDevice` bleibt die kanonische projektweite Vorlage. Ein Import darf diese Datensätze weder erzeugen noch ändern, solange der Nutzer dies nicht ausdrücklich bestätigt. - `CircuitDeviceRow.linkedProjectDeviceId` bleibt die optionale Verbindung zwischen einer Gerätezeile und genau einer Projektgerätevorlage. - Die bestehenden getrennten Drag-and-drop-Pfade für Projektgeräte, Gerätezeilen und Stromkreise bleiben bestehen. Externe Objekte erhalten einen vierten, fachlich eigenen Pfad. - Alle bestätigten Änderungen verwenden typisierte Commands mit `expectedRevision`, vollständiger Gegenrichtung und `project-command-transaction.persistence.ts` als gemeinsamer Transaktionsgrenze. - Snapshot-Erfassung, Restore und Projektduplikat bleiben explizite Adapter mit fester Fremdschlüsselreihenfolge und UUID-Remapping. - SQLite und die heutige Server-Komposition bleiben der einzige unterstützte Laufzeitadapter. ### Erweitern oder gezielt refaktorieren - `ProjectStateSnapshot` und der portable Projekttransfer werden additiv um den bestätigten externen Projektzustand erweitert. Bereits veröffentlichte Snapshot-Versionen werden nicht verändert. - Der Command-Dispatcher erhält schmale Stores für externe Konfiguration, Importübernahme, Objektplanung und Row-Zuordnung. Controller erhalten keine konkreten SQLite-Abhängigkeiten. - Der Stromkreislisteneditor erhält später einen separaten Drawer für unzugeordnete externe Objekte. Die bestehende Projektgeräteauswahl wird nicht dafür zweckentfremdet. - Vor der ersten externen Row-Zuordnung wird die Mengenhoheit einer `CircuitDeviceRow` explizit gemacht; Details stehen unter „Mengenmodell“. ### Hinzufügen - verlustarmer CSV-Transportadapter außerhalb von React und Circuit-Domain; - projektweite, versionierte Revit-CSV-Konfiguration; - eine zunächst implizite externe Modellquelle je Projekt; - Importbatches einschließlich Originaltransport und akzeptiertem Konfigurationsstand; - persistente externe Objekte mit `IfcGUID`, getrennten Quell- und Planungswerten und einzelnem Lebenszyklus; - Quellraum-Mappings auf interne Räume und Standardverteilungen; - explizite Verknüpfungen zu `ProjectDevice`, `CircuitDeviceRow` und optionaler abweichender Verteilung; - Vorschau-, Konflikt- und Exportprojektionen als reine Anwendungsservices; - fokussierte Parser-, Command-, Transaktions-, Snapshot-, Transfer- und End-to-End-Tests. ### Entfernen Es existiert kein unterstützter Revit-Laufzeitpfad. Deshalb wird in Phase 14 kein bestehender Fachpfad entfernt und keine Legacy-Kompatibilität eingeführt. ## Vorgeschlagenes Domänenmodell Die Namen sind ab Phase 14.1 verbindliche Arbeitsnamen. Tabellen verwenden die jeweilige englische Pluralform in `snake_case`. ### `ExternalModelSource` - stabile interne UUID; - `projectId`; - technischer Name und Quelltyp `revit_csv`; - der zuletzt bestätigte Importbatch wird aus der geordneten Batchhistorie abgeleitet und nicht als redundanter Zeiger gespeichert. In der ersten Ausbaustufe wird genau eine Quelle je Projekt automatisch angelegt. Es gibt bewusst keine sichtbare Mehrquellenverwaltung. Die Eindeutigkeit eines externen Objekts ist trotzdem von Anfang an `(sourceId, ifcGuid)`. ### `ExternalCsvConfiguration` - stabile UUID und `projectId` mit genau einer aktiven Konfiguration; - Konfigurationsschema-Version; - CSV-Dialekt: Encoding, BOM, Trennzeichen, Zeilenende, Quote-Zeichen, Dezimalformat und Kopfzeilenerkennung; - exakte Spaltenzuordnung; - geordnete, exakte Familie-und-Typ-Regeln; - monotoner Konfigurationsstand. Eine Änderung ersetzt den vollständigen erwarteten Konfigurationssnapshot in einem Command. Jeder bestätigte Importbatch speichert zusätzlich den dabei verwendeten Konfigurationssnapshot. Damit bleiben ältere Importe erklärbar, ohne eine zweite veränderbare Historientabelle einzuführen. ### `ExternalImportBatch` - stabile UUID, `projectId`, `sourceId`, Importart und Zeitstempel; - Dateiname, SHA-256 und zugehörige Projektrevision; - verwendete monotone Konfigurationsversion und vollständiger Konfigurationssnapshot; - Originaldatei als Bytes; - verlustarme logische Zellmatrix mit Zeilenklassen und Dialektmetadaten. Die Kombination aus Originalbytes und Matrix ist bewusst gewählt: Die Bytes belegen den unveränderten Eingang, die Matrix erlaubt einen gezielten Rückexport einzelner gemappter Objektzellen, ohne unbekannte Spalten, Titelzeilen, Leerzeilen oder Summenzeilen neu zu interpretieren. ### `ExternalRoomMapping` - stabile UUID, `sourceId` und normalisierter Quellraumschlüssel; - Quellgeschoss-, Raumnummer- und Raumname-Snapshot; - optionales `roomId`; - optionale `defaultDistributionBoardId`. Das Mapping bleibt Teil der optionalen externen Integration. Dadurch erhält das allgemeine Raummodell keine Revit-spezifische Pflichtbeziehung. ### `ExternalModelObject` - stabile interne UUID, `projectId`, `sourceId` und unveränderte `ifcGuid`; - letzter gesehener und letzter akzeptierter Importbatch; - akzeptierte Quellwerte getrennt als strukturierter Snapshot; - lokale Planungswerte für Anzeigename, Kategorie, Anschlussart, wirksame Menge, Leistung je Einheit, Gleichzeitigkeitsfaktor, `cosPhi`, Kostengruppe und Bemerkung; - explizite Override-Metadaten; - optionales `externalRoomMappingId`; - optionale abweichende `distributionBoardId`; - optionales `linkedProjectDeviceId`; - optionales `circuitDeviceRowId`; - Anwesenheitsstatus für bestätigte fehlende Objekte. Die n:1-Beziehung entsteht durch `circuitDeviceRowId` am Einzelobjekt: Viele einzeln nachverfolgbare IFC-Objekte dürfen genau einer Gerätezeile zugeordnet sein. Eine Mehrfachsteckdose bleibt ein einzelnes Objekt und trägt ihre wirksame Menge größer eins. Konflikte werden soweit möglich aus akzeptiertem Quellstand, neuem Vorschaustand und lokalen Overrides berechnet. Nur ein vom Nutzer bestätigter Anwesenheits- oder Planungszustand wird persistiert. ## Mengenmodell der Gerätezeile Die heutige `CircuitDeviceRow.quantity` unterscheidet nicht zwischen manueller Menge und verknüpften IFC-Objekten. Ohne Erweiterung könnte das Lösen eines Objekts manuelle Mengen löschen oder doppelt zählen. Vor Phase 14.3 wird deshalb `manualQuantity` ergänzt: ```text quantity = manualQuantity + Summe(effectiveQuantity aller verknüpften ExternalModelObjects) ``` - Bei der Migration erhält jede bestehende Row `manualQuantity = quantity`; ihr Ergebnis bleibt unverändert. - Eine ausschließlich aus externen Objekten erstellte Row startet mit `manualQuantity = 0`. - `quantity` bleibt zunächst der materialisierte Gesamtwert für bestehende Berechnungen, Filter und Exporte und wird im selben Command aktualisiert. - Ein externes Objekt wird nie geteilt und kann höchstens einer Row zugeordnet sein. - Objekte dürfen nur aggregiert werden, wenn die rowbestimmenden lokalen Werte übereinstimmen. Widersprüchliche Werte werden in der ersten Ausbaustufe nicht automatisch vereinheitlicht, sondern benötigen getrennte Rows oder eine ausdrückliche Nutzerentscheidung. - Eine bestehende Row mit manueller Menge darf externe Objekte aufnehmen; beim Lösen bleibt der manuelle Anteil erhalten. Für die UI vor Phase 14.3 bleibt noch festzulegen, ob eine nach dem Lösen leere Row stehen bleibt oder nach gesonderter Bestätigung gelöscht wird. Ein stiller Row-Lebenszyklus ist ausgeschlossen. ## Command-Schnittstellen Alle Payloads tragen `schemaVersion: 1`, vollständige erwartete und gewünschte Snapshots und werden mit der aktuellen Projektrevision geplant. Große Importcommands dürfen umfangreich sein; sie müssen für Redo deterministisch bleiben und dürfen spätere Quellstände nicht erneut auswerten. - `external-csv-configuration.update`: vollständige projektweite Konfiguration ändern. - `external-import.apply-initial`: Quelle, Batch, Raum-Mappings, externe Objekte und bestätigte Links atomar einfügen. - `external-import.apply-follow-up`: neuen Batch und die vollständigen erwarteten/gewünschten Änderungen bestehender, neuer und fehlender Objekte atomar übernehmen. - `external-model-object.update-planning`: lokale Werte und Overrides eines oder mehrerer Objekte ändern. - `external-model-object.update-project-device-link`: ProjectDevice-Links explizit setzen oder lösen, ohne das ProjectDevice zu verändern. - `external-model-object.assign-to-row`: Objekte einer bestehenden Row zuweisen und deren materialisierte Menge atomar aktualisieren. - `external-model-object.assign-to-new-row`: stabile neue Row einfügen, Objekte verknüpfen und gegebenenfalls den Reserve-Status aktualisieren. - `external-model-object.assign-to-new-circuit`: stabilen Circuit samt Schutz, Row und Objektlinks in einem Schritt einfügen. Das geplante BMK wird im Command gespeichert und bei Redo nicht neu berechnet. - `external-model-object.unassign-from-row`: einzelne Objektlinks lösen und die Menge exakt aktualisieren. - `external-model-object.delete-missing`: nur ausdrücklich bestätigte, weiterhin unveränderte fehlende Objekte löschen. Die Erzeugung eines neuen `ProjectDevice` verwendet weiterhin den vorhandenen `project-device.insert`-Command. Revit-Werte füllen lediglich das sichtbare Formular vor; erst dessen Bestätigung erzeugt die Vorlage. CSV-Vorschau und Rückexport sind reine Leseoperationen. Append-only Exportnachweise verändern keine Projektrevision und laufen über einen eigenen Audit-Store. ## Snapshot-, Transfer- und Migrationsfolgen - Phase 14.1 führt Migration `0002` für die Konfiguration ein und erhöht das Project-State-Snapshot-Schema additiv von 2 auf 3. Der Upgrader von Version 2 ergänzt `externalCsvConfiguration = null`. - Phase 14.2 führt Migration `0003` für Quelle, Batches, Raum-Mappings und Objekte ein und erhöht das Snapshot-Schema von 3 auf 4. Der Upgrader ergänzt leere externe Collections. - Phase 14.3 führt die additive Row-Spalte `manual_quantity` ein. Bestehende Werte werden einmalig aus `quantity` übernommen. - Snapshot-Capture und Restore erhalten Konfiguration, Quelle, bestätigte Batches, Raum-Mappings und Objekte in expliziter FK-Reihenfolge. - Beim Projektduplikat werden alle neuen internen UUIDs und internen Links remappt. `IfcGUID`, Quellwerte, Transportmatrix und unbekannte CSV-Inhalte bleiben unverändert. - Der Transfer-Envelope kann Version 1 bleiben; die enthaltene Project-State-Schema-Version wird additiv erhöht. - Vorhandene Migrationen und Snapshot-Upgrader werden nicht editiert. ## Implementierungsfolge ### 14.1 – CSV-Konfiguration und reine Vorschau 1. Transport-Domainverträge, Dialekt- und Mappingvalidatoren sowie kleine synthetische Fixtures ergänzen. **Erledigt.** 2. Zustandsfreien Parser und Serializer mit Round-trip-Tests für UTF-8-BOM, CRLF, Semikolon, vollständige Quotierung, Kopfzeile in Zeile 2 sowie Titel-, Leer-, Objekt- und Passthrough-Zeilen implementieren. **Erledigt für synthetische Testdaten; die Referenzdatei steht noch aus.** 3. Konfiguration über Migration, Snapshot v3, Transfer und den Command `external-csv-configuration.update` persistieren. **Erledigt.** 4. Vorschau-Endpunkt und deutschen Projekt-Wizard ergänzen. **Erledigt:** Konfigurations-Read/Write- und zustandsfreier Vorschau-Endpunkt sowie das deutsche Konfigurations-/Vorschaumodal. Der Server speichert keinen Entwurf: Bei Bestätigung wird die Datei erneut übertragen, erneut geparst und ihr Hash gegen die Vorschau geprüft. **Phase 14.1 ist damit technisch abgeschlossen.** Die fachliche GUI-Abnahme erfolgt vor Beginn der persistenten externen Objekte aus Phase 14.2. Abnahme: fokussierte Tests, vollständige Tests und alle vorgeschriebenen Build-/Typecheck-Schritte. Die lokal bereitgestellte Referenz-CSV wird mit `npm run revit:verify-reference` auf 897 Objektzeilen, 211 nichtleere Passthrough-Summenzeilen und einen bytegleichen Round-trip geprüft. Da die Referenzdatei reale Modelldaten enthalten kann, wird sie nicht automatisch in einen Commit aufgenommen. ### 14.2 – Persistente Objekte und Erstimport 1. Schema, Repositories und reine Identitäts-/Matchingregeln ergänzen. **Erledigt:** Migration `0003`, vollständiger externer Read-State sowie exaktes IFCGUID-, Raum- und Familie-und-Typ-Matching sind vorhanden. Es gibt weiterhin keinen Import-Write außerhalb eines Commands. 2. Snapshot v4, Restore und Projektduplikat samt UUID-Remapping ergänzen. **Erledigt:** Version 3 wird mit leerem externem Zustand hochgestuft; Capture, Restore, Undo/Redo und beide Transfermodi erhalten Originalbytes, Matrix und sämtliche internen Links. Duplikate remappen alle internen UUIDs, lassen IFCGUID und Quelltransport jedoch unverändert. 3. Erstimport-Command mit echten SQLite-Commit-/Rollback-Tests ergänzen. **Erledigt:** `external-import.apply-initial` wechselt ausschließlich zwischen leerem und vollständig bestätigtem externem Zustand. Er prüft Konfigurationsversion, Original-Hash, erneut geparste Matrix, vollständige IFCGUID-Menge, Quellwerte, explizite Overrides und projektinterne Links. Der Command verbietet CircuitDeviceRow-Links, ist ein atomarer Undo-Schritt und verwendet für Redo dieselben UUIDs und Bytes. Migration `0004` ergänzt die zuvor noch fehlende monotone Konfigurationsversion am Batch; `0003` bleibt unverändert. 4. Raum-, Verteilungs-, Klassifizierungs- und ProjectDevice-Schritte im Wizard ergänzen; der Import selbst erzeugt keine CircuitDeviceRow. **Erledigt:** Der zustandsfreie Planungs-Endpunkt liefert gruppierte Quellräume mit exaktem Raumnummernvorschlag, Familie-und-Typ-Gruppen, Objektvorschläge, Warnungszahlen sowie vorhandene Ebenen, Räume, Verteilungen und ProjectDevices. Er blockiert nach einem bereits bestätigten Erstimport und schreibt weder Entwurf noch Projektzustand. Der dedizierte Endpunkt verlangt denselben Datei-Hash und Konfigurationsstand wie die Planung, vollständige Entscheidungen für alle Quellräume und exakten Familie-und-Typ-Gruppen und baut daraus serverseitig stabile UUIDs. Nicht klassifizierte Familien blockieren. Raum-/Standardverteiler- und optionale ProjectDevice-Links werden bestätigt, Stromkreis- und Row-Links bleiben ausgeschlossen. Das breite Projektmodal zeigt Raumtreffer und Warnungen, bietet die vorhandenen Raum-, Verteiler- und ProjectDevice-Kataloge an und verlangt vor der atomaren Übernahme eine ausdrückliche Bestätigung. Fehlende Räume und ProjectDevices lassen sich über die regulären, vorausgefüllten Projektformulare anlegen und werden danach unmittelbar ausgewählt. Diese Kataloganlagen bleiben eigenständige, rückgängig machbare Projektrevisionen. Vor Beginn werden die oben vorgeschlagenen Namen, die erneute Dateiübertragung statt serverseitiger Entwürfe, die Konfigurationsversionierung und die Kombination aus Originalbytes und Matrix als Entscheidungen bestätigt. ### 14.3 – Editor und explizite Zuordnung 1. `manualQuantity` und Mengeninvarianten migrieren und testen. **Erledigt:** Migration `0005` übernimmt für jede bestehende Gerätezeile `manualQuantity = quantity`. Neue normale Zeilen und Mengenänderungen führen beide Werte gemeinsam; Snapshot/Transfer v5 erhält den Anteil und stuft v4 verlustfrei hoch. Die reine Mengenregel validiert den materialisierten Wert als manuellen Anteil plus Summe der unteilbaren externen Objektmengen. 2. Commands für vorhandene Row, neue Row, neuen Circuit und Lösen ergänzen. 3. Verteilungsbezogenen Drawer, Filter und Vorschau der Mengenwirkung ergänzen. 4. Einzel- und Mehrfach-Drag-and-drop samt Warnungen, Undo/Redo und Reload testen. Vor Beginn werden Drawerposition, Verhalten widersprüchlicher Mehrfachauswahl, Warnungsdialoge und der Lebenszyklus leerer Rows festgelegt. ### 14.4 – Strukturtreuer Rückexport 1. Exportprojektion gegen eine bekannte Projektrevision ergänzen. 2. Nur gemappte Objektzellen in einer Kopie der akzeptierten Matrix ersetzen. 3. Dialekt, Reihenfolge, unbekannte Zellen und Passthrough-Zeilen erhalten. 4. Download und append-only Exportnachweis ergänzen. Zahlenformat, leere Stromkreiswerte und Dateiname werden vorher fachlich festgelegt. ### 14.5 – Folgeimport und Konflikte 1. Deterministischen Diff nach `(sourceId, ifcGuid)` ergänzen. 2. Neu, geändert, unverändert, fehlend und konfliktbehaftet projizieren. 3. Einzel- und Sammelentscheidungen im Wizard ergänzen. 4. Akzeptierten Diff als einen atomaren Command mit vollständigem Undo/Redo übernehmen. ### 14.6 – Härtung und End-to-End-Abnahme 1. Alle Szenarien A bis G der verbindlichen Spezifikation automatisieren. 2. Referenzdatei über Vorschau, Erstimport, Zuordnung, Export, Folgeimport, Snapshot/Restore und Projektduplikat prüfen. 3. Abfrageindizes und große Payloads mit mehreren tausend Objekten messen. 4. Architektur-, API-, Betriebs- und Nutzerdokumentation auf den tatsächlich ausgelieferten Stand nachziehen. ## Risiken und Schutzmaßnahmen - **Mengenverlust:** `manualQuantity` trennt manuelle und externe Anteile; Commands ändern Links und materialisierte Menge gemeinsam. - **Stilles Überschreiben:** Quellwerte, lokale Werte und Overrides sind getrennt; jede Übernahme benötigt eine Nutzerentscheidung. - **ProjectDevice-Verfälschung:** Links ändern niemals die kanonische Vorlage; deren bestehende Commands bleiben alleinige Schreibgrenze. - **Nicht reproduzierbarer Export:** Jeder Batch hält Originalbytes, Matrix, Dialekt, Konfiguration, Hash und Projektrevision. - **Sehr große Undo-Payloads:** Importcommands speichern vollständige erwartete/Zielzustände. Größe und Transaktionsdauer werden in 14.2 gemessen, nicht durch indirekte oder nachträglich neu berechnete Payloads optimiert. - **BMK-Drift:** Neue BMKs werden einmal bei der Planung berechnet und im Command gespeichert; Import, Sortierung und Redo nummerieren nie implizit. - **Vertrauliche Referenzdaten:** Der Referenzprüfer läuft lokal gegen die bereitgestellte CSV. Vor einer Aufnahme dieser Datei in Git ist gesondert zu klären, ob sie ausreichend anonymisiert und zur Weitergabe freigegeben ist. ## Freigabepunkt Mit der Freigabe dieses Audits beginnt Arbeitspaket 14.1.1: reine Transportverträge, Validatoren und synthetische CSV-Fixtures. Dieses Paket ändert weder Datenbank noch GUI und führt keine Projektschreibvorgänge aus.