8.1 KiB
8.1 KiB
type, node_id, title, date, severity
| type | node_id | title | date | severity |
|---|---|---|---|---|
| review | review:2026-10-22-issue34-branch-review | #34 OCR 整份文档解析 合并前验收与审查报告 | 2026-10-22 | approved |
#34 OCR 整份文档解析 合并前验收与审查报告
- 分支
fix/issue34-ocr-document,基线25a90eb(1.3.10),Headcb1e08f(17 个提交,目标 1.3.11;本报告随后追加一个文档提交)。 - 设计
designs/2026-10-21-issue34-ocr-document-design.md(已获人类批准:H1/H5/H6 批准,H2 授权另开 #35/#36,H3 待下游确认,H4 发布逐步等指令);计划plans/2026-10-21-issue34-ocr-document.md。 - 结论: 实现与验证完成,Critical 0、Important 已全部修复。发布(合并/tag/上传/Release/关 #34)未执行,等人类指令。
1. 需求覆盖(issue #34 → 实现)
| issue 期望 | 实现 | 证据 |
|---|---|---|
| 上传按类型设 filename/Content-Type | 库按内容判定(H5 有意替换「调用方声明」): 图片魔数优先 → 前 1KB 内 %PDF- → doc.pdf,其余沿用 image.jpg;三个方法共用 |
test_monkey_ocr.py::TestSniffMedia、TestUploadLabelPerMethod、TestParseDocument::test_upload_label_matrix_for_the_document_entry;活体 recognize_text(PDF) 返回真实文本而非幻觉串 |
| 逐块 类型/页码/bbox/文字,服务阅读序 | OcrDocumentElement(继承 OcrLayoutElement + text);只读 _middle.json;表格为 HTML |
test_monkey_document.py(§5.1 契约逐行);4 份真实包离线冒烟 29/89/30/29 块全部与 middle/content_list(反转义)一致 |
| 整篇 Markdown | OcrDocumentResult.markdown,按名精确配对 .md |
同上;真实包 markdown == .md 原文 |
| 长文档超时与熔断确认 | 库内无延迟型判定(grep 已证);timeout_s 非总耗时上界,硬上限 = call_deadline_s ≤ lease_ttl_s;文档线独立 scope 配方 |
TestNoLatencyJudgement(含已有失败计数/半开探针两种前置状态)、持续慢速下载 → CallDeadlineExceeded、README「运维须知」 |
parse_layout 不动 |
签名/返回类型/错误文案不变;仅上传分支(H6)与共用第一段协议新增 download_url 校验 |
独立审查对 5501 个输入与 2486 个场景做基线差分,仅 %PDF- 字样载荷的上传标签有差异(已登记) |
2. 本会话证据(命令 → 结果)
| 声明 | 命令 | 结果 |
|---|---|---|
| 全套通过 | pytest tests/ -q --cov=src/polygateway(退出码取自文件,无管道) |
退出 0;2239 passed, 23 skipped, 113 deselected(slow);总覆盖 96% |
| 格式/lint/依赖契约 | make ci |
退出 0;108 files formatted、ruff All checks passed、Contracts: 1 kept, 0 broken |
| 复杂度 | radon cc <ocr.py, _monkey_document.py, monkey_ocr.py> -n C -s |
无 C 及以上(仅 openai_compat.py::complete 为未触及的既有 C) |
| 活体 | pytest tests/integration/test_monkey_ocr_document_live.py -m slow |
3 passed(8.85s);默认套件 3 deselected |
| 真实多页 PDF 端到端 | OcrClient.from_env("OCR_DOC") 调 rich.pdf(4 页)/tbl.pdf(2 页含表) |
89/30 个元素,与直连存证一致;表格 HTML 取出;各 1 次尝试 |
| 红→绿 | 每任务 scratchpad/T*-red.log → T*-green.log |
T1–T6 红灯原因均为目标行为缺失(导入失败或 AttributeError: no attribute 'parse_document') |
| 测试非空转 | 变异检查(还原/改坏实现 → 测试转红 → 恢复) | 本会话十余类变异全部被抓到: 异常边界放错位置(47 个失败)、status==500/前缀判据、同步解析、体积检查先于错误状态、_summarize、早期装配校验、整包上限、aread/有界读取、reasoning_applies、探针归还、download_url 校验、isinstance 分派;独立审查另做 86 个变异、0 存活 |
3. 评审轮次与处置
| 轮次 | 审查者 | 结论 | 处置 |
|---|---|---|---|
| 设计论证 | 独立 Plan subagent(含本机 MonkeyOCR 源码核对) | 弃「content_list 对位」改 middle-only 等 | 全部采纳(设计 §12) |
| 设计审查 | Codex(只读) | 否→修订后进入;9 条全部成立 | 全部修订(设计「审查记录」) |
| 计划审查 | Codex(只读) | 修订后进入执行;10 条全部成立,第 1 条为我方计划缺陷 | 全部修订(计划 §5) |
| 合并前独立验证 | 全新上下文 verifier | 无 Critical;Important 4 条 | I-1 异常漏出、I-2 整包上限无测试、I-3 业务词汇、I-4 三处空转测试——全部修复并用变异证明 |
| 整分支 Codex 审查 | Codex | 未完成: 沙箱报 usage limit,只读了设计/计划/部分代码即终止,无任何分级结论 | 以全新上下文的独立 Claude 对抗式审查替代(见下行);Codex 额度恢复后可补跑,不影响本报告其余结论 |
| 对抗式代码审查 | 全新上下文 Claude(自写模糊/变异脚本,假服务压测) | 建议合并;Critical 0,Important 3 | 见 §4 |
4. 对抗式审查发现与处置
| # | 发现 | 核验 | 处置 |
|---|---|---|---|
| I-1 | _summarize 由 hasattr 改 isinstance,鸭子类型 transport 结果以 AttributeError 漏出 |
本机复现(SimpleNamespace(text=...)) |
改回结构分派(有 markdown → 文档;有 text → 文本;其余版面),加回归测试 |
| I-2 | 文档路径的错误体 aread() 无上限(600 MiB 的 500 使 RSS 涨到 1.8 GiB) |
属实(基线非流式 get 同样,但新代码声称有界) |
错误体只读前 64 KiB 并复制成已缓冲响应;加测试证明只消费上限那么多 |
| I-3 | 畸形 download_url(控制字符/坏方括号/越界端口)让 httpx.InvalidURL 漏出;探针不归还 |
本机复现;parse_layout 基线同样 |
在共用的 _post_parse 一处校验,归瞬时错误、不发第二段请求;parse_layout 顺带受益(CHANGELOG 登记);不限制主机(基线接受绝对地址) |
| M-1 | 嗅探副作用: 前 1KB 含 %PDF- 字样的非 PDF 文本被改标;BM 两字节魔数太弱 |
属实 | BMP 加 DIB 头大小校验;CHANGELOG/README 登记副作用 |
| M-2 | 字节上限≠内存上限(JSON 解析后可达 23 倍;成员条数无上限) | 属实,仅服务异常时成立 | README 改为诚实口径;不实现 EOCD 预读(真实样本约 72 KB/页) |
| M-3 | to_thread 不是「立即生效」: GIL 下事件循环仍有停顿,取消后线程自然收尾 |
属实 | 文档改「基本不被占住」并给实测数 |
| M-4 | parse_layout 的 ZIP 路径仍会漏原生异常(基线即有) |
属实,按设计保持原样 | 后续项(见 §6) |
| M-5/6/7 | 设计文档结局表与实现不一致;类 docstring 过时;测试注释含业务词汇 | 属实 | 全部修正 |
| M-8 | page_idx 必须等于页序,服务若跳页则整份失败 |
设计取舍 | 保留;列入未验证项 |
5. 没能验证的部分(如实登记)
- 线上服务: 旋转页/带批注页/加密 PDF 的
doc.pdfvsimage.jpg差分;带密码 PDF 的服务端报错文案(若不在标记集合,走瞬时重试并计熔断);线上 backend 是否 sync-only(队头阻塞);真实 httpcore 逐次读超时行为(MockTransport 不执行它);need_drop恒为 False 的线上证实。 - 样本局限: 多行/多 span 文本块、
inline_equationspan、嵌套 caption/footnote 三条路径无真实样本,仅由构造 fixture 测试(已在 CHANGELOG/README 标注「未经实测」)。 - 未执行:
make wiki-check(需外部 Gitea Wiki 克隆路径,站点自 2026-08-02 下线);Redis 限流/熔断后端与 Postgres 遥测对新入口的组合(无对应环境新增用例,既有套件中的后端用例通过);整分支 Codex 审查(额度)。 - 下游: H3(CHSAnalyzer3 是否把「服务不可用」一族按延期重投处理)未向下游证实。
6. 后续项与待人类指令
| 项 | 状态 |
|---|---|
#35 共享 _classify_status 对确定性坏输入 500 仍归瞬时 |
已开 |
#36 recognize_text 不校验 success |
已开 |
parse_layout ZIP 路径的原生异常漏出(OverflowError/NotImplementedError/RuntimeError)与 download_url 主机限制 |
人类 2026-10-22 批准新开,已开 #37 |
发布: 合并 main → push → tag v1.3.11 → 构建 → 上传 registry → 验证已发布 → 建 Release/挂仓库 → 关闭 #34 |
人类 2026-10-22 下令发布,按 CLAUDE.md §4.4.1 逐步执行;CHANGELOG 定版日期 2026-10-22 |