fix(backlog): 修评审 3 HIGH — resume chain_key 真值 / 模板空白校验 / 续写链 resume E2E
1. resume_chain 回报真 chain_key:从 awaiting job.result 读回(run 时 _chain_result 持久化),不再按 job.kind 推断(kind 恒为通用常量 "chain",从不在 SUPPORTED_CHAINS → 总错回退 draft_volume)。continue_volume 的 resume 回执现报真值。 2. 模板 title/body 拒纯空白:StringConstraints(strip_whitespace, min_length=1), " " strip 后为空 → 422。 3. 续写链 resume 路径 E2E:continue_volume 第 1 章冲突 → interrupt → awaiting → resume 带裁决 → done,断言 resume 回执 / job result chain_key="continue_volume" (回归守卫 #1)。 测试:+resume continue_volume 单测(chain_key 真值)+2 模板空白 422 单测 +1 续写链 resume E2E。重生成 TS 客户端(仅 description 文案变化)。
This commit is contained in:
@@ -215,7 +215,9 @@ async def resume_chain(
|
||||
f"job {job_id} 已被并发续跑抢占或非 awaiting_input 态,不可重复续跑",
|
||||
)
|
||||
|
||||
chain_key = claimed.kind if claimed.kind in SUPPORTED_CHAINS else "draft_volume"
|
||||
# chain_key 真值:run 时 interrupt 把图 state 的 chain_key 持久进 job.result(_chain_result)。
|
||||
# 读回它,而非按 job.kind 推断(kind 恒为通用常量 JOB_KIND_CHAIN,从不在 SUPPORTED_CHAINS)。
|
||||
chain_key = _chain_key_from_result(claimed.result)
|
||||
|
||||
accept_op = build_accept_op(
|
||||
session_factory=session_factory,
|
||||
@@ -251,6 +253,17 @@ async def resume_chain(
|
||||
return ChainResumeAccepted(job_id=job_id, chain_key=chain_key)
|
||||
|
||||
|
||||
def _chain_key_from_result(result: dict[str, Any] | None) -> str:
|
||||
"""从 awaiting job 的 result 取真 chain_key(run 时由 _chain_result 持久化)。
|
||||
|
||||
缺失/非受支持 key(旧行/异常)→ 回退 "draft_volume"(保守默认,不崩)。
|
||||
"""
|
||||
key = (result or {}).get("chain_key")
|
||||
if isinstance(key, str) and key in SUPPORTED_CHAINS:
|
||||
return key
|
||||
return "draft_volume"
|
||||
|
||||
|
||||
def _chapter_repo_factory(session: AsyncSession) -> object:
|
||||
"""链节点(review 重读草稿)按 session 建 chapter draft repo。"""
|
||||
from ww_core.domain.chapter_repo import SqlChapterRepo
|
||||
|
||||
Reference in New Issue
Block a user