Explorer
/tmp/restic-stage/reports-reference/content-extraction-manueller-workflow-20260702.md
← Zurück ↓ Download
# Content Extraction — Manueller Workflow (Kandidat erstellen + bewerten) — 2026-07-02

**Status: Implementiert, lokal vollstaendig getestet inkl. Duplikatpruefung. Kein systemd, keine Nginx-Bindung.**

## Vorher-Pruefung (Schritt 1)
- App existierte, content_extraction.db existierte
- ce_sources: 877 Zeilen
- ce_items: 0, ce_ratings: 0, ce_notes: 0 (alle leer)
- YouTube Research lief unveraendert (MainPID 1952952, aktiv seit 12:33:39 UTC)
- knowledge.db mtime Baseline: 2026-07-02 12:39:57.497487969 UTC

## Backup-Pfade
- /opt/struktur/content-extraction/backups/db.py.20260702-195531.bak
- /opt/struktur/content-extraction/backups/app.py.20260702-195531.bak
- /opt/struktur/content-extraction/backups/index.html.20260702-195531.bak
- /opt/struktur/content-extraction/backups/content_extraction.db.20260702-195531.bak

## Geaenderte / neue Content-Extraction-Dateien
- db.py — Schema-Migration fuer ce_ratings (nachahmbarkeit TEXT-Enum -> INTEGER 1-5, neue Spalte erwarteter_nutzen), neue Funktionen get_source(), create_item_from_source(), get_item_detail(), save_item_rating(); Konstanten CONTENT_TYPES (12 Werte) und STATUS_VALUES (5 Werte)
- app.py — /sources und /items jetzt HTML-Seiten statt JSON, neue Routen POST /sources/{id}/create-item, GET /items/{id}, POST /items/{id}/rating
- templates/index.html — Navigation zu /sources und /items ergaenzt, Import-JS nutzt jetzt Importstatistik statt (entferntem) JSON-/sources-Aufruf
- templates/sources.html (neu) — Quellenliste mit Button "Kandidat erstellen"
- templates/items.html (neu) — Kandidatenliste mit Rating-Uebersicht
- templates/item_detail.html (neu) — Detailseite mit Bewertungsformular (Content-Typ, Status, Nachahmbarkeit 1-5, Aufwand, Umsetzbarkeit, erwarteter Nutzen, Begruendung) + Begruendungs-Verlauf
- requirements.txt — python-multipart ergaenzt (fuer FastAPI Form-Handling)

Keine Aenderung an: /opt/struktur/content-extraction/config.py, /opt/struktur/youtube-research/ (gesamter Ordner unangetastet).

## Warum eine weitere Schema-Migration noetig war
ce_ratings hatte aus dem urspruenglichen MVP-Entwurf nachahmbarkeit als TEXT-Enum (niedrig/mittel/hoch) und keine Spalte erwarteter_nutzen. Dieser Auftrag fordert explizit Nachahmbarkeit als Integer 1-5 und ein zusaetzliches Feld "erwarteter Nutzen". Da ce_ratings zum Migrationszeitpunkt nachweislich 0 Zeilen enthielt, wurde die Tabelle sicher per DROP+CREATE auf das neue Schema migriert (kein Datenverlust moeglich, da leer). Die Migration ist defensiv: sie greift nur, wenn die Spalte erwarteter_nutzen fehlt UND die Tabelle leer ist -- bei vorhandenen Daten wuerde sie bewusst nichts tun.

## Content-Typen und Statuswerte (implementiert wie gefordert)
Content-Typen: Muster, Idee, Hook, Struktur, Argument, Anleitung, Beispiel, Vorlage, Checkliste, Story, Framework, Umsetzungskandidat
Statuswerte: offen, pruefen, interessant, umsetzen, verwerfen
Serverseitige Validierung: ungueltige Werte fuehren zu HTTP 400, kein stiller Fallback.

## Ergaenzte Routen
- GET /sources — HTML-Liste aller ce_sources mit Button "Kandidat erstellen" je Zeile
- POST /sources/{source_id}/create-item — erzeugt ce_item, liefert created:true/false
- GET /items — HTML-Liste aller Kandidaten mit Rating-Kurzansicht
- GET /items/{item_id} — Detailseite mit Quelldaten, Bewertungsformular, Begruendungs-Verlauf
- POST /items/{item_id}/rating — speichert Content-Typ, Status, Rating (4 Felder) und Begruendung in einem Aufruf

