Yaojia Wang
|
ed0a679322
|
fix(backend): 多章链设显式 recursion_limit 防御硬化(CR-C2)
|
2026-07-08 10:32:37 +02:00 |
|
Yaojia Wang
|
72b3c81146
|
feat(review): 人物塑造 advisory 审(第五审,仅建议不阻断验收)
写→审链新增第五审「人物塑造」(灵感③/D2):advisory 单维——仅建议、不阻断
验收(不进 conflicts、不碰 assert_conflicts_resolved、不入 REVIEW_RESERVED_NAMES);
只做人物塑造、不做氛围。
- SPEC characterization_spec(analyst,reads=("characters",),writes=())+
prompts/characterization.md(只读、显式忽略文本长度与辞藻华丽度、引用逐字片段+置信度)
- schema CharacterizationReview{issues[...]}(全字段默认值守解析韧性)+ 注册 catalog
- 计数三处 22→23 + regen prompt_hashes.json(仅加一条)
- DB chapter_reviews 加 characterization JSONB nullable 列(迁移 f6a7b8c9d0e1)
- 接线:graph REVIEW_SPECS 追加 · chain ReviewRecordRepo · collect(extract/record) ·
review_repo(Protocol/Sql/_to_view/ReviewView) · sse(event/factory/section) · normalize 自动纳入
- 契约 ReviewHistoryItem 加 characterization(gen:api 已重生成)
- 前端 sse/history/useReviewStream + CharacterizationPanel(只展示无裁决 UI、置信度降序+低置信折叠)+ ReviewReport 挂面板
- 测试 test_characterization_does_not_block_accept + 计数/golden + collect/normalize + 前端 reducer/normalize/parse
守不变量 #2/#3/#9;依赖 ⑧(motive/appearance 作客观锚点)。
|
2026-07-06 17:08:38 +02:00 |
|
Yaojia Wang
|
1921b037a0
|
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 文案变化)。
|
2026-06-23 20:45:06 +02:00 |
|
Yaojia Wang
|
18aa87d751
|
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。
|
2026-06-23 20:09:08 +02:00 |
|
Yaojia Wang
|
d1ea83b191
|
fix(chain): 修评审 CRITICAL+HIGH — 链网关按 session 重建/日志脱敏/resume 原子化+所有权/死导入
- CRITICAL #1:链 write/review 节点经 gateway_builder 按节点自建 session 现建网关,
usage_ledger sink 绑活 session,随节点 commit 持久化;run_chain_job 不再转发请求网关
(其 session 在 BackgroundTask 跑时已关闭,记账行被静默丢弃)。新增 get_chain_gateway_builder
缝(仿 digest builder),get_chain_gateway 退化为纯 503 凭据预检。守不变量 #1。
- HIGH #2:chain_runner 失败日志不再记 str(exc)(可能含 key/连接串/LLM 输出),改记
_classify_job_error 脱敏文案 + exc_type(设计 §5)。
- HIGH #3:resume 端点原子抢占 awaiting→running(JobRepo.claim_awaiting_to_running 条件
UPDATE),抢不到 → 409,防并发 resume 双 Command(resume) 损坏图。
- HIGH #4:resume 校验 job.project_id == project_id(JobView 新增 project_id),不匹配 → 404。
- HIGH #5:resume 返回新 ChainResumeAccepted{job_id,chain_key},去掉无意义哨兵 start/count=0。
- HIGH #6:删 nodes.py 死导入 extract_conflicts(import + __all__)。
- 测试 #7:e2e 断言链跑后 usage_ledger 有行(#1 回归守卫)+ chapter_reviews 每章一行;
新增 claim 原子抢占单测 + resume 跨项目 404 / 并发 409 端点测。
|
2026-06-23 18:04:10 +02:00 |
|
Yaojia Wang
|
29349dc7ee
|
feat(api): C2 多章链 服务+端点+schema+checkpointer 接线
承 C1 链图(build_chain_graph),落地多章工作流链的 apps/api 壳:
- 3 端点 routers/chain.py:POST .../chains/{key}/run→202 ChainRunAccepted;
POST .../chains/runs/{job_id}/resume→202;GET /jobs/{id} 复用。校验:
count 1..50→422、未知 chain_key→404、resume 非 awaiting→409、无凭据→503。
- schemas/chain.py:ChainRunRequest/ChainRunAccepted/ChainResumeRequest
(ConflictDecision 复用 schemas/projects)。
- services/chain_runner.py:run_chain_job 仿 run_job 壳自建独立 session 驱动链图
(set_running→ainvoke→据 __interrupt__ 置 awaiting_input/done/failed);
build_accept_op 在 apps/api 装配验收事务闭包注入图节点(守 #3/#4);
token 不入 result/日志。
- services/chain_deps.py:get_checkpointer_factory(运行时 AsyncPostgresSaver
上下文 / 测试 MemorySaver)。
- 零迁移(设计 §7):复用 jobs,新增 status="awaiting_input" + JobRepo.set_awaiting,
awaiting 章经 result.awaiting_chapter;新错误码 ErrorCode.CONFLICT(409)。
- project_deps:build_chain_gateway/get_chain_gateway(按请求 tier writer/analyst/light
分派——单档网关恒返该档会错路由 review/digest)+ get_digest_gateway_builder。
单测 apps/api/tests/test_chain.py 12 用例(mock 网关 + MemorySaver + fake session/
accept_op,无 DB/无网络/无真 LLM):run/resume→202、未知 key 404、count 越界 422、
resume 非 awaiting 409、run_chain_job 无冲突→done、冲突→awaiting→resume→done、
错误脱敏、accept_op 冲突缺判→CONFLICT_UNRESOLVED。
门禁绿:ruff/format 干净 · mypy 193 Success · alembic 无漂移 · pytest 600 passed。
守不变量 #1/#3/#4/#5/#9。唯一新增 DDL(langgraph 检查点表)= C3 迁移。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
|
2026-06-23 17:12:53 +02:00 |
|