# AA-043-P34-R1 – Abschlussbericht ## A. Prüfzeitpunkt und Schutzgrenze **Prüfzeitpunkt:** `2026-08-27T23:01:33.877297+00:00` UTC. Autoritative Quelle: ```text /opt/struktur/youtube-research/knowledge.db ``` Die Datenbank wurde ausschließlich mit SQLite `mode=ro` geöffnet. Es wurden keine `INSERT`, `UPDATE`, `DELETE`, `ALTER TABLE`, `DROP`, `VACUUM`, `REINDEX`, Migrationen, Requeues, Provideraufrufe, Graphiti-POSTs oder Neo4j-Writes ausgeführt. ## B. Baseline Read-only-Ergebnis: ```text PRAGMA integrity_check: ok PRAGMA foreign_key_check: 485 rows ``` Verteilung: ```text chapters: 279 video_links: 206 sonstige: 0 ``` Die vollständige strukturierte Liste aller 485 Verstöße liegt zusätzlich als JSON-Artefakt vor und enthält je Zeile `table`, `rowid`, `parent`, `fkid`, Child-Datensatz und FK-Metadaten. ## C. Betroffene Foreign Keys Alle betroffenen Constraints sind: | Child-Tabelle | Child-Spalte | Parent-Tabelle | Parent-Spalte | ON UPDATE | ON DELETE | Verstöße | |---|---|---|---|---|---|---:| | `chapters` | `video_id` | `videos` | `id` | `NO ACTION` | `NO ACTION` | 279 | | `video_links` | `video_id` | `videos` | `id` | `NO ACTION` | `NO ACTION` | 206 | Weitere deklarierte Foreign Keys auf `videos` wurden ebenfalls ermittelt: - `transcript_segments.video_id → videos.id`: `NO ACTION` / `NO ACTION`; - `video_tags.video_id → videos.id`: `NO ACTION` / `NO ACTION`; - `notes.video_id → videos.id`: `NO ACTION` / `NO ACTION`; - `processing_runs.video_id → videos.id`: `NO ACTION` / `NO ACTION`; - `processing_queue.video_id → videos.id`: `NO ACTION` / `NO ACTION`; - `fundus_items.video_id → videos.id`: `NO ACTION` / `CASCADE`; - `e2e_extractions.video_id → videos.id`: `NO ACTION` / `CASCADE`. Für diese zusätzlichen Child-Tabellen wurde im aktuellen `foreign_key_check` kein weiterer Verstoß gefunden. ## D. Quantifizierung der Parent-Probleme ```text FK-Verstöße gesamt: 485 unterschiedliche fehlende IDs: 27 vorhandene videos-Zeilen: 1098 ``` Die 485 Zeilen sind daher **27 fehlende Parent-IDs mit insgesamt 485 referenzierenden Child-Zeilen**, nicht 485 unabhängige fehlende Videos. ### Betroffene IDs und Child-Mengen | fehlende `videos.id` | `chapters` | `video_links` | gesamt | |---:|---:|---:|---:| | 54 | 26 | 14 | 40 | | 65 | 27 | 12 | 39 | | 68 | 6 | 7 | 13 | | 71 | 0 | 6 | 6 | | 78 | 7 | 6 | 13 | | 80 | 9 | 1 | 10 | | 90 | 0 | 6 | 6 | | 97 | 0 | 11 | 11 | | 100 | 7 | 1 | 8 | | 102 | 10 | 10 | 20 | | 117 | 11 | 9 | 20 | | 119 | 15 | 8 | 23 | | 128 | 14 | 11 | 25 | | 134 | 9 | 5 | 14 | | 140 | 8 | 11 | 19 | | 195 | 16 | 13 | 29 | | 196 | 23 | 12 | 35 | | 251 | 16 | 14 | 30 | | 256 | 0 | 7 | 7 | | 258 | 0 | 3 | 3 | | 293 | 0 | 4 | 4 | | 299 | 10 | 12 | 22 | | 300 | 0 | 4 | 4 | | 301 | 9 | 1 | 10 | | 307 | 15 | 5 | 20 | | 311 | 0 | 3 | 3 | | 319 | 41 | 10 | 51 | | **Summe** | **279** | **206** | **485** | `chapters` betrifft 19 der 27 IDs, `video_links` 26 der 27 IDs, davon 18 IDs beide Childtypen. Top fehlende Parent-IDs nach referenzierenden Child-Zeilen: ```text 319=51, 54=40, 65=39, 196=35, 251=30, 195=29, 68=13, 78=13, 128=25, 299=22, 102=20, 117=20, 307=20, 140=19, 134=14, 119=23, 100=8, 256=7, 71=6, 80=10, 90=6, 97=11, 258=3, 293=4, 300=4, 301=10, 311=3 ``` ## E. Fachliche Bewertung der Child-Daten `chapters` enthält weiterhin fachliche Strukturinformationen: ```text video_id chapter index über die Zeilen-/ID-Reihenfolge start_seconds title ``` Die Chapter-Titel und Zeitmarken sind nicht als wertloser technischer Müll nachgewiesen. Sie könnten für Inhaltsnavigation oder Rekonstruktion relevant sein. `video_links` enthält weiterhin: ```text video_id label url ``` Die URLs sind externe Quellen-/Referenzlinks. Auch sie sind nicht als wertlos nachgewiesen. **Informationsverlust-Risiko:** Eine Löschung der 485 Child-Zeilen wäre derzeit nicht vertretbar. Es wurde nichts gelöscht. ## F. Rekonstruktion der Parent-Videos Für alle 27 fehlenden `videos.id` wurde read-only geprüft: - aktuelle `videos`-Tabelle; - `e2e_jobs`; - `e2e_extractions`; - `transcript_segments`; - `processing_runs`; - `graphiti_import_queue`; - `source_processing_registry`; - `content_extraction.db`, insbesondere `ce_sources.source_video_id`; - relevante Report-/Backup-Snapshots; - Obsidian- und vorhandene Pipelinepfade. Ergebnis: ```text vollständig rekonstruierbare Parent-Videos: 0 sicher remappbare Parent-Videos: 0 eindeutig obsolet nachgewiesene Child-Sätze: 0 unklare Fälle: 27 ``` Die `source_processing_registry` enthält für einige numerisch gleichnamige `source_id`-Werte Obsidian-Quellen. Das ist kein Nachweis, dass diese Werte frühere `videos.id` darstellen; die Identitäten dürfen nicht gleichgesetzt werden. Für die 27 fehlenden IDs existiert keine belastbare aktuelle YouTube-ID-/Titel-/URL-Zuordnung aus einer autoritativen Parent-Zeile. `ce_sources.source_video_id` liefert für diese IDs keine Zuordnung. ## G. Backup-Vergleich und Zeitpunkt Verglichene Snapshots: ```text /opt/struktur/reports/backfill-backups-20260717T181315Z/knowledge.db /opt/struktur/reports/obsidian-transcript-backup-20260717T193928Z/knowledge.db /opt/struktur/reports/aa043-p34/20260827T223847Z/knowledge.db.pre-migration.bak ``` Alle drei Snapshots zeigen: ```text foreign_key_check: 485 integrity_check: ok fehlende untersuchte Parent-IDs: alle weiterhin fehlend ``` Der FK-Zustand ist damit spätestens im Snapshot vom **14.07.2026** vorhanden. Ein älterer konsistenter Snapshot mit den 27 Parent-Zeilen wurde in den relevanten verfügbaren Snapshots nicht gefunden. Das belegt den historischen Bestand, aber nicht den exakten Löschzeitpunkt. ## H. Root-Cause-Bewertung ### Bewiesen 1. Die 27 `videos.id` existieren aktuell nicht. 2. `chapters` und `video_links` referenzieren diese IDs weiterhin. 3. Die Constraints stehen auf `ON DELETE NO ACTION`. 4. Die Verstöße bestanden bereits im ältesten gefundenen Snapshot vom 14.07.2026. 5. Der aktuelle produktive `db.py`-Pfad setzt `PRAGMA foreign_keys=ON`. 6. Der aktuelle `e2e_worker.py`-Verbindungsaufbau setzt ebenfalls `PRAGMA foreign_keys=ON`. ### Konkreter historischer plausibler Mechanismus Im archivierten E2E-Worker unter: ```text /opt/struktur/youtube-research/e2e-test/backups/20260718-103749/e2e_worker.py ``` existiert ein Reject-Pfad mit `DELETE FROM videos WHERE id=?`. Der dort sichtbare Verbindungsaufbau setzt `busy_timeout`, aber kein nachgewiesenes `PRAGMA foreign_keys=ON`. Im Reject-Pfad werden `chapters` und `video_links` nicht vorher gelöscht. Das passt technisch zum beobachteten Orphan-Muster: Ein Parent-Delete bei deaktivierter SQLite-FK-Prüfung kann Child-Zeilen zurücklassen. Dieser Pfad ist als **PLAUSIBEL** zu bewerten. Dass genau alle 27 betroffenen IDs durch diesen konkreten Lauf gelöscht wurden, ist nicht durch Run-/Job-Historie oder Parent-Metadaten nachgewiesen. ### Nicht nachgewiesen - exakter Erzeuger jedes einzelnen Orphans; - konkreter Löschzeitpunkt je Parent-ID; - ob IDs durch Reject, Cleanup, Restore oder eine andere historische Operation verschwanden; - `INSERT OR REPLACE INTO videos` als Ursache: im geprüften produktiven Writer-Code nicht nachgewiesen; - ein vollständiger historischer Run-/Attempt-Nachweis für alle 27 IDs. **Ursache noch nicht nachgewiesen.** ## I. Foreign-Key-Enforcement und aktuelles Risiko Aktuelle relevante Pfade: ```text /opt/struktur/youtube-research/db.py get_connection(): PRAGMA foreign_keys=ON delete_video(): löscht bekannte Child-Tabellen vor videos /opt/struktur/youtube-research/e2e_worker.py DB-Verbindung: PRAGMA foreign_keys=ON ``` Historische bzw. sonstige direkte SQLite-Verbindungen sind nicht durchgehend einheitlich instrumentiert. In den aktuellen produktiven Pfaden wurde jedoch kein weiterer sicherer `DELETE FROM videos`-Pfad mit fehlendem FK-Schutz gefunden. ```text AKTUELLES RISIKO: UNKLAR ``` Begründung: Der zentrale aktuelle Delete-/E2E-Code setzt FK-Prüfung, aber die gesamte Menge direkt öffnender Writer-Verbindungen und ihre Laufzeitaktivierung ist nicht als lückenloser Single-Writer-Nachweis bewiesen. Neue Orphans sind daher nicht sicher ausgeschlossen. ## J. Orphan-Klassifikation | Klasse | Anzahl Parent-IDs | Entscheidung | |---|---:|---| | `RECOVER_PARENT` | 0 | Parent nicht vollständig autoritativ rekonstruierbar | | `REMAP_CHILDREN` | 0 | kein anderer Parent eindeutig nachgewiesen | | `DELETE_ORPHAN_CHILDREN` | 0 | fachliche Obsoleszenz nicht bewiesen | | `UNCLEAR` | 27 | manuelle/weitere historische Prüfung erforderlich | Es werden keine Dummy-Videos angelegt und keine Child-Zeilen gelöscht oder umgehängt. ## K. Reparaturplan, nicht ausgeführt ### Für `UNCLEAR` 1. Child-Zeilen unverändert erhalten. 2. Historische Import-/Reject-/Cleanup-Logs gezielt nach den 27 IDs oder den zugehörigen damaligen YouTube-IDs suchen. 3. Falls eine vollständige Parent-Zeile aus einem autoritativen Snapshot gefunden wird: `RECOVER_PARENT` auf einer Kopie simulieren. 4. Falls nur eine zweifelsfreie andere Parent-ID nachgewiesen wird: `REMAP_CHILDREN` ausschließlich auf einer Kopie simulieren. 5. Keine Löschung ohne fachliche Entscheidung und Informationsverlustnachweis. ### Zulässige spätere Reparaturvarianten - **Parent restaurieren:** nur mit vollständiger, eindeutiger Parent-Provenienz; - **Children remappen:** nur bei zweifelsfreier Identität; - **Child-Löschung:** derzeit nicht freigegeben; - **Unverändert/manual review:** aktueller sicherer Zustand. Eine Reparatursimulation wurde nicht durchgeführt, weil für keinen der 27 Fälle eine eindeutige verlustfreie Operation vorliegt. ## L. P34-Auswirkung Bewertung: ```text GLOBALER ALTBESTAND ``` Begründung: - Die FK-Verstöße betreffen `chapters` und `video_links` → `videos`. - Die geplante KU-Schemaerweiterung betrifft `knowledge_units` und eine neue Provenienz-/Review-Struktur. - Zwischen den 485 Orphans und den geplanten KU-Feldern besteht kein direkter Foreign-Key-Zusammenhang. - Der frühere P34-Test wurde blockiert, weil der globale Abnahmetest `foreign_key_check=0` verlangte, nicht weil die KU-Migration technisch auf `videos` angewiesen ist. Für eine globale Qualitätsfreigabe der gemeinsamen KnowledgeDB bleibt der Befund trotzdem ein Abnahmeblocker, bis eine dokumentierte Reparatur- oder Ausnahmeentscheidung vorliegt. ## M. Dashboard Keine Dashboard-Änderung in diesem Auftrag. Eine spätere technische Überwachung sollte getrennt ausweisen: ```text FK-Verstöße gesamt betroffene Child-Tabellen fehlende Parent-IDs ältester bekannter Snapshot RECOVER_PARENT / REMAP_CHILDREN / DELETE_ORPHAN_CHILDREN / UNCLEAR ``` ## N. Empfehlung **Primäre Empfehlung: D – Ursache weiterhin unklar, keine produktive Änderung zulässig.** Eine Teilreparatur ist derzeit nicht sicher genug, weil für keinen der 27 fehlenden Parent-Datensätze eine vollständige, eindeutige Rekonstruktion oder ein zweifelsfreies Remapping nachgewiesen wurde. P34 darf erst nach einer separaten Entscheidung über `foreign_key_check=485` fortgesetzt werden. Ein kontrollierter KU-Pilot sollte nicht als Reparatur der Video-Altlast missbraucht werden. ## O. Schutzstatus ```text Produktive DB verändert = 0 KU-Migration = 0 KUs neu = 0 Backfill = 0 graphiti_release = 0 Graphiti-POSTs = 0 Neo4j-Writes = 0 Gold-Promotion = 0 FK-Reparatur = 0 ``` ## P. Artefakte Audit-JSON mit vollständiger `foreign_key_check`-Liste: ```text /opt/struktur/reports/aa043-p34-r1/20260827T230113Z/AA-043-P34-R1-audit.json ``` Der Abschlussbericht wird zusammen mit dem vollständigen Audit-JSON und den geprüften Skript-Hashes unter einem timestamped P34-R1-Verzeichnis abgelegt. ## Abschluss Arbeitsauftrag AA-043-P34-R1 erledigt – 485 historische Foreign-Key-Verstöße vollständig klassifiziert und sichere Reparatur-/Ausnahmeentscheidung für die Fortsetzung von P34 vorbereitet.