# 慧博 10 分钟快速采集工具开发方案 V001 创建人员:dev.developer.ana.cai 文件职责:冻结 `DEV-ANA-HIBOR-FAST-COLLECTION-20260729-001` 的模块边界、接口、额度语义、失败闭合、测试与性能验收方案。 管理规范/模板:`common/dev-doc/编码规范.md`;`common/dev-doc/开发审计规范.md`;`dev-doc/编码规范.md`;`dev-doc/开发审计规范.md`。 引用文件:`ana-doc/研报体系/研报采集角色说明.md` 第 4.1–4.3 节;`ai-yanbao-collector/工作说明.md` 第 6.4–6.5 节;`ai-yanbao-collector/worklog/2026-07-29-慧博APP研报自动采集与选取规则.md`;`HANDOFF-YANBAO-DEV-ANA-HIBOR-FAST-COLLECTION-TOOL-20260729-001`。 记录方式:重型开发方案;方案审核通过前不实现、不运行候选工具、不触发慧博下载额度。 ## 1. 事项与目标 - task:`DEV-ANA-HIBOR-FAST-COLLECTION-20260729-001` - owner:`dev.developer.ana.cai` - reviewer:`dev.reviewer.ana.cai` - request / review owner:`case_analysis.report_collector` - 目标:在不降低原件、SHA-256、页数、manifest、额度与访问控制要求的前提下,把单份正常采集的 median 控制在 8 分钟内、P90 控制在 10 分钟内;同查询批量首份不超过 10 分钟,后续每份增量目标不超过 4 分钟。 - 现状基线:中国中免 3 份任务从开始搜索到最终 manifest 约 54 分 44 秒;主要时间花在 20 屏探索扫描、反复截图定位、手工缓存轮询/复制、逐项校验与手工 manifest。 本事项不解析研报正文、不生成正文 Markdown、不输出研究结论,不取得、保存或传播认证秘密,不绕过登录、验证码、付费、订阅、权限或其他访问控制。 ## 2. 开发等级与实施关口 本事项为有上游任务的重型实现:包含多模块、子进程、缓存监听、额度账本、正式 PDF 原件、重跑恢复和性能 SLA。 固定顺序: 1. 登记开发事项、计划与本方案; 2. `dev.reviewer.ana.cai` 独立方案审核; 3. 方案 `PASS` 后实现; 4. L0/L1/L2 合成与无新增下载 dry-run; 5. 在当日额度账本和 STOP 规则内做真实性能验证; 6. 开发自检、执行日志与证据包; 7. `dev.reviewer.ana.cai` 独立实现/测试复审; 8. 向 `case_analysis.report_collector` 单次回传终态。 普通源码和内部测试产物按语义验收,不做普遍 Base64/逐字节预冻结。外部 PDF 原件、正式 manifest、额度账本、交付 receipt 和正式审计快照继续保持真实消费者所需的字节/哈希不可变边界。 ## 3. 技术选型与目录 使用 CPython 3.12 标准库为主,避免安装新包;PDF 可打开性优先调用已有 `pdfinfo`,缺少时可调用项目运行环境已提供的只读 PDF provider。所有可执行文件通过 CLI 参数、配置或 PATH 解析,不在代码中写个人机器绝对路径。 计划代码目录: ```text dev/ana-dev/hibor_fast_collection/ __init__.py __main__.py cli.py models.py budget.py adb.py ui.py quota.py cache.py archive.py manifests.py terminal.py dev/ana-dev/test/hibor_fast_collection/ fixtures/ fake_adb.py test_*.py ``` 不得把代码写入 `ana-data/` 或 `ai-yanbao-collector/`。真实运行数据仍由调用方指定到 `ana-data/tmp//` 或正式案例容器。 ## 4. 公共入口与 CLI 合同 唯一公共入口: ```text python -m hibor_fast_collection [arguments] ``` 命令: 1. `preflight`:只读检查 Python、ADB、唯一设备、MEmu、包名、缓存目录、屏幕尺寸、`pdfinfo` 与额度账本;不打开研报、不新增额度。 2. `dry-run`:使用 fake ADB/已有缓存只读快照/合成 PDF 验证选择、额度、缓存差分、归档、manifest、终态和计时;不得向真实设备发送点击。 3. `collect-one`:单份采集。 4. `collect-batch`:同查询批量采集,共用一次搜索和候选扫描。 5. `resume-postprocess`:仅处理已记录且 SHA-256 可确认的既有缓存,不重新打开 APP;若无法证明未产生新触发则拒绝运行。 公共必填参数:`--project-root`、`--task-spec`、`--adb`、`--pdfinfo`、`--output-root`。真实采集另需 `--quota-ledger`;路径必须位于项目根目录允许范围内。`task-spec` 至少包含 capability/version、task/handoff/requester/review_owner、query、quantity、destination、selection filters 和运行模式。 输出终态至少包含:task/handoff、status、started/ended、总耗时、阶段耗时、requested/triggered/success/failed/duplicate/gap、quota summary、有效文件、manifest/delivery/timing 路径、blocker、访问控制声明和 `report_collection_terminal` payload。 ## 5. 统一状态与时间预算 ### 5.1 终态 - `SUCCESS` - `PARTIAL_SUCCESS` - `TIME_BUDGET_STOP` - `PARTIAL_QUOTA_STOP` - `BLOCKED_INPUT` - `BLOCKED_ACCESS_CONTROL` - `BLOCKED_ENVIRONMENT` - `BLOCKED_AMBIGUOUS_MAPPING` - `VALIDATION_FAILED` - `INTERNAL_ERROR` 任何 10 分钟到时、进程超时或状态不确定都不得静默继续;保留有效子集并返回精确阶段、耗时和可行动 blocker。 ### 5.2 预算模型 `Budget` 只使用 `time.monotonic()` 做截止判断,wall-clock 仅用于审计时间戳。 - 单份默认总预算:600 秒;正常目标 480 秒。 - 同查询批量:从任务观察到首份终态不超过 600 秒;首份以后每份独立增量预算 240 秒。 - 所有 ADB、缓存轮询、pull、hash、pdfinfo、文件锁等待都有 `remaining()` 上限;子进程不得越过剩余预算。 - 到期时停止新的 UI 点击和下载触发;已完整拉取的文件只允许在剩余预算内完成原子归档,否则保留 staging 状态并返回 STOP,不伪造成功。 计时阶段固定为:`preflight`、`quota`、`ui_search`、`ui_scan`、`detail_and_trigger`、`cache_wait`、`copy`、`validation`、`manifest`、`terminal`。每阶段记录 monotonic start/end/elapsed 与 wall-clock start/end,写入 `timing_manifest.csv`。 ## 6. ADB、UI 与 FAST 选择 固定包名:`cn.com.hibor`。固定缓存目录:`/sdcard/Android/data/cn.com.hibor/files/myfile/`。 ### 6.1 预检 1. `adb devices -l` 必须恰有一个已授权、在线且符合 task spec 的本地模拟器;离线、多设备或身份不确定立即停止。 2. `dumpsys package` 确认包名存在;只读确认前台包、屏幕尺寸和缓存目录可读。 3. 对缓存目录建立只读基线:远端路径、名称、字节数、mtime;不得修改、删除或重命名原件。 4. 检查输出父目录与额度账本;不得预删冲突目标。 ### 6.2 UI 驱动 优先级:`uiautomator dump` 的可见文本/边界 → 截图锚点/模板 → 按屏幕比例归一的受限坐标。OCR 作为可插拔只读 provider,仅在显式配置且本机可用时启用;未配置 OCR 不得伪称执行 OCR。 UI 动作只允许白名单:启动/回到慧博、聚焦搜索、清空/输入查询、搜索、纵向翻页、打开候选详情、打开原文、返回。每次动作前验证当前包和页面锚点,漂移或出现登录/验证码/付费/订阅/权限词即停止。 正常截图只保留:开始、结果页、详情页、结束;异常额外保留一张当前页。不得恢复每次点击一张图的高开销模式。 ### 6.3 FAST 扫描 1. 最少扫描 3 屏,正常最多 5 屏;20 屏/100 个不重复候选仍是硬上限而非默认目标。 2. 每屏只收集可见客观字段,按现行硬过滤和评分规则计算;不新增主观质量分。 3. 达到 `quantity + 2` 个合格候选,且最近连续 2 屏 top-K 集合与分值均未改善时早停。 4. 5 屏后仍不足时才进入扩展扫描,直至数量满足、连续 3 屏无新增合格项或达到硬上限。 5. 同机构默认最多 1 份;去重、并列顺序、页数/日期/分析师/机构规则完全继承第 4.2 节。 ## 7. 缓存监听与原件归档 ### 7.1 缓存差分 在打开原文前记录 reservation 和当前缓存快照。触发后后台轮询目录元数据;只要出现唯一新增候选并连续两次(间隔 1–2 秒)字节数稳定,即进入后处理,不等待阅读器完整渲染。 出现多个新增文件、旧文件变化、远端 stat/hash 不可读或目标映射不唯一时返回 `BLOCKED_AMBIGUOUS_MAPPING`;不得按缓存文件名猜测标题、机构或日期。 ### 7.2 原件与项目副本 1. 远端只读取得字节数和 SHA-256。 2. `adb pull` 到本事项 staging;不得对远端原件做写、删、改名。 3. 校验本地前 5 字节 `%PDF-`、字节数、SHA-256。 4. 调用 `pdfinfo` 检查可打开性、页数、加密状态;详情页页数与 PDF 页数不一致时失败。 5. 标准命名:`<机构>-<主体>-<标题短句>-.pdf`,仅清理 Windows 非法字符。 6. 最终归档用 Python `open(..., 'xb')` / 等价 CreateNew,写入后 flush+fsync 并只读复核;目标存在时不覆盖。相同 SHA-256 登记 duplicate,不同 SHA-256 报冲突。 PDF 与 SHA-256 为权威原件。工具不读取正文文本、不做 OCR 正文、不生成研究内容。 ## 8. 额度账本 固定账本:`ana-data/tmp/report-collection-control/daily_quota_.csv`,时区 `Asia/Shanghai`。 ### 8.1 初始化与保守基线 2026-07-29 已知中国中免任务至少触发 3 份不同研报。若当日账本不存在,首次真实测试必须以 append-only `BASELINE_ESTIMATE` 建立 `confirmed_consumed>=3`,引用 `HIBOR-CHINA-DUTYFREE-20260729-001`,不得从 0 开始。若 APP 可见剩余额度推导出更高消耗,用 `CORRECTION` 追加提高,不改写历史;低于本地保守值时仍取更保守者。 ### 8.2 事件状态机 使用单文件互斥锁、append、flush+fsync: 1. 点击新研报原文前追加 `RESERVE`,`active_reservation_delta=+1`。 2. 确认触发追加 `CONSUME_CONFIRMED`,confirmed +1、reservation -1。 3. 无法判断是否触发追加 `CONSUME_UNCERTAIN`,uncertain +1、reservation -1。 4. 确认未触发追加 `RELEASE`,reservation -1。 5. 更正只追加 `CORRECTION`,必须引用原 event_id。 崩溃遗留 reservation 在后续运行中继续占用,除非有可复核证据追加释放或更正。 ### 8.3 硬限制 `safe_available=max(0,27-confirmed-uncertain-active_reservations)`。正常目标 25,硬停止 27,永久余量 3。第 26–27 份只用于已接收任务收尾/替换/缺口;28–30 禁止自动化使用。任何时点安全可用量不足即返回 `ACCEPTED_PARTIAL_QUOTA`、`QUEUED_NEXT_DAY` 或 `PARTIAL_QUOTA_STOP`。 ## 9. Manifest、delivery 与终态 ### 9.1 Manifest 按角色说明最小字段加慧博专用字段逐行追加;成功、失败、重复、冲突和 STOP 都必须记录。CSV 使用标准转义;append 前加锁,append 后 flush+fsync。正式行必须能复核 task、requester/review_owner、source cache、原件与副本 bytes/hash、PDF magic、openability、page_count、encryption、selection reason 和 quota event。 ### 9.2 delivery.md 仅包含元数据、文件链接、选取依据、状态、缺口和额度摘要;禁止写研报正文或研究结论。 ### 9.3 report_collection_terminal 工具生成公开能力契约所需 JSON/Markdown payload,由调用方通过 Codex 原生任务单次发送。工具本身不向外部线程发消息;避免把通信权限嵌入采集程序。 ## 10. 重跑、恢复与幂等 1. 普通 UI/缓存失败在同一任务内最多重试 2 次,不重复消耗同一已确认研报;打开不同研报必须新增额度事件。 2. 任何已有正式文件都不覆盖;复用前必须校验 SHA-256、字节数、PDF magic 和 manifest 关系。 3. `resume-postprocess` 只能消费已记录 cache identity/remote hash,且明确 `reused_without_new_trigger`;证据不足则拒绝。 4. 失败后保留已验证 PDF 和 manifest 行;临时半成品标记 `.partial`/staging,不被视为正式成功。 5. 每次运行生成唯一 `run_id`、`run_meta.json`、`timing_manifest.csv` 和 terminal;重跑不得复用完成标记冒充新结果。 ## 11. 测试设计 ### 11.1 L0/L1 - `py_compile`/import。 - 标准库 `unittest` 覆盖 Budget、候选硬过滤/评分/早停、文件名清理、quota reducer/state machine、CSV quoting、manifest、terminal schema。 - 反例:多设备、包缺失、缓存不可读、access-control 词、目标冲突、多个新增文件、大小不稳定、hash 不一致、非 PDF、页数不一致、锁失败、超时、残留 reservation、硬停止 27。 ### 11.2 L2 合成与无新增下载 dry-run - fake ADB 模拟设备/页面/缓存演进/远端 hash/pull。 - 使用合成最小 PDF 与既有缓存只读样本,验证 0 次真实点击、0 个新 trigger。 - dry-run 必须生成 timing/manifest/delivery/terminal 的测试输出并证明不写正式原件、不修改真实账本。 ### 11.3 真实性能验证 1. 至少 10 个真实单份样本;每份记录总耗时与全部阶段耗时。 2. 真实测试前初始化/读取当日额度账本,保守纳入已知 3 次中国中免触发。 3. 本事项最多新增 10 个 distinct trigger;任何时候不得越过 27。额度不足时保留样本并顺延,不得把缺样本伪装为通过。 4. 每份验收 `%PDF-`、远端/本地 bytes 与 SHA-256、openability、page count、manifest、quota ledger。 5. 统计 median 和 nearest-rank P90;正常样本 median<=480s、P90<=600s。登录/验证码/付费/权限、模拟器离线、APP 服务不可用单列为 external blocker,不计成功样本且不得伪装达标。 6. 至少一次同查询批量验证;首份<=600s,后续每份增量目标<=240s。若样本不足以证明 P90,则结论为 `INSUFFICIENT_PERFORMANCE_SAMPLES` 而非 PASS。 ## 12. 审核与验收矩阵 方案审核必须确认: 1. 固定包名/缓存目录与角色规范一致; 2. 10 分钟 STOP 由 monotonic budget 可执行; 3. FAST 只是早停优化,不改变硬过滤/评分/20 屏上限; 4. 缓存稳定后后处理,不依赖阅读器完整渲染; 5. PDF 原件、remote/local bytes/hash、页数和 CreateNew 不降级; 6. 30/25/27/3、reservation、confirmed/uncertain 和账本追加语义正确; 7. 2026-07-29 基线至少 3; 8. 真实样本最多新增 10,额度不足会停止/顺延; 9. access control、认证秘密、正文解析、研究结论、外部消息均未越权; 10. dry-run、单份、批量、恢复和失败矩阵可测。 实现审核必须以源码、测试命令、运行日志、真实 PDF/manifest/quota/timing 证据和性能矩阵为准;开发员不得自审。 ## 13. 风险与非目标 - UI 结构更新:锚点失败时 STOP 并输出截图/页面证据,不猜坐标。 - ADB/MEmu 抖动:有界重试,设备或连接身份不确定即 STOP。 - 缓存映射歧义:宁可保留缺口,不按文件名猜。 - 文件/账本并发:文件锁、append、fsync;锁不确定不继续。 - SLA 风险:先以 stage timing 定位瓶颈;不得通过跳过 hash、页数、manifest 或额度登记来达标。 - 本期不开发登录、验证码、付费处理,不做云服务,不做数据库,不做研报正文解析或研究结论。 ## 14. 当前状态 `PENDING_INDEPENDENT_DESIGN_REVIEW`。 在 exact `dev.reviewer.ana.cai` 返回方案 `PASS` 前,不创建上述候选源码,不启动候选工具,不进行 ADB/APP 真实采集或消耗额度。