edit | blame | history | raw

B 站博主动态采集辅助工具 MVP 开发工作记录

  • 日期:2026-08-04
  • AI:infodev-2
  • 角色:dev.developer.project.secondary
  • 事项:DEV-PROJECT-INFO-BILI-DYNAMIC-COLLECTOR-MVP-20260804-001
  • 上游:REQ-BILI-DYNAMIC-COLLECTOR-20260804-001
  • 请求方 Codex task:019fcc5d-798f-7ea1-8325-3a4d1f2dc5a5
  • 共享审核员:dev.reviewer.project / inforev / 019fb7c5-e1fd-7df0-8ec9-c87edea4215d

1. 接手与分类

已读取需求、项目规范、项目配置、common/本地编码与审计规范、project 开发工作区说明,并核对本角色写入范围。事项限定为一个 stdlib 本地 CLI、一个示例配置、一个测试文件、一份脱敏 fixture 和一页用法,不联网、不控制浏览器、不并发执行业务、不下载内容、不写正式采集目录,按“有需求文档的轻量实现”执行,不创建重型编码方案。

正式 F:\video\<博主名>\ana-data/news-<博主名>/ 的路径授权扩展仍由 project.admin 处理。本开发不等待该配置,只在测试临时目录和 dev/tmp/bili-dynamic-collector-mvp/ 验证。

2. 实现

  • dev/project-dev/bili_dynamic_collector.py
  • check:最近时间窗、动态/opus/BV/URL 去重、Windows 安全 stem、待办 JSON、append-only manifest。
  • move-completed:明确映射、下载完成度、下载目录边界、链接/reparse、后缀、重名和唯一性预检;partial + fsync + SHA-256 + hard-link no-overwrite 提交;失败追加 MOVE_FAILED,成功后再删除源。
  • handoff:复核目标范围和 SHA-256,生成内容寻址且 sent=false 的 Codex 原生任务草稿,不自动发送。
  • 全入口拒绝认证/会话字段;无网络或浏览器依赖。
  • 示例:dev/project-dev/bili_dynamic_collector.example.json,只指向开发 tmp。
  • 测试/fixture:dev/project-dev/test/test_bili_dynamic_collector.pydev/project-dev/test/fixtures/bili_dynamic_collector/dynamic_items.json
  • 说明:dev-doc/project-doc/B站博主动态采集辅助工具.md;目录入口已补充。

3. 验证

  • py_compile:PASS。
  • CLI help:PASS。
  • 目标 unittest:6/6 PASS / 0.610s
  • project flat discover:69/69 PASS / 49.873s
  • 离线 CLI smoke:首次 check=TODO_GENERATED/new=3;55 字节非媒体 fixture move=VIDEO_MOVED;handoff=HANDOFF_DRAFT_READY/sent=false;相同输入复跑=NO_NEW_ITEMS/new=0
  • overlap safety:同 state 重叠调用一方按 E_STATE_LOCKED 停止,结束后无残留锁,串行重跑成功。
  • git diff --check:PASS。
  • mbx validate --project project-info --governanceOK/projects=1/warnings=0
  • 证据:dev/tmp/bili-dynamic-collector-mvp/selfcheck.md

4. 需求—代码自检

  • 72 小时配置、稳定标识去重、manifest 字段与状态、Windows 时间命名:已实现并测试。
  • 重跑跳过、失败可重试、重名停止、下载目录到目标目录安全移动:已实现并测试。
  • 视频处理员交接摘要和定时检查入口:已实现;草稿不自动发送。
  • 账号口令/cookie/token、访问控制绕过、浏览器扩展自动化、真实下载和正式采集写入:代码中不存在,smoke 动作为 0。
  • 既有 ana-data/news-青枫浦上Q/ 与其他正式采集内容:未读取、未修改。

5. 当前状态与限制

当前状态:PENDING_SHARED_REVIEWER_LIGHT_IMPLEMENTATION_REVIEW

