feat(chain): F2 续写式链 continue_volume——上一章 accepted 正文作前文引子

- core write_chapter 支持续写模式:chain_key==continue_volume 时经注入的
  chapter_repo.latest_accepted 读上一章已验收终稿,build_continuation_context
  改写 volatile(仅断点后块,守不变量 #9;core 不 import apps/api)。
- ChapterDraftRepo 协议加 latest_accepted;draft_volume 行为不变(无回归)。
- apps/api SUPPORTED_CHAINS 加 continue_volume;run 端点透传 chain_key 选模式
  (chain_runner 经 initial_chain_state 把 chain_key 落入 ChainState)。
- 单测(mock 网关+MemorySaver+fake session):续写第二章请求含第一章正文;
  draft_volume 不注入前文;端点 202 透传 chain_key。守不变量 #1/#5。
This commit is contained in:
Yaojia Wang
2026-06-23 20:09:08 +02:00
parent 61398a1452
commit 18aa87d751
4 changed files with 157 additions and 10 deletions

View File

@@ -252,6 +252,28 @@ async def test_run_chain_returns_202_and_schedules_job(
assert len(_noop_run_chain_job) == 1
async def test_run_continue_volume_chain_returns_202_and_forwards_chain_key(
_noop_run_chain_job: list[dict[str, Any]],
) -> None:
"""F2continue_volume 链受支持 → 202且 chain_key 透传给 run_chain_job续写模式"""
project_repo = FakeProjectRepo()
job_repo = FakeJobRepo()
pid = await _seed_project(project_repo)
app = _app(project_repo, job_repo)
async with _client(app) as client:
resp = await client.post(
f"/projects/{pid}/chains/continue_volume/run",
json={"start_chapter_no": 2, "count": 2},
)
assert resp.status_code == 202
body = resp.json()
assert body["chain_key"] == "continue_volume"
assert len(_noop_run_chain_job) == 1
assert _noop_run_chain_job[0]["kwargs"]["chain_key"] == "continue_volume"
async def test_run_chain_unknown_key_returns_404(
_noop_run_chain_job: list[dict[str, Any]],
) -> None: