docs(chain): 补 PROGRESS 台账 — Chain Workflow 交付/交叉评审/CRITICAL修复/合并汇总 + 出口 + 剩余下一步

This commit is contained in:
Yaojia Wang
2026-06-23 18:40:20 +02:00
parent 513bf71689
commit 9627845abc

View File

@@ -111,6 +111,7 @@ T0.1 monorepo 骨架 ✅ @devops · T0.2 16 MVP 表迁移无漂移users st
> 格式:`- [YYYY-MM-DD] @skill 完成/进展 Txx — 一句话结果 + 影响的契约/文件`
- [2026-06-23] @orchestrator**🎉 多章工作流链Chain Workflow交付 + 多 agent 交叉评审 + CRITICAL 修复 + 合并 developmerge `513bf71`**。对标星月「一键多章」+ 差异化「每章过四审、遇冲突才停人」。设计契约 `docs/design/chain-workflow.md`commit `5ee9799`)。**多 agent 逐学科建造**(契约先行、目录单写者):**C1 @llm**(`7f3eaab`) LangGraph **cyclic 链图** `orchestrator/chain/{state,nodes,graph}.py``build_chain_graph`write→review→decide→accept 循环 + **interrupt-on-conflict** + resume删死代码 `build_write_graph``write_node` 本体留用7 单测 mock 网关+fake session+MemorySaver·**C2 @backend**(`29349dc`) 服务/3 端点/schema/checkpointer 接线(见下条)·**C3 @db**(`548b7ab`) langgraph 检查点 4 表迁移 `d3e4f5a6b7c8``autocommit_block` 避开 `CREATE INDEX CONCURRENTLY` 与 alembic 事务死锁;`env.py` `include_object` 豁免这 4 表防漂移误报)·**C4 @qa**(`061792d`) E2E `tests/test_chain_workflow_e2e.py` 真 pg + mock 网关零 token无冲突两章全自动 + 冲突→interrupt→awaiting→resume→accept。**3 路对抗交叉评审**python/fastapi/不变量)在**绿门禁下仍揪出 1 CRITICAL + 7 HIGH**——证伪"测试过=没问题"CRITICAL=链把**绑请求 session 的 gateway** 传进 BackgroundTask后台跑时 session 已关→write/review 的 `usage_ledger.record()` 写进死 session **静默丢失**(链计费全丢,违 #1E2E 清了 ledger 却没断言其存在故漏掉)。**修复**(`d1ea83b`):网关改 `chain_gateway_builder` 按节点 session 重建(仿 `digest_gateway_builder`/`style.py`);日志脱敏(`_classify_job_error`+`exc_type`,去 `str(exc)`§5resume 原子 claim `JobRepo.claim_awaiting_to_running`(防并发双跑同 thread_id非 awaiting→409+ 所有权校验(`JobView.project_id`跨项目→404`ChainResumeAccepted`(去 start/count=0 哨兵);删死导入 `extract_conflicts`**补回归断言**(链 `usage_ledger` 必有行 + `chapter_reviews` 每章一行)。**出口DoD✅**:后端门禁绿 ruff/format 干净 · mypy **194 Success** · alembic **无漂移**(业务表零迁移,复用 `jobs.status=awaiting_input` + `result.awaiting_chapter`;唯一新 DDL=langgraph 检查点表)· pytest **608 passed**+6 回归测)。首次真正启用 LangGraph checkpointer/interrupt。守不变量 #1/#3/#4/#5/#9。**剩余下一步(未做)**:① 前端链 UI`pnpm gen:api` 纳入 run/resume + 发起页/进度轮询/awaiting 裁决续跑面板,复用 `ConflictAdjudication`);② §12 文档回写 `ARCHITECTURE.md §5.2`(补 cyclic 链图 + 更正现状:写章直连流式/单章 accept 为事务/链图首启 checkpointer③ 未 push 远端。可选:续写/扩写节点入链UGC 链市场需多租户deferred
- [2026-06-23] @backend**✅ Chain Workflow C2多章链 服务+端点+schema+checkpointer 接线,分支 `feat/chain-workflow`**。承 C1(@llm)链图(`build_chain_graph` §3.3),落地服务/端点壳:① **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、项目不存在→404、resume job 不存在→404、resume 非 awaiting→**409 新码 `CONFLICT`**、无凭据→503。② **schema**`schemas/chain.py``ChainRunRequest/ChainRunAccepted/ChainResumeRequest``ConflictDecision` 复用)。③ **服务**`services/chain_runner.py``run_chain_job` 仿 `run_job` 壳自建独立 session 驱动链图set_running→ainvoke→据 `__interrupt__``awaiting_input``done`/`failed``build_accept_op` 在 apps/api 装配验收事务闭包注入图节点,守 #3/#4token 不入 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见 gotcha+ `get_digest_gateway_builder`。**单测**`apps/api/tests/test_chain.py` 12 用例mock 网关 + MemorySaver + fake session/accept_op无 DB/无网络/无真 LLMrun→202、resume→202、未知 key 404、count 越界(>50/0) 422、resume 非 awaiting 409、项目/ job 不存在 404、run_chain_job 无冲突→done+written 满、冲突→awaiting→resume→done、错误脱敏、accept_op 冲突缺判→CONFLICT_UNRESOLVED。**全仓门禁绿**ruff/format 干净、mypy **193 Success**、alembic **无漂移**(无 ORM 变更、pytest **600 passed**。守不变量 #1/#3/#4/#5/#9。记 contracts C-Chain 稳定 + 2 decision + 3 gotcha。**唯一新增 DDLlanggraph 检查点表)= C3 迁移;前端链 UI = 契约稳定后 @frontend follow-up本期非目标。**
- [2026-06-22] @orchestrator**🎉 T6 创作工具箱(通用生成器框架)全工具箱交付 + 独立复核(分支 `feat/t6-creation-toolbox`**。多 agent 并行波次Wave 0@llm T6.5 ‖ @backend 描述符类型 ‖ P2 收尾)→ Wave A@backend T6.2+T6.3 TOOLBOX+端点合龙,契约稳定点)→ Wave B@frontend T6.6 ‖ @qa T6.4)→ Wave C 收口,目录单写者零写冲突、契约先行、零返工。**@llm T6.5**`ww_agents` +7 输出 schema + 7 specbook-title/blurb/name/golden-finger/glossary/opening/fine-outline只声明 tier #2+ `build_outline_chapter_context`with_outline_chapter 策略)。**@frontend T6.6**`gen:api` 纳入 3 端点;`app/projects/[id]/toolbox/page.tsx`(RSC) + `components/toolbox/{ToolboxPage,ToolCard,GeneratorRunner}` + `lib/toolbox/*`(声明驱动纯函数,按 `input_fields` 渲染表单、按 `output_kind` 渲染预览、可入库者复用 `ConflictAdjudication` 走 409→ack+ LeftNav「工具箱」+ ⌘K `nav-toolbox`/`action-gen-*`legacy 3 跳现页不回归。**@qa T6.4**`tests/test_t6_toolbox_e2e.py` 5 用例真 pg + mock 网关零 token**未发现端点 bug**。**P2 收尾**:限流→`decisions.md` 记延后单用户原型noopener/Committable 经查本分支早已修;`provider_deps.py` 残留 `type:ignore` 为 SDK 私有属性探活、load-bearing 保留。**最终独立复跑全仓门禁绿**:后端 ruff/format 干净、mypy **195 Success**、alembic **无漂移**descriptor 在代码、复用既有表零建表迁移、pytest **583 passed**;前端 gen:api/lint/tsc/vitest **279**/build OK。守不变量 #2(只声明 tier/#3(预览不写库、入库经验收 gate/#9system_prompt 进缓存前块)。**"加生成器=加一份声明" 经实证8 个新生成器复用同一通用执行器 + 同一前端组件)。** **实景 browse 复验(工具箱卡片栅格→脑洞预览→词条入库)待做。** 后续可选 P5封面图像轨道 / 自定义 skill 运行期 schema / 收敛已有 3 竖井。
- [2026-06-20] UX计划 B0(可控版)+F1(控件) — **✅ 本章注入透明 可控版(分支 `feat/ux-b0-controllable-injection`,提交 `0d473e7` 后端 + `6449c31` 前端,未合 develop**。在 B0 读端点之上加作者微调,守不变量 #6「确定性选择」的作者兜底。**后端**(@backend/@db)`PUT /projects/{id}/chapters/{no}/injection``InjectionOverrideRequest{pinned,excluded,recent_n(1..20→422)}``InjectionResponse`(新增回显 `pinned`/`excluded``selected[].reasons` 可含新值 **`author_pin`**`select_relevant_entities``pinned/excluded` frozenset 入参pin 强制纳入加 author_pin / excluded 强制剔除且**优先于 pin**`assemble``override` 关键字参recent_n 覆盖回看章数);**GET injection + PUT + draft 流式端点同读同一覆盖**(看到的=写章用的)。持久化:**新表 `chapter_injection`**(迁移 `ad2c4c663daf`,唯一 `(project_id,chapter_no)`;复用 outline 行污染 beats 已否决)+ 新 `domain/injection_repo.py``InjectionOverride`/`EntityRef`/`SqlInjectionOverrideRepo`upsert 只 flush 端点 commit。**前端**(@frontend)`gen:api` 纳入 PUT + 新 schema`lib/workbench/injection.ts` override 纯函数(`currentOverride`/`withPinToggled`/`withExcluded`/`withRestored`/`withRecentN`/`isPinned`,钳 1..20`useInjection``saving` 态 + `togglePin/exclude/restore/setRecentN`PUT 后以服务端确定结果为准、写失败可读文案不改本地态);`ChapterAssistant` 每实体 📌置顶/✕排除 + 「近 N 章」步进器 + 「已排除」恢复区。**全仓门禁绿**:后端 ruff/format/mypy **163**/alembic 无漂移/pytest **476**;前端 lint/tsc/vitest **183**/build。记 contracts C3 再扩。**实景 browse 复验待做。** UX 计划余项R1/R2/R3 审稿人体学 + Tier4。