diff --git a/_AI_USAGE_LOG.md b/_AI_USAGE_LOG.md index 96099de..3cb6238 100644 --- a/_AI_USAGE_LOG.md +++ b/_AI_USAGE_LOG.md @@ -82,4 +82,5 @@ | 2026-08-11 | Agent 实现 | T13(架构审查整改,P1):黄金集 + 评分器(OV4)。新建 src/genesis/eval/ 包:golden_set.py(GoldenCase/GoldenSet,YAML 加载,samples/ 真实脱敏样本作 input_ref 基线)、scorer.py(ChapterScorer 按 §7.2 指标体系打分);确定性维度 traceability(resolver 验证 source_uri 可解析率)/placeholder_residue(无 {{...}} 残留)/chapter_completeness(章节覆盖期望集合);LLM 语义维度经 llm_evaluators 钩子注入(默认中性分,待 Phase5);新增 tests/test_eval_scorer.py(9 用例:各维度/聚合/钩子/空输入);tests/fixtures/eval/golden_set.yaml 示例黄金集(2 case);同步 design.md §7.5 黄金集与评分器机制化说明(定位为 CI 质量门禁);TDD 验证 RED(模块缺失 + NameError)→ GREEN(聚焦 8 passed)→ 全量 240 passed 覆盖 100.00%(1279 stmts/308 br),fail_under=99 达标 | src/genesis/eval/__init__.py, src/genesis/eval/golden_set.py, src/genesis/eval/scorer.py, tests/test_eval_scorer.py, tests/fixtures/eval/golden_set.yaml, docs/design.md, _AI_USAGE_LOG.md | deepseek-v4-flash-free | | 2026-08-11 | Agent 实现 | T17(架构审查整改,P1):docx 注入原型提前(OV8)。新建 src/genesis/writer/ 包:docx_injector.py(DocxInjector 用原生 python-docx 实现 §6.6 占位符注入);Block 模型(paragraph/heading/table);章节级 {{section:id}} → 替换为内容块 docx 元素序列,行内 {{meta}} → 元信息填充;残留检查:未替换 {{...}} 抛 DocxInjectError(与 §6.6 规范一致);格式精度:注入 heading 继承模板 Heading 样式、原有内容样式不被破坏;新增 tests/test_docx_injector.py(5 用例:章节/行内替换/残留报错/heading 样式继承/原内容保留);同步 design.md §6.7 渲染链路 T17 原型说明;TDD 验证 RED(模块缺失)→ GREEN(聚焦 5 passed)→ 全量 245 passed 覆盖 100.00%(1361 stmts/340 br),fail_under=99 达标 | src/genesis/writer/__init__.py, src/genesis/writer/docx_injector.py, tests/test_docx_injector.py, docs/design.md, _AI_USAGE_LOG.md | deepseek-v4-flash-free | | 2026-08-11 | Agent 实现 | T7(架构审查整改,P2):提取 _validate_path helper(I8 DRY)。source_aggregator.py 三处重复校验(扩展名白名单 + 存在性)提取为模块级 _validate_path(path, allowed_exts) → Path(保留 ValueError/FileNotFoundError 语义与错误信息),parse 三分支改用 helper;外部契约(未知扩展名→ValueError、不存在→FileNotFoundError)不变;新增 3 用例直接测 helper(坏扩展名/缺失/返回 Path);TDD 验证 RED(helper 不存在)→ GREEN(聚焦 13 passed)→ 全量 248 passed 覆盖 100.00%(1356 stmts/332 br),fail_under=99 达标 | src/genesis/parsers/source_aggregator.py, tests/test_source_aggregator.py, _AI_USAGE_LOG.md | deepseek-v4-flash-free | +| 2026-08-11 | Agent 实现 | T10(架构审查整改,P3):Writer 串行约束写回文档(I14)。纯文档任务:design.md §6.8 后新增 §6.8.1 串行生成约束(理由:章间引用依赖前章 WriterState、并行收益低复杂度高、Token 友好;落地点:编排层 POST /generate 严格按模板顺序串行、UI 展示预估总时长与逐章进度、禁止并发多章);api-design §4.3 补串行消费说明(对应 design §6.8.1);web-ui-design 进度 UI 补串行语义(预计=章数×单章 3-5 分)与禁止并发说明。无代码/测试变更,全量 248 passed 覆盖 100.00% 不回归 | docs/design.md, docs/api-design.md, docs/web-ui-design.md, _AI_USAGE_LOG.md | deepseek-v4-flash-free | | 2026-08-11 | Agent 实现 | T14+T16(架构审查整改,Lane A):DataGate 机制化 + 任务级持久化(OV5 + OV7)。新建 src/genesis/orchestrator/ 包:datagate.py(DataGate.load(source, selector):子集加载 + 规模保护 max_total_rows=500 无 selector 拒绝全量 + token 预算 max_total_tokens=8000 复用 CJK 保守估算 + 未知表容错)+ task_queue.py(TaskQueue ABC + PersistentTaskQueue SQLite 落盘:enqueue/poll/update_status/get/cancel/recover/close + 幂等去重 §5.3 + recover 将 running→failed、pending 保留);新建 tests/test_datagate.py(8 用例:子集/规模保护/1000 行 Excel selector 放行/token 预算/未知表/空 selector)+ tests/test_task_queue.py(11 用例:CRUD/幂等缓存/重开不丢/recover 语义/防御分支);同步 agent-runtime-design.md(§4.2 原则→机制 + §3.5/3.6 任务级恢复已实现)、api-design.md §5.2/5.3、design.md §8.4.1;TDD 验证 RED(模块缺失/错误消息不匹配)→ GREEN(聚焦 8+8 passed)→ 全量 218 passed 覆盖 100.00%(1140 stmts/278 br),fail_under=99 达标 | src/genesis/orchestrator/__init__.py, src/genesis/orchestrator/datagate.py, src/genesis/orchestrator/task_queue.py, tests/test_datagate.py, tests/test_task_queue.py, docs/agent-runtime-design.md, docs/api-design.md, docs/design.md, _AI_USAGE_LOG.md | deepseek-v4-flash-free | diff --git a/docs/api-design.md b/docs/api-design.md index 9eb7d39..2812ec7 100644 --- a/docs/api-design.md +++ b/docs/api-design.md @@ -191,9 +191,15 @@ WS /api/ws/sessions/{id} ### 4.3 进程内调用 vs 队列 ``` -默认(InMemoryQueue): +默认(InMemoryQueue): Orchestrator 进程内 asyncio 任务池消费队列 状态与任务结果共享内存(FastAPI 进程内) +``` + +> **串行生成约束(T10 文档化,对应 design.md §6.8.1 / I14)**:同一会话的逐章生成 +> 任务**严格按模板章节顺序串行消费**。`POST /generate` 投递后不并发执行多章—— +> 后章依赖前章 `WriterState` 摘要(design §6.9),并行会造成竞态。单章失败可独立 +> `regenerate-chapter` 重试,不影响其余章。 (v2 预留)RedisQueue/ValkeyQueue: Orchestrator 投递 → Redis/Valkey Stream diff --git a/docs/design.md b/docs/design.md index 1f58fcc..8cbf75f 100644 --- a/docs/design.md +++ b/docs/design.md @@ -918,6 +918,25 @@ style_map: └──────────────────────────────────────────────────────────┘ ``` +#### 6.8.1 串行生成约束(T10 文档化,I14) + +> 架构审查 I14 裁定:**Writer 各章必须串行生成,不得并行**。本约束为设计基线, +> 而非实现细节,需在编排层与 UI 显式体现。 + +**理由**: +1. **章间引用依赖**:后章(如「3.2 画面一覧」)需引用前章(「2. 機能一覧」)的 + 表结构与摘要,串行保证前章 `WriterState` 已就绪(§6.9),避免竞态或空引用 +2. **并行收益低、复杂度高**:单章生成 3-5 分钟,并行需解决状态回写锁与 + 跨章引用一致性,复杂度远超收益(编审查 OV 一致结论) +3. **Token 友好**:前章摘要注入后章 prompt 的方式(§6.9)天然要求前章先完成 + +**约束落地点**: +- 编排层:`POST /generate` 投递任务后,同一会话的逐章任务**严格按模板章节顺序串行消费** + (共享 orchestrator/,状态机 `writing` 态内顺序推进;单章失败可独立 retry,不影响其他章) +- UI:生成按钮触发后展示**预估总时长**(章数 × 单章 ~3-5 分钟)与逐章进度 + (「第 3/12 章生成中」),让用户对串行等待有预期 +- 实现反模式(禁止):同一会话并发投递多章生成任务、跳过 WriterState 直接全量重载 + ### 6.9 章间引用机制(WriterState) ``` diff --git a/docs/web-ui-design.md b/docs/web-ui-design.md index c73ee39..4110c53 100644 --- a/docs/web-ui-design.md +++ b/docs/web-ui-design.md @@ -252,6 +252,10 @@ │ 适用规则: 写入规则_v3 │ │ │ │ [中途中断] [查看日志] │ +``` +> **串行约束(T10 / I14)**:章节严格按模板顺序**串行**生成,预计时间 = 章数 × 单章 +> ~3-5 分钟(design §6.8.1)。UI 展示「第 N/总章 生成中」与逐章进度,让用户对 +> 串行等待有预期;禁止并发触发多章生成(会造成 WriterState 竞态)。 │ │ │ ┌─ 规则冲突 (浮动卡片) ───────────────────┐ │ │ │ ⚠ 检测到规则冲突(DB设计章) │ │