# CODE-DESIGN-PROJECT-INFO-BILI-DYNAMIC-REFRESH-COLLECTOR-V005 创建人员:`dev.developer.project.secondary / infodev-2` 事项:`DEV-PROJECT-INFO-BILI-DYNAMIC-REFRESH-COLLECTOR-20260813-001` 需求:`REQ-BILI-DYNAMIC-COLLECTOR-20260804-001` 性质:既有重型事项的受控 runtime 超时合同增量设计 前序组合方案:V001+V002+V003+V004 状态:`PENDING_ORIGINAL_REVIEWER_RUNTIME_DELTA_REVIEW / IMPLEMENTATION_FROZEN` ## 1. 变更来源与冻结基线 前序离线实现最终复审 `PASS/0`: - result message=`msg_20260814015709581_78422206`; - audit=`DEV-AUDIT-PROJECT-INFO-BILI-DYNAMIC-REFRESH-COLLECTOR-HOLD1-F4-DURABLE-CREATE-REREVIEW-20260814-001`; - audit snapshot=`495824/95ACC6236CB9F787137FC64F0DACBD796972258BB16E492B84928AD7565ED783`; - product=`bili_dynamic_refresh.py|109597|5C813E3023319A4DEB38AC7213135D52F7DB3E137D9306F642A94941AF8011BD`; - tests=`test_bili_dynamic_refresh.py|53314|5895C8409DF753C67A3E1429FF50048F7BE7850CABC63B13EBA42A55CBE85E10`; - 正式 manifest=`51598/0E69AF2AF1C4B0014D2033A21F3986E283ECFD758EA652E7F2416006736C8D73/48 lines`。 生产运行槽 018/019/020 连续三小时均在 exact 目标页的一次受支持 reload 或 direct goto 后、可见 DOM/evaluate 读取完成前超时,正确形成 `REFRESH_FAILED_PAGE_UNREADABLE`,正式 manifest 不变。这三个 terminal slot 是不可变历史:不得改判、覆盖、重交旧 evidence 或把当前页面内容追溯写入旧 run。 本设计不重开 UID、五终态、coverage/no-new、mixed-history catalog、双 manifest 事务、slot/latest、formal lock 与崩溃恢复合同。 ## 2. 只读诊断事实 诊断入口:`dev/tmp/bili-dynamic-refresh-collector-20260813-001/runtime-read-timeout-diagnosis-20260814.json`。 本轮没有 reload、goto 或任何页面写动作。使用现有 Chrome 受支持控制面精确认领目标标签后: | 受支持只读面 | wall | 结果 | |---|---:|---| | `playwright.evaluate` 最小 document 状态 | 21,343 ms | PASS | | `dom_cua.get_visible_dom` | 21,355 ms | PASS | | viewport screenshot | 21,389 ms | PASS | 页面返回 `document.readyState=complete`、`visibilityState=visible`、正文可见文本长度 19,890,页面 console error/warn=0。三条独立读面都在约 21.3 秒后成功,并伴随控制运行时自身的有界遥测超时信号;未保存 endpoint、key、payload 或 raw error。 因此可复核根因是:**冻结的 page-ready=15s、DOM-read=8s 低于当前受支持 Chrome 控制路径的共同调用延迟**。业务 DOM/selector 不是三条读面共同失败的原因。内部遥测实现是否为唯一原因不作过度断言。 ## 3. 最小受支持运行修复 ### 3.1 单 action、单 observation 每一小时 run 只允许以下控制序列: 1. `refresh-begin` 创建同一 run/pending/slot; 2. 通过 Chrome `openTabs()` 精确选择 `https://space.bilibili.com/1420210197/dynamic`;现有 exact tab 只 `reload()` 一次,没有 exact tab 才 `goto(exact_url)` 一次;二者合计始终为 1; 3. action 返回或达到其有界超时后,**不得再次 reload/goto**; 4. 同一标签只调用一次 source-controlled `playwright.evaluate` observation;该调用在一个页面作用域内机械取得 ready/url/title/creator、可见 cards、unparsed nodes、终止标记和现有 extractor 所需字段; 5. 不再串行调用 `waitForLoadState + domSnapshot + evaluate`,也不以 screenshot、visible DOM、坐标或 Raw CDP 作降级; 6. controller 只按既有 CreateNew `.partial`→fsync→rename 写 exact evidence;CLI 仍是唯一验证与持久化入口。 这不是页面/API 绕过,不新增 Chrome 权限,不读取 Cookie、token、localStorage、profile、header、响应体或签名 URL。 ### 3.2 固定预算 新增 source-controlled runtime contract,冻结: ```text contract_id=bili-supported-chrome-visible-runtime-v2 overall_deadline_seconds=120 refresh_action_timeout_seconds=35 observation_timeout_seconds=45 page_internal_settle_timeout_seconds=15 max_refresh_count=1 max_observation_count=1 ``` `refresh-begin` 的 pending deadline 固定为 started+120s。35s action 与 45s observation 都受同一单调总 deadline 约束;内部 settle 仅发生在同一个 evaluate 内,不产生第二个浏览器控制调用。任一阶段不得无界等待、重试或在总 deadline 后写 evidence。 配置与 evidence 必须同时绑定 runtime contract id/bytes/SHA-256。V005 对未来 runtime-v2 run 精确替代 V001/V002 的 `timeout_seconds=30`、`page_ready_timeout_seconds=15`、`dom_read_timeout_seconds=8` 配置语义: - `refresh` 配置必须且只允许新增 `overall_deadline_seconds=120`、`refresh_action_timeout_seconds=35`、`observation_timeout_seconds=45`、`page_internal_settle_timeout_seconds=15`;这些值是冻结常量,不是可调范围; - 新配置中出现旧三个 timeout 字段,或新字段缺失/非整数/不等于冻结值,均在 `refresh-begin` 任何 pending/lock/business 写前以 `E_CONFIG` 失败关闭; - `refresh-begin` 成功 stdout 必须回显 runtime contract id/SHA-256 与四个冻结预算,便于 controller 在浏览器动作前核对; - 新 begin 创建 pending schema 3 并绑定 runtime contract id/SHA-256、四预算、action/observation 上限和单调 deadline;已有 schema 2 pending 只允许按其原合同恢复/终结,不得升级、换绑或触发 runtime-v2 浏览器动作; - 新 run 的安全诊断 exact keys 替换为 `{code,overall_deadline_seconds,refresh_action_timeout_seconds,observation_timeout_seconds}`;不保留语义已过期的 page-ready/DOM-read 字段,也不保存 raw browser error。 实现只扩展现有 `RefreshConfig` 和安全诊断 schema,不创建服务、浏览器 daemon 或新调度器。 ### 3.3 action timeout 后的保守投影 受支持 action 调用超时可能已经触发页面刷新,因此绝不重试。之后仍允许唯一一次 observation,用于区分“页面实物可读”与“控制面完全不可读”,但不得伪称 action 已确认完成: | action | observation | 允许终态 | |---|---|---| | confirmed | exact READABLE + 新完整条目 | `NEW_ITEMS_SAVED` | | confirmed | exact READABLE + coverage complete + 无新增 | `REFRESH_CONFIRMED_NO_NEW` | | timeout | exact READABLE + 新完整条目 | 可保存新条目,但 coverage/no-new token 必为 false;状态仍按已有新条目合同 | | timeout | exact READABLE + 无新增/coverage | `PARTIAL_DISCOVERY_UNCONFIRMED`;绝不 no-new | | 任意 | observation timeout/error | `REFRESH_FAILED_PAGE_UNREADABLE` | | 任意 | exact login/captcha/access/identity mismatch | `REFRESH_BLOCKED_AUTH_OR_ACCESS` | 新增 `refresh_action_outcome=CONFIRMED|TIMEOUT|ERROR`,以及 bounded elapsed buckets;不得写 raw browser error。`REFRESH_CONFIRMED_NO_NEW` 新增硬门 `refresh_action_outcome=CONFIRMED`。 ## 4. 证据 schema 增量 未来 runtime-v2 的 browser evidence schema 固定升级为 3;schema 2 仅可用于与旧 pending/terminal identity 精确一致的历史恢复,不可提交到 schema 3 pending。在既有 evidence 根增加 exact runtime object: ```text runtime_contract={contract_id,contract_bytes,contract_sha256} runtime_observation={ refresh_action_outcome, refresh_action_elapsed_ms, observation_outcome, observation_elapsed_ms, refresh_count, observation_count } ``` - elapsed 必须为 0..对应预算的整数;timeout 可等于预算上界; - `refresh_count` 与 `observation_count` 都只能为 1,且必须与 pending schema 3 中的动作预算一致; - source-controlled observation 输出不接受由调用者直接声称的 coverage totals;CLI 继续从 observations/cards/unparsed/marker 重算; - 旧 V1 evidence 仅作为已经落定 slot 的历史证据,不允许提交给新 run;新 run 只接受 runtime-v2; - 任何 contract/hash/elapsed/action count/timeout drift 均 `E_EVIDENCE_SCHEMA`,两份 manifests 不变。 ## 5. 实现边界 设计 PASS 后才允许修改: - `dev/project-dev/bili_dynamic_collector.py`:runtime contract config/上限; - `dev/project-dev/bili_dynamic_refresh.py`:runtime-v2 evidence/schema/no-new action-confirmed 硬门; - `dev/project-dev/bili_dynamic_page_extract.js`:单次 evaluate 的 bounded ready+visible extraction 包装,不做网络或存储访问; - 新增 `dev/project-dev/bili_dynamic_browser_runtime_contract.json`; - 对应 example、fixtures、tests、工具说明、实现证据和必要 append-only 执行账。 不得修改正式 manifest,不得新增浏览器扩展权限、Raw CDP、坐标控制、Cookie/session、本地 profile、网络 API、下载、媒体、`F:\video`、formal ana-data 或转写能力。 ## 6. 离线验收合同 1. 21.5s action + 21.5s observation 在 35/45/120 合同内成功,控制调用数 exact 1+1; 2. action=35s timeout 后 observation exact 一次,refresh count 仍为1;无新增必须 partial,no-new token=0; 3. observation=45s timeout 为 unreadable,formal/state business manifests 不变; 4. overall 120s 截止后无调用、无 evidence 写入; 5. action timeout + 可见新完整 item 可保存,但不得产生 no-new/coverage complete; 6. confirmed action + exact complete no-new 仍必须通过原 V002 observation/coverage 全硬门; 7. runtime contract/hash/elapsed/count/action-outcome 任一漂移 fail closed; 8. 018/019/020 旧 slot 原 bytes 不变且不能作为新 run evidence; 9. synthetic unique secret sentinel 不进入 evidence/log/stdout;合法 `cookies` 标识符不误杀,Cookie/session 值读取仍为0; 10. 原 36 项目标测试、formal 48/22/16/5/1 只读验收和 F2/F3/F4 合同不回退。 不要求设计/实现复审进行真实 reload、goto、网络或正式写入。若后续实现 PASS,首次新 runtime smoke 必须由 requester/admin 单独调度,仅作用于新小时槽,且最多一次 action、零重试。 ## 7. 当前冻结状态 - product code/test/fixture modification=0(相对于 F4 PASS snapshot); - 本轮 Chrome reload/goto=0;只读页面诊断已完成并释放标签; - network/download/formal write/Cookie/session/Raw CDP/F:\video/media/transcription=0; - 正式 manifest 仍为 `51598/0E69AF2AF1C4B0014D2033A21F3986E283ECFD758EA652E7F2416006736C8D73/48`; - 实现保持冻结,等待原 `dev.reviewer.project/inforev` 对 V005 聚焦设计复审。