Explorer
/proc/560/root/tmp/write_forensics_report.py
← Zurück ↓ Download
import json,datetime
from pathlib import Path
d=json.load(open('/tmp/retrieval_forensics.json')); L=[]
def a(x=''):L.append(x)
def text(x,n=240):return str(x or '').replace('\n',' ')[:n]
def ident(x):return x.get('youtube_id') or x.get('source_identity') or x.get('id') or x.get('fact','')[:80]
a('# Wissenspipeline – Deep-Research-Retrieval-Forensik');a();a(f"**Read-only-Erhebung:** `{d['checked_at']}` UTC  ");a('**Keine Änderungen:** Ranking, FTS5, KUs, Graphiti, Testquellen, Scope und Prompts wurden nicht verändert.');a()
a('## 1. Executive Summary');a();a('- Der aktuelle Query-Code verwendet fünf Schichten: `videos_fts`/FTS5, `kdata_fts`, `knowledge_units`, Graphiti `/search` und einen begrenzten Obsidian-Testfallback.');a('- FTS5 liefert echte BM25-Scores; K-DATEN-FTS5 liefert keinen Score und kein `ORDER BY`, sondern die ersten bis zu 12 MATCH-Zeilen.');a('- Knowledge Units werden mit `ORDER BY id DESC LIMIT 10` selektiert; es gibt keinen KU-Relevanzscore. Die letzten vier werden in den Synthese-Kontext übernommen.');a('- Graphiti liefert Facts ohne verlässlichen Score; die API-Antwort enthält im verwendeten Pfad nur Fact und Score, keine belastbare Source-Identity pro Fact.');a('- Obsidian-Sprintdateien werden in `obs()` nur über Dateiname und Token-Vorkommen gefunden, bis zu sechs Treffer, ohne Source-/Derived-/Synthetic-Rankinggewicht.');a('- Der Final Context ist eine feste Quoten-/Reihenfolgelogik: Obsidian alle Treffer, K-DATEN bis 8, KUs bis 4, FTS5 bis 4, Graphiti bis 4; anschließend 12.000 Zeichen Gesamtkontext.');a('- Der Heinz-Eisen-Kontrollfall findet nach dem Pilot echte K-DATEN-FTS5- und KU-Kandidaten; finale Primärdokumente sind im RAW-Candidate-Set vorhanden, aber die K-DATEN-FTS-Reihenfolge ist nicht fachlich priorisiert.');a()
a('## 2. Aktuelle Retrieval-Pipeline');a();a('| Schicht | Implementierung | Rohlimit | Score | Final-Context-Regel |');a('|---|---|---:|---|---|');a('| YouTube-FTS5 | `fts()` → `videos_fts MATCH`, `ORDER BY score DESC` | 8 | `-bm25()` | erste 4 |');a('| K-DATEN-FTS5 | `kfts()` → `kdata_fts MATCH` | 12 | keiner | erste 8 |');a('| Knowledge Units | `kus()` → `statement LIKE`, `ORDER BY id DESC` | 10 | keiner | erste 4 |');a('| Graphiti | `graph()` → `POST /search` | 8 | API liefert häufig `null` | erste 4 |');a('| Obsidian | `obs()` → nur `Solutions/Nutzwert-Sprint-*.md`, Token Count | 6 | `relevance` als Dateitrefferzahl | alle gefundenen |');a();a('Nach der Rohabfrage werden FTS nach Video-ID, K-DATEN nach `source_identity`, KUs nach `(source_identity, statement)` und Graphiti nach Fact-Text dedupliziert. Diese Deduplizierung findet innerhalb der jeweiligen Schicht statt; ein generisches Cross-Layer-Source-/Derived-Join existiert nicht.');a()
a('## 3. Testfragen und Roh-/Final-Matrix');a()
for label,x in d['questions'].items():
 a(f"### Frage {label}");a();a(f"**Frage:** {x['question']}");a(f"**Tokens:** `{', '.join(x['tokens'])}`");a(f"**FTS-Ausdruck:** `{x['fts_query']}`");a();a('| Retriever | Rohkandidaten | Scorebereich | Final übernommen |');a('|---|---:|---|---:|')
 for layer,rows in x['raw_candidates'].items():
  scores=[r.get('score') for r in rows if isinstance(r.get('score'),(int,float))]; sr=f"{min(scores):.3f}–{max(scores):.3f}" if scores else 'kein Score'; final=sum(b['layer']==('videos_fts5' if layer=='fts5' else layer) for b in x['final_context']); a(f'| `{layer}` | {len(rows)} | {sr} | {final} |')
 a();a('#### RAW CANDIDATES');a();a('| Layer | Rang | Rohscore/Relevanz | Source Identity/ID | Titel/Pfad/Statement/Fact | Behandlung/Grund |');a('|---|---:|---:|---|---|---|')
 for layer,rows in x['raw_candidates'].items():
  for rank,r in enumerate(rows,1):
   sc=r.get('score',r.get('relevance','—')); ii=ident(r); title=r.get('title') or r.get('original_path') or r.get('statement') or r.get('fact') or r.get('path') or ''
   finalpos=next((i+1 for i,b in enumerate(x['final_context']) if b['layer']==('videos_fts5' if layer=='fts5' else layer) and b['identity']==ii),None)
   reason='übernommen in Schichtquote' if finalpos else 'nach Rohlimit/Finalquote nicht übernommen'
   a(f'| `{layer}` | {rank} | {sc} | `{text(ii,130)}` | {text(title,260)} | {reason} |')
 a();a('#### FINAL CONTEXT');a('| Position | Layer | Identity | Technische Positionierungsregel |');a('|---:|---|---|---|')
 for i,b in enumerate(x['final_context'],1):a(f"| {i} | `{b['layer']}` | `{text(b['identity'],180)}` | {text(b.get('reason'),180)} |")
 a();a('Die Rohkandidaten sind die tatsächlich aus den jeweiligen Funktionen zurückgegebenen Zeilen. „Final übernommen“ bedeutet nur, dass die Zeile nach der schichtinternen Deduplizierung in die feste Kontextquote gelangte; es bedeutet nicht fachliche Richtigkeit.');a()
