创建人员:dev.developer.ana.cai
文件职责:append-only 修复 V001 独立审核的 6 个 blocking findings,并冻结可直接实现、测试和复核的模块 API、状态模型、时间边界、原子归档、额度并发与性能样本合同。
predecessor:CODE-DESIGN-ANA-HIBOR-FAST-COLLECTION-V001=15549/ecacaaea740454ae56e928ef58af4a5d5e706334b1ac917c8647db8a8eb3edf9。
predecessor review:AUDIT-DEV-ANA-HIBOR-FAST-COLLECTION-DESIGN-V001=HOLD/6/6,审计入口 ana-doc/案例审计报告.md。
记录方式:V001 保持不可变;V002 对冲突处拥有后继优先级,V001 已通过的包名、缓存、访问控制、原件、额度上限、角色和零实现关口全部继续有效。普通源码/内部测试按语义验收,PDF、正式 manifest、额度账本和终态证据按真实消费者要求做哈希与不可变验证,不恢复普遍逐字节预冻结。
V002 必须同时关闭:
BLOCK-HIBOR-DESIGN-01:逐模块 API、调用图、canonical model/schema、主键、错误与 exit 总映射;BLOCK-HIBOR-DESIGN-02:任务观察时点传递、单一 monotonic deadline、子进程/锁/I/O/terminal 的有界生命周期;BLOCK-HIBOR-DESIGN-03:PROVISIONAL_VISIBLE 与 DETAIL_CONFIRMED 分离,早停失效后的 cursor 恢复与补扫;BLOCK-HIBOR-DESIGN-04:同目录 staging、完整验证后原子 no-replace 发布、崩溃恢复与 package closure;BLOCK-HIBOR-DESIGN-05:额度 read-fold-reserve 原子临界区、事件主键/幂等、并发和 replay;BLOCK-HIBOR-DESIGN-06:10 个 trigger 的预登记总体、批量计数、SLA failure 与 external exclusion 口径。方案复审 PASS 前仍禁止创建候选源码/测试、运行 Python/ADB/APP/dry-run、创建额度账本或产生真实下载 trigger。
cli.main() 是唯一 orchestration owner;其余模块不得互相创建 run、写 terminal、追加额度或自行启动外部命令。RunContext 由 CLI 创建一次并只读传递。外部命令全部通过 ProcessSupervisor.run(argv: Sequence[str], ...),必须是 argv list、shell=False;模块不得调用 os.system、shell 字符串、隐式 PATH 脚本或自行 subprocess.*。
下列为包内唯一 public API;未列函数/类必须以下划线开头,测试不得依赖其实现细节。
| 模块 | 唯一公共 API | 返回/异常 | owner |
|---|---|---|---|
models.py |
load_task_spec(path: Path) -> TaskSpec;validate_task_spec(x: Mapping) -> TaskSpec;to_ordered_dict(model) -> dict |
仅抛 ContractError(code, field, detail) |
CLI |
budget.py |
Budget.start(observed_at_utc: str, total_ms: int, close_reserve_ms: int, clock: Clock) -> Budget;remaining_ms(kind: Literal['work','close']) -> int;checkpoint(phase: Phase, operation: str, kind='work') -> None;slice(max_ms: int, teardown_ms: int) -> int |
到期抛 BudgetExpired; wall-clock 回退/未来时间/启动前已耗尽抛 ContractError |
CLI |
process.py |
ProcessSupervisor.run(argv: Sequence[str], cwd: Path, budget: Budget, phase: Phase, input_bytes: bytes|None, max_stdout: int, max_stderr: int) -> ProcessResult |
不抛裸异常;所有可观测结果封装;liveness unknown 置 LIVENESS_UNKNOWN |
ADB/PDF provider only |
adb.py |
AdbClient.preflight(ctx) -> DeviceSnapshot;list_cache(ctx) -> tuple[RemoteFile,...];remote_sha256(ctx,path)->str;pull(ctx,remote,local_staging)->PullResult;ui_dump(ctx)->UiSnapshot;screenshot(ctx,dst_staging)->ArtifactDraft;tap/swipe/input_text/back/start_package(ctx,...) -> ActionReceipt |
只经 ProcessSupervisor;包/设备/cache 身份漂移为 typed stop | UI/cache |
ui.py |
FastScanner.scan(ctx, checkpoint: ScanCheckpoint|None) -> ScanOutcome;confirm_detail(ctx,candidate)->Candidate;restore(ctx,checkpoint)->ScanCheckpoint;trigger(ctx,candidate,reservation)->TriggerReceipt |
不写 quota/PDF/terminal;每次动作前后验证 anchor/package | CLI |
quota.py |
QuotaLedger.snapshot(ctx)->QuotaSnapshot;reserve(ctx, report_key, slot_id)->ReservationResult;confirm(ctx,reservation,trigger)->QuotaEvent;mark_uncertain(...);release(...);raise_baseline(ctx,floor,evidence_ref)->QuotaEvent |
每次 API 内部独占一次完整 read-validate-fold-check-append-fsync-reopen 临界区 | CLI |
cache.py |
CacheWatcher.capture_baseline(ctx)->CacheBaseline;wait_unique_stable(ctx,baseline,trigger)->CacheMatch |
只读远端;歧义/超时返回 typed stop | CLI |
archive.py |
ArchiveManager.stage_pull(ctx,match)->ArtifactDraft;validate(ctx,draft,detail)->ValidatedArtifact;publish_no_replace(ctx,validated,destination)->PublishedArtifact;recover(ctx,recovery_record)->RecoveryResult |
不写 manifest/quota/terminal;正式路径只通过原子 publish 出现 | CLI |
manifests.py |
append_manifest(ctx,row)->ManifestReceipt;write_delivery(ctx,package)->PublishedArtifact;write_timing(ctx,rows)->PublishedArtifact |
同目录 staging+验证+no-replace;manifest 单锁 append 并 fsync | CLI |
terminal.py |
build_terminal(ctx,package,stop)->TerminalRecord;persist_terminal(ctx,record)->TerminalReceipt;render_public_payload(record)->str |
不发送消息;console payload 永远可生成,持久化失败如实记录 | CLI |
cli.py |
main(argv: Sequence[str]|None=None)->int |
捕获所有 typed/untyped 错误,按第 5 节唯一映射返回 | public |
cli.main
-> models.load_task_spec
-> Budget.start
-> AdbClient.preflight + QuotaLedger.snapshot
-> FastScanner.scan
-> AdbClient.ui_dump/screenshot/action
-> FastScanner.confirm_detail
-> CacheWatcher.capture_baseline
-> QuotaLedger.reserve
-> FastScanner.trigger
-> QuotaLedger.confirm|mark_uncertain|release
-> CacheWatcher.wait_unique_stable
-> ArchiveManager.stage_pull -> validate -> publish_no_replace
-> append_manifest
-> write_delivery -> write_timing
-> build_terminal -> persist_terminal -> render_public_payload
collect-batch 仅在 CLI 层循环 item;每个 item 使用独立 report_key、reservation、artifact 和 manifest row,共享 search/scan checkpoint。任何模块不得反向调用 CLI 或 terminal。
Id:非空 ASCII [A-Za-z0-9._:-]{1,160};PathText:绝对 Windows 路径字符串;RemotePath:以固定 cache root 开头的 POSIX 路径。UtcTime:UTC RFC3339,毫秒 3 位,后缀 Z;Hash:小写 64 位十六进制;Bytes/Millis:非负 JSON integer;BOOL 只允许 JSON true/false。true|false。TaskSpec V002(有序 27 键)schema_version,task_id,handoff_id,requester,review_owner,mode,query,quantity,destination_root,output_root,quota_ledger,adb_executable,pdfinfo_executable,package_name,cache_root,device_serial,observed_at_utc,total_budget_ms,close_reserve_ms,batch_increment_budget_ms,min_screens,normal_max_screens,hard_max_screens,hard_max_candidates,selection_filters,performance_slot_id,performance_plan_id
schema_version='HIBOR_FAST_TASK_SPEC_V002';mode=DRY_RUN|COLLECT_ONE|COLLECT_BATCH|RESUME_POSTPROCESS。package_name='cn.com.hibor';cache_root='/sdcard/Android/data/cn.com.hibor/files/myfile/'。quantity INT 1..10;collect-one 的 total_budget_ms=600000;collect-batch 的 total_budget_ms=600000+240000*(quantity-1);close_reserve_ms=10000;batch_increment_budget_ms=240000;screens=3/5/20;candidates=100。device_serial STRING|null;dry-run 必须 null,真实模式必须非空并与唯一设备一致。performance_slot_id/performance_plan_id 均 STRING|null;真实性能运行必须非空,普通生产采集均为 null。selection_filters 为有序对象:subject:string,allowed_institutions:array<string>|null,report_types:array<string>,date_from:YYYY-MM-DD,date_to:YYYY-MM-DD,min_pages:int,max_pages:int,analyst_required:bool,max_per_institution:int;不得含评分之外的主观字段。Candidate V002(有序 22 键)candidate_id,report_key,state,query,screen_index,rank_on_screen,result_title,result_institution,result_date,result_pages,result_analysts,detail_title,detail_institution,detail_date,detail_pages,detail_analysts,detail_fingerprint,hard_filter_pass,score,duplicate_of,reject_code,checkpoint_id
state=DISCOVERED|PROVISIONAL_VISIBLE|DETAIL_OPENED|DETAIL_CONFIRMED|REJECTED|TRIGGER_RESERVED|TRIGGERED|CACHE_MATCHED|ARCHIVED|FAILED。PROVISIONAL_VISIBLE 后非空;detail 字段在 DETAIL_CONFIRMED 后非空;此前为 null。hard_filter_pass 为 BOOL|null,仅 DETAIL_CONFIRMED/REJECTED 可非空;score 为 INT|null,仅 result 字段完整时可非空。duplicate_of/reject_code 为 STRING|null;被拒/重复时必须提供其一。稳定 top-K 只能使用 PROVISIONAL_VISIBLE 的 provisional ranking 作为“暂停扫描”依据,最终 trigger 集只允许 DETAIL_CONFIRMED && hard_filter_pass=true && duplicate_of=null。ScanCheckpoint V002(有序 10 键)checkpoint_id,query,screen_index,scroll_count,page_fingerprint,first_visible_key,last_visible_key,seen_candidate_ids,provisional_top_ids,created_at_utc
数组顺序为实际扫描顺序;page_fingerprint 是 UI dump 规范化可见节点的 SHA-256,不是截图内容推断。restore 后 query、screen/scroll、first/last key 和 fingerprint 必须全部一致,否则 UI_CURSOR_RESTORE_FAILED。
QuotaEvent CSV V002(固定 18 列)schema_version,event_id,idempotency_key,ledger_date,event_seq,event_type,task_id,handoff_id,run_id,slot_id,report_key,reservation_id,ref_event_id,confirmed_delta,uncertain_delta,reservation_delta,baseline_floor,created_at_utc
event_id=sha256(ledger_date+'|'+idempotency_key+'|'+event_type+'|'+event_seq);idempotency_key=sha256(task_id+'|'+handoff_id+'|'+slot_id+'|'+report_key)。event_type=BASELINE_ESTIMATE|CORRECTION_RAISE|RESERVE|CONSUME_CONFIRMED|CONSUME_UNCERTAIN|RELEASE。baseline_floor 为 INT;baseline 首次至少 3,correction 只能提高 floor,ref_event_id 指向证据事件。0/0/+1;confirmed:+1/0/-1;uncertain:0/+1/-1;release:0/0/-1;其余组合非法。QUOTA_REPLAY_CONFLICT。TimingRow CSV V002(固定 12 列)schema_version,run_id,item_id,phase,operation,monotonic_start_ns,monotonic_end_ns,elapsed_ms,wall_start_utc,wall_end_utc,outcome,detail_code
phase=preflight|quota|ui_search|ui_scan|detail_and_trigger|cache_wait|copy|validation|manifest|delivery|timing|terminal;outcome=PASS|STOP|FAIL|SKIP。monotonic 只允许进程内差值,wall 仅审计。
ManifestRow CSV V002(固定 34 列)schema_version,row_id,task_id,handoff_id,run_id,item_id,slot_id,requester,review_owner,query,candidate_id,report_key,title,institution,report_date,analysts,selection_reason,remote_path,remote_bytes,remote_sha256,local_path,local_bytes,local_sha256,pdf_magic_ok,pdf_openable,page_count,encrypted,quota_reservation_id,quota_terminal_event_id,status,stop_code,created_at_utc,reused_without_new_trigger,external_evidence_hash
row_id=sha256(task_id|run_id|item_id|report_key|status);成功必须 34 键全部有值或合法 null,且 remote/local bytes/hash 相等、magic/openable true、encrypted false、page_count 与详情一致。status=SUCCESS|DUPLICATE|FAILED|STOPPED;非 SUCCESS 的未知证据保持 null,禁止填造。external_evidence_hash 是该行对应正式 PDF 的 SHA-256;无正式 PDF 时为 null。PackageState V002 与终态(有序字段)每个 item 的 package row 为:item_id,report_key,state,trigger_attempted,quota_state,staging_path,final_path,manifest_row_id,delivery_present,timing_present,terminal_present,stop_code。
TerminalRecord V002 固定 30 键:
schema_version,task_id,handoff_id,run_id,mode,status,exit_code,stop_code,blocker,observed_at_utc,started_at_utc,ended_at_utc,total_elapsed_ms,work_deadline_reached,close_deadline_reached,requested,triggered,succeeded,failed,duplicates,gaps,quota_confirmed,quota_uncertain,quota_active,quota_safe_available,items,manifest_path,delivery_path,timing_path,prohibited_action_attestation
items 按 item_id 排序,元素即上述 package row。任何路径不存在时 null;prohibited_action_attestation 固定对象:remote_original_modified:false,credential_persisted:false,access_control_bypassed:false,body_parsed:false,research_conclusion_generated:false,external_message_sent:false。
provisional_set:结果页可见字段通过“可先判断”的过滤规则;只用于决定是否暂停扫描、安排详情复核,不等于合格候选。confirmed_set:详情页字段与结果页一致、所有硬过滤通过、去重完成;只有该集合可 reservation/trigger。stable_top_k:连续两屏 provisional top quantity+2 的 id+score 不变,只产生 PAUSE_FOR_DETAIL,不产生最终早停。quantity+2 且两屏稳定时保存 checkpoint,暂停扫描并按 score/既有并列规则逐个 confirm_detail。DETAIL_RESULT_MISMATCH 并 REJECTED。confirmed_set>=quantity 才允许最终结束扫描;否则调用 restore(checkpoint),从该 cursor 的下一未处理屏继续。恢复路径固定为:回到搜索入口→重新输入同 query→按 scroll_count 重放纵向翻页→比较 first/last visible key 与 page_fingerprint→从已记录 seen ids 后继续。每步都受 Budget;任一 anchor/fingerprint 不一致停止,不猜坐标。测试必须覆盖详情失败、详情/结果不一致、重复候选、trigger 未发生、早停后补扫成功、恢复 fingerprint 漂移和硬上限不足。
调用方在观察请求且环境可用时写入 TaskSpec.observed_at_utc;CLI 启动立即读取同主机 UTC,并计算 startup_elapsed_ms=now_utc-observed_at_utc。允许时钟前进,若 observed 在未来超过 2 秒、无法 parse、时差计算异常或 startup elapsed 已达到 600000ms,返回 BLOCKED_INPUT/TIME_BUDGET_STOP,不触发 UI。
CLI 随后记录 start_monotonic_ns,并创建:
close_deadline=start_monotonic + max(0,600000-startup_elapsed_ms);work_deadline=close_deadline-10000ms;最后 10 秒只用于 kill/drain、quota 收口、timing/terminal,不得启动新 UI、pull、hash、publish 或 manifest 行。min(close_deadline, item_start+240000ms) 的 item deadline。总体任务不得超过首份 600 秒;如任务明确允许批量持续,batch task spec 必须把 total_budget_ms 写成 600000+240000*(quantity-1),首份仍独立 600 秒。V002 默认按该公式验证,不接受其他值。所有 SLA 总耗时使用 ended_at_utc-observed_at_utc 与进程 monotonic elapsed 交叉核对;偏差超过 2 秒为 timing invalid,样本计失败。
ProcessSupervisor 总状态机固定状态:NOT_STARTED -> STARTED -> EXITED;异常分支 START_FAILED;deadline 分支 TIMEOUT -> TERMINATE_ONCE -> WAIT_BOUNDED -> EXITED_AFTER_TERMINATE|LIVENESS_UNKNOWN。
budget.slice(max_ms, teardown_ms=3000) 必须返回正值;argv 非空字符串数组,shell=False,cwd 固定,stdin/stdout/stderr 为 binary pipes 或 DEVNULL。JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,先 suspended create、成功 assign 后 resume;任一步失败时不运行未受管 child。非 Windows 测试用新 process group 等价模拟。communicate(timeout=slice);stdout/stderr 各有上限,超限立即进入 terminate,不截断后冒充成功。TerminateJobObject,随后 wait/communicate 最多 min(3000ms,close_remaining);确认 exit 后才返回。不能确认时关闭 Job handle并返回 LIVENESS_UNKNOWN,CLI 只做内存 terminal,不再读/写可能被 child 改动的 artifact。ProcessResult 固定字段:argv_redacted,started,pid,exit_code,timed_out,terminate_issued,exited,liveness_unknown,stdout_bytes,stderr_bytes,stdout_truncated,stderr_truncated,started_at_utc,ended_at_utc,elapsed_ms,error_code。凭据永不进入 argv/stdin/output。min(2000ms,work_remaining);失败 LOCK_TIMEOUT,不得阻塞到 deadline。flush/fsync、pdfinfo 等不可中断边界仅在 work_remaining>=5000ms 时进入;进入前后均 checkpoint。调用返回晚于 work deadline 时结果一律 TIME_BUDGET_STOP,即使 bytes/hash 正确也不得发布/登记 SUCCESS。.hibor-staging/,名称 <run_id>.<item_id>.<nonce>.part,以 os.open(O_CREAT|O_EXCL|O_WRONLY) 创建;staging 永不被当正式 PDF。os.fsync,关闭;独占只读 reopen,验证 %PDF-、remote/local bytes/hash、pdfinfo open/page/encryption 和详情页一致。CreateHardLinkW(final,staging):同卷、原子创建新目录项、final 已存在则失败且绝不替换;随后只读 reopen final 再校验 bytes/hash,最后 unlink staging。若 hard-link capability/reparse/volume 不符合,预检 STOP,不降级为覆盖 rename/copy。.part;crash after link before unlink:final 与 .part 指向同一已验证文件;恢复以 file-id+bytes/hash 证明同一后清理 staging。不同 hash、unknown file-id 或 final reparse 一律冲突 STOP。DUPLICATE,复用原文件但不重复 consume;其他 object/hash→FINAL_PATH_CONFLICT。不删除、截断、覆盖或改名模拟器原件和既有正式文件。| state | PDF staging | final PDF | quota terminal | manifest | delivery | timing | terminal | 允许后继 | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| P00_INIT | N | N | N | N | N | N | N | preflight | ||||||||
| P01_RESERVED | N | N | N | N | N | N | N | trigger | ||||||||
| P02_TRIGGER_UNKNOWN | N | N | U | N | N | N | N | close only | ||||||||
| P03_CACHE_MATCHED | N | N | V | N | N | N | N | stage | ||||||||
| P04_STAGING_PARTIAL | I | N | V | N | N | N | N | recover/stop | ||||||||
| P05_STAGING_VALID | V | N | V | N | N | N | N | publish | ||||||||
| P06_PUBLISHED | N | V | V | V | N | N | N | N | manifest | |||||||
| P07_MANIFESTED | N | V | V | V | V | N | N | N | delivery | |||||||
| P08_DELIVERY | N | V | V | V | V | V | N | N | timing | |||||||
| P09_TIMING | N | V | V | V | V | V | V | N | terminal | |||||||
| P10_CLOSED | N | V | V | N | V | U | N | V | N | V | N | V | N | V | N | none |
N=absent,V=known valid,I=known partial/invalid,U=unknown。顺序固定:quota trigger 终结→PDF publish→manifest→delivery→timing→terminal。上游失败不补造下游;P10 terminal 根据实际 presence 记录,不要求为了“闭包好看”写假文件。
每个 staging 创建后同步写一个同目录 recovery JSON(同样 O_EXCL),字段为 schema_version,run_id,item_id,remote_path,remote_bytes,remote_sha256,staging_path,final_path,stage,created_at_utc。resume-postprocess 仅在:无 active UI/process、quota 已是 confirmed/uncertain、remote identity 不变、staging/final 可安全复核时继续;否则 STOP。故障注入点固定为 create 前、每 1MiB 后、fsync 前后、hardlink 前后、final reopen 后、manifest/delivery/timing/terminal 前后,断言正式路径不会指向 partial。
账本旁固定 daily_quota_<date>.lock。第一次以 O_CREAT 建立普通 lock file,之后所有进程打开同一文件并用 msvcrt.locking(LK_NBLCK,1) 锁第 0 字节;lock file 不删除。每个 quota public API 在同一个锁持有期内严格执行:
read all bytes -> strict CSV/header/date/row validation -> fold -> idempotency lookup -> APP visible remainder conservative reconcile(if provided) -> safe_available check -> construct one row -> append -> flush -> fsync -> reopen/read/fold verify -> unlock。
锁前后都 checkpoint;锁 timeout/ledger unreadable/invalid/reopen mismatch 为 STOP,不点击原文。不得缓存旧 fold 后另开写事务。
baseline_floor=max(all BASELINE_ESTIMATE/CORRECTION_RAISE.baseline_floor);2026-07-29 首次必须 >=3,证据 ref 为中国中免任务。confirmed=baseline_floor + count(unique idempotency keys terminal CONSUME_CONFIRMED);uncertain=count(...CONSUME_UNCERTAIN);active=count(RESERVE without exactly one terminal)。safe_available=max(0,27-confirmed-uncertain-active);APP 可见剩余若可信,则 app_consumed=30-visible_remaining,有效 confirmed floor 取本地与 APP 更保守者;APP 不可信不降低本地值。RESERVE 只在 safe_available>=1、同 key 无 terminal/active 时写入。写入并 reopen 验证前不得点击。CONSUME_CONFIRMED/UNCERTAIN/RELEASE 必须引用 active reservation 并使其恰好终结一次;重复相同请求返回原 event,不追加。必须用两个真实测试进程竞争最后一个 safe slot,唯一一个 RESERVE 成功;覆盖锁 timeout、append 前崩溃(无行)、append 后 fsync 前/后、reopen mismatch、同 CLI 重放、同 handoff 不同 payload 冲突、残留 reservation、release/confirmed/uncertain replay、baseline>=3、correction raise、跨日 ledger、APP 值更保守。所有测试用临时账本,不接 APP、不消耗额度。
precedence 从高到低:LIVENESS_UNKNOWN/STATE_UNCERTAIN -> ACCESS_CONTROL -> TIME_BUDGET -> QUOTA -> INPUT -> ENVIRONMENT -> AMBIGUOUS_MAPPING -> VALIDATION -> INTERNAL -> PARTIAL/SUCCESS。高优先级证据不得被后续低优先级覆盖。
| terminal status | stop/error family | exit |
|---|---|---|
SUCCESS |
全部 requested item P10 success | 0 |
PARTIAL_SUCCESS |
至少一个 success,存在非 quota/time 的已知 gap | 2 |
TIME_BUDGET_STOP |
deadline/late I/O/subprocess timeout | 10 |
PARTIAL_QUOTA_STOP |
safe_available 不足且有有效子集 | 11 |
BLOCKED_INPUT |
task/schema/replay contract | 12 |
BLOCKED_ACCESS_CONTROL |
login/CAPTCHA/paywall/subscription/permission | 13 |
BLOCKED_ENVIRONMENT |
device/package/cache/tool/lock/liveness known failure | 14 |
BLOCKED_AMBIGUOUS_MAPPING |
cache/candidate/final identity 多义 | 15 |
VALIDATION_FAILED |
PDF/hash/page/manifest/package validation | 16 |
INTERNAL_ERROR |
未分类异常,证据保持 null | 20 |
STATE_UNCERTAIN |
child/file/quota liveness 或事实未知 | 27 |
成功子集存在时,TIME/QUOTA/ACCESS/STATE_UNCERTAIN 仍保留该高优先级 terminal,不降为 partial。CLI 捕获裸异常为 INTERNAL_ERROR/20;任何 terminal 中 status/exit_code/stop_code/blocker 必须互相符合本表。
row_id replay 同整行返回已有;冲突 STOP。delivery.md 只列元数据、文件路径、选择理由、状态、缺口与额度摘要,不含正文/结论;其源数据必须来自已验证 model,不从文件名猜。timing_manifest.csv 固定 12 列,所有已进入阶段均有一行,未进入阶段不造行。terminal_path=null,terminal_present=false。工具不发送 Codex/网络消息。py_compile、import、禁止 API/shell/credential 静态扫描。real_adb_action_count=0,trigger_count=0,real_quota_write_count=0。在第一次真实 reserve 前生成并锁定 performance_plan.json:10 个 primary item + 最多 3 个 no-trigger alternate;字段固定 plan_id,created_at_utc,slot_id,mode,batch_id,item_order,query,expected_report_identity,external_exclusion_allowed,selected_from_readonly_discovery。该计划的实际 bytes/hash 写入执行日志,之后不替换已触发 slot。
固定总体:
| slots | mode | 计入单份样本 | trigger 上限 | 批量角色 |
|---|---|---|---|---|
PERF-S01..PERF-S06 |
6 次 collect-one |
6 | 6 | 无 |
PERF-B01-I01..I04 |
1 次同 query collect-batch 的 4 个 item |
4 | 4 | I01=首份,I02-I04=增量 |
PERF-A01..A03 |
预登记 alternate | 仅替代 trigger 前 external-excluded primary | 合计仍不得超过 10 | 保持被替代 slot mode |
因此批量每个 item 同时是一个真实单份样本,正式 PASS 分母固定为 10,distinct trigger 最大也是 10;不得为了凑 PASS 触发第 11 份。alternate 仅在 reserve/点击前出现有证据的 external blocker 时替换,且被替代 primary 永久标 EXCLUDED_PRETRIGGER_EXTERNAL。
TIME_BUDGET_STOP、internal、validation、mapping、quota-state failure 都保留在分母并令 performance acceptance 失败,不能删样本。ceil(0.9*10)=9 个。任何计入样本非成功、任何验证项失败或样本少于 10,整体只能 PERFORMANCE_FAILED 或 INSUFFICIENT_PERFORMANCE_SAMPLES。INSUFFICIENT_PERFORMANCE_SAMPLES 顺延到次日新 ledger;不同日期样本可合并,但每个 slot 仍唯一、每日日限独立,统计不可重置失败 slot。设计 PASS 后按以下顺序实施:
| blocker | V002 closure | 强制测试 |
|---|---|---|
| 01 | 第 2–3、8 节 API/schema/call graph/exit | schema/order/null/extra-key/typed error |
| 02 | 第 5 节 observed→monotonic、Job child、bounded I/O | hang/kill/lock/late copy/hash/fsync/terminal |
| 03 | 第 4 节 provisional/confirmed/checkpoint | mismatch/duplicate/detail fail/补扫/漂移 |
| 04 | 第 6、9 节 staging+hardlink+closure | 每边界 crash、冲突、duplicate、恢复 |
| 05 | 第 3.5、7 节 atomic quota/replay | 双进程、崩溃、重复、残留、跨日 |
| 06 | 第 10.2–10.3 节固定 6+4 population | external exclusion、failure inclusion、median/P90 |
实现不得以跳过 hash、页数、manifest、quota、access-control 或 terminal closure 换取 SLA。开发员只做实现与自检,最终由 dev.reviewer.ana.cai 独立审核。
PENDING_INDEPENDENT_DESIGN_REREVIEW。
V002 复审 PASS 前,候选源码/测试/额度账本仍不存在;不得运行 Python、ADB、慧博 APP、真实或合成采集。当前真实 trigger 增量=0,2026-07-29 已知外部基线仍按至少 3 保守处理。