diff --git a/tests/render/test_render_html.py b/tests/render/test_render_html.py index 895db59..fbf46a3 100644 --- a/tests/render/test_render_html.py +++ b/tests/render/test_render_html.py @@ -93,3 +93,20 @@ def test_render_html_easy_layout_font_size(): html = render_html(_build_result()) assert "font-size: 18px" in html assert "text-align: left" in html + + +# Bug regression (2026-08-25): pipeline._final_verdict() escalates a REVISE that +# survives max_revise to HUMAN_REVIEW (spec 6.8 case d), but render_html() read +# result.fidelity.verdict — the pre-escalation value — so the exact "we could not +# fix it, so we stopped" case rendered as "수정 필요" instead of "검수 필요". +# The badge MUST follow EasyReadResult.verdict (the pipeline's final verdict). +def test_render_html_badge_follows_final_verdict_not_last_fidelity_check(): + result = _build_result() + result.fidelity = FidelityReport(slots=[], verdict=Verdict.REVISE) + result.verdict = Verdict.HUMAN_REVIEW + + html = render_html(result) + + assert "badge-human_review" in html + assert "검수 필요" in html + assert "수정 필요" not in html diff --git a/tests/web/test_handler.py b/tests/web/test_handler.py index ce2cba6..6823b0b 100644 --- a/tests/web/test_handler.py +++ b/tests/web/test_handler.py @@ -78,3 +78,20 @@ def test_handler_output_pictogram_src_is_gradio_servable(): assert 'src="assets/pictograms/' not in html, "raw core path leaked into Gradio HTML unrewritten" assert "/gradio_api/file=" in html, "pictogram present but not rewritten to Gradio serving scheme" assert str(webapp._PICTOGRAMS_DIR) in html + + +# Bug regression (2026-08-25): when the revise loop exhausts max_revise the +# pipeline's final verdict is HUMAN_REVIEW, but the web badge read +# result.fidelity.verdict (still REVISE) and showed "Fidelity 재교정됨 🔁" — +# a success signal on output that still has the amount missing. +def test_handler_badge_says_human_review_when_revise_loop_exhausts(): + # Always drops the amount and the deadline -> REVISE every round -> exhausted. + dropping = FakeProvider(default="건강보험료를 기한 안에 내세요.") + + _, _, fid_badge = webapp.simplify_handler( + "건강보험료 1,295,400원을 2026년 7월 17일까지 납부하세요.", None, + next(iter(webapp.LEVEL_CHOICES)), dropping, + ) + + assert "검수" in fid_badge + assert "재교정" not in fid_badge diff --git a/ttobak/render.py b/ttobak/render.py index 2c4c67b..0770256 100644 --- a/ttobak/render.py +++ b/ttobak/render.py @@ -57,7 +57,10 @@ def render_html(result: EasyReadResult) -> str: disclaimer, the (non-validated) K-ER score + per-rule violations, the fidelity verdict badge, and pictograms as file-path references only. """ - badge_class, badge_label = _VERDICT_BADGE[result.fidelity.verdict] + # The badge MUST show the pipeline's FINAL verdict, not the last single + # fidelity check: a REVISE that survives max_revise is escalated to + # HUMAN_REVIEW (spec 6.8 case d) and the reader has to see that. + badge_class, badge_label = _VERDICT_BADGE[result.verdict] template = _env.get_template(_TEMPLATE_NAME) return template.render( disclaimer=_DISCLAIMER, @@ -70,7 +73,7 @@ def render_html(result: EasyReadResult) -> str: {"rule": v.rule, "span": v.span, "severity": v.severity.value, "suggestion": v.suggestion} for v in result.ker.violations ], - fidelity_verdict=result.fidelity.verdict.value, + fidelity_verdict=result.verdict.value, fidelity_badge_class=badge_class, fidelity_badge_label=badge_label, pictograms=[{"src": _pictogram_src(p.glyph_id), "caption": p.caption} for p in result.pictograms], diff --git a/ttobak/web/app.py b/ttobak/web/app.py index 6e4d3c1..ef6f4f1 100644 --- a/ttobak/web/app.py +++ b/ttobak/web/app.py @@ -193,7 +193,7 @@ def simplify_handler(text_input: str, file_obj, level_label: str, provider: LLMP doc = parse(source, mime) result = simplify(doc, level, provider) html = _serve_pictograms_via_gradio(render_html(result)) - return html, _ker_badge(result.ker), _fidelity_badge(result.fidelity.verdict) + return html, _ker_badge(result.ker), _fidelity_badge(result.verdict) except Exception as exc: # noqa: BLE001 — 데모 UI는 어떤 실패도 메시지로 표시 msg = _html.escape(str(exc)) or "변환 중 오류가 발생했습니다." return f'
변환 오류: {msg}
', "", ""