限制:动态正文、原图和扩展任务仍由人工/浏览器扩展取得;目标文件系统不支持同目录 hard-link 时安全停止;正式路径授权完成前只使用开发 tmp/fixture 配置。未发送媒体处理交接,未创建定时任务。

6. 独立安全审查终态

  • 回执:HANDOFF-INFOREV-INFODEV2-BILI-DYNAMIC-COLLECTOR-MVP-IMPLEMENTATION-REVIEW-RESULT-20260804-001
  • 结论:HOLD_5_TERMINAL_SNAPSHOT;目标 6/6、project 69/69、编码/治理/UTF-8 均通过,但 5 个实质阻断未关闭。
  • 阻断:实现实际满足重型门禁但无已审设计;映射选择器不强制全一致且批量同源可先部分提交;源删除失败的 exit 4 在原映射重跑时降级;manifest 不经过秘密字段 gate;生成的原生 handoff 草稿缺少必填身份与 scope/evidence/expected_action。
  • 可保留:源码、文档、fixture、自检和测试作为隔离开发快照;check 只允许在 dev/tmp/TemporaryDirectory 对完全可信、无秘密、人工确认的一实体一来源输入做演示。
  • 禁止:不得把工具作为已验收采集器交付;不得对真实下载或正式目录运行 move-completed,不得调度/并发生产使用,不得发送当前 handoff Markdown,不得依赖 manifest 秘密保护或 retained-source 重试语义,不得写 F:\video 或正式 ana-data
  • 按请求方即时收尾约束,不开启后继设计、返修复审、授权或外部动作。最终状态:TERMINAL_HOLD_DEVELOPMENT_SNAPSHOT_ONLY

7. 请求方恢复 HOLD/5 最小修复

  • 新授权:终态交付后,请求方明确“继续推进”,只修独立审核 F1—F5,不扩大产品范围。
  • 分类已纠正为重型;已创建 dev-doc/project-doc/开发方案/CODE-DESIGN-PROJECT-INFO-BILI-DYNAMIC-COLLECTOR-MVP-HOLD5-REPAIR-V001.md
  • V001 只冻结 exact selector/同源批次零副作用、retained-source 告警粘性、manifest 统一 secret gate 和完整稳定 native handoff envelope;网络、浏览器、下载和正式路径继续排除。
  • 当前代码、配置、测试和 fixture 未修改;状态=V001_DESIGN_REVIEW_PENDING

8. V001 设计复审 HOLD/1 与 V002 限定修订

  • 原共享审核员返回 HOLD/1;重型分类、选择器一致性方向、manifest 秘密字段检查和规范原生 handoff 均已通过。
  • 唯一冲突是终态重跑与 source_file 物理身份预检的先后关系。V002 固定为:全批选择器与实体唯一性先行;随后读取最新状态;仅 ACTIVE_MOVE 进入源/目标预检;已移动和 retained-source 终态均从 manifest 投影且不依赖当前源是否存在。
  • 代码、配置、测试和 fixture 继续冻结,等待 V002 限定设计 PASS。

9. V002 限定复审 HOLD/1 与 V003 最终收紧

  • 原顺序冲突已经关闭;唯一剩余项是 V002 的“无移动终态”措辞可能扩大活动状态。
  • V003 废止该措辞,ACTIVE_MOVE 只允许精确的 TODO_QUEUEDMOVE_FAILED;处理阶段、缺失/空白状态及未知状态全部在阶段 B 前以 E_STATUS、exit 3 零副作用停止。
  • 追加一组参数化 CLI 入口反例合同;实现仍保持冻结,等待最后一次限定设计复审。

