# B 站动态主动刷新采集器实现与验证证据 事项:`DEV-PROJECT-INFO-BILI-DYNAMIC-REFRESH-COLLECTOR-20260813-001` 需求:`REQ-BILI-DYNAMIC-COLLECTOR-20260804-001` 实施者:`dev.developer.project.secondary / infodev-2` 审核员:`dev.reviewer.project / inforev` ## 1. 使用入口 ```powershell python -B dev/project-dev/bili_dynamic_collector.py ` --config dev/project-dev/bili_dynamic_collector.example.json ` refresh-begin python -B dev/project-dev/bili_dynamic_collector.py ` --config dev/project-dev/bili_dynamic_collector.example.json ` refresh-commit ` --input ``` `refresh-begin` 与 `refresh-commit` 是离线协调入口,不控制 Chrome、不联网,也不读取 Cookie、token、localStorage 或页面源代码。页面操作者必须把一次受支持刷新产生的有限、无秘密 JSON evidence 写到 `refresh-begin` 返回的精确路径,再由 `refresh-commit` 校验和落账。 刷新身份固定为 `青枫浦上Q / 1420210197 / https://space.bilibili.com/1420210197/dynamic`,每个 run 最多刷新一次。页面 evidence 由 `bili_dynamic_page_observation_contract.json` 与 `bili_dynamic_page_extract.js` 的精确哈希绑定;cards 与 unparsed nodes 按 DOM 位置互斥。只有页面身份、正文、时间窗与终止标记共同证明覆盖完整时,空结果才可成为 `REFRESH_CONFIRMED_NO_NEW`。公开搜索或 API 只能作非权威补充发现,空结果、`-412`、验证码、访问限制和不可读页面永远不能证明 no-new。 五个正式终态为: - `NEW_ITEMS_SAVED`:有通过合同的新正文、原图或视频 metadata,内容与 state/formal 两份 manifest 一致提交; - `REFRESH_CONFIRMED_NO_NEW`:页面观察完整且所有已解析实体均被历史 catalog 去重; - `REFRESH_FAILED_PAGE_UNREADABLE`:刷新后页面就绪或只读提取超时/失败; - `REFRESH_BLOCKED_AUTH_OR_ACCESS`:页面明确登录、验证码、访问控制或等价阻断; - `PARTIAL_DISCOVERY_UNCONFIRMED`:页面覆盖不完整或只有非权威公开发现,不能确认无新增。 ## 2. 审核基线与实现入口 - 组合方案:V001 + V002 + V003 + V004;V004 最终锁协议复审为 `PASS/0`。 - 主 CLI:`dev/project-dev/bili_dynamic_collector.py` - refresh 协调层:`dev/project-dev/bili_dynamic_refresh.py` - 页面 observation 合同:`dev/project-dev/bili_dynamic_page_observation_contract.json` - 只读提取脚本:`dev/project-dev/bili_dynamic_page_extract.js` - 示例配置:`dev/project-dev/bili_dynamic_collector.example.json` - 原功能回归:`dev/project-dev/test/test_bili_dynamic_collector.py` - refresh 测试:`dev/project-dev/test/test_bili_dynamic_refresh.py` - fixture 说明:`dev/project-dev/test/fixtures/bili_dynamic_refresh/README.md` 原采集器的 check、move-completed、handoff 与终态证据合同保留;只新增 refresh 配置、两个 CLI 子命令和独立 refresh 模块。 正式前像 `ana-data/news-青枫浦上Q/manifest.jsonl` 为 48 行事件账。离线 catalog 验收复算为 22 个 identity component、16 个已保存实体、5 个视频跟踪实体和 1 个可重试实体。 ## 3. 已实现合同 1. `refresh-begin` 创建 schema 2 pending 和一小时一个的 durable slot,绑定 run/config/contract/extractor/evidence path 与进程 identity;同一 UTC 小时不重复启动。 2. `refresh-commit` 严格校验 duplicate-key、UTF-8、路径、run、时钟、页面身份、观察计数、cards/unparsed 位置互斥、终止标记和安全发现状态。 3. 页面不可读和无凭据公开 endpoint `-412` 分别重放为 `REFRESH_FAILED_PAGE_UNREADABLE` 与非权威 partial/access evidence;两者都不能进入 no-new。 4. mixed-history loader在不改正式账的前提下复算事件身份、状态与保存文件 hash;新正文、图片和视频 metadata 使用同一 catalog 去重。 5. state lock 使用稳定一字节 kernel-backed 文件和短生命周期 owner metadata;正式 manifest lock 使用进程创建 identity、同目录同卷 quarantine、generation 与 claim attempt,恢复歧义一律停止。 6. 新内容提交同时构造 state/formal manifest 候选并记录事务 phase;正式锁、artifact、双 manifest 和 terminal slot 的 crash-reopen 由 pending 驱动恢复,失败不会冒充成功或 no-new。 7. 最近运行只保留 168 个 slot;terminal evidence 与 latest 投影由 run/status/hash 绑定,重复 commit 返回同一终态而不重复正式事件。 ## 4. 离线验证 ```powershell python -B -m py_compile ` dev/project-dev/bili_dynamic_collector.py ` dev/project-dev/bili_dynamic_refresh.py python -B -m unittest ` dev/project-dev/test/test_bili_dynamic_collector.py ` dev/project-dev/test/test_bili_dynamic_refresh.py python -B dev/project-dev/bili_dynamic_collector.py --help ``` 结果:`22/22 PASS`;`py_compile=PASS`;CLI help 显示 `check / move-completed / handoff / refresh-begin / refresh-commit` 五个入口。 refresh 九项非真空测试覆盖:真实 timeout/`-412` 状态、no-new 终止标记硬门、cards/unparsed 互斥与位置冲突、正文双 manifest 提交、168 小时 slot 与 pending 恢复、kernel-backed state lock、正式 48/22/16/5/1 catalog、dead formal lock 同卷接管。原 13 项继续覆盖既有采集器安全合同。 项目回归按文件拆分后,本任务两份测试均通过。发现的项目级异常不属于本任务: - `bili_authenticated_extension/test_protocol.py` 1 项和 `test_native_host.py` 6 项被独立产品源码树中的四个 `__pycache__/*.pyc` 触发 exact-source-set fail closed;本事项未删除或修改该独立产品缓存/源码。 - `bili_authenticated_extension_managed_load/test_managed_load.py` 在有界单文件运行中长期未终止;仅停止已确认属于该测试命令的子进程,未杀其他 Python/MCP 进程,也未修改该独立产品。 - 其余已完成的逐文件回归未发现本任务回退;长耗时的股票估值 V2 59 项也通过。 项目回归结论是 `本任务通过;整库受两个独立环境/长时问题阻断,已精确归因`,不宣称整库全绿。 ## 5. 正式数据与真实动作边界 - 正式 manifest 开发前像为 `51598 bytes / 0E69AF2AF1C4B0014D2033A21F3986E283ECFD758EA652E7F2416006736C8D73 / 48 lines`;最终检查必须仍完全一致。 - 本实现只在 `TemporaryDirectory` 和示例 `tmp/` 路径运行。正式 `ana-data` 写入为 0。 - 2026-08-13 的既有一次真实样本只用于脱敏离线重放:目标标签 reload 恰好一次,15 秒页面边界和 8 秒只读 evaluate 均超时,结果固定为 `REFRESH_FAILED_PAGE_UNREADABLE`;无凭据公开 endpoint 返回 `code=-412`,只支持 partial/access 附证。 - 本轮新 Chrome reload、DOM/evaluate、公开 API、network retry、Cookie/session 读取、下载、媒体写入、`F:\video`、扩展/policy/HKCU、转写均为 0。 - 实现 PASS 只表示离线协调器可交付,不自动授权真实刷新或正式内容写入;运营动作仍由请求方/管理员按独立边界调度。 ## 6. 实现审核状态 当前状态:`IMPLEMENTATION_COMPLETE_PENDING_ORIGINAL_REVIEWER`。本文件记录开发者冻结证据;最终可用结论以同一 task、同一 `dev.reviewer.project / inforev` 实现复审终态为准。 ## 7. HOLD/4 聚焦修复与复验(覆盖第 6 节状态) - 首次实现复审正式终态为 `HOLD/4`,MB-X 结果消息为 `msg_20260813173933589_7efe75d8`。本节仅闭环该结果列出的 F1—F4,不重开 V001+V002+V003+V004 已通过设计,不扩大产品或真实动作范围。 - F1:`page_observation.cards` 与 `items` 现在按规范化 `dynamic_id/opus_id/bvid/dedupe_keys/content_type/published_at/source_url` 精确双向绑定;重复绑定漂移、跨卡 token 重叠、缺项、额外项和内容属性不一致均以 `E_EVIDENCE_ITEM_BINDING` 失败关闭,不能投影为无新增。 - F2:mixed-history catalog 现在跨全部 JSONL 行构造 identity union,并验证 schema 1/2 状态、身份、URL/BVID/opus 一致性与 schema 2 artifact path/bytes/SHA-256;状态优先级固定为 saved、video tracking、retry-only,冲突组件失败关闭。 - F3:每小时终态 slot 与 `latest.json` 冻结为精确八键索引;无正式变化显式记录 `NO_FORMAL_CHANGE` receipt;slot/latest 均写后读回。`EVIDENCE_BOUND` 与 `TERMINAL_RECORDED` 重开可复算终态、重建缺失/较旧 latest 并清理自身 pending,冲突 latest 不覆盖。 - F4:V004 `CREATE_PLANNED` 在持有进程死亡或 PID reuse 时按同 generation、attempt+1 换绑;已存在失败 claim 先移动到同卷 quarantine,并写入/验证 owner marker,成功恢复后只清理本次所有权范围。 - 新增 reviewer 非真空反例覆盖观察/条目缺失与重叠、跨行 catalog 冲突与 schema 2 artifact 漂移、无变化与正式提交 receipt、slot/latest 写入故障及重开、CREATE_PLANNED absent/existing claim 两类恢复。 - 最终目标测试为 collector 13 项 + refresh 17 项,共 `30/30 PASS`;`py_compile=PASS`、CLI help exit 0。整库 discover 未作为本事项通过证据:已确认的 authenticated-extension `__pycache__` exact-set 失败与 managed-load 长时项属于独立产品,本修复未修改或清理它们。 - 正式 manifest 终检仍为 `51598 bytes / 0E69AF2AF1C4B0014D2033A21F3986E283ECFD758EA652E7F2416006736C8D73 / 48 lines`。Chrome、网络、下载、正式采集、`F:\video`、Cookie/session、扩展/HKCU 与转写动作均为 0。 - 当前状态更新为 `HOLD4_FOCUSED_REPAIR_COMPLETE_PENDING_LIMITED_REREVIEW`;最终结论仍以原 task、原 `dev.reviewer.project / inforev` 限定复审为准。 ## 8. HOLD/3 F2—F4 聚焦修复(覆盖第 7 节状态) - 第二次限定复审正式终态为 `HOLD/3`,MB-X 结果消息为 `msg_20260813204949399_274b6660`;F1 observation/items 已关闭,本节只修 F2—F4。 - F2:schema 2 `creator_uid` 必须是与配置精确相等的 string;schema 1 数字 `stable_id` 仅接受 1—32 位 ASCII digits,33 位和全角数字均失败关闭。schema 1 冻结历史 UID 兼容口径保持不变。 - F3:pending CreateNew 后、STARTED 前崩溃会从 durable pending 机械重建同一 run 的 exact STARTED slot,并返回同 run_id;既有 slot 只有 exact STARTED 或 exact planned TERMINAL 可接受,第三内容永不 replace。`TERMINAL_RECORDED` 重开会复算 planned schema、receipt、当前双 manifest identity 和 exact terminal slot bytes,再补 latest/cleanup。 - F4:失败 claim 先把 exact quarantine intent、规范相对路径、archive/quarantine 目录 identity、bytes/hash/attempt 写入 pending,再执行 no-overwrite rename。Windows 使用 `MoveFileExW(MOVEFILE_WRITE_THROUGH)` 且不带 replace;rename 后 flush/readback 目录项。主 lock 已删除时 terminal cleanup 仍继续删除 exact quarantine/failed claims/owner marker,空目录崩溃点可重开完成并 flush 父目录。 - 新增非真空反例覆盖 schema2 integer UID、schema1 超长/非 ASCII stable ID、pending→STARTED 崩溃同 run、STARTED/TERMINAL 第三 slot、tampered planned receipt、failed-claim intent 后 rename 前崩溃、no-overwrite target、目录 flush 与主锁先删后的 cleanup reopen。 - 最终目标测试为 collector 13 项 + refresh 21 项,共 `34/34 PASS`;`py_compile=PASS`。正式 48 行 catalog 仍只读通过 `48 events / 22 components / 16 saved / 5 video / 1 retryable`。 - 正式 manifest 仍为 `51598 bytes / 0E69AF2AF1C4B0014D2033A21F3986E283ECFD758EA652E7F2416006736C8D73 / 48 lines`。Chrome、网络、下载、正式采集、`F:\video`、Cookie/session、扩展/HKCU 与转写动作均为 0。 - 当前状态=`HOLD3_F2_F4_REPAIR_COMPLETE_PENDING_LIMITED_REREVIEW`。 ## 9. HOLD/1 F4 formal-lock durable-create 聚焦修复(覆盖第 8 节状态) - 原 reviewer 正式回执 `msg_20260814002856995_85f04dca` 为 `HOLD/1`;F2/F3 保持关闭,本轮只关闭 `F4_NEW_FORMAL_CLAIM_CREATE_NOT_READBACK_OR_DIRECTORY_DURABLE`。 - 新增单一 `_durable_formal_lock_claim` 门:所有 formal-lock CreateNew 均先完成文件 flush/fsync,再做 lexical lstat、精确 bytes/length/SHA-256 回读、父目录 fsync,并在持久化后再次精确回读;只有全部成功后才允许写入 `HELD/NEW_LOCK_HELD`。 - post-create 第三内容漂移、读取失败或父目录 fsync 失败均保留 `PLANNED/CREATE_PLANNED`;第三内容不覆盖。精确 lock 已创建但目录 fsync 失败时,同一 pending 可在重开后重新验证/持久化并晋升。 - 新增公开反例覆盖 drift/readback/fsync 三类故障,并用真实子 Python 进程在 CreateNew 后父目录 fsync 前、以及 `NEW_LOCK_HELD` 后两个断点 kill;重开均沿 durable pending 恢复,正式 manifest 和第三内容保持不变。 - 限定反例 `2/2 PASS`;目标全量 collector 13 + refresh 23=`36/36 PASS`;refresh 单文件 `23/23 PASS`;`py_compile=PASS`、CLI help exit 0、governance=`OK/projects1/warnings0`。 - 正式 manifest 冻结前像仍为 `51598 bytes / 0E69AF2AF1C4B0014D2033A21F3986E283ECFD758EA652E7F2416006736C8D73 / 48 lines`;Chrome/network/download/formal write/`F:\video`/Cookie/session/extension/HKCU/media/transcription 均为 0。 - 当前状态:`F4_DURABLE_CREATE_REPAIR_COMPLETE_PENDING_LIMITED_REREVIEW`;最终结论以原 task、原 `dev.reviewer.project/inforev` 限定复审为准。 ## 10. V005+V006 supported Chrome runtime 超时合同实现 - F4 离线实现复审已于 `msg_20260814015709581_78422206` 获 `PASS/0`。随后生产槽 018/019/020 连续投影为 `REFRESH_FAILED_PAGE_UNREADABLE`;这些槽与 evidence 保持不可变,未改判、覆盖或重交。 - 只读诊断显示同一 complete/visible/content-bearing 页面上,supported evaluate/visible-DOM/screenshot 分别约 21343/21355/21389ms 后成功,故可复核问题是旧 15s/8s 合同低于共同控制路径延迟,不把业务 selector 或单个内部组件过度断言为唯一根因。 - V005 设计首次复审 `HOLD/1`,消息=`msg_20260814050003153_4b3b36b1`;V006 精确拆分 PRE/POST dispatch error 后组合设计于 `msg_20260814051716904_5ebc133f` 获 `PASS/0`。 - 新 runtime-v2 固定 `120/35/45/15s` 总体/action/observation/internal-settle 预算,只允许一次 supported reload/goto 和一次 source-controlled evaluate,retry=0;runtime contract bytes/SHA、pending/evidence schema3、实际 action/observation count 与 elapsed 墙钟机械绑定。 - `PRE_DISPATCH_ERROR` 固定 0/0、零保存、unreadable;`POST_DISPATCH_ERROR` 固定 action count1,若可读新完整条目可保守保存但不得 coverage/no-new,可读空为 partial,读取失败为 unreadable。TIMEOUT 同样永不确认 no-new;CONFIRMED 才能结合旧 coverage 硬门产生 no-new。 - 原 schema2 pending 仅保留历史恢复/终结能力,不可升级或触发 runtime-v2 动作。旧 timeout 配置字段在 begin 前 `E_CONFIG`,example 已改为四个 exact runtime-v2 常量。 - 新增 runtime contract JSON、单 evaluate bounded-settle extractor 以及 8 项入口/矩阵测试;collector13+refresh31=`44/44 PASS`,`py_compile=PASS`、CLI help exit0。 - 正式 manifest 仍为 `51598 bytes / 0E69AF2AF1C4B0014D2033A21F3986E283ECFD758EA652E7F2416006736C8D73 / 48 lines`。实现与测试期间 Chrome/reload/goto/network/download/formal write/Raw CDP/Cookie/session/`F:\video`/media/transcription=`0`。 - 当前状态=`V005_V006_RUNTIME_REPAIR_COMPLETE_PENDING_LIMITED_IMPLEMENTATION_REVIEW`;首次新 runtime smoke 必须在本实现复审 PASS 后由 requester/admin 另行调度。 ## 11. runtime HOLD/5 权威纠偏与完整修复(覆盖第 10 节状态) - 当前唯一权威 runtime 实现审核终态是 `msg_20260814065631653_4be06bb5 / HOLD/5`,对应 `DEV-AUDIT-PROJECT-INFO-BILI-DYNAMIC-REFRESH-COLLECTOR-V005-V006-RUNTIME-LIMITED-IMPLEMENTATION-REVIEW-20260814-001`。旧消息 `msg_20260814015709581_78422206` 仅关闭 V004 formal-lock durability;误发撤回 `msg_20260814080254352_57428c14` 不撤销、不覆盖 runtime HOLD/5。 - F1:新增 source-controlled `bili_dynamic_refresh_controller.py`。controller 独占 tab 选择、dispatch 前后状态、单调计数、HMAC capability attestation、CreateNew partial→file fsync→no-overwrite rename→parent fsync→readback;begin 不回显 capability,调用者手写/篡改 outcome 无法绑定成功终态。 - F2:controller 向唯一 supported evaluate 传入 source-controlled extractor 与固定 15 秒调用表达式;deterministic adapter 生成 creator、cards、unparsed fingerprints、terminal marker、items 和 observation。真实 Node fixture 驱动 readable-new、empty、unparsed、identity 四态;受控 adapter 另覆盖 access blocked,均进入产品 evidence→CLI 链而非 Python 手写观察。 - F3:总 deadline 同时约束 action、observation、evidence durable completion 与 binding。evidence 写后立即复算同一 monotonic deadline;跨线时只删除本次 exact owned payload、fsync 父目录并保持 pending=`AWAITING_EVIDENCE`。`bind_controller_evidence` 另以 pending wall deadline 拒绝迟到绑定;CLI deadline+ε 不保存、不推进 manifest。 - F4:schema2 pending 在 begin、commit、controller 三入口均是 recovery-only;`AWAITING_EVIDENCE × slot present/missing × deadline before/after` 矩阵不会返回 `BROWSER_REFRESH_REQUIRED`,controller 在任何 browser adapter 调用前拒绝。 - F5:final URL、UID、name、profile 任一不匹配,在 CONFIRMED、TIMEOUT、POST_DISPATCH_ERROR 三种已派发结果下均持久化为 `REFRESH_BLOCKED_AUTH_OR_ACCESS/E_CREATOR_MISMATCH/exit3`;terminal slot/latest 完成、pending 清理、no-new=false、正式 manifest 不变。 - reviewer 聚焦反例=`6/6 PASS / 7.427s`,其中包含 F2 五态链、F4 12 组合和 F5 4×3 矩阵;refresh 全量=`37/37 PASS / 15.384s`;collector+refresh=`50/50 PASS / 20.114s`;`py_compile=PASS`、CLI help exit0、strict UTF-8/no BOM/trailing whitespace=`PASS`、secret literal scan=`0`、governance=`OK/projects1/warnings0`。 - project discover 完整执行=`Ran 191 tests in 172.129s / failures=46 / skipped=6`。本任务 collector+refresh 零失败;7 个 failure records 位于独立 authenticated-extension(既有 `__pycache__` exact-source 漂移),39 个位于独立 managed-load(fixture 在 `E_BUILD_CONTRACT` 审计/批准门失败)。本事项不删除缓存、不改这些产品,也不把整库宣称为全绿。 - 正式 manifest 测试前后严格保持 `51598 bytes / 48 lines / 0E69AF2AF1C4B0014D2033A21F3986E283ECFD758EA652E7F2416006736C8D73`。本轮 Chrome、network、refresh-begin 正式调用、formal write、Cookie/session、Raw CDP、download、media、`F:\video`、transcription 均为 0。 - 当前状态=`RUNTIME_HOLD5_F1_F5_REPAIR_COMPLETE_PENDING_ORIGINAL_REVIEWER`;只接受原 task、原 `dev.reviewer.project/inforev` 的新实现复审终态。