Skip to content

feat(orchestrator): --book-mode — Planung je Hauptkapitel, Extraktion global (#346) - #349

Merged
TillQuandel merged 1 commit into
masterfrom
feat/346-book-mode
Jul 18, 2026
Merged

feat(orchestrator): --book-mode — Planung je Hauptkapitel, Extraktion global (#346)#349
TillQuandel merged 1 commit into
masterfrom
feat/346-book-mode

Conversation

@TillQuandel

Copy link
Copy Markdown
Owner

Closes #346.

PR 3/3 des Implementierungsplans #345/#346 (baut auf PR 1 [Outline-Split, #348] + PR 2 [dedup_concept_candidates/cap_candidates_balanced, #347] auf).

Ablauf (Kurzfassung)

Neues CLI-Flag --book-mode (argparse mutually-exclusive-Group mit dem deprecated --by-chapter). Kapitel partitionieren nur die Planung, nie die Extraktion — Notes synthetisieren weiterhin über Kapitelgrenzen (Kern-Kontrakt).

  1. Nur bei nutzbarem Outline-Split (chunks[0].source == "outline" und len > 1) — sonst transparenter Fallback auf den Normalpfad mit Diagnose-Print.
  2. _run_planner_stage je Hauptkapitel (plan_text = hall_text = chunk.text).
  3. Kandidaten sammeln, chapter_keys index-aligned mitführen (Key = chunk.title); secondary_mentions kapitelübergreifend dedupliziert in related_mentions.
  4. Globale dedup_concept_candidates (Survivor-Keys per id() rückverfolgt, index-aligned rekonstruiert).
  5. Skip-Action-Kandidaten VOR dem Cap heraus (PR-2-Review-Erkenntnis), dann Budget min(n_Kapitel × BOOK_MODE_CONCEPTS_PER_CHAPTER, BOOK_MODE_MAX_TOTAL) (12/120) und cap_candidates_balanced mit chapter_word_counts.
  6. EIN globaler Extractor-Lauf: run_extractors_per_concept(text, merged_plan, …) mit Volltext.
  7. Background-Extractor hart aus (wie by-chapter, --by-chapter deaktiviert den Background-Extractor still (background_map={} hart verdrahtet) #102).
  8. Diagnose-Prints (Kapitel i/N; Rohkandidaten → nach Dedup → nach Cap).

_run_planner_stage ist ein reiner 1:1-Refactor aus _plan_and_extract (Planner-Call + Halluzinations-Filter). Der Konzept-Cap bleibt beim Aufrufer, weil book-mode den wortanteil-balancierten Cap fährt. Normal- und by-chapter-Verhalten unverändert.

Geänderte Dateien

  • generative/orchestrator.py--book-mode-Wiring, _run_book_mode, _run_planner_stage-Refactor, mutually-exclusive-Group, _background_extractor_by_chapter_skip_line mode-aware (rückwärtskompatibel).
  • generative/config.pyBOOK_MODE_CONCEPTS_PER_CHAPTER=12, BOOK_MODE_MAX_TOTAL=120 (ENV-Escape-Hatch).
  • generative/ui_strings.pyorch.arg.book_mode neu, orch.arg.by_chapter mit Deprecated-Hinweis.
  • generative/tests/test_book_mode_wiring.py — Contract-Tests (neu).

generative/pipeline/pdf_chunker.py (PR-1-Stand) unberührt.

Contract-Tests (test_book_mode_wiring.py, alle grün)

Test Kontrakt
test_normal_path_extracts_from_full_text Normalpfad plant auf Overview, extrahiert aus Volltext
test_by_chapter_extracts_from_chunk_text --by-chapter plant + extrahiert je Kapitel aus chunk.text
test_book_mode_plans_locally_extracts_globally Kern-Regression: Planner je Kapitel, EIN Extractor-Lauf, full_text == Volltext, Kandidaten aus beiden Kapiteln
test_book_mode_without_outline_falls_back_to_normal source != outline → Normalpfad (Planner genau 1x auf Overview) + Diagnose
test_planner_calls_equal_chapters_and_candidates_within_budget Planner-Calls == Kapitelzahl; Kandidaten ≤ Budget
test_book_mode_filters_skip_actions_before_cap Skip-Action-Kandidaten erreichen den Extractor nie
test_book_mode_dedups_secondary_mentions_across_chapters secondary_mentions einmal (dedupliziert) in related_mentions
test_book_mode_skips_background_extractor Background-Extractor läuft nie (auch bei aktivem Gate)
test_book_mode_and_by_chapter_are_mutually_exclusive Doppel-Flag → SystemExit
test_cap_budget_zero_keeps_only_secondary_mentions PR-2-Nachzügler: budget=0 → nur secondary_mentions überleben
test_cap_missing_chapter_word_count_no_crash PR-2-Nachzügler: Kapitel-Key ohne word-count → get(k,0)-Fallback, kein Crash

RED-Nachweis (TDD)

Vor der Implementierung (nur Testdatei vorhanden): 6 failed, 5 passed — die 6 book-mode-spezifischen Tests failten (u. a. test_book_mode_plans_locally_extracts_globallyassert 1 == 2, test_planner_calls…AttributeError auf BOOK_MODE_CONCEPTS_PER_CHAPTER, test_book_mode_skips_background_extractor → Background lief). Nach Implementierung: 15 passed (11 neu + 4 by-chapter-Bestandstests unverändert grün).

Suite

  • uv run pytest generative lib/decision_engine/tests shared/tests -q: 6293 passed, 11 skipped, 9 deselected (396 s).
  • ruff check generative/ lib/decision_engine/ shared/: All checks passed.
  • ruff format --check: already formatted.
  • uv sync --extra dev --locked sauber; Import-Herkunft aus Worktree bestätigt.

… global (#346)

Neues CLI-Flag --book-mode (mutually exclusive mit dem deprecated --by-chapter).
Kapitel partitionieren NUR die Planung, nie die Extraktion — Notes synthetisieren
weiterhin über Kapitelgrenzen (Kern-Kontrakt).

Ablauf: Planner je Hauptkapitel (nur bei nutzbarem Outline-Split, sonst transparenter
Normalpfad-Fallback mit Diagnose) → Kandidaten mit index-alignierten Kapitel-Keys →
secondary_mentions kapitelübergreifend dedupliziert in related_mentions → globale
dedup_concept_candidates → Skip-Action-Filter vor dem Cap → Budget
min(n_Kapitel x 12, 120) → wortanteil-balancierter cap_candidates_balanced → EIN
globaler Extractor-Lauf über den Volltext. Background-Extractor aus (wie by-chapter).

_run_planner_stage als reiner 1:1-Refactor aus _plan_and_extract (Planner-Call +
Halluzinations-Filter); Normal-/by-chapter-Verhalten unverändert.

config: BOOK_MODE_CONCEPTS_PER_CHAPTER=12, BOOK_MODE_MAX_TOTAL=120 (ENV-Escape-Hatch).

Closes #346.
@TillQuandel
TillQuandel merged commit d7246bd into master Jul 18, 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.

[MITTEL] Hybrid-Buchplanung: Planner je Hauptkapitel, Extraktion global (Konzeptdichte #343)

2 participants