"""Tests for dynamic word ceiling scaling. The standard generator's max_words used to be a fixed cap per tier; for a 600-word dense note dump on L3 it would compress to 140 words and silently drop observations. ``_scale_max_words_for_notes_density`` exists to let the cap stretch upwards when the inspector's bullets carry more content than the baseline assumes. """ from __future__ import annotations from app.generator.prompts import ( _bullets_word_count, _scale_max_words_for_notes_density, _word_target_for_involvement, ) def test_bullets_word_count_handles_empty() -> None: assert _bullets_word_count(None) == 0 assert _bullets_word_count([]) == 0 assert _bullets_word_count(["", " "]) == 0 def test_bullets_word_count_sums_words() -> None: bullets = ["roof tiles slipped at south elevation", "rising damp at rear"] assert _bullets_word_count(bullets) == 10 def test_scale_max_words_no_growth_for_sparse_notes() -> None: assert _scale_max_words_for_notes_density(180, 40) == 180 def test_scale_max_words_grows_for_dense_notes() -> None: grown = _scale_max_words_for_notes_density(180, 600) assert grown > 180 huge = _scale_max_words_for_notes_density(180, 3000) assert huge > grown def test_scale_max_words_respects_absolute_ceiling() -> None: huge = _scale_max_words_for_notes_density(180, 50_000) assert huge <= 2400 def test_word_target_grows_with_bullets() -> None: sparse = _word_target_for_involvement(3, 50) dense = _word_target_for_involvement( 3, 50, bullets=["damp " * 400], ) assert dense[1] >= sparse[1]