a('## 4. Nutzwert-Sprint-Dokumente');a();a('| Datei | Source Identity | Klassifikation | Zeitpunkt/Größe | Retriever | Rankingbehandlung |');a('|---|---|---|---|---|---|')
for x in d['sprint_sources']:a(f"| `{x['path']}` | `{x['source_identity']}` | {x['source_type']} | {x['mtime']} / {x['size']} B | Obsidian-Fallback; Importer-State `done`, kein Graphiti-UUID-Feld | keine Test-/Derived-Abwertung; wenn Tokenmatch, vollständig in Kontext |")
a();a('Die vier Dateien wurden am 2026-09-03 über den bestehenden Obsidian-Importer-Lauf erkannt und als `done` im Importer-State geführt. Im verwendeten Query-Code gibt es jedoch keine Abfrage von Importer-State, `document_type`, `promotion_policy`, `source_version` oder Synthetic-/Test-Markierung. Der Obsidian-Fallback prüft nur Name, Text und Tokenhäufigkeit.');a('Sie erscheinen deshalb bei A–C wiederholt prominent, weil ihre Inhalte die allgemeinen Frage-Tokens enthalten und der Fallback alle passenden Sprintdateien priorisiert vor K-DATEN, KU, FTS und Graphiti in den Kontext einfügt.');a('Ob sie als unabhängige Evidence gezählt werden, wird nicht semantisch verhindert: Die Source Identity ist je Datei verschieden; ein Cross-Layer-Join zu Originalquellen existiert für diese Testdateien nicht.');a()
a('## 5. Bekannte Hermes-/Agenten-/Second-Brain-Quellen');a();a('Die gezielte Bestandsprüfung bestätigt, dass relevante Quellen vorhanden sind, unter anderem:');a('- Hermes: YouTube-ID `6KSjegH9vIA`, „Der erste KI-Agent, der sich selbst verbessert“; `0bNutTb5KwE`, „Obsidian macht Claude Code 10x schlauer“; `TlaR2_IRLUA`, „Ist Hermes der OpenClaw-Killer?“');a('- Second Brain/Obsidian: `NVUCQ-pzBn4`, „Obsidian + Claude Code: So baust du dein zweites Gehirn“; `LKp0xwbGsRY`, „Claude Code + Obsidian bauen mein Second Brain!“');a('- Agenten/Autonomie: `RXNGGNASt8I`, „Die nächste Stufe hat begonnen - Claude Code Agents sind da“; `DFgZud3ayXw`, Context Engineering/Claude-Code-Kurs; `8rXugE921aY`, Codex/Automationen.');a('- Subagents/Skills: `mfg2G1cNfnc`, `AAC4npr_qdk`, `9nnsszlfE0w` und mehrere Skill-/Agent-Kurse.');a('- Kosten/Token: `Le4oP-3mFes`, „OpenClaw Kosten um 97% reduziert“; `NS2NrRzcyHI`, OpenWebUI/OpenRouter.');a('- LLM-Wiki/Wissensbasis: `RU8Ad_5rrnE`, `7rXwA_1Ye5c`, `O-KNlOXwemI`.');a();a('Diese Quellen sind in Videos/FTS5 und teilweise als Obsidian-Artefakte/KUs vorhanden. Ob sie bei A–C in den jeweiligen FTS-Rohkandidaten auftauchen, hängt vom wörtlichen OR-Tokenausdruck ab; semantische Query Expansion gibt es nicht. Die vorhandene Quelle `u2b6Gfpe_U4` („RAG, Hybrid-Suche oder Wiki?“) erscheint z.B. bei A, andere inhaltlich passende Hermes-/Second-Brain-Quellen nicht in den jeweiligen Top-8-Rohlisten. Sie gehen nicht durch einen späteren Filter verloren, sondern werden bei der jeweiligen Rohabfrage gar nicht geliefert oder liegen außerhalb der festen Quote.');a()
a('## 6. Detailanalyse Frage A');a();a('- Die Rohabfrage liefert 8 YouTube-FTS5-Kandidaten, darunter direkt relevante Treffer wie `wYfDIzG5cuw` (Paperclip/Agenten) und `u2b6Gfpe_U4` (RAG/Hybrid-Suche/Wiki), aber auch allgemeine Claude-/NotebookLM-Videos.');a('- Die vier Nutzwert-Sprint-Dokumente werden vor allen anderen Schichten in den Final Context eingefügt. Das erklärt ihre Dominanz: Positionierung ist regelbasiert, nicht aus einem gemeinsamen Score abgeleitet.');a('- K-DATEN-FTS liefert bei A trotzdem 12 Heinz-Eisen-Projektkandidaten, obwohl die Frage nicht projektbezogen ist. Ursache ist fehlende Relevanzsortierung im `kdata_fts`-SELECT und OR-Matching allgemeiner Tokens.');a('- Fachlich relevante Agenten-/Second-Brain-Quellen werden nicht durch einen dokumentierten Ausschlussfilter verdrängt; sie erscheinen nur dann, wenn sie das wörtliche FTS5-OR-Matching treffen und in die Top-8 gelangen.');a('- Die 10 stärksten rein fachlichen Kandidaten lassen sich mit dem aktuellen System nicht belastbar als globale Top-10 bestimmen, weil die Retriever-Skalen nicht vergleichbar sind und K-DATEN/KU/Graphiti keinen vergleichbaren Score besitzen. Die forensisch sichtbaren direkten Kandidaten sind `wYfDIzG5cuw`, `u2b6Gfpe_U4`, `81pDusm5nZE`, `NVUCQ-pzBn4`, `LKp0xwbGsRY`, `6KSjegH9vIA`, `RXNGGNASt8I`, `DFgZud3ayXw`, `mfg2G1cNfnc` und `3FreGdxznSs`; das ist eine fachliche Prüfliste, kein gemessener gemeinsamer Rang.');a()
a('## 7. Detailanalyse Frage B');a();a('- Frage B erhält wie A eine feste Obsidian-Sprintquote, zusätzlich K-DATEN-Projektinhalte, obwohl die Frage allgemein KI-Agenten-Ausfälle/Kosten betrifft.');a('- Die KUs für B enthalten bereits konkrete Heinz-Eisen-Liefer-/Rechnungsformulierungen, weil „Kosten“, „Lieferung“, „Menge“ oder andere breite Tokens matchen. Diese sind formal `PLAUSIBEL/PENDING`, werden aber nicht nach Projektrelevanz bewertet.');a('- FTS5 liefert mehrere Agenten-/Wissensbasis-/Best-Practice-Videos, darunter `1Vcs4Jhca7c`, `9PFTLjuELs8` und `u2b6Gfpe_U4`; sie erscheinen in der FTS-Quote, nicht in einer gemeinsamen Rankingentscheidung.');a('- Graphiti liefert breite Facts wie KI-Agenten-/Remotion-/Digital-Twin-Aussagen ohne einheitliche Source-Metadaten im Response.');a('- Der tatsächliche Beitrag einer Quelle zur finalen LLM-Antwort ist aus dem System nicht rückwirkend als Attribution messbar; der Kontext markiert Schicht und Identity, nicht die später verwendeten Sätze.');a()
a('## 8. Detailanalyse Frage C');a();a('- C findet FTS5-Quellen zu Second Brain, Claude Cowork, Kosten und Automatisierung, aber auch breite/irrelevante Treffer.');a('- Sprint A–C gelangen durch den eigenen Obsidian-Fallback in den Kontext, sobald ihre generischen Tokens matchen; es gibt keine Abwertung wegen Test-/Synthetic-Status.');a('- K-DATEN liefert acht Heinz-Eisen-Dokumente in der Roh-/Finalquote, obwohl die Frage Agenten-Langzeitbetrieb betrifft. Das ist ein direkter Beleg für die fehlende Relevanzsortierung des K-DATEN-FTS.');a('- Quellen zu „Langzeitbetrieb“ fehlen als wörtlicher FTS5-Begriff (`Langzeitbetrieb` liefert 0 in der gezielten Topicprüfung), obwohl inhaltlich verwandte Quellen zu Loops, Skills, Kosten, Second Brain und Agenten vorhanden sind. Das ist Query-/Token-Limitierung, keine nachgewiesene Datenabwesenheit.');a()
a('## 9. Kontrollfall Heinz Eisen');a();a('- Nach dem K-DATEN-Pilot findet Frage D echte K-DATEN-FTS5-Kandidaten, K-DATEN-KUs und die vorhandenen Obsidian-Sprintdateien.');a('- K-DATEN-FTS5 liefert 12 Kandidaten ohne Score. Die finale Auftragsbestätigung und beide Projekt-Excel-Dateien sind in den Rohkandidaten vorhanden, aber ihre Position ist nicht aus einer fachlichen Scorefunktion abgeleitet.');a('- K-DATEN-KUs liefern relevante Statements, darunter „Lüftungseinheiten ... 5 Geräte gesamt“, „Lieferung von 5 ... SmartFan Pro BT“ und die finale Auftragsbestätigung mit 5.');a('- Frühere 4er- und 6er-Angebote sind ebenfalls im Bestand. Die aktuelle Query-Schicht besitzt keine explizite Regel „finale Auftragsbestätigung > älteres Angebot“. Ein LLM kann den zeitlichen/document-type-Kontext interpretieren, aber die Priorisierung ist nicht formal im Retriever abgesichert.');a('- Primärquellenkette ist vorhanden: Original → `kdata_documents`/SHA-256 → Derived Markdown → `kdata_fts` → KU/Provenienz → Queue. Die drei Primär-Graphiti-Queue-Zeilen 1327, 1328 und 1340 stehen aktuell auf `retry_wait` wegen Provider-HTTP-429; keine Graphiti-Episode ist dafür bestätigt.');a()
a('## 10. Score-Normalisierung, Merge und Ranking');a();a('| Retriever | Messbarer Bereich in diesem Lauf | Normalisierung | Fusion |');a('|---|---|---|---|');a('| YouTube-FTS5 | A 11.583–14.689; B 9.457–13.159; C 12.504–16.832; D 9.980–12.801 | nein, nur BM25 innerhalb FTS | feste Quote 4 |');a('| K-DATEN-FTS5 | kein Score | nein | SQL-Reihenfolge/erste 8 |');a('| Knowledge Units | kein Score; `id DESC` | nein | feste Quote 4 |');a('| Graphiti | meist `null` | nein | Antwortreihenfolge/erste 4 |');a('| Obsidian | Token-Relevance intern; nicht als Score ausgegeben | nein | alle bis 6, vor anderen Schichten |');a();a('Scores verschiedener Retriever sind technisch nicht vergleichbar. Es gibt keine Rank Fusion, keine z-Score-/MinMax-Normalisierung, keine Reciprocal-Rank-Fusion und keine globale Qualitäts-/Evidence-Gewichtung.');a()
a('## 11. Deduplizierung und Evidence-Zählung');a();a('- FTS5: Deduplizierung nach YouTube-ID/Video-ID.');a('- K-DATEN-FTS5: Deduplizierung nach `source_identity`, daher unterschiedliche Originaldateien bleiben unterschiedliche Kandidaten.');a('- KUs: Deduplizierung nach `(source_identity, statement)`, nicht nach Originalprojekt-/Dokumentfamilie.');a('- Graphiti: Deduplizierung nach Fact-Text, nicht nach Source Identity.');a('- Obsidian: dedupliziert nur über die im Fallback gebildete Identität; kein Join auf K-DATEN-Originalhash.');a('- Eine Original→Extraction→Derived→KU→Graphiti-Kette ist für K-DATEN relational vorbereitet, aber der Query-Merge behandelt die Repräsentationen nicht als einen Evidence-Ursprung über alle Schichten.');a('- Damit können mehrere Dokumentversionen und Derived-Repräsentationen parallel als Quellen erscheinen. Ob sie als unabhängige Belege gezählt werden, ist in der Query-Schicht nicht fachlich kontrolliert.');a()
a('## 12. Synthese-Prompt und Kontext');a();a('- Prompt in `knowledge_query.py:synth()` enthält: deutsche Antwort, quellengebunden, mehrere Belege kombinieren, Widersprüche/Unsicherheit benennen, nichts erfinden, Evidenzmangel ausdrücken.');a('- Modell: `qwen/qwen3.7-flash`; `temperature=0.1`; `max_tokens=5000`; HTTP-Timeout 60 Sekunden.');a('- Context-Reihenfolge: Obsidian-Testfallback, K-DATEN-FTS5, vier KUs, vier YouTube-FTS5, vier Graphiti-Facts. Gesamtlänge 12.000 Zeichen.');a('- Quellenlabels werden in den Kontext geschrieben; die spätere Antwort kann diese Labels zitieren, aber eine automatische Satz-zu-Quelle-Attribution wird nicht berechnet.');a('- Es gibt keine explizite Prompt-Regel „aktuelle Treffer sind nicht gleich vollständiger Wissensbestand“. Der Prompt fordert Evidenzgrenzen, verhindert aber nicht jede Generalisierung aus dem vorhandenen Kandidatenset.');a('- Providerfehler/HTTP 429 werden neutral behandelt; in diesem Forensiklauf wurden keine neuen Synthese-Writes ausgelöst.');a()
a('## 13. Hypothesen H1–H10');a();a('| Hypothese | Bewertung | Technischer Nachweis |');a('|---|---|---|');
rows=[('H1 Test-/Derived-Dokumente übergewichtet','bestätigt','Obsidian-Testfallback priorisiert Sprintdateien; kein Test-/Derived-Gewicht im Ranking.'),('H2 FTS5 passend, später verdrängt','teilweise bestätigt','FTS5-Kandidaten bleiben als vier feste FTS-Contextplätze; es gibt keine globale Fusion, aber sie werden nicht vollständig verdrängt.'),('H3 KU dominieren wegen fehlender Score-Normalisierung','teilweise bestätigt','KU `id DESC`, keine Scores; feste Viererquote, keine globale Dominanzmessung.'),('H4 Graphiti semantisch breit/unscharf','bestätigt','Facts ohne verlässlichen Score/Source-Attribution; mehrere fachfremde Facts in A–D.'),('H5 Retriever-Scores unvergleichbar','bestätigt','Nur FTS5 liefert BM25; K-DATEN/KU/Graphiti haben keinen gemeinsamen Score.'),('H6 Source/Derived nicht im Ranking','bestätigt','Rankingcode fragt weder `document_type`, `sensitivity`, `promotion_policy` noch Source/Derived ab.'),('H7 Derived-Repräsentationen zählen mehrfach','teilweise bestätigt','Schichtinterne Dedup vorhanden; kein Cross-Layer-Join von Originalhash/Source Identity im Merge.'),('H8 zu viele schwache Treffer/zu wenig Primärquellen','bestätigt','Feste Quoten plus 12.000-Zeichen-Truncation; irrelevante K-DATEN/Graphiti-Treffer gelangen in den Kontext.'),('H9 Query zu wortwörtlich','bestätigt','Tokens/OR bzw. LIKE; keine Synonym-/Topic-/Entity-Expansion; `Langzeitbetrieb` 0 trotz verwandter Quellen.'),('H10 Trefferabwesenheit wird als Bestandsabwesenheit interpretiert','teilweise bestätigt','Prompt fordert Evidenzgrenzen nicht Bestandsprüfung; Query liefert keine Vollständigkeits-/Coverage-Metrik.'),]
for r in rows:a(f'| {r[0]} | **{r[1]}** | {r[2]} |')
a()
a('## 14. Zentrale Root-Cause-Matrix');a();a('| Problem | Beobachtet | Root Cause bewiesen? | Technische Ursache | Betroffene Fragen | Schweregrad | Spätere Maßnahme |');a('|---|---|---|---|---|---|---|');a('| Sprint-/Synthetic-Priorisierung | Sprint A–D wiederholt vorn | ja | eigener Obsidian-Fallback vor allen Schichten, keine Markierungsgewichtung | A–D | NORMAL | Source-/Derived-/Teststatus in Relevanz und Contextquote berücksichtigen |');a('| K-DATEN ohne Relevanzscore | Heinz-Dokumente in A–C | ja | `kdata_fts` ohne `ORDER BY`/Score; OR-MATCH breiter Tokens | A–D | KRITISCH | kdata-Relevanzscore/Projektfilter/Rank-Join |');a('| Scores nicht vergleichbar | nur FTS5 BM25 | ja | keine Normalisierung/Fusion | A–D | KRITISCH | getrennte Schichtscores plus kontrollierte Rank Fusion |');a('| KU-Auswahl nach ID | aktuelle/zuletzt angelegte KUs bevorzugt | ja | `ORDER BY id DESC LIMIT 10`, keine Relevanz-/Sourcequalität | A–D | NORMAL | KU-Suche mit Source-/Statement-/Relevanzranking |');a('| Graphiti-Facts unscharf | fachfremde Facts | ja | `/search` liefert breite Facts, Score null, keine Source-Attribution | A–D | NORMAL | Graphiti-Ergebnis mit Identity/Score/Scope filtern |');a('| Cross-Layer-Duplikate | gleiche Dokumentfamilie mehrfach möglich | teilweise | Dedup nur schichtintern | D, auch A–C | NORMAL | Originalhash/Source-Version über alle Layer joinen |');a('| Keine Coverage-Aussage | Kandidat ≠ vollständiger Bestand | ja | Query liefert keine Bestands-/Scope-Vollständigkeit | A–D | NORMAL | Antwortmetadaten um Coverage/Limitations ergänzen |');a('| Providerabhängigkeit | Synthese nicht jederzeit garantiert | ja | OpenRouter HTTP 429/Timeout | A–D | NORMAL | bestehende Provider-/Backoff-Policy prüfen, nicht im Forensikauftrag ändern |');a()
a('## 15. Maximal fünf priorisierte Maßnahmen');a();a('1. **KRITISCH – K-DATEN-Relevanzranking:** `kdata_fts` um scorebasierte Suche und `ORDER BY` ergänzen; Projekt-/Dokumenttyp- und Exact-Entity-Signale verwenden. Risiko: echte Treffer können bei falscher Gewichtung sinken. Test: Heinz-Kontrollfall plus A–C. Rollback: DB-/Codebackup.');a('2. **KRITISCH – gemeinsame Score-/Rank-Fusion:** FTS5, K-DATEN, KU und Graphiti nicht numerisch direkt vergleichen; pro Schicht normalisieren oder kontrollierte Rank Fusion mit festen Qualitätsregeln. Test: Kandidaten-/Context-Matrix vorher/nachher.');a('3. **NORMAL – Source/Derived/Test-Gate:** Sprint-/Synthetic-Dateien als Test/Derived markieren und nicht als unabhängige Evidence behandeln. Test: A–D mit Source-Counts. Rollback: Markierungs-/Codebackup.');a('4. **NORMAL – Cross-Layer-Identity:** Originalhash, Source Identity und Source-Version über FTS/KU/Obsidian/Graphiti zu einer Evidence-Kette verknüpfen. Test: K-DATEN-Primärquellen und drei Repräsentationsketten.');a('5. **NORMAL – Coverage-/Evidenzhinweis:** Antwort muss unterscheiden zwischen „nicht in Kandidaten“ und „nicht im Bestand“ und Limits/Scope anzeigen. Test: unbekannte Frage, D und gezielte Bestandsabfrage.');a()
a('## 16. Explizit nicht verändert');a('- keine Rankinggewichte');a('- keine Retriever abgeschaltet');a('- keine Sprint-/Testquelle gelöscht');a('- keine Scope Policy geändert');a('- keine Query Expansion eingebaut');a('- keine Embeddings/Graphiti-Daten geändert');a('- keine FTS5-Kandidaten verändert');a('- keine Knowledge Units geändert');a('- kein Synthese-Prompt geändert');a('- keine Datenbankmigration oder Queue-Aktion im Forensikauftrag');a()
a('## 17. Nachweisartefakt');a('- Roh-/Final-Matrix: `/tmp/retrieval_forensics.json`');a('- Query-Code: `/home/hermes/knowledge_query.py` bzw. `/opt/struktur/knowledge-pipeline-aggregator-staging/knowledge_query.py`');a('- K-DATEN-Adapter: `/home/hermes/kdata_adapter.py`');a('- Live Graphiti: `http://127.0.0.1:8644/search`');a('- Live Knowledge DB: `/opt/struktur/youtube-research/knowledge.db`');a('- Sprint-Importer-State: `/opt/struktur/obsidian-graphiti-import/obsidian_graphiti_import.db`');a();a('Arbeitsauftrag Wissenspipeline-Retrieval-Forensik erledigt.')
Path('/home/hermes/Wissenspipeline-Retrieval-Forensik.md').write_text('\n'.join(L)+'\n',encoding='utf8'); print({'path':'/home/hermes/Wissenspipeline-Retrieval-Forensik.md','lines':len(L),'bytes':Path('/home/hermes/Wissenspipeline-Retrieval-Forensik.md').stat().st_size,'last_line':L[-1]})