feat(orchestrator): 续写链前一章无已验收终稿发 warning——静默丢前文引子可观测(CR-L1)
This commit is contained in:
@@ -13,6 +13,7 @@ from collections.abc import AsyncIterator
|
||||
from contextlib import asynccontextmanager
|
||||
from typing import Any
|
||||
|
||||
import structlog
|
||||
from langchain_core.runnables import RunnableConfig
|
||||
from langgraph.checkpoint.memory import MemorySaver
|
||||
from langgraph.types import Command
|
||||
@@ -446,6 +447,57 @@ async def test_write_chapter_continue_volume_injects_prior_accepted_text() -> No
|
||||
assert "前文正文" in write_input # build_continuation_context 的小节标题
|
||||
|
||||
|
||||
async def test_continue_volume_warns_when_prior_chapter_unaccepted() -> None:
|
||||
"""continue_volume 写第 2 章但第 1 章无已验收终稿 → 静默丢前文引子须发 warning(CR-L1)。"""
|
||||
h = _make_harness(conflicts=[])
|
||||
# accepted_store 故意留空:第 1 章尚无已验收正文 → 续写丢失前文引子(静默降级)。
|
||||
state = initial_chain_state(
|
||||
project_id=PROJECT,
|
||||
user_id=USER,
|
||||
start_chapter_no=2,
|
||||
count=1,
|
||||
chain_key="continue_volume",
|
||||
)
|
||||
|
||||
with structlog.testing.capture_logs() as logs:
|
||||
await write_chapter(
|
||||
state,
|
||||
gateway_builder=h["gateway_builder"],
|
||||
session_factory=h["session_factory"],
|
||||
memory_repos_factory=h["memory_repos_factory"],
|
||||
chapter_repo_factory=h["chapter_repo_factory"],
|
||||
assemble=h["assemble"],
|
||||
)
|
||||
|
||||
warning = next(e for e in logs if e["event"] == "chain_prior_accepted_missing")
|
||||
assert warning["log_level"] == "warning"
|
||||
assert warning["chapter_no"] == 2
|
||||
|
||||
|
||||
async def test_continue_volume_first_chapter_does_not_warn() -> None:
|
||||
"""第 1 章前一章号 < 1,无前文属预期(非降级)→ 不应发缺前文 warning。"""
|
||||
h = _make_harness(conflicts=[])
|
||||
state = initial_chain_state(
|
||||
project_id=PROJECT,
|
||||
user_id=USER,
|
||||
start_chapter_no=1,
|
||||
count=1,
|
||||
chain_key="continue_volume",
|
||||
)
|
||||
|
||||
with structlog.testing.capture_logs() as logs:
|
||||
await write_chapter(
|
||||
state,
|
||||
gateway_builder=h["gateway_builder"],
|
||||
session_factory=h["session_factory"],
|
||||
memory_repos_factory=h["memory_repos_factory"],
|
||||
chapter_repo_factory=h["chapter_repo_factory"],
|
||||
assemble=h["assemble"],
|
||||
)
|
||||
|
||||
assert not [e for e in logs if e["event"] == "chain_prior_accepted_missing"]
|
||||
|
||||
|
||||
async def test_continue_volume_chain_second_chapter_sees_first_chapter_text() -> None:
|
||||
"""全图 E2E:continue_volume 两章——第 2 章请求上下文含第 1 章正文(不变量 #1/#5)。"""
|
||||
h = _make_harness(conflicts=[])
|
||||
|
||||
Reference in New Issue
Block a user