10. V003 PASS 与五项实现

  • V003 最终限定设计审核=PASS/0;V001+V002+V003 成为唯一实施合同,随后才修改代码/配置/测试。
  • F2:所有 selector 单独命中且全一致;整批 entity 唯一后才分类;活动行做 source identity/target 预检,任何预检失败不写 manifest/目标/源。
  • F3:retained-source 在源存在或后续人工删源的相同 mapping 重跑中均保持 exit 4、原目标/hash/失败原因和 manifest bytes。
  • F4:manifest 每行在 schema/identity/status 前走递归 secret gate,三个命令共用。
  • F5:配置化精确 route,生成完整 deterministic native handoff,--now 不影响相同证据的 handoff bytes,仍不自动发送。
  • 验证:目标 11/11 PASS / 1.393s;新鲜闭环 1/1 PASS / 0.226s;project 74/74 PASS / 48.657s;外部动作 0。
  • 当前等待同一共享审核员一次限定实现复审。

11. 限定实现复审 HOLD/2

  • 独立正向复验目标 11/11、新鲜闭环 1/1、project 74/74 全 PASS,五项主要修复与无外部动作边界保留。
  • 剩余两项 fail-closed 阻断:终态持久证据缺失仍可能成功投影;manifest 标量换行可注入原生 handoff。
  • 按请求方“PASS/0 或明确剩余阻断返回”的单回合约束,本轮不再修改代码或自动开第二次实现复审;状态=HOLD_2_ISOLATED_DEVELOPMENT_SNAPSHOT_ONLY

12. HOLD/2 持续授权与 fail-closed 返修

  • 请求方明确要求继续至 PASS/0;无需新设计,只修审核 F1/F2。
  • 新增 terminal 状态证据校验与 handoff 全消费标量控制字符/格式校验;错误只返回安全字段路径。
  • 新增 19 组参数化反例,逐组验证 exit 3、E_MANIFEST、业务树/manifest/目标不变、无残留且 stdout 不含污染值。
  • 目标 13/13、新鲜闭环 1/1、project 76/76 PASS;外部动作和 fixture 修改均为 0。
  • 当前等待原共享审核员限定复审;若仍有同边界问题按新授权继续最小闭环。

13. HOLD/2 fail-closed 限定复审 PASS/0

  • 回执=HANDOFF-INFOREV-INFODEV2-BILI-DYNAMIC-COLLECTOR-MVP-HOLD2-FAIL-CLOSED-REREVIEW-RESULT-20260805-001;结论=PASS/0、阻断=0
  • F1 terminal persisted evidence fail-closed 与 F2 handoff manifest 标量控制字符/格式注入均 CLOSED;原阻断反例 2/2、目标 13/13、project 76/76 均由审核员独立复跑通过。
  • 审计=DEV-AUDIT-PROJECT-INFO-BILI-DYNAMIC-COLLECTOR-MVP-HOLD2-FAIL-CLOSED-LIMITED-IMPLEMENTATION-REREVIEW-20260805-001;回执时文件=250254/43FD12548388E3760DCB52644273E54318591D44CE3D83E42013E1699F8D64B2
  • 当前=PASS_0_PROJECT_TOOL_DELIVERABLE;开发与复审链关闭,不追加功能或真实运行。网络、浏览器、下载、自动 native send、调度、F:\video 和正式 ana-data 仍需另行明确授权。

14. 请求方接收关闭

  • 回执=HANDOFF-VIDEO-DOWNLOADER-INFODEV2-BILI-DYNAMIC-COLLECTOR-PASS0-ACK-20260805-001 / ACCEPTED;关联最终交付=HANDOFF-INFODEV2-VIDEO-DOWNLOADER-BILI-DYNAMIC-COLLECTOR-MVP-PASS0-FINAL-20260805-001
  • 请求方确认 PASS/0 工具与证据完整,本事项状态=ACCEPTED_CLOSED;不再修改代码、测试、配置或 fixture。
  • 请求方声明当前博主真实浏览器/下载、F:\video\青枫浦上Q、正式 ana-data、原生转写交接和每小时调度已有既有授权;执行由视频下载员负责,开发员本轮动作仍为 0。
  • 后续新缺陷另行回传,当前保持空闲。