Document Linear Excel integration

This commit is contained in:
Julian Appel 2026-09-29 22:28:16 +02:00
parent ae318a51ac
commit d4803a18d2
16 changed files with 932 additions and 2316 deletions

View file

@ -2,12 +2,17 @@
Stand: 29.09.2026. Geprüfter Code: `cf022b2`.
**Status: R0 abgeschlossen, Freigabe für R1–R10 ausstehend.** Dieser Bericht
**Status: R0 abgeschlossen und mit Korrekturen für R1 freigegeben.** Dieser Bericht
ist ein Umsetzungsvorschlag, kein Nachweis einer bereits implementierten
Excel-Anbindung. Der neue Nutzerauftrag ersetzt die CSV-/IfcGUID-Vorgaben und
die alte Phasenliste 14.0–14.6. R1 bereinigt die bestehenden Dokumente; R0
ändert weder Laufzeitcode noch Datenbank noch Oberfläche.
Die 13 Freigabekorrekturen vom 29.09.2026 sind in den
[verbindlichen Anforderungen](revit-excel-integration-requirements.md) und im
[R0–R10-Plan](revit-excel-phase-14-plan.md) eingearbeitet. Bei Abweichungen
gelten diese beiden R1-Dokumente.
## 1. Geprüfter Bestand und Keep/Change/Remove
Gelesene Grundlagen: `AGENTS.md`, `docs/current-architecture.md`,
@ -90,7 +95,7 @@ Die Datei ist unversioniert und darf nicht committed werden.
| Objektidentitäten | 487 syntaktisch passende Worksharing-IDs, keine Duplikate |
| Kopfzeilenkommentare | 14, zu den 14 Spalten nach der ID-Spalte |
| Fehlende Raumangaben | 67 Objekte ohne Raumnummer und Raumname |
| IfcGUID-Duplikate | 2 Gruppen nichtleerer doppelter Werte |
| IfcGUID-Duplikate | Keine bei exaktem, case-sensitivem Vergleich |
| Formeln | Keine; synthetische Tests dafür erforderlich |
| Spaltendefinitionen | 16, obwohl nur 15 Datenspalten vorhanden sind |
@ -100,9 +105,15 @@ gekürzt werden. Das Muster enthält die neuen getrennten Stromkreisfelder und
die Bezeichnung noch nicht. Fehlende Rückgabespalten werden angezeigt; sie
dürfen nicht ohne Linear-Parameterbindung erfunden werden.
Die frühere Angabe von zwei IfcGUID-Duplikatgruppen war falsch: PowerShells
standardmäßiges Gruppieren verglich ohne Beachtung der Groß-/Kleinschreibung.
Ein erneuter ordinaler, case-sensitiver Vergleich ergab keine Duplikate. Die
Summenzeile hat nur in B490 einen Wert; `Familie und Typ` ist leer.
Nicht nachgewiesen: erfolgreicher Rückimport in Linear, dessen genaue
Auswertung der Kommentar-/VML-Metadaten und der ExcelJS-Roundtrip. R2 prüft
die Struktur, R8/R10 benötigen zusätzlich einen realen Linear-Abnahmelauf.
Auswertung der Kommentar-/VML-Metadaten und der ExcelJS-Roundtrip. R2 endet
deshalb mit einer aus der Musterdatei erzeugten Rückgabedatei und einem
verbindlichen Linear-Test durch den Nutzer vor R3.
## 3. Bibliothek, Adapter und Uploadgrenzen
@ -123,18 +134,12 @@ Blocker wird die Bibliotheksentscheidung neu vorgelegt.
Vorgeschlagene Grenzen, zentral konfiguriert und synthetisch getestet:
- ausschließlich `.xlsx`, passender OOXML-Inhalt und ZIP-Signatur; kein
`.xlsm`, verschlüsseltes Archiv, VBA, ActiveX oder externe Workbook-Links;
- maximal 10 MiB Upload, 100 MiB tatsächlich entpackte Daten, 2.000 ZIP-
Einträge, 50.000 Zeilen, 256 Spalten und 2 Millionen materialisierte Zellen;
- genau ein Arbeitsblatt; keine Formelausführung, kein Nachladen von URLs;
- ZIP-Vorprüfung vor ExcelJS: Verzeichniseinträge, doppelte Pfade,
Kompressionsverfahren und tatsächliche entpackte Bytezahl prüfen.
Zentralverzeichnisangaben allein schützen nicht vor manipulierten Archiven.
Begrenzte Dekompression mit Node-Bordmitteln, keine zweite direkte Library;
- Parser in begrenztem Worker mit Zeit-/Speichergrenze; Abbruch ohne DB-
Schreibvorgang. API-Body-Limit auf Uploadgrenze einschließlich Base64-
Overhead abstimmen, statt global beliebige Requestgrößen zuzulassen.
- ausschließlich `.xlsx`, kein `.xls` oder `.xlsm`;
- maximal 10 MiB Upload;
- genau ein Arbeitsblatt und keine Formelausführung;
- feste Zeilen-, Spalten- und Zellgrenzen nach dem Einlesen.
Es gibt keinen eigenen ZIP-Prüfer und keinen Parser-Worker.
Neutrale Matrix: Blattname, Kopfzeilen-/Startpositionen, Spaltenmetadaten
(Index, Name, Kommentartext, erkannter Parametertyp/Einheit), geordnete
@ -144,11 +149,14 @@ optionale Transportmetadaten; fachlich zählt nur der gecachte skalare Wert.
Fehlender Cache oder Fehlerwert erzeugt einen Hinweis bzw. bei Pflichtfeldern
einen Blocker. Originalbytes bleiben unverändert gespeichert.
Fehlende ID bei sonstigen Objektdaten blockiert; Leer-/eindeutige Summenzeilen
werden ignoriert. Nicht passende nichtleere IDs blockieren ebenfalls.
Worksharing-ID bleibt als Quelltext erhalten, Matching ist exakt; ungültige
Leerzeichen/uneindeutige Schreibweisen werden gemeldet statt still korrigiert.
IfcGUID wird optional gespeichert, doppelte Werte sind nur Hinweise.
Eine Zeile ohne Worksharing-ID ist nur verdächtig, wenn `Familie und Typ`
gefüllt ist. Sie erzeugt einen Hinweis und wird übersprungen, ohne zu
blockieren. Andere ID-lose Zeilen, auch die Summenzeile mit Inhalt in B,
werden still übersprungen. Nicht passende nichtleere IDs blockieren.
Worksharing-ID und IfcGUID bleiben als Quelltext erhalten und werden exakt,
ordinal und case-sensitiv verglichen; ungültige äußere Leerzeichen werden
gemeldet statt still korrigiert. IfcGUID wird optional gespeichert, doppelte
Werte sind nur Hinweise.
Numerische Projektion rundet Leistung auf 0,01 W, nicht die gespeicherte
Quellzelle. Mengen aus `socketCount` müssen positive ganze Zahlen sein.
@ -170,8 +178,7 @@ Neuer neutraler Vertrag `ExternalModelConfiguration`, Schema-Version 1:
{
schemaVersion: 1,
layout: {
headerRow: 1, firstDataRow: 3, firstDataColumn: 1,
idColumn: "Worksharing-ID"
headerRow: 1, firstDataRow: 3, firstDataColumn: 1
},
circuitMode: "combined" | "separate",
columns: {
@ -200,8 +207,8 @@ Neuer neutraler Vertrag `ExternalModelConfiguration`, Schema-Version 1:
```
Zeilen/Spalten sind intern 1-basiert; UI stellt Spalten als A, B, … dar.
`layout.idColumn` und `columns.worksharingId` werden gemeinsam gesetzt und
müssen übereinstimmen. Jede gemappte Kopfzeile muss eindeutig auflösbar sein;
Es gibt nur `columns.worksharingId` und kein separates `layout.idColumn`.
Jede gemappte Kopfzeile muss eindeutig auflösbar sein;
doppelte Ausgabebelegungen werden abgelehnt. Freie Eingabe bleibt zulässig,
aber ein nicht existierender Name erzeugt vor Import/Export einen konkreten
Fehler. Erkennung und Vorbelegung nutzen die exakten Standardnamen aus dem
@ -217,8 +224,8 @@ Referenzierte Gerätearten können nicht kommentarlos entfernt werden.
Startwerte: je Feld ProjectDevice vor Geräteart vor leer. Anzeigename:
Auswahlkenner, sonst Geräteartname, sonst Familie/Typ. Quellleistung bleibt
Quelle; eine Übernahme geschieht nur als sichtbare Planungsentscheidung.
Fehlender GZF bleibt vor Zuordnung leer; verlangt der Row-Vertrag einen Wert,
wird `1` sichtbar vorgeschlagen und ausdrücklich bestätigt. Geräteart-
Fehlender GZF wird sichtbar mit `1` vorbelegt, ohne zusätzliche Bestätigung.
Geräteart-
Änderungen schreiben keine vorhandenen Objekt-Overrides oder Rows um.
## 5. Konkretes Persistenzschema
@ -228,20 +235,21 @@ Bestehende UUID-/Projekt-FKs und Eigentumsprüfungen werden beibehalten.
| Tabelle | Zielspalten / Constraints |
| --- | --- |
| `external_model_configurations` (ersetzt CSV-Tabelle) | `id TEXT PK`, `project_id TEXT NOT NULL UNIQUE FK projects`, `configuration_version INTEGER NOT NULL CHECK > 0`, `configuration JSON NOT NULL`. Enthält obiges vollständiges Aggregat. |
| `external_model_configurations` (ersetzt CSV-Tabelle) | `id TEXT PK`, `project_id TEXT NOT NULL UNIQUE FK projects`, `configuration JSON NOT NULL`. Enthält obiges vollständiges Aggregat; keine eigene Versionszählung. |
| `external_model_sources` | `id`, `project_id UNIQUE`, `name`, `source_type = revit_xlsx`. Genau eine implizite Quelle je Projekt. |
| `external_import_batches` | Bestehende IDs, Importart, Zeit, Dateiname, SHA-256, `applied_project_revision`, `configuration_version`, `configuration_snapshot JSON`, `original_bytes BLOB`, `document JSON`; Matrix jetzt typisiert und transportneutral. Unveränderlich innerhalb des aktiven Zustands; Undo/Restore darf ganze Batches entfernen/wiederherstellen. |
| `external_import_batches` | Letzter Batch vollständig mit IDs, Importart, Zeit, Dateiname, SHA-256, Objektzahl, `applied_project_revision`, `configuration_snapshot JSON`, `original_bytes BLOB`, `document JSON`; ältere Batches nur als Metadaten Datum, Dateiname, SHA-256 und Objektzahl. |
| `external_room_mappings` | Vorhandene Felder einschließlich normalisiertem Quellraumschlüssel, `room_id`, `default_distribution_board_id`; UNIQUE `(source_id, normalized_source_room_key)` bleibt. |
| `external_model_objects` | Bestehende interne IDs/Links; neu `worksharing_id TEXT NOT NULL`, UNIQUE `(source_id, worksharing_id)`; `ifc_guid TEXT NULL`, ohne Unique; `device_type_id TEXT NOT NULL` als validierter Verweis in das Konfigurationsaggregat. |
| Objektzustand | `accepted_source_values JSON` mit rohen typisierten Werten für Raum, Familie/Typ, Marker, Menge, Bemerkung und alle Rückgabefelder; `planning_values JSON` mit Anzeigename, Kategorie, Anschlussart, effektiver Menge, Einzelleistung W, nullable GZF/cosPhi/Kostengruppe/Bemerkung; `overridden_fields JSON`; bisherige Batch-/Raum-/Board-/ProjectDevice-/Row-Verweise und `presence_status` bleiben. |
| `external_export_batches` (neu) | `id TEXT PK`, `project_id FK`, `project_revision INTEGER`, `import_batch_id TEXT`, `exported_at_iso TEXT`, `file_name TEXT`, `sha256 TEXT`, `configuration_version INTEGER`, `scope TEXT`, `object_count INTEGER`. Append-only Audit-Store. |
| `external_export_batches` (neu) | `id TEXT PK`, `project_id FK`, `project_revision INTEGER`, `import_batch_id TEXT`, `exported_at_iso TEXT`, `file_name TEXT`, `sha256 TEXT`, `configuration_snapshot/hash`, `scope TEXT`, `object_count INTEGER`. Append-only Audit-Store. |
`import_batch_id` des Exportnachweises ist absichtlich eine historische UUID
ohne löschenden FK: Undo eines Imports oder Snapshot-Restore darf den Nachweis
nicht entfernen. Exportnachweise liegen außerhalb rücksetzbarer Fachsnapshots
und werden beim Projektduplikat nicht als dort erfolgte Exporte ausgegeben.
Sie bleiben beim Originalprojekt erhalten; diese Abgrenzung wird in R1
dokumentiert. Importbatches selbst gehören vollständig zu Snapshot/Transfer.
dokumentiert. Nur der letzte Importbatch gehört mit Bytes und Matrix zu
Snapshot/Transfer; ältere Batches werden dort nur als Metadaten erhalten.
Indices: bisherige Projekt-/Presence-, Board- und Row-Indices behalten;
zusätzlich `(project_id, device_type_id)`, `external_room_mapping_id`,
@ -252,9 +260,9 @@ Transaktion; bloße Existenz eines UUID-FK genügt nicht.
Effektiver Verteiler: ein gemeinsamer Resolver verwendet bei verknüpften
Objekten die Row/Circuit-Verteilung, sonst die Objektabweichung, sonst die
Raumvorgabe. `distributionBoardId = null` bedeutet Raumvorgabe verwenden;
bei fehlender Vorgabe ist das Objekt ohne Verteiler. Room-/Board-
Sammeländerungen prüfen alle betroffenen Row-Links und lehnen inkonsistente
Umbuchungen ab, bis diese ausdrücklich gelöst/verschoben sind.
bei fehlender Vorgabe ist das Objekt ohne Verteiler. Eine Änderung des
Raum-Standardverteilers betrifft nur unzugeordnete Objekte; verknüpfte Objekte
folgen immer der Row-Verteilung und blockieren diese Änderung nicht.
Planungswerte bleiben von Quellwerten getrennt. Nach Row-Zuordnung sind
Objekt-Planungswerte eingefrorene Startwerte; Anzeige, Abweichung und Export
@ -272,7 +280,7 @@ Snapshots der betroffenen Datensätze, keine ungesicherten Teilpatches.
| Command | Payload-Skizze und Gegenrichtung |
| --- | --- |
| `external-model-configuration.update` v1 | `{ expected, target }` einschließlich Layout, Mapping, Gerätearten und Regeln. Inverse tauscht Fachinhalt; Versionsgeneration siehe unten. |
| `external-model-configuration.update` v1 | `{ expected, target }` einschließlich Layout, Mapping, Gerätearten und Regeln. Inverse tauscht den vollständigen Fachinhalt; keine eigene Konfigurationsversion. |
| `external-import.apply-initial` v2 | `{ expectedConfiguration, targetConfiguration, expected, target }`. Quelle, Batch, Mapping, Objekte und neue Regeln zusammen; Inverse stellt leeren externen und vorherigen Konfigurationsinhalt wieder her. Keine Rows. |
| `external-import.apply-follow-up` v1 | `{ configuration: transition, batch: transition, roomMappings: transitions, objects: transitions, rows: quantityTransitions, decisions }`; Server erzeugt deterministischen Diff und alle UUIDs. Inverse tauscht alle betroffenen Zustände. |
| `external-model-object.update-planning` v1 | `{ objects: transitions }`; nur ungebundene Objekte; geänderte Felder in Overrides. Einzel-/Sammelbearbeitung identischer Regeln. |
@ -290,32 +298,29 @@ Entwürfe und werden erst mit dem Import atomar persistiert. Nach separater
Kataloganlage aktualisiert der Wizard die Projektrevision und plant neu,
ohne lokale Entscheidungen zu verlieren.
Konfigurationsgeneration: `configurationVersion` erhält bei jedem
Konfigurationswechsel einschließlich Undo/Redo/Restore die neu entstehende
Projektrevision. Sie ist damit strikt steigend, aber nicht lückenlos.
Historienbefehle vergleichen den erwarteten Fachinhalt und die aktuelle
Projektversion; die administrative Generation wird serverseitig neu erzeugt.
Die Inverse restauriert alle Fachwerte exakt, nicht einen alten Zählerstand.
Importbatches behalten ihre ursprüngliche Generation und ihren Snapshot.
Ein Restore/Projekttransfer erhält diese Herkunft; die aktive Konfiguration
wird an die Revision des Zielprojekts gebunden. Prüfen: Änderung → Undo →
anderer Zweig darf niemals denselben Vorschau-Token wieder gültig machen.
Die Konfiguration hat keine eigene Versionszählung. Vorschau und Apply binden
sich an `expectedRevision`; weil auch Undo/Redo neue, strikt steigende
Projektrevisionen erzeugen, wird ein veralteter Plan eindeutig ungültig.
Importbatches speichern eine vollständige Konfigurationskopie. Prüfen:
Änderung → Undo → anderer Zweig darf niemals denselben Plan wieder gültig
machen.
XLSX wird vor der synchronen SQLite-Transaktion in einer serverinternen
Vorbereitung geparst. Apply überträgt Bytes erneut; Hash, Matrix und
Entscheidungen werden erneut validiert. Im Store werden Revision,
Konfigurationsinhalt/-generation, erwartete Objekte, Links und vollständiger
Konfigurationsinhalt, erwartete Objekte, Links und vollständiger
vorbereiteter Plan atomar geprüft. Vorbereitete Daten sind keine vom Client
behauptete Validierung: Generic-Command-Requests dürfen Importcommands nicht
an dieser serverseitigen Vorbereitung vorbeischleusen. Undo/Redo benutzen
denselben Prüfdienst für persistierte Bytes vor der Transaktion. Keine
asynchronen Callbacks in `better-sqlite3`-Transaktionen.
an dieser serverseitigen Vorbereitung vorbeischleusen. Undo/Redo lesen und
parsen keine Excel-Datei; sie wenden ausschließlich die gespeicherten
Vorher-/Nachher-Zustände an. Keine asynchronen Callbacks in
`better-sqlite3`-Transaktionen.
Allgemeine Row-/Circuit-/Gruppen-/Board-/Raum-/ProjectDevice-Löschungen
erhalten Guards, solange externe Referenzen betroffen sind. Nutzer lösen die
Referenzen zuvor ausdrücklich über die passenden Commands. Guards gelten
auch in Unterbaum- und History-only-Pfaden. Dadurch werden vorhandene
Commands nicht unbemerkt zu unvollständigen externen Löschcommands.
Row-/Circuit-/Gruppen-Löschcommands erfassen verknüpfte Objekte vollständig.
Nach der Warnung `X Revit-Objekte werden wieder unzugeordnet` lösen sie die
Links im selben Command; ihre Inverse stellt sie exakt wieder her. Sperren
bleiben nur für das Löschen referenzierter Verteiler und Räume und gelten auch
in Unterbaum- und History-only-Pfaden.
## 7. Migration, Snapshot 10, History und Transfer
@ -351,7 +356,8 @@ allgemeine Commands können nach dem Reset zusätzlich an ihren exakten
Vorbedingungen scheitern; das bleibt eine sichere, sichtbare Ablehnung.
Snapshot v10 enthält aktive Excel-Konfiguration, Gerätearten/Regeln, Quelle,
alle Batches mit Originalbytes/Matrix, Raum-Mappings, Objekte und Links.
den letzten Batch mit Originalbytes/Matrix, ältere Batches nur als Metadaten
sowie Raum-Mappings, Objekte und Links.
Upgrade v1–9: bestehende nicht-externe Upgrader erhalten. Nur wenn
`externalCsvConfiguration` fehlt/null ist **und** der externe Zustand leer
ist, verlustfrei auf v10 heben. Auch eine gespeicherte CSV-Konfiguration
@ -389,12 +395,13 @@ separater append-only Audit-Write, ohne Projektrevision oder Undo-Schritt.
Bei Auditfehler kein Erfolg/download; ein Eintrag belegt Dateierzeugung,
nicht einen tatsächlich abgeschlossenen Browserdownload.
Die Revit-Seite zeigt Status, Aktionen und eine paginierte Objekttabelle
(Vorschlag: 100 Zeilen pro Seite). Filter-/Sortierzustand, UUID-Auswahl und
Sammelaktionen sind unabhängig vom DOM. „Alle gefilterten“ verwendet eine
explizit aufgelöste Auswahl zur bekannten Revision; keine Mutation anhand
eines inzwischen veränderten Filters. Große Auswahlmengen werden nicht in
getrennte Undo-Schritte aufgeteilt. Kein vollständiges Batch-Blob im DTO.
Die Revit-Seite lädt einmal eine kompakte Objektliste. Filterung und Sortierung
laufen im Client; die Tabelle wird virtualisiert und verwendet keine Server-
Pagination. Filter-/Sortierzustand, UUID-Auswahl und Sammelaktionen sind
unabhängig vom DOM. „Alle gefilterten“ wird vor einer Mutation zu einer
expliziten ID-Auswahl an der aktuellen Revision aufgelöst. Große Auswahlmengen
werden nicht in getrennte Undo-Schritte aufgeteilt. Kein vollständiges
Batch-Blob im DTO.
Einstellungen verwenden Musterdatei-Erkennung mit editierbaren Positionen,
Feld-Dropdowns/freier Eingabe und Kommentar-Typ-/Einheitenanzeige. Regeln
@ -430,10 +437,10 @@ gegen den **zuletzt importierten**, nicht den zuletzt exportierten Stand.
Umfang: alle im letzten Batch vorhandenen Objekte / abweichende / explizite
Auswahl. Fehlende Objekte haben keine aktuelle Originalzeile und werden
nicht künstlich wieder eingefügt. Alle Spalten bleiben, nicht ausgegebene
Parameter behalten importierte Werte. Fehlende benötigte Zielspalten bzw.
Linear-Bindungen blockieren die betreffende Exportkonfiguration mit Hinweis
auf einen neuen vollständigen Linear-Export. Dateiname gemäß Auftrag mit
bereinigtem Projektnamen und Tagesdatum.
Parameter behalten importierte Werte. Fehlende optionale Spalten für
Bezeichnung, Leistung, Spannung und Strom werden mit Hinweis übersprungen.
Nur fehlende Stromkreisspalten des gewählten Modus blockieren. Dateiname gemäß
Auftrag mit bereinigtem Projektnamen und Tagesdatum.
Folgeimport matcht ausschließlich Worksharing-ID. Ein neuer Batch speichert
immer den vollständigen letzten Quellstand. Unveränderte Objekte werden
@ -457,12 +464,12 @@ nach Freigabe; keine Fortschreibung der alten 14.0–14.6-Liste.
| Paket | Arbeit und entscheidende Abnahme |
| --- | --- |
| R1 | Neue Excel-Anforderungen und R0–R10-Plan; alte Dokumente archivieren/auf Verweise kürzen; AGENTS, Architektur, History-Doku, Phase-14-Abschnitt, LLM-Kontext und alle Links nachziehen. Referenzdatei gezielt ignorieren. |
| R2 | XLSX-Adapter und lokaler Referenzprüfer mit Pfadargument. Synthetischer Roundtrip für Kommentare, Blattname, Spaltenbreiten, Typen, Header-/Startpositionen, unbekannte Spalten, Auswahl und Summenausschluss; ZIP-/Formelgrenzen. Keine DB-Änderung. |
| R2 | XLSX-Adapter und lokaler Referenzprüfer mit Pfadargument. Synthetischer Roundtrip für Kommentare, Blattname, Spaltenbreiten, Typen, Header-/Startpositionen, unbekannte Spalten, Auswahl und Summenausschluss. Aus der lokalen Musterdatei entsteht eine Rückgabedatei mit geänderten Werten. Danach Nutzerabnahme in Linear; R3 bleibt bis zum Erfolg gesperrt. Bei Fehlschlag vor R3 OOXML-Direktänderung als Alternative vorlegen. Keine DB-Änderung. |
| R3 | Neue Konfiguration/Identität, additive Migration, Snapshot 10, Transfer und History-Ablehnungen; Backend-CSV entfernen. Parser-Vorbereitung von synchroner Transaktion trennen. |
| R4 | Revit-Seite, Navigation, Einstellungen; Projektseitenmodal und dessen CSV-Frontend-Verträge entfernen. |
| R5 | Erstimport mit atomaren Regeln, Geräten, Raum-/Board- und Objektentscheidungen; ProjectDevice-Vorbelegung nach Priorität; ein Import-Undo-Schritt. |
| R6 | Objekt-Reads, Paging/Filter, Sammel-Commands und Overrides; verwandte Lösch-/Referenzguards vollständig absichern. |
| R7 | Gruppierung, Drag-and-drop, Row-Indikatoren und Lösen inklusive aktueller Row-Werte; drei Drop-Ziele und Reload/Undo/Redo. |
| R6 | Kompakte Objekt-Reads, clientseitige Filter/Sortierung, Virtualisierung, Sammel-Commands und Overrides. |
| R7 | Gruppierung, Drag-and-drop, Row-Indikatoren und Lösen inklusive aktueller Row-Werte; drei Drop-Ziele, atomare Objektlösung beim Row-/Circuit-/Gruppen-Löschen und Reload/Undo/Redo. |
| R8 | Drei Exportumfänge, gemeinsame Abweichungsprojektion, typisierte Rückgabe, append-only Nachweis und Linear-Strukturabnahme. |
| R9 | Kontrollierter Folgeimport, fehlende Objekte, explizites Löschen, mengenwirksame Entscheidungen und atomare Inverse. |
| R10 | Vollständige synthetische Ende-zu-Ende-Kette einschließlich Neustart, Snapshot/Restore und Duplikat; mehrere Tausend Objekte; Doku auf ausgelieferten Stand. |
@ -492,19 +499,19 @@ Zusätzlich erforderliche neue Prüfungen:
- Migration mit externen Row-Anteilen; keine Phantomlast und unveränderte BMKs.
- v1–9 ohne CSV verlustfrei, mit CSV klare Ablehnung; alte Command-Inversen
und alte Restore-Payloads ebenfalls ohne Teilwrites ablehnen.
- Config-Änderung/Undo/Neuzweig invalidiert alte Pläne; Apply mit anderem
- Config-Änderung/Undo/Neuzweig invalidiert alte Pläne über `expectedRevision`; Apply mit anderem
Dateiinhalt, fehlenden Entscheidungen oder fremden UUIDs rollt vollständig
zurück. Später Historyfehler rollt auch Regeln, Links und Mengen zurück.
- Gebundene Row ändern → Export → Lösen → Undo/Redo behält fachliche Werte.
- Mehrfachsteckdosen: unterschiedliche effektive Mengen, identische
Einzelwerte, richtige Gruppierung und objektweise Rückgabeleistung.
- Löschen über alle Unterbaum-/History-Pfade kann externe FKs nicht still
nullen. Fremde Verteilungen/Räume/Kategorien und Gerätearten blockieren.
- Row-/Circuit-/Gruppen-Löschen löst externe Links im Command und stellt sie
per Undo wieder her. Raum-/Verteilerlöschen mit Referenzen blockiert.
- Export-Audit scheitert: keine fachliche Revision; SHA-256 entspricht exakt
den gelieferten Bytes. Snapshot/Restore entfernt keine Exportnachweise.
- 5.000/10.000 synthetische Objekte: Parserzeit, Peak-Speicher, Payloadgröße,
Command-/Snapshot-Dauer und UI-Reaktionszeit messen; höchstens eine
paginierte Seite im DOM, stabile Auswahl über Seitenwechsel.
Command-/Snapshot-Dauer und UI-Reaktionszeit messen; nur sichtbare Zeilen im
DOM, stabile Auswahl über virtuelle Bereiche.
Wesentliche Restrisiken: Linear-Kommentarbindung ist nur anhand des
Exports beobachtet; ExcelJS-Releasepflege und Roundtrip sind in R2 zu
@ -515,7 +522,7 @@ externen Zustand begrenzt und nur nach verifiziertem Backup zulässig.
Fehlende Zielparameter im Muster verlangen einen neuen vollständigen
Linear-Export, keine geratenen GUID-Kommentare.
**Freigabepunkt:** Der Nutzerauftrag verlangt wörtlich
„R0. Audit (danach stoppen und Freigabe abwarten)“.
Mit Freigabe dieses Vorschlags beginnt R1; R0 selbst autorisiert keine
Installation, Migration oder Implementierung von R1–R10.
**Freigabepunkt:** R0 wurde am 29.09.2026 mit den in R1 dokumentierten
Korrekturen freigegeben. R2 besitzt einen neuen verbindlichen Freigabepunkt:
Vor Beginn von R3 muss der Nutzer die in R2 erzeugte Rückgabedatei erfolgreich
in Linear getestet haben.