Extract _match_any helper and declarative _FORBIDDEN_MATERIAL_RULES table to replace repetitive per-category for-loops. Reduces cyclomatic complexity from C(11) to A(3). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add app/question_gen/postprocess.py with zero-LLM deterministic post-processing for generated questions: - shuffle_options: deterministic option permutation with answer remapping - check_referent_blacklist: detect self-referential language (this clip, etc.) - check_verbatim: word-level n-gram overlap ratio measurement - has_time_anchor: timestamp and temporal phrase detection - check_forbidden_material: T1/T7 source material validation - run_postprocess: orchestration returning PostprocessResult Tests: 31 unit tests covering all functions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>