"""Audit the two staged shadow runs and write the result document.""" from collections import Counter from pathlib import Path import hashlib,json ROOT=Path(__file__).resolve().parents[2] OUT=ROOT/'test/context-shadow-20260917' def read(path):return json.loads(path.read_text(encoding='utf-8')) def audit(label): folder=OUT/label;s=read(folder/'shadow-summary.json') rows=[json.loads(line) for line in (folder/'shadow-trials.jsonl').read_text(encoding='utf-8').splitlines()] negative=[json.loads(line) for line in (folder/'shadow-negative.jsonl').read_text(encoding='utf-8').splitlines()] assert len(rows)==s['total']==s['accepted']==896 assert {r['jac'] for r in rows}==set(range(896)) assert all(r['reason']=='accepted' and r['referenceCount']==r['candidateCount'] for r in rows) assert all(r['candidateCount']==r['probeCount']+r['appends'] for r in rows) assert sum(r['baselineCount']!=r['probeCount'] for r in rows)==s['countDifferent'] assert sum(any(a!=b for a,b in r['mapping']) for r in rows)==s['slotRelocationTrials'] assert sum(sum(a!=b for a,b in r['mapping']) for r in rows)==s['relocatedSlots'] assert sum(r['appends'] for r in rows)==s['appends'] assert [sum(r['path']==i for r in rows) for i in range(4)]==s['paths'] assert s['mismatches']==s['liveContamination']==s['forbiddenNativeCalls']==s['rejected']==0 for key in ['tailEqual','liveTailEqual','memoImmutable','untouchedProbeEqual','metadataImmutable']:assert s[key]==896 assert len(negative)==s['negativePassed'] and all(n['reason']==n['expected'] and n['unchanged'] for n in negative) assert not (folder/'first-mismatch.json').exists() s['negativeReasonCounts']=dict(Counter(n['reason'] for n in negative)) s['example200']=next(r for r in rows if r['jac']==200) s['measurement']=read(folder/'measurement.json') return s def main(): a=audit('r288');b=audit('position52') worker_sha=hashlib.sha256((OUT/'worker/model.exe').read_bytes()).hexdigest() assert a['validatedWorkerSha256']==b['validatedWorkerSha256']==worker_sha assert a['measurement']['hashes']==b['measurement']['hashes'] build=read(OUT/'worker/build.json');assert build['wholeContextGuardUnchanged'] result=dict(r288=a,position52=b,workerSha256=worker_sha,productionPathChanged=False) (OUT/'validation.json').write_text(json.dumps(result,ensure_ascii=False,indent=2)+'\n',encoding='utf-8') lines=['# 最小 context shadow replay 验证结果', '', '## 1. Candidate 能否逐位复现 Reference', '', '**可以,在本轮两个 operation 的已覆盖路径和严格前置条件下,1,792 次 shadow replay 全部通过,出口不一致为 0。** R288 先完成全部 896 次;同一 worker 二进制通过该阶段后,才运行 position 52 的 896 次。', '', '参考答案始终是**同一个当前 probe 入口的独立深拷贝,真实执行原 operation 后的出口**。没有把 baseline 出口当参考。baseline 只提供本 Jacobian 内的局部语义记录,不提供用于恢复的完整 context。', '', '| 统计 | group 6 / R288 / position 16 | group 18 / R475 / position 52 |', '|---|---:|---:|'] for title,key in [('shadow 总次数','total'),('可重放','accepted'),('自然轨迹 reject','rejected'),('Reference/Candidate 不一致','mismatches'),('入口 count 不同','countDifferent'),('发生 slot relocation 的 probe','slotRelocationTrials'),('重定位逻辑 slot 数量','relocatedSlots'),('追加条目总数','appends'),('PT hit','ptHit'),('PT miss','ptMiss'),('PH hit','phHit'),('PH miss','phMiss'),('独立后续 evaluator 返回值/dy/w/context 一致','tailEqual'),('后续 evaluator 与主仿真返回值/dy/w 一致','liveTailEqual'),('memo 条目只读验证','memoImmutable'),('未写入的 probe 数据保持不变','untouchedProbeEqual'),('局部 metadata 未被 Reference/Candidate 改写','metadataImmutable'),('Candidate 物理 native 调用','forbiddenNativeCalls'),('主 context/浮点环境污染','liveContamination')]: lines.append(f'| {title} | {a[key]} | {b[key]} |') lines += ['', '### 如何保证比较有意义', '', '1. 在目标 probe 的 operation 前,深拷贝 property states、全部 pipe 槽、scalar memo 的全部 entries 和计数,分别绑定到 Reference/Candidate 私有存储。两路没有共享可写 context。', '2. Reference 调用该位置的原始表达式。Candidate 只解释 baseline 捕获的 query/read/valid/allocate/write/OR/scalar-get 语义;物理 native 入口有运行时禁入检查。Reference 执行期间不能补写 Candidate 的记录。', '3. Candidate 从自己的 probe 副本建立 overlay。重新扫描当前有序 entries,采用原 PT/PH 的 exact `==` 和 medium 比较语义找 first-match;用逻辑 ID 映射结果,追加使用当前 count。', '4. 所有条件成功后进入无失败分支的 commit,仅按记录顺序更新实际写入字段、valid OR、count、指定 pipe 槽、memo 命中计数及显式输出;不复制 baseline context,也不覆盖 probe 未写字段。reject 前没有向 Candidate 或输出提交任何存储。', '5. 逐位比较输出、所有 active property 字段、valid bits、全部 pipe 字段、memo entries/计数、warning observer、errno 和 x87/SSE 环境。私有指针按“绑定到各自当前 owner”检查;不要求两个独立 allocation 的地址相等。数值字段没有容差或近似比较。', '6. 两个独立出口继续执行同一份原 evaluator 后续代码,实测返回状态、完整 dy/w、context 和 memo 计数一致;再与主仿真的真实 evaluator 返回值/dy/w 核对。主仿真仍然执行原 operation,没有采用 Candidate 输出,没有进入真实 skip 路径。', '7. 两轮主仿真的状态、输出、事件及全部 896 个 132×132 Jacobian 仍与未插桩基线逐字节一致。whole-context guard 源码哈希保持一致。', '', 'operation 本身返回一个 double,没有单独的 int 成功码;报告中的 evaluator 状态来自两条后续执行路径,不是用 `isfinite(output)` 代替。', '', '### 两个具体入口例子(Jacobian 200)', '', '| 项目 | R288 | position 52 |', '|---|---|---|'] for title,key in [('baseline count','baselineCount'),('当前 probe count','probeCount'),('Reference 出口 count','referenceCount'),('Candidate 出口 count','candidateCount'),('逻辑 slot → 当前 slot','mapping')]:lines.append(f'| {title} | `{a["example200"][key]}` | `{b["example200"][key]}` |') lines += ['', 'R288 保留 probe 原 slot 12,在 13、14 追加;position 52 保留 probe slot 74 的压力/温度差异,查询重新扫描后仍 miss,再在 75、76 追加。', '', '## 2. 哪些路径已经可以 replay', '', '| 查询路径 | R288 次数 | position 52 次数 |', '|---|---:|---:|'] for i,name in enumerate(['近零流量,无物性查询','PT miss → PT miss','PH miss → PT miss → PT hit → PT miss','PH hit → PT hit → PT miss']):lines.append(f'| {name} | {a["paths"][i]} | {b["paths"][i]} |') lines += ['', '以上“可 replay”指本轮相应 operation 的完整 0–10 s 轨迹,且所有 runtime guard 同时成立。PH miss 的 h 登记与 valid OR、后续对刚追加逻辑条目的 PT hit 都保留。近零流量不追加物性条目,但仍执行 pipe 的有序写入,包括 valid=0 的同值写入。', '', 'R288 的 638 次 count 差异中,67 次属于无查询/无追加路径,因此只有 571 次发生实际 slot relocation。position 52 同理,24 次 count 差异中有一次无追加。不能把 count 差异次数当作重定位次数。', '', '## 3. 哪些情况仍必须 reject / fallback', '', '自然轨迹中各 reject 分类均为 0。为防止“全成功但拒绝机制无效”,另在私有副本中执行下列负例,要求 reject 且整个 Candidate 与输出 sentinel 逐字节不变;这些不计入自然轨迹的 896 次。', '', '| reject 分类 | R288 负例通过次数 | position 52 负例通过次数 |', '|---|---:|---:|'] for reason in sorted(set(a['negativeReasonCounts'])|set(b['negativeReasonCounts'])):lines.append(f'| `{reason}` | {a["negativeReasonCounts"].get(reason,0)} | {b["negativeReasonCounts"].get(reason,0)} |') lines += ['', '严格拒绝边界:', '', '- 记录不属于当前 Jacobian/operation、源代码不再匹配已验证 worker、记录溢出或未知语义事件。', '- 输入改变、first-match 逻辑映射冲突、hit/miss 路径改变、已消费字段或 valid 掩码结果不一致。', '- 容量不足或 scratch、非空 observer、未覆盖的已有 entry 原地更新、pipe 命中分支变化、非有限结果或未覆盖路径。', '- memo owner/lifetime/recording 不符合只读约束、所需 scalar key 未命中或值不匹配。Candidate 不调用物理 fallback 来弥补 memo miss。', '- 舍入模式、SSE 控制模式或所需异常状态不满足已验证条件;已记录的非零 errno 前置条件不成立。', '', '负例包括第一次追加完成后第二次容量检查失败、末尾未知事件、末尾非有限输出,因此覆盖了 overlay 已发生大量修改后的回滚,不只是入口早退。position 52 的 PH-hit 样本还直接改变 probe 已有条目的 rho 和 MU 位,确认消费值/valid guard 生效。', '', 'Jacobian memo 的 entries 始终只读,但 Reference 的 scalar get 会增加 reuses 计数。Candidate 在 overlay 中验证同一 bit-key 查找结果,并在 commit 中重放对应计数增量。没有将 baseline 的 recording/put 副作用照搬到 probe。', '', '验证期间发现并修复了 Windows 诊断隔离问题:该工具链的 `fesetenv` 不完整恢复 SSE 控制寄存器。负例现在保存/恢复完整 x87/SSE 环境,并验证 SSE 单独改变时会拒绝。修复前失败证据保存在 `test/context-shadow-20260917/env-restore-investigation/`;本报告仅使用修复后的同一构建全量重跑结果。', '', '## 4. Runtime metadata 需要多少', '', '| 当前实现 | R288 | position 52 |', '|---|---:|---:|', f'| 单条语义事件 | {a["eventBytes"]} B | {b["eventBytes"]} B |', f'| 最大事件数 | {a["eventMax"]} | {b["eventMax"]} |', f'| 每条 operation 记录实际使用范围 | {a["metadataMin"]}–{a["metadataMax"]} B | {b["metadataMin"]}–{b["metadataMax"]} B |', f'| 每阶段为 512 个事件预留 | {a["metadataReserved"]} B | {b["metadataReserved"]} B |', '', '记录包括:Jacobian/operation 身份、四个显式输入、出口值、query 完整 key/逻辑命中关系、实际消费的字节值与 valid 掩码、创建顺序、字段更新/OR、scalar key/value、memo 绑定及环境前置条件。**不保存 baseline 完整 property/pipe context 用于 replay。** 只保留当前 Jacobian 的一条目标 operation 记录。', '', f'事务 scratch 另需一个 {a["contextCopyBytes"]} B 的 overlay;本诊断为入口、Reference、Candidate、回滚检查及双路后续比较共保留 7 个 context 副本、2 个 {a["frameCopyBytes"]} B frame。它们是 shadow 验证工作内存,不能算作未来 skip 每条记录都必须长期保存的 metadata。slot 映射临时表为 256 个 int(当前 ABI 1,024 B)。', '', '这是当前保守事件表示的实测大小,未做去重或压缩,也没有据此评价性能。', '', '## 5. 是否具备最小真实 skip 实验的条件', '', '**已具备针对这两个单独 operation、上述四种已验证路径的下一阶段实验条件。** 下一步必须继续保持严格 guard、事务 commit、reject 后原执行以及独立 Reference 抽查/全量对比;先对 R288 单点实验,再单独考虑 position 52。', '', '本轮没有实现真实 skip,也没有移除或放宽 whole-context guard。结论不适用于整个 R475、全部 reuse interval、新模型、其他 native kernel、容量耗尽/observer 非空/已有 entry 原地更新等未验证分支;Linux 尚未运行本实验。双路执行和详细检查的时长不作性能证据。', '', '## 复现与证据', '', '依赖上一轮保留的 access worker 和未插桩 baseline 文件。准备阶段核对 access worker 源码哈希;第二阶段核对第一阶段通过的 worker 二进制 SHA-256。', '', '```powershell', r'.venv-win\Scripts\python.exe tests/manual/diagnose_context_shadow.py prepare', r'.venv-win\Scripts\python.exe tests/manual/diagnose_context_shadow.py run --position 16', r'.venv-win\Scripts\python.exe tests/manual/diagnose_context_shadow.py run --position 52', r'.venv-win\Scripts\python.exe tests/manual/analyze_context_shadow.py', '```', '', '生成文件位于 `test/context-shadow-20260917/`:`worker/build.json`、各阶段 `shadow-trials.jsonl`、`shadow-summary.json`、`shadow-negative.jsonl`、`measurement.json`,以及汇总的 `validation.json`。若出现不一致,会输出首个不同字段和完整入口/两路 context、frame、metadata 到 `first-mismatch.json`。最终两阶段均未生成该文件。', '', f'最终 worker SHA-256:`{worker_sha}`。', '', '全量主轨迹哈希(两阶段相同):', ''] for name,digest in a['measurement']['hashes'].items():lines.append(f'- {name}: `{digest}`') target=ROOT/'tests/manual/context_shadow_report.md';target.write_text('\n'.join(lines)+'\n',encoding='utf-8') print(json.dumps(dict(total=a['total']+b['total'],accepted=a['accepted']+b['accepted'],mismatches=0,negativePassed=a['negativePassed']+b['negativePassed'],report=str(target)),ensure_ascii=False,indent=2)) if __name__=='__main__':main()