Skip to content

refactor(generative): Wiring-Dedup + RunContext statt 19er-Tupel (#152)#227

Merged
TillQuandel merged 3 commits into
masterfrom
refactor/152-runcontext
Jul 12, 2026
Merged

refactor(generative): Wiring-Dedup + RunContext statt 19er-Tupel (#152)#227
TillQuandel merged 3 commits into
masterfrom
refactor/152-runcontext

Conversation

@TillQuandel

@TillQuandel TillQuandel commented Jul 12, 2026

Copy link
Copy Markdown
Owner

Setzt #152 um. Draft, bis die reale E2E-Abnahme nachgeholt ist (RAM-blockiert, s. u.). Closes #152 (bei Merge).

Was

  1. _plan_and_extract(...) — die zwei nahezu identischen Wiring-Blöcke (Normalpfad vs. --by-chapter: planner.run → filter_hallucinated → cap_actionable_concepts → secondary_mention-Filter → run_extractors_per_concept) sind dedupliziert; by-chapter iteriert über die gemeinsame Funktion. Jede Planner-/Extractor-Änderung berührt künftig EINE Stelle.
  2. RunContext (frozen Dataclass, generative/schemas/run_context.py, Muster CitationMeta/RuntimeConfig) ersetzt das 19er-Positions-Tupel von _run_extraction_stages; der --load-drafts-Pfad (_load_draft_state) liefert dieselbe Struktur (Rekonstruktion inkl. Zitier-Seite bei PDFs ohne /PageLabels = physischer Index statt gedruckter Seite (Offset-Sonderdrucke) #95/Zitat-Metadaten (Autor + Jahr) ohne Quellendeckung — LLM konfabuliert (Merrill 2006, Knowles→Landry 2019) #96/Subscription-Backend: CLI-Timeout (300s) killt Läufe bzw. verschluckt Konzepte still — kein Retry-Budget, Exit 0 trotz Verlust #210-Kommentare 1:1 migriert); main() greift per Attribut zu — kein Mega-Unpacking mehr.

Verhaltens-Erhalt (Kern des Reviews)

Alle 7 Pfad-Divergenzen bewusst parametrisiert erhalten (kein stiller Semantik-Wechsel): background_map={} hart im by-chapter (#102 bleibt offen), kumulatives remaining_concepts-Dekrement (Äquivalenz count_actionable == len(actionable) im Review verifiziert), chunk.text vs. overview/text als Planner-/Filter-Basis (drei getrennte Text-Params), related_mentions-Dedup, concept_map-setdefault-Merge, Stage-Labels/Ellipsis pro Pfad. Einzige gewollte Änderungen: by-chapter erbt durch die Dedup die Planner-/Extractor-_spans (No-op ohne Phoenix; BackgroundExtractor-Span bleibt korrekt Normal-only).

RED-Beweis (TDD)

test_orchestrator_quality_wiring.py von Positions-Indizes (result[7], result[-1], …) auf Attribut-Zugriffe umgeschrieben → gegen den Tupel-Code 2 failed (AttributeError: 'tuple' object has no attribute 'citation'/'quality_report') → nach Refactor grün. Keine Assertion abgeschwächt (Attribut-Asserts sind strikter).

Suite

5766 passed, 3 skipped, 4 deselected (339 s); ruff format+check sauber. CI-Smoke-E2E (voller main()-Stage-0–7 auf examples/zettelkasten-primer.pdf, LLM gestubbt, inkl. CrossRef-Override-Zweig der historischen Wiring-Bugs), by-chapter-capsys-Integrationstests: grün und unverändert. Der _save_draft_state_load_draft_state-Roundtrip war zunächst nur eine manuelle Probe (Kontrollrunden-Fund: keine CI-Abdeckung) — jetzt als committeter Regressionstest generative/tests/test_load_draft_state_roundtrip.py (Commit 91ef915: alle 19 RunContext-Felder, citation-Factory inkl. physical_pages-Spy; Suite 5766 → 5767 passed).

Offene Abnahme: realer E2E-Dry-Run (Grund für Draft-Status)

Der geforderte reale LLM-Lauf wurde protokollkonform NICHT gestartet: freier RAM die gesamte Session 1,1–2,1 GB (< 3-GB-Guard; RAM-Kill-Lehre aus den #185-Messläufen). Nachhol-Kommando (aus dem Worktree, sobald ≥ 3 GB frei):

ATOMIC_DB_PATH=<Worktree>/.cache/e2e-abnahme.db python generative/orchestrator.py --source examples/zettelkasten-primer.pdf --dry-run

Erfolgskriterien: Exit 0, ≥1 Note in .cache/eval/baseline/zettelkasten-primer/, kein [Stage-6-Crash], kein Traceback. Der Lauf ergänzt echte Backend-Calls + Stage 8 — die geänderte Wiring-Logik selbst ist durch Smoke+Suite+Roundtrip abgedeckt.

Reviews

  • Task-Review (Opus): Approved, 0 Critical/Important; alle 7 Divergenzen einzeln alt-gegen-neu verifiziert (inkl. Dekrement-Timing-Analyse und continue-Semantik des leeren Kapitels). 1 Minor: citation-Feld könnte Optional[CitationMeta] typisiert sein (Kosmetik, Backlog).
  • Cross-Model (Mistral magistral-medium): 0 Funde („verhaltenserhaltend, keine neuen Fehler").

Kontrollrunde (2026-07-12, zweite unabhängige Review-Ebene)

  • Opus-Kontroll-Review (Fehlerfindung mit Fokus Verhaltens-Erhalt + Behauptungs-Drift, Selbstverifikationspflicht, Laufzeit-Proben gegen den Worktree): 0 verhaltens-ändernde Bugs. Alle 7 Pfad-Divergenzen per Direktprobe reproduziert; count_actionable == len(actionable)-Äquivalenz per Probe bestätigt; RunContext-Konstruktion nutzt ausschließlich Keyword-Args (Positionsrisiko strukturell ausgeschlossen); stdout/Stage-Labels exakt erhalten. 8 Kandidaten aktiv widerlegt (u. a. Empty-Chapter-related-Akkumulation, Dekrement-Timing, source_path-Identität). Einziger Fund (Low, Coverage): die --load-drafts-Rekonstruktion hatte keinen committeten Regressionstest, und die Roundtrip-Formulierung im Body implizierte CI-Abdeckung — beides behoben: Test nachgezogen (91ef915), Body-Satz korrigiert (s. o.).
  • Mistral-Schwerpunkt-Resample (Linse Feld-für-Feld-Datenfluss / Tupel-Position→Feld-Zuordnung / by-chapter-Akkumulation): 0 Funde.
  • Mistral Runde 2 über den Nachbesserungs-Diff (nur Testdatei): keine Korrektheitsfehler; 1 als HOCH gelabelter, der Substanz nach kosmetischer Punkt (redundanter Konstanten-Assert len(TEXT.split()) == 10 neben dem eigentlichen ctx.word_count-Assert) — adjudiziert: harmlos, dokumentiert die Herleitung des Erwartungswerts, kein Handlungsbedarf.

Tilltime added 3 commits July 12, 2026 16:18
Frozen-Dataclass generative/schemas/run_context.py als benannter Ersatz fuer das
19er-Positions-Tupel, das _run_extraction_stages bisher zurueckgab. Stil analog
zu CitationMeta/RuntimeConfig ("einmal bauen, alle lesen"). Noch nicht verdrahtet
- reine Typ-Einfuehrung, damit dieser Commit gruen bleibt.
- Gemeinsame _plan_and_extract(): die duplizierte Planner->(Cap)->Background->
  Extractor-Kette (by-chapter vs. Normalpfad) liegt jetzt an EINER Stelle. Die
  bug-anfaellige Verdrahtung (welcher Text in planner.run/filter_hallucinated/
  run_extractors_per_concept, welche background_map) ist single-source; nur die
  7 dokumentierten Pfad-Divergenzen (Textbasis, Cap-Semantik, Background-Gate,
  related-Akkumulation, concept_map-Merge, Stage-Labels, Ellipsis) bleiben
  parametrisiert - Verhalten pro Pfad exakt erhalten.
- _run_extraction_stages und _load_draft_state liefern beide dieselbe
  RunContext-Struktur; main() greift per Attribut zu statt 19er-Tupel-Unpacking.
  Die load-drafts-Rekonstruktion (q_title/citation/word_count, #95/#96/#210)
  wandert nach _load_draft_state.
- Positions-Tests in test_orchestrator_quality_wiring.py auf Attributzugriff
  umgeschrieben (RED->GREEN-Hebel).
- Folge (Div. 7): by-chapter erbt Planner-/Extractor-Spans (Bookkeeping ohne
  model-Feld, keine Aggregations-Auswirkung); BackgroundExtractor-Span bleibt
  normalpfad-only, da by-chapter den Background-Extractor bewusst nicht faehrt.
…truktion (#152)

_save_draft_state -> _load_draft_state baut citation (ueber _build_citation
inkl. physical_pages-Zweit-Check #95/#96), q_title, word_count,
dropped_total und extractor_failures aus dem persistierten State neu auf -
bislang nur manuell verifiziert. Test fixiert alle 19 RunContext-Felder
gegen einen realistischen, minimalen Zustand ueber tmp_path (keine
LLM-/Netz-/Vault-Zugriffe).
@TillQuandel

Copy link
Copy Markdown
Owner Author

Reale E2E-Abnahme nachgeholt und BESTANDEN (2026-07-12 abends, entkoppelter Lauf nach Maintainer-Go trotz RAM < 3 GB):

  • --source examples/zettelkasten-primer.pdf --dry-run, isolierte DB (ATOMIC_DB_PATH → Worktree), echte LLM-Calls (planner/extractor sonnet-4-6, verifier/critic haiku-4-5).
  • Exit sauber, 0 Fehler-Signaturen (kein Traceback, kein [Stage-6-Crash], kein MemoryError — Log+stderr gegrept).
  • Artefakte: 1 Vault-Note (vault__Linking.md) + 1 Merge-Stub unter generative/.cache/eval/baseline/zettelkasten-primer/; 1 Note in quality_history (Stage-8-Eval lief mit).
  • Kennzahlen: 664,0 s gesamt (davon Stage-8 +171,6 s); 587.898 Tokens (Out 52.096, Cache-R 331.540, Cache-C 204.198).
  • Abgedeckter Pfad: Normalpfad real end-to-end (Planner → Extractor ×2 → Verifier/Critic → Writer → Stage-8); by-chapter + --load-drafts via Suite-Integrationstests (capsys bzw. Roundtrip-Regressionstest 91ef915).
  • Nebenbefund, KEINE Regression: [warn] DB-Write fehlgeschlagen: no such table: note_evals — der Orchestrator ruft init_db() nirgends auf (auf master identisch, per Grep beider Stände verifiziert); bei frischer ATOMIC_DB_PATH existiert das Schema nie und die Best-effort-Writes warnen still. Wird als separates Issue erfasst.

Ein erster Lauf-Versuch wurde nach ~7,5 min vom 10-Minuten-Tool-Timeout der Orchestrator-Session gekillt (Trace zeigte bis dahin gesunde Calls) — kein Code-Problem; Wiederholung entkoppelt via Start-Process.

Damit ist die Draft-Bedingung erfüllt.

@TillQuandel TillQuandel marked this pull request as ready for review July 12, 2026 17:52
@TillQuandel TillQuandel merged commit 56a3a39 into master Jul 12, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Orchestrator-Wartbarkeit: by-chapter-Wiring-Duplikation + 18er-Positions-Tupel -> RunContext

2 participants