## UI-Ergaenzung
Quellenliste (Button pro Zeile), Kandidatenliste, Detailseite mit vollstaendigem Bewertungsformular. Keine automatische Bewertung, keine KI-Funktion -- alle Werte werden ausschliesslich manuell per Formular uebergeben.

## Lokaler Test ohne systemd (Schritt 9)
App manuell gestartet: venv/bin/uvicorn app:app --host 127.0.0.1 --port 8100 (nohup, kein systemd-Unit).

Waehrend des ersten Startversuchs fehlte die Abhaengigkeit python-multipart (fuer FastAPI Form(...)-Parameter) -- via pip installiert und requirements.txt ergaenzt, danach sauberer Start.

| Schritt | Ergebnis |
|---|---|
| /health | 200 |
| /sources (HTML) | 200, 877 Zeilen mit "Kandidat erstellen"-Buttons |
| POST /sources/1/create-item | 200 — {"item": {...id:1, source_id:1, content_type:"unbestimmt", status:"offen"...}, "created": true} |
| /items | 200 — "Content-Kandidaten (1)" |
| /items/1 | 200 — Detailseite mit Quelldaten und Formular |
| POST /items/1/rating (content_type=Hook, status=interessant, nachahmbarkeit=4, aufwand=niedrig, umsetzbarkeit=hoch, erwarteter_nutzen=hoch, rationale="Guter Hook, leicht uebertragbar auf eigene Videos") | 200 — vollstaendiges Item mit Rating und Notiz zurueckgegeben |
| /items/1 erneut abgerufen | 200 — Werte korrekt im Formular vorausgewaehlt, Begruendung im Verlauf sichtbar; per direkter DB-Abfrage verifiziert |
| POST /sources/1/create-item (Duplikatversuch) | 200 — {"item": {...id:1...}, "created": false} -- kein neues Item erzeugt |

Prozess danach sauber beendet, Port 127.0.0.1:8100 anschliessend frei, kein content-extraction-Prozess mehr aktiv.

## Getestete Quell-ID / erzeugte Kandidaten-ID
- Quelle: ce_sources.id = 1 (source_video_id 26, YouTube-ID FVuqEATzMWI, "Alle reden ueber Claude Skills... SO GEHT'S wirklich")
- Kandidat: ce_items.id = 1

## Gespeicherte Bewertung (ce_ratings.item_id = 1)
- nachahmbarkeit: 4
- aufwand: niedrig
- umsetzbarkeit: hoch
- erwarteter_nutzen: hoch
- Begruendung (ce_notes): "Guter Hook, leicht uebertragbar auf eigene Videos"
- Content-Typ: Hook, Status: interessant

## Duplikatpruefung
Zweiter Aufruf von POST /sources/1/create-item lieferte created:false und den bereits existierenden Kandidaten zurueck. ce_items blieb bei 1 Zeile. SQL-Pruefung (GROUP BY source_id HAVING COUNT(*) > 1) lieferte 0 Treffer -- keine Duplikate. Zusaetzlich strukturell durch UNIQUE(source_id)-Constraint auf DB-Ebene abgesichert.

## Verifikation (Schritt 10)
| Groesse | Vorher | Nachher |
|---|---|---|
| knowledge.db mtime | 2026-07-02 12:39:57.497487969 UTC | 2026-07-02 12:39:57.497487969 UTC — identisch, keine Aenderung |
| ce_sources | 877 | 877 — unveraendert |
| ce_items | 0 | 1 |
| ce_ratings | 0 | 1 |
| ce_notes | 0 | 1 |

## Bestaetigung: YouTube Research unveraendert
MainPID und ActiveEnterTimestamp von youtube-research.service vor und nach diesem Auftrag identisch (1952952, seit 12:33:39 UTC). Keine Datei unter /opt/struktur/youtube-research/ angefasst, kein Schreibzugriff auf knowledge.db (nur die bereits etablierte read-only Verbindung wurde in diesem Auftrag gar nicht neu aufgerufen -- der Workflow arbeitet ausschliesslich auf bereits importierten ce_sources-Daten).

## Bestaetigung: kein systemd / kein Nginx / kein oeffentlicher Zugriff
- Kein neuer systemd-Unit angelegt oder gestartet.
- Keine Nginx-Config angelegt.
- Keine Subdomain aktiviert.
- Keine automatische KI-Extraktion, kein Graphiti- oder Obsidian-Schreibzugriff, keine Fundus-Daten migriert.
- App lief nur temporaer manuell auf 127.0.0.1, wurde nach dem Test beendet.