"""WriterAgent 防御分支覆盖(P0 补测)。 覆盖:_resolve_prompt 直返回 Prompt、引擎异常状态无详情、LLM 返回非法 data 触发重试。 """ import pytest from types import SimpleNamespace from genesis.inference.types import Prompt from genesis.writer.writer_agent import WriterAgent, WriterGenerationError from genesis.writer.writer_state import WriterState from genesis.writer.models import ChapterSpec, GenerationContext class _Registry: def get_or_create(self, name, template): return Prompt(name=name, version="1", template=template) class _FailedEngine: def chat_structured(self, **kw): return SimpleNamespace(status="failed", data=None) # 无 error / error_code class _BadDataEngine: def chat_structured(self, **kw): return SimpleNamespace(status="ok", data={"title": "x", "blocks": None}) def _ctx(): return GenerationContext( chapter_id="db_design", title="DB 設計", template_marker=ChapterSpec(chapter_id="db_design", title="DB 設計", section_placeholder=None), structured_source="src", write_rules=["W"], design_rules=["D"], template_styles={"Heading 1"}, output_language="ja", ) def _agent(engine, max_retries=1): return WriterAgent( session_id="s", engine=engine, prompt_registry=_Registry(), state=WriterState(["db_design"]), max_retries=max_retries, ) def test_resolve_prompt_passthrough_when_registry_returns_prompt(): assert isinstance(_agent(_FailedEngine())._resolve_prompt(), Prompt) def test_engine_failed_status_without_details_raises(): with pytest.raises(WriterGenerationError, match="failed"): _agent(_FailedEngine()).generate_chapter(_ctx()) def test_invalid_llm_data_triggers_retry_and_raises(): with pytest.raises(WriterGenerationError, match="重试耗尽"): _agent(_BadDataEngine()).generate_chapter(_ctx())