22 KiB
设备窗口 #2 运行手册(P7 收官:门 3 终局 + bsl stats + CTS AFTER)
一条命令产出三样东西:CONTRACT-P7 §7.2 的门 3 读数(36 例 × DirectVulkan × --use-pbuffer,
monolith ×1 + inproc ×3 + spawn ×3 + inproc RUN_AHEAD=0 ×1,同一 reboot-clean 会话)、
M2/M3 的 bsl-esc-menu 设备读数(MOBILEGL_PIPE_STATS 下的 /proc/<pid>/maps 行数峰值与 wbuf[]),
以及 §7.3 门 5 的 CTS AFTER(五块 KHR-GL46,inproc × DirectVulkan,对 device-window-1/CTS-base)。
脚本在 ~/w7/notes/p7/window2/(仓库副本 docs/Disaggregated/notes/p7/device-window-2/tools/)。
参数:<pipe-sha> = 最终功能包全部落地后的集成树提交;<stamp> 缺省 p7w7-<sha8>。
输出根 ~/w7/logs/p7w7/<stamp>/。设备 Redmi 2f7cbe2e,包 top.mobilegl.plugin.p7w1.trace(原地 install -r,不卸载任何东西)。
0. 前置(不占设备,开窗前核对)
<pipe-sha>必须含p7/devprep的跑器修复(fe4c8745:run_android_retrace_local.py能从 POSIX 主机起跑、 每遍之前清掉上一遍的产物)。没拣就会在第一步被lib.sh以名字拒绝;应急可export W2_TOOLS_OVERRIDE=~/w7/p7-devprep(只借工具,APK 仍按<pipe-sha>构建)。- Windows 侧 adb server 在跑并看得见
2f7cbe2e。WSL 的/usr/sbin/adb经 mirrored networking 连的就是它; server 没了在 Windows 上adb start-server,不要在 WSL 里起(会抢 5037 而看不见 USB)。 - 手机
/data/local/tmp/mgcts有glcts、gl_cts/、mgprobe(窗口 1 部署,现仍在;缺则sh ~/w7/logs/cts-a64/deploy/deploy.sh 2f7cbe2e)。 - 窗口期间没有别的 agent 用手机、主机不并行跑 gate(超时是墙钟)。「没有别的 agent」由锁保证:本波次所有 agent 都以
flock -w 3600 /home/swung/w7/locks/2f7cbe2e.lock <cmd>用手机;window.sh在 build 之后、preflight 之前拿同一把锁 (lib.sh的W2_SHARED_LOCK),一直持有到 restore 结束——两步之间别的 agent 插不进来;单独起的某一步自己拿、自己放。 拿锁是flock -o:脚本以同样的参数在 flock 进程下重跑,锁 fd 不传给子进程(步骤留下的 adb server / supervisor 启动器不会把锁 带出窗口)。等锁最多W2_SHARED_LOCK_WAIT(默认 3600 s),等不到退出 75、不碰手机。窗口自己的步骤锁W2_LOCK照旧。 手机若有锁屏密码,reboot 后要手动解锁一次(preflight 等sys.user.0.ce_available=true最多 10 min)。
1. 一条命令
bash ~/w7/notes/p7/window2/detach.sh ~/w7/logs/p7w7/window-<sha8>.log ~/w7/notes/p7/window2/window.sh <pipe-sha>
tail -f ~/w7/logs/p7w7/window-<sha8>.log # 结束行 "=== WINDOW 2 DONE <stamp>",其后打印 verdict
detach.sh = setsid nohup … < /dev/null &,与终端 / 工具 10 min 上限脱钩;它打印的 pid 是新会话的进程组长,
要停整个窗口用 kill -- -<pid>(只杀 pid 本身会留下正在跑的那一步,且放掉共享锁)。中断后原命令重跑即续:
每步完成写 <out>/steps/<step>.done;门 3 逐 (arm, case) 写 gate3/state/<arm>/<case>.done——只在该对要求的每一遍都留下
result.json 与 actual PNG 时才写,否则日志记 INCOMPLETE、gate3/progress.tsv 第 6 列 INCOMPLETE、不写 .done,下次整对重跑
(残档先删;遍数按首跑冻结在 gate3/arms.txt 的 repeat=);CTS 逐块写 cts/runs/<block>/.done——只在该块是完整读数时才写:
run_cts.py 退出 0,且 60-reduce.py --check-block(与判读同一段代码)确认 cts/report-<block>.json 对 caselist 里每个未 skip 的用例
都有结果、unrun.txt 为空;否则不写,原因进 cts/runs/<block>/complete.txt。每块另存所跑 caselist 的副本 cts/runs/<block>/caselist.txt
(caselist.path 指向的构建树删掉之后,输出目录仍能单独判读)。循环跑完仍有 INCOMPLETE 时 30-gate3.sh / 50-cts-after.sh 退出 3:window.sh 不给该步写 .done、
照走后面各步(reduce 与 restore 每次都跑),结尾打 WINDOW 2 INCOMPLETE … left open;原命令再跑一次只补缺的——若上一遍已 restore,
它先以 21-preflight.sh <stamp>(不重启)回到同一 boot 会话(重新钉频、stay-on;boot_id 变了就停;reboot-clean.txt 不改写,
session/resumed.txt 记一笔)。
会话(CONTRACT-P7 §7.2「同一 reboot-clean 会话」):session/boot-id.txt 是本窗口唯一的会话。30-gate3.sh 每对前后读手机
boot_id,与它不同立即停;每对的 .done 与每遍归档的 repeat-NN/boot_id.txt 都记 boot_id=… boot_id_before=…;60-reduce.py
要求四臂所有记录是同一个 boot_id 且等于 session/boot-id.txt,否则 GATE3 INVALID-SESSION。
中断后要删什么(先比 adb -s 2f7cbe2e shell cat /proc/sys/kernel/random/boot_id 与 <out>/session/boot-id.txt):
- boot_id 没变(主机 / WSL / adb 断、脚本被杀、某步 INCOMPLETE):什么都不删,原命令重跑。没
.done的对 / 块整对 / 整块重跑, 残档由脚本先删。只想重跑某个已完成的对:删gate3/state/<arm>/<case>.done与steps/gate3.done(CTS 块同理:cts/runs/<block>/.done与steps/cts.done),再原命令重跑。 - boot_id 变了(手机重启过):门 3 已完成的对全部作废(
30-gate3.sh在下一对之前就停;21-preflight.sh不带--reboot也停;带--reboot时只要gate3/state里还有.done就拒绝,防漏删)。删gate3/state/、gate3/archive/、gate3/logs/、gate3/progress.tsv、gate3/pin-*.txt与steps/preflight.done、steps/gate3.done,然后原命令重跑(preflight 带--reboot起新会话;session/found.env、gate3/cases.txt、gate3/arms.txt保留——「找到时」状态、分母与遍数不变)。bsl 与 CTS 不受会话约束,保留。 - 或者换 stamp 从头开(
window.sh <pipe-sha> <new-stamp>),旧目录留作记录。
不重启:window.sh <pipe-sha> --no-reboot(门 3 要 reboot-clean,只在复跑时用)。
2. 步骤(等价的逐条命令)与耗时
| # | 命令 | 做什么 | 估时 |
|---|---|---|---|
| 1 | 10-build.sh <sha> [<stamp>] |
~/w7/p7w7-tree-<sha8>(pipe 的 detached worktree,子模块从 pipe 拷,LFS fixture 随 checkout)里构建 APK(assembleTraceRelease,.p7w1 并排 id,debuggable,显式 stamp,debug keystore 签名)与主机制品(build-host:libMobileGL.so/libMobileGLServer.so/mobilegl_trace_replay + catalog),两端 stamp 字符串各 ≥1 |
6 min(dry:APK 131 s、host 223 s) |
| 2 | 21-preflight.sh <stamp> --reboot |
记录「找到时」的状态(supervisor、stay-on、钉频、Doze 白名单)→ reboot,前后 boot_id 必须不同 → 唤醒、svc power stayon true → pin_device.sh pin,check 为 PINNED 或 PINNED-1100(本板 pwrlevel 0 实跑 1100 MHz,窗口 1 已记,脚本期望值过期) |
2–3 min |
| 3 | 20-install.sh <stamp> |
adb install -r;设备上 base.apk 的 sha256 必须等于签名 APK,versionName 带 <sha7>;等 dex2oat 空闲 |
~1 min |
| 4 | 30-gate3.sh <stamp> |
36 例(--matrix 的 DirectVulkan 集减 create-indirect / 1.21.11-main-menu / photon-v1.3b,冻结在 gate3/cases.txt)× 四臂;iterationrp 带 apk.yml:460-462 三个 Magma 旋钮;每遍 result.json / actual PNG / 双角色日志 / transport-proof / logcat 归档;每臂前后 pin check;每对前后核 boot_id(§1「会话」),.done 只在每遍都有 result.json + actual PNG 时写,否则退出 3 留待续跑 |
55–65 min |
| 5 | 40-bsl-stats.sh <stamp> |
bsl-esc-menu × {inproc, spawn} 各 1 遍,MOBILEGL_PIPE_STATS=1 PERIOD=1;先 force-stop 再起设备端 root 采样器(0.25 s:maps 行数、VmRSS、VmHWM;排除 argv 带 tcp:// 的 supervisor server);wbuf[] 从归档日志取 |
~1 min |
| 6 | 50-cts-after.sh <stamp> |
APK 的 arm64 libMobileGL.so 推到 mgcts 并在设备上核 sha256;AFTER 环境 = $BASE 的 flag + MOBILEGL_TRANSPORT=inproc + ROLE_SPLIT_STATE=1 STRICT_ERRORS=1 RUN_AHEAD=1;臂证明(mgprobe PASS 且 logcat 有 inproc 解析句与 Config: IPC … strict=1 role-split-state=1 run-ahead=1、0 Fatal;再用一个 glcts 用例证一次,其 StatusCode 记进 arm-proof.txt,不是 Pass / Fail 时打 WARN);五块依次跑(顺序同 $BASE),每块 qpa_report --json(块的 .done 只在 run_cts 退出 0 且 60-reduce.py --check-block 判完整时写,否则退出 3 留待续跑),最后 cts_multi_report 出与 $BASE 同形的 JSON;UBO(GTF)块不跑:本 glcts 无 GTF 模块(ID-P7-16) |
6–7 min(pipe 头 lib inproc 实测 358 s;$BASE monolith 372 s) |
| 7 | 60-reduce.py <stamp> |
写 verdict.txt / verdict.json(见 §3);每遍都跑。自检:python3 60-reduce-selftest.py(主机,不占设备,~4 s) |
<10 s |
| 8 | 90-restore.sh <stamp> |
Home;am force-stop 包(回放后缓存的 app 进程与 spawn 回放留下的 libMobileGLServer.so @mgl-… 子进程会一直占着几百 MB);把 $BASE 库推回 /data/local/tmp/mgcts(设备 sha256 ≠ $BASE = IDENTITY.txt 的 7f58aa0b… 时才推,推后在设备上核 sha,结果行进 restored.txt);supervisor 若开窗时在跑则以 tcp_device_server.py start --allow-idle(同 listen / token / Doze 状态文件)在新 APK上重启并核实在听;解钉频(MIUI 启动 boost 会让 check 短暂读成 DRIFT,重读至多 20 s);stay-on 复原;每遍都跑(幂等) |
~15 s |
合计:构建 ~6 min + 设备 ~65–80 min ≈ 1.3–1.5 h。外推依据见 §5。
3. 判读 verdict.txt
- 门 3,先看
-- session行:session/boot-id.txt与四臂的每条记录(gate3/state/<arm>/<case>.done的boot_id/boot_id_before、 每遍repeat-NN/boot_id.txt)必须是同一个 boot_id;有第二个值、有记录不带 boot_id(含本规则之前的旧.done)、或缺session/boot-id.txt, 整门判GATE3 INVALID-SESSION,与图无关。全部通过但不是门本身的读数时不记PASS:分母不是 36 记PASS-SUBSET, 会话不是 reboot-clean(session/reboot-clean.txt)记PASS-NOT-REBOOT-CLEAN,末行注明「不是判据」,退出码非 0。 逐例PASS / FAIL / INCOMPLETE+ 原因:monolith 本身通过且确是 monolith(该遍mobilegl.log(及 client / server 日志)没有Config: IPC也没有MOBILEGL_TRANSPORT=行;没有日志即「未证」);inproc 与 spawn 各 3 遍齐全、该对有.done、每遍臂证明 (transport-proof.jsonpassed)通过、每遍 ssim ≥ 阈值、同一臂内三遍 actual PNG SHA-256 相同、每遍|ssim − monolith| ≤ 0.0005; OpenRA 在 monolith / inproc / spawn 每遍都1.000000且 mismatch 0;一遍的 logcat 与上一遍逐字节相同记STALE。-- arm identity行汇总 monolith 身份与 split 臂 transport-proof 的通过数。RUN_AHEAD=0臂只记录 (ssim、SHA、Config: IPC全是run-ahead=0的证明);它的 runner rc=1 是--require-inproc要求run-ahead=1的已知副作用(E1)。 末行GATE3 PASS: 36/36才是门 3。 - 跨臂同图不是门(ruling: integrator 2026-09-23):§7.2 的「三遍逐位相同」是臂内判据——inproc 自己三遍、spawn 自己三遍各自逐位相同。
inproc / spawn / monolith 三臂之间 actual PNG 是否相同只报告:逐例列
i==s==m(yes/i==s/no),-- cross-arm行给同图例数, 不同的例各打一行WARN cross-arm <case>: monolith <sha> | inproc <sha> | spawn <sha>;WARN 不改变该例与门 3 的判定 (跨臂的门是每遍|ssim − monolith| ≤ 0.0005)。 - BSL:每臂每进程(app / server)的 maps 行数峰值、VmRSS / VmHWM 峰值、
wbuf[wbufs wlivepk wdefpk wdefsync]。 - CTS:五块(shader-image / ssbo / dsa / texture / packed-pixels)缺一不可:每块要有
cts/runs/<block>/.done、非空且有结果的cts/report-<block>.json,以及读得到、非空的 caselist(先用输出目录里的副本runs/<block>/caselist.txt,没有才用caselist.path所指的文件;指向的文件没了、是空的、或两者都没有,不拿报告自己的用例顶替),否则该块记MISSING、整体CTS INCOMPLETE、退出码 ≠ 0—— 0 例的块永远不是读数。UBO 块(GTF-GL46.gtf31.GL3Tests.uniform_buffer_object*,p7-ubo-gl46.txt90 例)显式记unrun (not in this glcts)(设备 glcts 无 GTF 模块,ID-P7-16),不入判据。 每块 BASE 与 AFTER 的P/F/NS/W/X(W = CompatibilityWarning / QualityWarning 等,X = Crash / Timeout / InternalError / ResourceError / DeviceHang / Incomplete), rate = Pass / (Pass + Fail)(§7.3 原文:NS 不入分母;warning 与 crash 也不在分母里),delta pp;块判据 delta ≥ −0.5 pp、 新增 crash = 0 单独硬红(AFTER 为 X 而 BASE 不是——Fail→Crash 也算——另加 hung.txt;X 也是非 Pass,进 Pass→非 Pass 名单)、unrun.txt为空。 两边的 rate 只在两边都有结果的用例上算(同口径);$BASE没有的用例打WARN <block>: N case(s) have no $BASE result,不进两边的 rate, 其中的 crash 仍算新增。AFTER 一个 Pass / Fail 都没有而$BASE有(例如全变 NotSupported:rate 无从算起,$BASE的 Pass 全丢)→ 该块 FAIL;$BASE自己没有 Pass / Fail → 该块 INCOMPLETE——算不出 delta 的块永远不是 PASS。NotSupported 数与$BASE不同时打WARN <block>: NotSupported …(只作信息:合同口径 NS 不入分母;变成 NS 的 Pass 在 Pass→非 Pass 名单里)。(info)列与每块的info行是旧口径 Pass / (结果数 − NS):BASE、AFTER 两个 rate 与 delta,只供对照,不判。另列 Pass→非 Pass 与非 Pass→Pass 的逐例名单; AFTER 高出 0.5 pp 以上只标注不判红。某块用的不是工具树里完整的p7-<block>-gl46.txt(--limit子集)时,全部通过也只记CTS PASS-SUBSET。 - 末行
WINDOW2 GATE3 <v> | CTS <v> -> exit <n>:门 3 为PASS(36/36、reboot-clean、同一会话)且 CTS 为PASS(五块完整)才是 0;PASS-SUBSET/PASS-NOT-REBOOT-CLEAN不是判据,退出 1;门 3 没跑(无gate3/cases.txt)记NOT-RUN,同样非 0。reduce的退出码只作记录:红的门也要走完 restore。 - 自检(主机,~4 s):
python3 60-reduce-selftest.py(门 3 按 36 例造)——造目录验:缺块 →CTS INCOMPLETE;boot_id 变 / 旧.done/ 缺boot-id.txt→GATE3 INVALID-SESSION;monolith 日志带Config: IPC→ FAIL;跨臂不同 → WARN 仍 PASS;臂内不同 → FAIL;只由 rate 定的块 (dsa 1 / 2 / 4 例 Pass→Fail:−0.270 pp PASS、−0.541 pp FAIL、364/6/0/1/0 −1.081 pp FAIL,无 crash);caselist 没了 / 为空 / 全 NotSupported → MISSING / FAIL 而非 PASS;2 例门 3、非 reboot-clean、--limitCTS →PASS-SUBSET/PASS-NOT-REBOOT-CLEAN且退出非 0;$BASE缺的用例与 NS 变化 → WARN;--check-block的 0 / 3;dry run 数据上的合同口径 (60-reduce-selftest-pre14e1c8b9.json= pre-14e1c8b9 五块相对$BASE的差异)dsa −0.272 pp;~/w7/logs/devprep/w2/pre-14e1c8b9在时再对原始输出验一遍。--reducer <py>可对别的 reducer 跑同一套检查(red-once)。
4. 入库清单 → docs/Disaggregated/notes/p7/device-window-2/
verdict.txt、verdict.json、timing.tsv;session/(found.env、reboot-clean.txt、boot-id*.txt、apk.sha256、apk-on-device.sha256、
apk-install.txt、pin-*.txt、device.txt、restored.txt);gate3/{cases.txt,excluded.txt,arms.txt,progress.tsv,pin-*.txt};
bsl/<arm>/{peaks.txt,wbuf.txt,wbuf-gauges.txt};cts/{IDENTITY 即 deploy/IDENTITY.txt,arm-proof.txt,preflight.txt,report-*.txt,report-*.json,after-*.json,after-*.md,pin-*.txt}、
cts/runs/*/{crashed,hung,unrun,skipped,complete,caselist}.txt 与 caselist.path。归档图像与日志(gate3/archive/、bsl/*/archive/、qpa)留在 ~/w7/logs/p7w7/<stamp>/,
在 README 里记绝对路径(>2 MiB 不入库)。主机制品 <out>/host/ 与 host.sha256 供之后的 TCP 对照(run_tcp_matrix.py --library/--runner,同 stamp)。
5. Dry run(2026-09-23,已装 p7w6 APK 45759c30…,只证管线,不是判据)
命令:dry-run-p7w6.sh(W2_APK_OVERRIDE=~/w7/logs/p7w6/trace-p7w6.apk,W2_TOOLS_OVERRIDE=~/w7/p7-devprep,不重启,钉频)。
| 步 | 结果 | 墙钟 |
|---|---|---|
| preflight(无 reboot) | found:supervisor 在跑、stay-on 15、UNPINNED;pin → PINNED | 5 s |
install --verify-only |
设备 base.apk sha256 = 45759c30…,versionName 26.09.0e16ca2-trace |
<1 s |
| 门 3:OpenRA + iris-bsl-in-world × 四臂 × 1 | 8 次回放全部归档;OpenRA 四臂 1.000000 / 0;bsl-in-world 四臂 0.997010 同 SHA;spawn 证明 server role in pid …;ra0 两例 run-ahead=0,rc=1(预期) |
63 s(7–8 s/例/臂) |
| bsl stats inproc(+ 第二轮 spawn) | 两臂 0.999791667、SHA 155dcdd1…(= W6/E0a);p7w6 读数:inproc app maps 峰 8536 行 / VmHWM 823 MB;spawn server 7401 行 / 343 MB,client 4595 行 / 555 MB;wbuf[wbufs=28 wlivepk=1052 wdefpk=3312832 wdefsync=24] |
14 s/臂 |
| CTS AFTER dsa 前 20 例 | 部署 p7w6 lib 12861aa1… 并核 sha;mgprobe PASS;mgprobe 与 glcts 的臂证明 PROVEN;BASE 19/0/0/1 vs AFTER 19/0/0/1,+0.000 pp,0 新 crash;之后 $BASE lib 7f58aa0b… 推回 |
1–2 s/块 |
| restore | Home、supervisor 在新起的 tcp://0.0.0.0:40613 在听、UNPINNED、stay-on 15、Doze 白名单同开窗 |
5 s |
构建脚本 @ 14e1c8b9,stamp p7w7dry-14e1c8b9(未安装) |
APK f2ca6b02…(id .p7w1、versionName 26.09.14e1c8b-trace、同 debug 证书),lib stamp 串 1;主机制品 stamp 串 1 |
358 s |
| CTS 计时样本:p7w6 inproc 全 ssbo + dsa | ssbo 124/124;dsa P/F/NS/W/X 366/3/0/1/1,合同口径 −0.272 pp(旧口径 −0.539),1 新 crash(见 §6) | 3 s + 9 s |
CTS 预读:pipe 头 14e1c8b9 的 arm64 lib(取自上行未安装的 APK,只推到 mgcts)五块全跑 |
见 §6:dsa 与 shader-image 各 1 个新 crash;之后 $BASE lib 推回并核 sha |
358 s |
外推:窗口 1 同机同口径的逐例间隔(E0a monolith 39 例 360 s、E0a inproc 342 s、W4 inproc 412 s;最慢 derivative 30 s、 bsl-esc-menu 15–30 s)与本次 dry run 的 7–8 s/例一致,36 例一遍 ≈ 5.5–7 min;8 遍 ≈ 45–55 min,另加 144 次 runner 调用的 启动 / 汇总页与每臂 pin check ≈ 5 min → 门 3 55–65 min。CTS 五块 inproc 实测 358 s(shader-image 9 / ssbo 3 / dsa 9 / texture 108 / packed-pixels 220 s)。
6. 已知事实与限制
- 门 5 在 pipe 头
14e1c8b9上会红(预读,非判据,逐例归属在docs/Disaggregated/notes/p7/device-window-2/dry-run/pre-14e1c8b9-cts/attribution.txt):同一 lib 的 monolith 与 inproc 逐例对照(inproc 带或不带三个 split 旋钮结果相同):KHR-GL46.direct_state_access.renderbuffers_storage:monolith Pass,inproc SIGABRTFatal{ReplyTooLarge, "ReadPixels 256x512 0x1908/0x1406 2097152 > 2097136"}——RGBA/FLOAT 回读恰 2 MiB,比一个 reply 槽的载荷上限(槽 − 16 B 头,MG_Remote/Transport/ReplySlot.h:166-169)多 16 B;客户端在发射前具名拒绝 (MG_Remote/Client/ClientSession.cpp:2319,ID-47:「chunked readback 是 P6 债」)。…renderbuffers_storage_multisample:monolith Pass,inproc Fail。两例合计 dsa 按合同口径 Pass/(Pass+Fail) 为 −0.272 pp (368/370 → 366/369,在 0.5 pp 内;旧口径 Pass/(结果数 − NS) 为 −0.539 pp)——dsa 红在 1 个新 crash,不在 rate。 新 reducer 在该数据上的读数:docs/Disaggregated/notes/p7/device-window-2/dry-run/pre-14e1c8b9-cts/verdict-contract.txt。KHR-GL46.shader_image_load_store.incomplete_textures:monolith Fail($BASE亦非 Pass),inproc SIGABRTFatal{UnmigratedVerb, "Magma:image-view-window"}(MG_Backend/DirectVulkan/Renderer/UniformManager.cpp:151)——Fail 变 Crash,按门 5 是新 crash。…shader_image_load_store.advanced-sync-vertexArray:$BASEPass,pipe 头 monolith 与 inproc 都 Fail——不是分离缺陷,是 p7w1 之后两臂共有的漂移。KHR-GL46.texture_border_clamp.Texture2DArrayCompressed:整块里 Fail 一次,单跑三臂都 Pass——抖动。- 其余:ssbo、packed-pixels 与
$BASE相同;texture +0.960 pp;shader-image 整体 +4.284 pp(合同口径;旧口径 +2.9,3 例修好)。 终局窗口之前要么修(ReadPixels 分块或放大 reply 槽;image-view-window的 incomplete-texture 形状 decline 成 GL 语义而不是 Fatal),要么由集成者裁定。
- dry run 暴露并已修的两处:
run_android_retrace_local.py只会用 Git Bash 起跑(WSL 下每例 FileNotFoundError),且一遍没产出时会归档上一遍的图(假「逐位相同」)——fe4c8745,带 red-once 单测; 脚本自身的pipefail+grep -q把在跑的 supervisor 读成「不在」——已改为先取输出再匹配。 $BASE的机器可读 JSON(CTS-base/README 所称base-DirectVulkan-monolith-p7w1-9be62cbc.json)此前不在任何树里;已按cts_multi_report.py --adopt-legacy从~/w7/logs/cts-a64/base/runs重生成入tools/cts/baselines/(数字与 README 表逐块一致;texture 因 skip 表 1 例记 INCOMPLETE 是该工具的口径)。 判据本身用的是入库的CTS-base/report-*.json逐例结果。$BASE库的 IDENTITY 写 stampp7w1-d260f110,README / JSON 名写9be62cbc:两者是同一补丁(d260f110与9be62cbc同题提交),只是命名差。- 每次回放的
am force-stop会杀 TCP supervisor;restore 负责按开窗状态复原。